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 "../console_io.h"
101 #include "../cmdarg_err.h"
102 #include "../version_info.h"
103 #include "../merge.h"
104 #include "../alert_box.h"
106 #include <wsutil/file_util.h>
109 #include "../capture_ui_utils.h"
110 #include "../capture-pcap-util.h"
111 #include "../capture_ifinfo.h"
112 #include "../capture.h"
113 #include "../capture_sync.h"
117 #include "../capture-wpcap.h"
118 #include "../capture_wpcap_packet.h"
119 #include <tchar.h> /* Needed for Unicode */
120 #include <commctrl.h>
124 #include "gtk/file_dlg.h"
125 #include "gtk/gtkglobals.h"
126 #include "gtk/color_utils.h"
127 #include "gtk/gui_utils.h"
128 #include "gtk/color_dlg.h"
129 #include "gtk/filter_dlg.h"
130 #include "gtk/uat_gui.h"
132 #include "gtk/main.h"
133 #include "gtk/main_airpcap_toolbar.h"
134 #include "gtk/main_filter_toolbar.h"
135 #include "gtk/menus.h"
136 #include "gtk/main_packet_list.h"
137 #include "gtk/main_statusbar.h"
138 #include "gtk/main_statusbar_private.h"
139 #include "gtk/main_toolbar.h"
140 #include "gtk/main_welcome.h"
141 #include "gtk/drag_and_drop.h"
142 #include "gtk/capture_file_dlg.h"
143 #include "gtk/main_proto_draw.h"
144 #include "gtk/keys.h"
145 #include "gtk/packet_win.h"
146 #include "gtk/stock_icons.h"
147 #include "gtk/find_dlg.h"
148 #include "gtk/recent.h"
149 #include "gtk/follow_tcp.h"
150 #include "gtk/font_utils.h"
151 #include "gtk/about_dlg.h"
152 #include "gtk/help_dlg.h"
153 #include "gtk/decode_as_dlg.h"
154 #include "gtk/webbrowser.h"
155 #include "gtk/capture_dlg.h"
156 #include "gtk/capture_if_dlg.h"
157 #include "gtk/tap_dfilter_dlg.h"
158 #include "gtk/prefs_column.h"
159 #include "gtk/prefs_dlg.h"
162 #include "../image/wsicon16.xpm"
163 #include "../image/wsicon32.xpm"
164 #include "../image/wsicon48.xpm"
165 #include "../image/wsicon64.xpm"
166 #include "../image/wsiconcap16.xpm"
167 #include "../image/wsiconcap32.xpm"
168 #include "../image/wsiconcap48.xpm"
173 #include "airpcap_loader.h"
174 #include "airpcap_dlg.h"
175 #include "airpcap_gui_utils.h"
179 #include <epan/crypt/airpdcap_ws.h>
182 #ifdef NEW_PACKET_LIST
183 #include "gtk/new_packet_list.h"
187 * Files under personal and global preferences directories in which
188 * GTK settings for Wireshark are stored.
190 #define RC_FILE "gtkrc"
194 /* "exported" main widgets */
195 GtkWidget *top_level = NULL, *pkt_scrollw, *tree_view_gbl, *byte_nb_ptr_gbl;
197 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
198 static GtkWidget *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
199 static GtkWidget *main_first_pane, *main_second_pane;
201 /* internally used widgets */
202 static GtkWidget *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
205 GtkWidget *airpcap_tb;
206 int airpcap_dll_ret_val = -1;
209 GString *comp_info_str, *runtime_info_str;
210 gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
212 guint tap_update_timer_id;
215 static gboolean has_console; /* TRUE if app has console */
216 static void destroy_console(void);
217 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
219 static void console_log_handler(const char *log_domain,
220 GLogLevelFlags log_level, const char *message, gpointer user_data);
223 capture_options global_capture_opts;
227 static void create_main_window(gint, gint, gint, e_prefs*);
228 static void show_main_window(gboolean);
229 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
230 static void main_save_window_geometry(GtkWidget *widget);
233 /* Match selected byte pattern */
235 match_selected_cb_do(gpointer data, int action, gchar *text)
237 GtkWidget *filter_te;
238 char *cur_filter, *new_filter;
240 if ((!text) || (0 == strlen(text))) {
241 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
246 filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
249 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
251 switch (action&MATCH_SELECTED_MASK) {
253 case MATCH_SELECTED_REPLACE:
254 new_filter = g_strdup(text);
257 case MATCH_SELECTED_AND:
258 if ((!cur_filter) || (0 == strlen(cur_filter)))
259 new_filter = g_strdup(text);
261 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
264 case MATCH_SELECTED_OR:
265 if ((!cur_filter) || (0 == strlen(cur_filter)))
266 new_filter = g_strdup(text);
268 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
271 case MATCH_SELECTED_NOT:
272 new_filter = g_strconcat("!(", text, ")", NULL);
275 case MATCH_SELECTED_AND_NOT:
276 if ((!cur_filter) || (0 == strlen(cur_filter)))
277 new_filter = g_strconcat("!(", text, ")", NULL);
279 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
282 case MATCH_SELECTED_OR_NOT:
283 if ((!cur_filter) || (0 == strlen(cur_filter)))
284 new_filter = g_strconcat("!(", text, ")", NULL);
286 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
290 g_assert_not_reached();
295 /* Free up the copy we got of the old filter text. */
298 /* Don't change the current display filter if we only want to copy the filter */
299 if (action&MATCH_SELECTED_COPY_ONLY) {
300 GString *gtk_text_str = g_string_new("");
301 g_string_append(gtk_text_str, new_filter);
302 copy_to_clipboard(gtk_text_str);
303 g_string_free(gtk_text_str, TRUE);
305 /* create a new one and set the display filter entry accordingly */
306 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
308 /* Run the display filter so it goes in effect. */
309 if (action&MATCH_SELECTED_APPLY_NOW)
310 main_filter_packets(&cfile, new_filter, FALSE);
313 /* Free up the new filter text. */
318 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
322 if (cfile.finfo_selected) {
323 filter = proto_construct_match_selected_string(cfile.finfo_selected,
325 match_selected_cb_do((data ? data : w), action, filter);
330 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
334 if (cfile.finfo_selected) {
335 filter = proto_construct_match_selected_string(cfile.finfo_selected,
337 if ((!filter) || (0 == strlen(filter))) {
338 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
339 "Could not acquire information to build a filter!\n"
340 "Try expanding or choosing another item.");
345 color_display_with_filter(filter);
348 color_filters_reset_tmp();
350 color_filters_set_tmp(filt_nr,filter, FALSE);
352 cf_colorize_packets(&cfile);
358 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
360 gchar *selected_proto_url;
361 gchar *proto_abbrev = data;
366 if (cfile.finfo_selected) {
367 /* open wiki page using the protocol abbreviation */
368 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
369 browser_open_url(selected_proto_url);
370 g_free(selected_proto_url);
373 case(ESD_BTN_CANCEL):
376 g_assert_not_reached();
382 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
385 const gchar *proto_abbrev;
389 if (cfile.finfo_selected) {
390 /* convert selected field to protocol abbreviation */
391 /* XXX - could this conversion be simplified? */
392 field_id = cfile.finfo_selected->hfinfo->id;
393 /* if the selected field isn't a protocol, get it's parent */
394 if(!proto_registrar_is_protocol(field_id)) {
395 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
398 proto_abbrev = proto_registrar_get_abbrev(field_id);
400 if (!proto_is_private(field_id)) {
401 /* ask the user if the wiki page really should be opened */
402 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
403 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
405 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
407 "The Wireshark Wiki is a collaborative approach to provide information "
408 "about Wireshark in several ways (not limited to protocol specifics).\n"
410 "This Wiki is new, so the page of the selected protocol "
411 "may not exist and/or may not contain valuable information.\n"
413 "As everyone can edit the Wiki and add new content (or extend existing), "
414 "you are encouraged to add information if you can.\n"
416 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
418 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
419 "which will save you a lot of editing and will give a consistent look over the pages.",
420 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
421 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
423 /* appologize to the user that the wiki page cannot be opened */
424 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
425 "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
427 "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
429 "Since this is a private protocol, such information is not available in "
430 "a public wiki. Therefore this wiki entry is blocked.\n"
432 "Sorry for the inconvenience.\n",
433 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
438 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
440 gchar *selected_proto_url;
441 gchar *proto_abbrev = data;
445 if (cfile.finfo_selected) {
446 /* open reference page using the protocol abbreviation */
447 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
448 browser_open_url(selected_proto_url);
449 g_free(selected_proto_url);
452 case(ESD_BTN_CANCEL):
455 g_assert_not_reached();
460 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
463 const gchar *proto_abbrev;
467 if (cfile.finfo_selected) {
468 /* convert selected field to protocol abbreviation */
469 /* XXX - could this conversion be simplified? */
470 field_id = cfile.finfo_selected->hfinfo->id;
471 /* if the selected field isn't a protocol, get it's parent */
472 if(!proto_registrar_is_protocol(field_id)) {
473 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
476 proto_abbrev = proto_registrar_get_abbrev(field_id);
478 if (!proto_is_private(field_id)) {
479 /* ask the user if the wiki page really should be opened */
480 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
481 "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
483 "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
485 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
486 simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
488 /* appologize to the user that the wiki page cannot be opened */
489 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
490 "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
492 "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
494 "Since this is a private protocol, such information is not available on "
495 "a public website. Therefore this filter entry is blocked.\n"
497 "Sorry for the inconvenience.\n",
498 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
504 is_address_column (gint column)
506 if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) ||
507 (cfile.cinfo.col_fmt[column] == COL_RES_SRC) ||
508 (cfile.cinfo.col_fmt[column] == COL_DEF_DST) ||
509 (cfile.cinfo.col_fmt[column] == COL_RES_DST)) &&
510 strlen(cfile.cinfo.col_expr.col_expr_val[column]))
519 get_ip_address_list_from_packet_list_row(gpointer data)
521 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
522 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
525 GList *addr_list = NULL;
529 #ifdef NEW_PACKET_LIST
530 fdata = (frame_data *) new_packet_list_get_row_data(row);
532 fdata = (frame_data *) packet_list_get_row_data(row);
538 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
539 cfile.pd, fdata->cap_len, &err, &err_info))
541 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
542 cf_read_error_message(err, err_info), cfile.filename);
546 epan_dissect_init(&edt, FALSE, FALSE);
547 col_custom_prime_edt(&edt, &cfile.cinfo);
549 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo);
550 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
552 /* First check selected column */
553 if (is_address_column (column)) {
554 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column]));
557 for (col = 0; col < cfile.cinfo.num_cols; col++) {
558 /* Then check all columns except the selected */
559 if ((col != column) && (is_address_column (col))) {
560 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col]));
564 epan_dissect_cleanup(&edt);
571 get_filter_from_packet_list_row_and_column(gpointer data)
573 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
574 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
580 #ifdef NEW_PACKET_LIST
581 fdata = (frame_data *) new_packet_list_get_row_data(row);
583 fdata = (frame_data *) packet_list_get_row_data(row);
589 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
590 cfile.pd, fdata->cap_len, &err, &err_info)) {
591 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
592 cf_read_error_message(err, err_info), cfile.filename);
595 /* proto tree, visible. We need a proto tree if there's custom columns */
596 epan_dissect_init(&edt, have_custom_cols(&cfile.cinfo), FALSE);
597 col_custom_prime_edt(&edt, &cfile.cinfo);
599 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata,
601 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
603 if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
604 strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
605 /* leak a little but safer than ep_ here */
606 if (cfile.cinfo.col_fmt[column] == COL_CUSTOM) {
607 header_field_info *hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[column]);
608 if (hfi->parent == -1) {
610 buf = se_strdup(cfile.cinfo.col_expr.col_expr[column]);
611 } else if (hfi->type == FT_STRING) {
612 /* Custom string, add quotes */
613 buf = se_strdup_printf("%s == \"%s\"", cfile.cinfo.col_expr.col_expr[column],
614 cfile.cinfo.col_expr.col_expr_val[column]);
618 buf = se_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
619 cfile.cinfo.col_expr.col_expr_val[column]);
623 epan_dissect_cleanup(&edt);
630 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
632 match_selected_cb_do(data,
634 get_filter_from_packet_list_row_and_column(data));
637 /* This function allows users to right click in the details window and copy the text
638 * information to the operating systems clipboard.
640 * We first check to see if a string representation is setup in the tree and then
641 * read the string. If not available then we try to grab the value. If all else
642 * fails we display a message to the user to indicate the copy could not be completed.
645 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
647 GString *gtk_text_str = g_string_new("");
648 char labelstring[256];
649 char *stringpointer = labelstring;
653 case COPY_SELECTED_DESCRIPTION:
654 if (cfile.finfo_selected->rep->representation != 0) {
655 g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
658 case COPY_SELECTED_FIELDNAME:
659 if (cfile.finfo_selected->hfinfo->abbrev != 0) {
660 g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
663 case COPY_SELECTED_VALUE:
664 if (cfile.edt !=0 ) {
665 g_string_append(gtk_text_str,
666 get_node_field_value(cfile.finfo_selected, cfile.edt));
673 if (gtk_text_str->len == 0) {
674 /* If no representation then... Try to read the value */
675 proto_item_fill_label(cfile.finfo_selected, stringpointer);
676 g_string_append(gtk_text_str, stringpointer);
679 if (gtk_text_str->len == 0) {
680 /* Could not get item so display error msg */
681 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
683 /* Copy string to clipboard */
684 copy_to_clipboard(gtk_text_str);
686 g_string_free(gtk_text_str, TRUE); /* Free the memory */
690 /* mark as reference time frame */
692 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
696 frame->flags.ref_time=1;
698 frame->flags.ref_time=0;
700 cf_reftime_packets(&cfile);
701 #ifdef NEW_PACKET_LIST
702 new_packet_list_queue_draw();
707 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
711 timestamp_set_type(TS_RELATIVE);
712 recent.gui_time_format = TS_RELATIVE;
713 #ifdef NEW_PACKET_LIST
714 cf_timestamp_auto_precision(&cfile);
715 new_packet_list_queue_draw();
717 cf_change_time_formats(&cfile);
723 g_assert_not_reached();
726 if (cfile.current_frame) {
727 set_frame_reftime(!cfile.current_frame->flags.ref_time,
728 cfile.current_frame, cfile.current_row);
734 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
736 static GtkWidget *reftime_dialog = NULL;
740 if (cfile.current_frame) {
741 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
742 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
743 "%sSwitch to the appropriate Time Display Format?%s\n\n"
744 "Time References don't work well with the currently selected Time Display Format.\n\n"
745 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
746 simple_dialog_primary_start(), simple_dialog_primary_end());
747 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
749 set_frame_reftime(!cfile.current_frame->flags.ref_time,
750 cfile.current_frame, cfile.current_row);
754 case REFTIME_FIND_NEXT:
755 find_previous_next_frame_with_filter("frame.ref_time", FALSE);
757 case REFTIME_FIND_PREV:
758 find_previous_next_frame_with_filter("frame.ref_time", TRUE);
764 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
766 find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
770 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
772 find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
776 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
779 gchar *help_str = NULL;
780 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
782 gboolean has_blurb = FALSE;
783 guint length = 0, byte_len;
784 GtkWidget *byte_view;
785 const guint8 *byte_data;
790 /* if nothing is selected */
791 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
794 * Which byte view is displaying the current protocol tree
797 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
798 if (byte_view == NULL)
801 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
802 if (byte_data == NULL)
805 cf_unselect_field(&cfile);
806 packet_hex_print(byte_view, byte_data,
807 cfile.current_frame, NULL, byte_len);
810 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
813 set_notebook_page(byte_nb_ptr_gbl, finfo->ds_tvb);
815 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
816 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
817 g_assert(byte_data != NULL);
819 cfile.finfo_selected = finfo;
820 set_menus_for_selected_tree_row(&cfile);
823 if (finfo->hfinfo->blurb != NULL &&
824 finfo->hfinfo->blurb[0] != '\0') {
826 length = (guint) strlen(finfo->hfinfo->blurb);
828 length = (guint) strlen(finfo->hfinfo->name);
830 finfo_length = finfo->length + finfo->appendix_length;
832 if (finfo_length == 0) {
834 } else if (finfo_length == 1) {
835 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
837 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
839 statusbar_pop_field_msg(); /* get rid of current help msg */
841 help_str = g_strdup_printf(" %s (%s)%s",
842 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
843 finfo->hfinfo->abbrev, len_str);
844 statusbar_push_field_msg(help_str);
848 * Don't show anything if the field name is zero-length;
849 * the pseudo-field for "proto_tree_add_text()" is such
850 * a field, and we don't want "Text (text)" showing up
851 * on the status line if you've selected such a field.
853 * XXX - there are zero-length fields for which we *do*
854 * want to show the field name.
856 * XXX - perhaps the name and abbrev field should be null
857 * pointers rather than null strings for that pseudo-field,
858 * but we'd have to add checks for null pointers in some
859 * places if we did that.
861 * Or perhaps protocol tree items added with
862 * "proto_tree_add_text()" should have -1 as the field index,
863 * with no pseudo-field being used, but that might also
864 * require special checks for -1 to be added.
866 statusbar_push_field_msg("");
869 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
873 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
875 collapse_all_tree(cfile.edt->tree, tree_view_gbl);
878 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
880 expand_all_tree(cfile.edt->tree, tree_view_gbl);
883 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
885 if (cfile.finfo_selected) {
886 column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
887 cfile.finfo_selected->hfinfo->abbrev);
888 /* Recreate the packet list according to new preferences */
889 #ifdef NEW_PACKET_LIST
890 new_packet_list_recreate ();
892 packet_list_recreate ();
894 if (!prefs.gui_use_pref_save) {
897 cfile.cinfo.columns_changed = FALSE; /* Reset value */
901 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
904 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
906 /* the mouse position is at an entry, expand that one */
907 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
908 gtk_tree_path_free(path);
912 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
913 if (cfile.edt->tree) {
914 guint32 tmp = g_resolv_flags;
915 g_resolv_flags = RESOLV_ALL;
916 proto_tree_draw(cfile.edt->tree, tree_view_gbl);
917 g_resolv_flags = tmp;
922 main_set_for_capture_file(gboolean have_capture_file_in)
924 have_capture_file = have_capture_file_in;
926 main_widgets_show_or_hide();
932 /* get the current geometry, before writing it to disk */
933 main_save_window_geometry(top_level);
935 /* write user's recent file to disk
936 * It is no problem to write this file, even if we do not quit */
937 write_profile_recent();
940 /* XXX - should we check whether the capture file is an
941 unsaved temporary file for a live capture and, if so,
942 pop up a "do you want to exit without saving the capture
943 file?" dialog, and then just return, leaving said dialog
944 box to forcibly quit if the user clicks "OK"?
946 If so, note that this should be done in a subroutine that
947 returns TRUE if we do so, and FALSE otherwise, and if it
948 returns TRUE we should return TRUE without nuking anything.
950 Note that, if we do that, we might also want to check if
951 an "Update list of packets in real time" capture is in
952 progress and, if so, ask whether they want to terminate
953 the capture and discard it, and return TRUE, before nuking
954 any child capture, if they say they don't want to do so. */
957 /* Nuke any child capture in progress. */
958 capture_kill_child(&global_capture_opts);
961 /* Are we in the middle of reading a capture? */
962 if (cfile.state == FILE_READ_IN_PROGRESS) {
963 /* Yes, so we can't just close the file and quit, as
964 that may yank the rug out from under the read in
965 progress; instead, just set the state to
966 "FILE_READ_ABORTED" and return - the code doing the read
967 will check for that and, if it sees that, will clean
969 cfile.state = FILE_READ_ABORTED;
971 /* Say that the window should *not* be deleted;
972 that'll be done by the code that cleans up. */
975 /* Close any capture file we have open; on some OSes, you
976 can't unlink a temporary capture file if you have it
978 "cf_close()" will unlink it after closing it if
979 it's a temporary file.
981 We do this here, rather than after the main loop returns,
982 as, after the main loop returns, the main window may have
983 been destroyed (if this is called due to a "destroy"
984 even on the main window rather than due to the user
985 selecting a menu item), and there may be a crash
986 or other problem when "cf_close()" tries to
987 clean up stuff in the main window.
989 XXX - is there a better place to put this?
990 Or should we have a routine that *just* closes the
991 capture file, and doesn't do anything with the UI,
992 which we'd call here, and another routine that
993 calls that routine and also cleans up the UI, which
994 we'd call elsewhere? */
997 /* Exit by leaving the main loop, so that any quit functions
998 we registered get called. */
1001 /* Say that the window should be deleted. */
1007 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1011 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1012 gtk_window_present(GTK_WINDOW(top_level));
1013 /* user didn't saved his current file, ask him */
1014 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1015 "%sSave capture file before program quit?%s\n\n"
1016 "If you quit the program without saving, your capture data will be discarded.",
1017 simple_dialog_primary_start(), simple_dialog_primary_end());
1018 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1021 /* unchanged file, just exit */
1022 /* "main_do_quit()" indicates whether the main window should be deleted. */
1023 return main_do_quit();
1029 main_pane_load_window_geometry(void)
1031 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1032 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1033 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
1034 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1040 main_load_window_geometry(GtkWidget *widget)
1042 window_geometry_t geom;
1044 geom.set_pos = prefs.gui_geometry_save_position;
1045 geom.x = recent.gui_geometry_main_x;
1046 geom.y = recent.gui_geometry_main_y;
1047 geom.set_size = prefs.gui_geometry_save_size;
1048 if (recent.gui_geometry_main_width > 0 &&
1049 recent.gui_geometry_main_height > 0) {
1050 geom.width = recent.gui_geometry_main_width;
1051 geom.height = recent.gui_geometry_main_height;
1052 geom.set_maximized = prefs.gui_geometry_save_maximized;
1054 /* We assume this means the width and height weren't set in
1055 the "recent" file (or that there is no "recent" file),
1056 and weren't set to a default value, so we don't set the
1057 size. (The "recent" file code rejects non-positive width
1058 and height values.) */
1059 geom.set_size = FALSE;
1061 geom.maximized = recent.gui_geometry_main_maximized;
1063 window_set_geometry(widget, &geom);
1065 main_pane_load_window_geometry();
1066 statusbar_load_window_geometry();
1071 main_save_window_geometry(GtkWidget *widget)
1073 window_geometry_t geom;
1075 window_get_geometry(widget, &geom);
1077 if (prefs.gui_geometry_save_position) {
1078 recent.gui_geometry_main_x = geom.x;
1079 recent.gui_geometry_main_y = geom.y;
1082 if (prefs.gui_geometry_save_size) {
1083 recent.gui_geometry_main_width = geom.width;
1084 recent.gui_geometry_main_height = geom.height;
1087 if(prefs.gui_geometry_save_maximized) {
1088 recent.gui_geometry_main_maximized = geom.maximized;
1091 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
1092 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
1093 statusbar_save_window_geometry();
1096 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1100 /* save file first */
1101 file_save_as_cmd(after_save_exit, NULL);
1103 case(ESD_BTN_QUIT_DONT_SAVE):
1106 case(ESD_BTN_CANCEL):
1109 g_assert_not_reached();
1114 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1118 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1119 /* user didn't saved his current file, ask him */
1120 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1121 "%sSave capture file before program quit?%s\n\n"
1122 "If you quit the program without saving, your capture data will be discarded.",
1123 simple_dialog_primary_start(), simple_dialog_primary_end());
1124 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1126 /* unchanged file, just exit */
1132 print_usage(gboolean print_ver) {
1142 fprintf(output, "Wireshark " VERSION "%s\n"
1143 "Interactively dump and analyze network traffic.\n"
1144 "See http://www.wireshark.org for more information.\n"
1147 wireshark_svnversion, get_copyright_info());
1151 fprintf(output, "\n");
1152 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1153 fprintf(output, "\n");
1156 fprintf(output, "Capture interface:\n");
1157 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1158 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1159 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1160 fprintf(output, " -p don't capture in promiscuous mode\n");
1161 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1162 fprintf(output, " -Q quit Wireshark after capturing\n");
1163 fprintf(output, " -S update packet display when new packets are captured\n");
1164 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1165 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
1166 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1168 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1169 fprintf(output, " -D print list of interfaces and exit\n");
1170 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1171 fprintf(output, "\n");
1172 fprintf(output, "Capture stop conditions:\n");
1173 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1174 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1175 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1176 fprintf(output, " files:NUM - stop after NUM files\n");
1177 /*fprintf(output, "\n");*/
1178 fprintf(output, "Capture output:\n");
1179 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1180 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1181 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1182 #endif /* HAVE_LIBPCAP */
1184 /*fprintf(output, "\n");*/
1185 fprintf(output, "Input file:\n");
1186 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1188 fprintf(output, "\n");
1189 fprintf(output, "Processing:\n");
1190 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1191 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1192 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1194 fprintf(output, "\n");
1195 fprintf(output, "User interface:\n");
1196 fprintf(output, " -C <config profile> start with specified configuration profile\n");
1197 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1198 fprintf(output, " -J <jump filter> jump to the first packet matching the (display) filter\n");
1199 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
1200 fprintf(output, " -m <font> set the font name used for most text\n");
1201 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1202 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
1203 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1204 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1206 fprintf(output, "\n");
1207 fprintf(output, "Output:\n");
1208 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1210 fprintf(output, "\n");
1211 fprintf(output, "Miscellaneous:\n");
1212 fprintf(output, " -h display this help and exit\n");
1213 fprintf(output, " -v display version info and exit\n");
1214 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1215 fprintf(output, " persdata:path - personal data files\n");
1216 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1217 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1219 fprintf(output, " --display=DISPLAY X display to use\n");
1234 printf(PACKAGE " " VERSION "%s\n"
1241 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1242 runtime_info_str->str);
1250 * Print to the standard error. On Windows, create a console for the
1251 * standard error to show up on, if necessary.
1252 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1253 * terminal isn't the standard error?
1256 vfprintf_stderr(const char *fmt, va_list ap)
1261 vfprintf(stderr, fmt, ap);
1265 fprintf_stderr(const char *fmt, ...)
1270 vfprintf_stderr(fmt, ap);
1275 * Report an error in command-line arguments.
1276 * Creates a console on Windows.
1279 cmdarg_err(const char *fmt, ...)
1283 fprintf_stderr("wireshark: ");
1285 vfprintf_stderr(fmt, ap);
1287 fprintf_stderr("\n");
1291 * Report additional information for an error in command-line arguments.
1292 * Creates a console on Windows.
1293 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1294 * terminal isn't the standard error?
1297 cmdarg_err_cont(const char *fmt, ...)
1302 vfprintf_stderr(fmt, ap);
1303 fprintf_stderr("\n");
1307 #if defined(_WIN32) || ! defined USE_THREADS
1309 Once every 3 seconds we get a callback here which we use to update
1310 the tap extensions. Since Gtk1 is single threaded we dont have to
1311 worry about any locking or critical regions.
1314 tap_update_cb(gpointer data _U_)
1316 draw_tap_listeners(FALSE);
1320 /* Restart the tap update display timer with new configured interval */
1321 void reset_tap_update_timer(void)
1323 g_source_remove(tap_update_timer_id);
1324 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, tap_update_cb, NULL);
1329 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1330 use threads all update_thread_mutex can be dropped and protect/unprotect
1331 would just be empty functions.
1333 This allows gtk2-rpcstat.c and friends to be copied unmodified to
1334 gtk1-wireshark and it will just work.
1336 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1338 update_thread(gpointer data _U_)
1342 g_get_current_time(&tv1);
1343 g_static_mutex_lock(&update_thread_mutex);
1344 gdk_threads_enter();
1345 draw_tap_listeners(FALSE);
1346 gdk_threads_leave();
1347 g_static_mutex_unlock(&update_thread_mutex);
1349 g_get_current_time(&tv2);
1351 /* Assuming it took less than configured time to update tap listeners... */
1352 if( (tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) >
1353 (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1354 /* Wait for remainder of configured time */
1355 g_usleep((tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) -
1356 (tv2.tv_sec * 1000000 + tv2.tv_usec));
1363 protect_thread_critical_region(void)
1365 #if !defined(_WIN32) && defined USE_THREADS
1366 g_static_mutex_lock(&update_thread_mutex);
1370 unprotect_thread_critical_region(void)
1372 #if !defined(_WIN32) && defined USE_THREADS
1373 g_static_mutex_unlock(&update_thread_mutex);
1378 * Periodically process outstanding hostname lookups. If we have new items,
1379 * redraw the packet list and tree view.
1383 resolv_update_cb(gpointer data _U_)
1385 /* Anything new show up? */
1386 if (host_name_lookup_process(NULL)) {
1387 if (pkt_scrollw->window)
1388 gdk_window_invalidate_rect(pkt_scrollw->window, NULL, TRUE);
1389 if (tv_scrollw->window)
1390 gdk_window_invalidate_rect(tv_scrollw->window, NULL, TRUE);
1393 /* Always check. Even if we don't do async lookups we could still get
1394 passive updates, e.g. from DNS packets. */
1399 /* Set the file name in the name for the main window and in the name for the main window's icon. */
1401 set_display_filename(capture_file *cf)
1405 if (!cf->is_tempfile && cf->filename) {
1406 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1407 add_menu_recent_capture_file(cf->filename);
1411 win_name = g_strdup_printf("%s - Wireshark", cf_get_display_name(cf));
1412 set_main_window_name(win_name);
1416 GtkWidget *close_dlg = NULL;
1419 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1421 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1426 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1428 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1433 main_cf_cb_file_closing(capture_file *cf)
1436 /* if we have more than 10000 packets, show a splash screen while closing */
1437 /* XXX - don't know a better way to decide whether to show or not,
1438 * as most of the time is spend in a single eth_clist_clear function,
1439 * so we can't use a progress bar here! */
1440 if(cf->count > 10000) {
1441 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1442 "%sClosing file!%s\n\nPlease wait ...",
1443 simple_dialog_primary_start(),
1444 simple_dialog_primary_end());
1445 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1448 /* Destroy all windows, which refer to the
1449 capture file we're closing. */
1450 destroy_packet_wins();
1451 file_save_as_destroy();
1453 /* Restore the standard title bar message. */
1454 set_main_window_name("The Wireshark Network Analyzer");
1456 /* Disable all menu items that make sense only if you have a capture. */
1457 set_menus_for_capture_file(NULL);
1458 set_menus_for_captured_packets(FALSE);
1459 set_menus_for_selected_packet(cf);
1460 set_menus_for_capture_in_progress(FALSE);
1461 set_capture_if_dialog_for_capture_in_progress(FALSE);
1462 set_menus_for_selected_tree_row(cf);
1464 /* Set up main window for no capture file. */
1465 main_set_for_capture_file(FALSE);
1467 main_window_update();
1471 main_cf_cb_file_closed(capture_file *cf _U_)
1473 if(close_dlg != NULL) {
1474 splash_destroy(close_dlg);
1481 main_cf_cb_file_read_started(capture_file *cf _U_)
1483 tap_dfilter_dlg_update();
1485 /* Set up main window for a capture file. */
1486 main_set_for_capture_file(TRUE);
1490 main_cf_cb_file_read_finished(capture_file *cf)
1492 set_display_filename(cf);
1494 /* Enable menu items that make sense if you have a capture file you've
1495 finished reading. */
1496 set_menus_for_capture_file(cf);
1498 /* Enable menu items that make sense if you have some captured packets. */
1499 set_menus_for_captured_packets(TRUE);
1503 static GList *icon_list_create(
1504 const char **icon16_xpm,
1505 const char **icon32_xpm,
1506 const char **icon48_xpm,
1507 const char **icon64_xpm)
1509 GList *icon_list = NULL;
1510 GdkPixbuf * pixbuf16;
1511 GdkPixbuf * pixbuf32;
1512 GdkPixbuf * pixbuf48;
1513 GdkPixbuf * pixbuf64;
1516 if(icon16_xpm != NULL) {
1517 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1519 icon_list = g_list_append(icon_list, pixbuf16);
1522 if(icon32_xpm != NULL) {
1523 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1525 icon_list = g_list_append(icon_list, pixbuf32);
1528 if(icon48_xpm != NULL) {
1529 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1531 icon_list = g_list_append(icon_list, pixbuf48);
1534 if(icon64_xpm != NULL) {
1535 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1537 icon_list = g_list_append(icon_list, pixbuf64);
1544 main_capture_set_main_window_title(capture_options *capture_opts)
1546 GString *title = g_string_new("");
1548 g_string_append(title, "Capturing ");
1549 if(capture_opts->iface) {
1550 g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
1552 g_string_append(title, "- Wireshark");
1554 set_main_window_name(title->str);
1555 g_string_free(title, TRUE);
1559 main_capture_cb_capture_prepared(capture_options *capture_opts)
1561 static GList *icon_list = NULL;
1563 main_capture_set_main_window_title(capture_opts);
1565 if(icon_list == NULL) {
1566 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1568 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1570 /* Disable menu items that make no sense if you're currently running
1572 set_menus_for_capture_in_progress(TRUE);
1573 set_capture_if_dialog_for_capture_in_progress(TRUE);
1575 /* Don't set up main window for a capture file. */
1576 main_set_for_capture_file(FALSE);
1580 main_capture_cb_capture_update_started(capture_options *capture_opts)
1582 /* We've done this in "prepared" above, but it will be cleared while
1583 switching to the next multiple file. */
1584 main_capture_set_main_window_title(capture_opts);
1586 set_menus_for_capture_in_progress(TRUE);
1587 set_capture_if_dialog_for_capture_in_progress(TRUE);
1589 /* Enable menu items that make sense if you have some captured
1590 packets (yes, I know, we don't have any *yet*). */
1591 set_menus_for_captured_packets(TRUE);
1593 /* Set up main window for a capture file. */
1594 main_set_for_capture_file(TRUE);
1598 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1600 capture_file *cf = capture_opts->cf;
1601 static GList *icon_list = NULL;
1603 set_display_filename(cf);
1605 /* Enable menu items that make sense if you're not currently running
1607 set_menus_for_capture_in_progress(FALSE);
1608 set_capture_if_dialog_for_capture_in_progress(FALSE);
1610 /* Enable menu items that make sense if you have a capture file
1611 you've finished reading. */
1612 set_menus_for_capture_file(cf);
1614 /* Set up main window for a capture file. */
1615 main_set_for_capture_file(TRUE);
1617 if(icon_list == NULL) {
1618 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1620 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1622 if(global_capture_opts.quit_after_cap) {
1623 /* command line asked us to quit after the capture */
1624 /* don't pop up a dialog to ask for unsaved files etc. */
1630 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1632 /* Don't set up main window for a capture file. */
1633 main_set_for_capture_file(FALSE);
1637 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1640 capture_file *cf = capture_opts->cf;
1642 static GList *icon_list = NULL;
1644 /*set_display_filename(cf);*/
1646 /* Enable menu items that make sense if you're not currently running
1648 set_menus_for_capture_in_progress(FALSE);
1649 set_capture_if_dialog_for_capture_in_progress(FALSE);
1651 /* Restore the standard title bar message */
1652 /* (just in case we have trouble opening the capture file). */
1653 set_main_window_name("The Wireshark Network Analyzer");
1655 if(icon_list == NULL) {
1656 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1658 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1660 /* We don't have loaded the capture file, this will be done later.
1661 * For now we still have simply a blank screen. */
1663 if(global_capture_opts.quit_after_cap) {
1664 /* command line asked us to quit after the capture */
1665 /* don't pop up a dialog to ask for unsaved files etc. */
1670 #endif /* HAVE_LIBPCAP */
1673 main_cf_cb_packet_selected(gpointer data)
1675 capture_file *cf = data;
1677 /* Display the GUI protocol tree and packet bytes.
1678 XXX - why do we dump core if we call "proto_tree_draw()"
1679 before calling "add_byte_views()"? */
1680 add_main_byte_views(cf->edt);
1681 main_proto_tree_draw(cf->edt->tree);
1683 /* The user is searching for a string in the data or a hex value,
1684 * highlight the field that is found in the tree and hex displays. */
1685 if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1686 highlight_field(cf->edt->tvb, cfile.search_pos,
1687 (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1688 cfile.search_pos = 0; /* Reset the position */
1691 /* A packet is selected. */
1692 set_menus_for_selected_packet(cf);
1696 main_cf_cb_packet_unselected(capture_file *cf)
1698 /* Clear out the display of that packet. */
1699 clear_tree_and_hex_views();
1701 /* No packet is selected. */
1702 set_menus_for_selected_packet(cf);
1706 main_cf_cb_field_unselected(capture_file *cf)
1708 set_menus_for_selected_tree_row(cf);
1712 main_cf_cb_file_save_reload_finished(gpointer data _U_)
1714 set_display_filename(&cfile);
1715 set_menus_for_capture_file(&cfile);
1719 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1722 case(cf_cb_file_closing):
1723 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1724 main_cf_cb_file_closing(data);
1726 case(cf_cb_file_closed):
1727 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1728 main_cf_cb_file_closed(data);
1730 case(cf_cb_file_read_started):
1731 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1732 main_cf_cb_file_read_started(data);
1734 case(cf_cb_file_read_finished):
1735 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1736 main_cf_cb_file_read_finished(data);
1738 case(cf_cb_packet_selected):
1739 main_cf_cb_packet_selected(data);
1741 case(cf_cb_packet_unselected):
1742 main_cf_cb_packet_unselected(data);
1744 case(cf_cb_field_unselected):
1745 main_cf_cb_field_unselected(data);
1747 case(cf_cb_file_save_started):
1748 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1750 case(cf_cb_file_save_finished):
1751 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1753 case(cf_cb_file_save_reload_finished):
1754 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1755 main_cf_cb_file_save_reload_finished(data);
1757 case(cf_cb_file_save_failed):
1758 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1761 g_warning("main_cf_callback: event %u unknown", event);
1762 g_assert_not_reached();
1768 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1771 case(capture_cb_capture_prepared):
1772 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1773 main_capture_cb_capture_prepared(capture_opts);
1775 case(capture_cb_capture_update_started):
1776 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1777 main_capture_cb_capture_update_started(capture_opts);
1779 case(capture_cb_capture_update_continue):
1780 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1782 case(capture_cb_capture_update_finished):
1783 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1784 main_capture_cb_capture_update_finished(capture_opts);
1786 case(capture_cb_capture_fixed_started):
1787 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1788 main_capture_cb_capture_fixed_started(capture_opts);
1790 case(capture_cb_capture_fixed_continue):
1791 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1793 case(capture_cb_capture_fixed_finished):
1794 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1795 main_capture_cb_capture_fixed_finished(capture_opts);
1797 case(capture_cb_capture_stopping):
1798 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1799 /* Beware: this state won't be called, if the capture child
1800 * closes the capturing on it's own! */
1803 g_warning("main_capture_callback: event %u unknown", event);
1804 g_assert_not_reached();
1810 get_gui_compiled_info(GString *str)
1812 get_epan_compiled_version_info(str);
1814 g_string_append(str, ", ");
1815 #ifdef HAVE_LIBPORTAUDIO
1816 #ifdef PORTAUDIO_API_1
1817 g_string_append(str, "with PortAudio <= V18");
1818 #else /* PORTAUDIO_API_1 */
1819 g_string_append(str, "with ");
1820 g_string_append(str, Pa_GetVersionText());
1821 #endif /* PORTAUDIO_API_1 */
1822 #else /* HAVE_LIBPORTAUDIO */
1823 g_string_append(str, "without PortAudio");
1824 #endif /* HAVE_LIBPORTAUDIO */
1826 g_string_append(str, ", ");
1828 get_compiled_airpcap_version(str);
1830 g_string_append(str, "without AirPcap");
1832 #ifdef NEW_PACKET_LIST
1833 g_string_append(str, ", with new_packet_list");
1838 get_gui_runtime_info(GString *str)
1841 g_string_append(str, ", ");
1842 get_runtime_airpcap_version(str);
1846 g_string_append(str, ", ");
1847 u3_runtime_info(str);
1853 read_configuration_files(char **gdp_path, char **dp_path)
1855 int gpf_open_errno, gpf_read_errno;
1856 int cf_open_errno, df_open_errno;
1857 int gdp_open_errno, gdp_read_errno;
1858 int dp_open_errno, dp_read_errno;
1859 char *gpf_path, *pf_path;
1860 char *cf_path, *df_path;
1861 int pf_open_errno, pf_read_errno;
1864 /* Read the preference files. */
1865 prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1866 &pf_open_errno, &pf_read_errno, &pf_path);
1868 if (gpf_path != NULL) {
1869 if (gpf_open_errno != 0) {
1870 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1871 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1872 strerror(gpf_open_errno));
1874 if (gpf_read_errno != 0) {
1875 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1876 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1877 strerror(gpf_read_errno));
1880 if (pf_path != NULL) {
1881 if (pf_open_errno != 0) {
1882 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1883 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1884 strerror(pf_open_errno));
1886 if (pf_read_errno != 0) {
1887 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1888 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1889 strerror(pf_read_errno));
1896 /* if the user wants a console to be always there, well, we should open one for him */
1897 if (prefs_p->gui_console_open == console_open_always) {
1902 /* Read the capture filter file. */
1903 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1904 if (cf_path != NULL) {
1905 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1906 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1907 strerror(cf_open_errno));
1911 /* Read the display filter file. */
1912 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1913 if (df_path != NULL) {
1914 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1915 "Could not open your display filter file\n\"%s\": %s.", df_path,
1916 strerror(df_open_errno));
1920 /* Read the disabled protocols file. */
1921 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1922 dp_path, &dp_open_errno, &dp_read_errno);
1923 if (*gdp_path != NULL) {
1924 if (gdp_open_errno != 0) {
1925 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1926 "Could not open global disabled protocols file\n\"%s\": %s.",
1927 *gdp_path, strerror(gdp_open_errno));
1929 if (gdp_read_errno != 0) {
1930 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1931 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1932 *gdp_path, strerror(gdp_read_errno));
1937 if (*dp_path != NULL) {
1938 if (dp_open_errno != 0) {
1939 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1940 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1941 strerror(dp_open_errno));
1943 if (dp_read_errno != 0) {
1944 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1945 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1946 strerror(dp_read_errno));
1955 /* Check if there's something important to tell the user during startup.
1956 * We want to do this *after* showing the main window so that any windows
1957 * we pop up will be above the main window.
1961 check_and_warn_user_startup(gchar *cf_name)
1963 check_and_warn_user_startup(gchar *cf_name _U_)
1966 gchar *cur_user, *cur_group;
1967 gpointer priv_warning_dialog;
1969 /* Tell the user not to run as root. */
1970 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
1971 cur_user = get_cur_username();
1972 cur_group = get_cur_groupname();
1973 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1974 "Running as user \"%s\" and group \"%s\".\n"
1975 "This could be dangerous.", cur_user, cur_group);
1978 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
1979 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
1983 /* Warn the user if npf.sys isn't loaded. */
1984 if (!stdin_capture && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
1985 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1986 "The NPF driver isn't running. You may have trouble\n"
1987 "capturing or listing interfaces.");
1988 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
1989 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
1996 /* And now our feature presentation... [ fade to music ] */
1998 main(int argc, char *argv[])
2000 char *init_progfile_dir_error;
2003 gboolean arg_error = FALSE;
2005 extern int info_update_freq; /* Found in about_dlg.c. */
2006 const gchar *filter;
2014 char *gdp_path, *dp_path;
2017 gboolean start_capture = FALSE;
2018 gboolean list_link_layer_types = FALSE;
2022 gboolean capture_option_specified = FALSE;
2029 gint pl_size = 280, tv_size = 95, bv_size = 75;
2030 gchar *rc_file, *cf_name = NULL, *rfilter = NULL, *jfilter = NULL;
2031 dfilter_t *rfcode = NULL;
2032 gboolean rfilter_parse_failed = FALSE;
2035 GtkWidget *splash_win = NULL;
2036 GLogLevelFlags log_flags;
2037 guint go_to_packet = 0;
2038 gboolean jump_backwards = FALSE, saved_bw = FALSE;
2039 dfilter_t *jump_to_filter = NULL;
2044 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2045 #define OPTSTRING_B "B:"
2047 #define OPTSTRING_B ""
2048 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2049 #else /* HAVE_LIBPCAP */
2050 #define OPTSTRING_B ""
2051 #endif /* HAVE_LIBPCAP */
2053 #ifdef HAVE_PCAP_CREATE
2054 #define OPTSTRING_I "I"
2056 #define OPTSTRING_I ""
2059 #define OPTSTRING "a:b:" OPTSTRING_B "c:C:Df:g:Hhi:" OPTSTRING_I "jJ:kK:lLm:nN:o:P:pQr:R:Ss:t:u:vw:X:y:z:"
2061 static const char optstring[] = OPTSTRING;
2064 * Get credential information for later use, and drop privileges
2065 * before doing anything else.
2066 * Let the user know if anything happened.
2068 get_credential_info();
2069 relinquish_special_privs_perm();
2072 * Attempt to get the pathname of the executable file.
2074 init_progfile_dir_error = init_progfile_dir(argv[0], main);
2076 /* initialize the funnel mini-api */
2077 initialize_funnel_ops();
2079 #ifdef HAVE_AIRPDCAP
2080 AirPDcapInitContext(&airpdcap_ctx);
2084 /* Load wpcap if possible. Do this before collecting the run-time version information */
2087 /* ... and also load the packet.dll from wpcap */
2088 wpcap_packet_load();
2091 /* Load the airpcap.dll. This must also be done before collecting
2092 * run-time version information. */
2093 airpcap_dll_ret_val = load_airpcap();
2095 switch (airpcap_dll_ret_val) {
2096 case AIRPCAP_DLL_OK:
2097 /* load the airpcap interfaces */
2098 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2100 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2101 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2102 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2105 airpcap_if_active = NULL;
2109 /* select the first ad default (THIS SHOULD BE CHANGED) */
2110 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2115 * XXX - Maybe we need to warn the user if one of the following happens???
2117 case AIRPCAP_DLL_OLD:
2118 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2121 case AIRPCAP_DLL_ERROR:
2122 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2125 case AIRPCAP_DLL_NOT_FOUND:
2126 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2130 #endif /* HAVE_AIRPCAP */
2132 /* Start windows sockets */
2133 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2136 profile_store_persconffiles (TRUE);
2138 /* Assemble the compile-time version information string */
2139 comp_info_str = g_string_new("Compiled ");
2141 g_string_append(comp_info_str, "with ");
2142 g_string_append_printf(comp_info_str,
2143 #ifdef GTK_MAJOR_VERSION
2144 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
2147 "GTK+ (version unknown)");
2149 g_string_append(comp_info_str, ", ");
2151 get_compiled_version_info(comp_info_str, get_gui_compiled_info);
2153 /* Assemble the run-time version information string */
2154 runtime_info_str = g_string_new("Running ");
2155 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2157 /* Read the profile independent recent file. We have to do this here so we can */
2158 /* set the profile before it can be set from the command line parameterts */
2159 recent_read_static(&rf_path, &rf_open_errno);
2160 if (rf_path != NULL && rf_open_errno != 0) {
2161 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2162 "Could not open common recent file\n\"%s\": %s.",
2163 rf_path, strerror(rf_open_errno));
2166 /* "pre-scan" the command line parameters, if we have "console only"
2167 parameters. We do this so we don't start GTK+ if we're only showing
2168 command-line help or version information.
2170 XXX - this pre-scan is done before we start GTK+, so we haven't
2171 run gtk_init() on the arguments. That means that GTK+ arguments
2172 have not been removed from the argument list; those arguments
2173 begin with "--", and will be treated as an error by getopt().
2175 We thus ignore errors - *and* set "opterr" to 0 to suppress the
2178 optind_initial = optind;
2179 while ((opt = getopt(argc, argv, optstring)) != -1) {
2181 case 'C': /* Configuration Profile */
2182 if (profile_exists (optarg)) {
2183 set_profile_name (optarg);
2185 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2189 case 'h': /* Print help and exit */
2195 if (strcmp(optarg, "-") == 0)
2196 stdin_capture = TRUE;
2199 case 'P': /* Path settings - change these before the Preferences and alike are processed */
2200 status = filesystem_opt(opt, optarg);
2202 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2206 case 'v': /* Show version and exit */
2212 * Extension command line options have to be processed before
2213 * we call epan_init() as they are supposed to be used by dissectors
2214 * or taps very early in the registration process.
2218 case '?': /* Ignore errors - the "real" scan will catch them. */
2223 /* Init the "Open file" dialog directory */
2224 /* (do this after the path settings are processed) */
2225 set_last_open_dir(get_persdatafile_dir());
2227 /* Set getopt index back to initial value, so it will start with the
2228 first command line parameter again. Also reset opterr to 1, so that
2229 error messages are printed by getopt().
2231 XXX - this seems to work on most platforms, but time will tell.
2232 The Single UNIX Specification says "The getopt() function need
2233 not be reentrant", so this isn't guaranteed to work. The Mac
2234 OS X 10.4[.x] getopt() man page says
2236 In order to use getopt() to evaluate multiple sets of arguments, or to
2237 evaluate a single set of arguments multiple times, the variable optreset
2238 must be set to 1 before the second and each additional set of calls to
2239 getopt(), and the variable optind must be reinitialized.
2243 The optreset variable was added to make it possible to call the getopt()
2244 function multiple times. This is an extension to the IEEE Std 1003.2
2245 (``POSIX.2'') specification.
2247 which I think comes from one of the other BSDs.
2249 XXX - if we want to control all the command-line option errors, so
2250 that we can display them where we choose (e.g., in a window), we'd
2251 want to leave opterr as 0, and produce our own messages using optopt.
2252 We'd have to check the value of optopt to see if it's a valid option
2253 letter, in which case *presumably* the error is "this option requires
2254 an argument but none was specified", or not a valid option letter,
2255 in which case *presumably* the error is "this option isn't valid".
2256 Some versions of getopt() let you supply a option string beginning
2257 with ':', which means that getopt() will return ':' rather than '?'
2258 for "this option requires an argument but none was specified", but
2260 optind = optind_initial;
2263 /* Set the current locale according to the program environment.
2264 * We haven't localized anything, but some GTK widgets are localized
2265 * (the file selection dialogue, for example).
2266 * This also sets the C-language locale to the native environment. */
2269 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2270 gtk_init (&argc, &argv);
2272 cf_callback_add(main_cf_callback, NULL);
2274 capture_callback_add(main_capture_callback, NULL);
2276 cf_callback_add(statusbar_cf_callback, NULL);
2278 capture_callback_add(statusbar_capture_callback, NULL);
2281 /* Arrange that if we have no console window, and a GLib message logging
2282 routine is called to log a message, we pop up a console window.
2284 We do that by inserting our own handler for all messages logged
2285 to the default domain; that handler pops up a console if necessary,
2286 and then calls the default handler. */
2288 /* We might want to have component specific log levels later ... */
2292 G_LOG_LEVEL_CRITICAL|
2293 G_LOG_LEVEL_WARNING|
2294 G_LOG_LEVEL_MESSAGE|
2297 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2299 g_log_set_handler(NULL,
2301 console_log_handler, NULL /* user_data */);
2302 g_log_set_handler(LOG_DOMAIN_MAIN,
2304 console_log_handler, NULL /* user_data */);
2307 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2309 console_log_handler, NULL /* user_data */);
2310 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2312 console_log_handler, NULL /* user_data */);
2314 /* Set the initial values in the capture options. This might be overwritten
2315 by preference settings and then again by the command line parameters. */
2316 capture_opts_init(&global_capture_opts, &cfile);
2318 global_capture_opts.snaplen = MIN_PACKET_SIZE;
2319 global_capture_opts.has_ring_num_files = TRUE;
2322 /* Initialize whatever we need to allocate colors for GTK+ */
2325 /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2326 filter = get_conn_cfilter();
2327 if ( *filter != '\0' ) {
2328 info_update_freq = 1000; /* Milliseconds */
2331 /* We won't come till here, if we had a "console only" command line parameter. */
2332 splash_win = splash_new("Loading Wireshark ...");
2333 if (init_progfile_dir_error != NULL) {
2334 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2335 "Can't get pathname of Wireshark: %s.\n"
2336 "It won't be possible to capture traffic.\n"
2337 "Report this to the Wireshark developers.",
2338 init_progfile_dir_error);
2339 g_free(init_progfile_dir_error);
2342 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2344 /* Register all dissectors; we must do this before checking for the
2345 "-G" flag, as the "-G" flag dumps information registered by the
2346 dissectors, and we must do it before we read the preferences, in
2347 case any dissectors register preferences. */
2348 epan_init(register_all_protocols,register_all_protocol_handoffs,
2349 splash_update, (gpointer) splash_win,
2350 failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2351 write_failure_alert_box);
2353 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2355 /* Register all tap listeners; we do this before we parse the arguments,
2356 as the "-z" argument can specify a registered tap. */
2358 /* we register the plugin taps before the other taps because
2359 stats_tree taps plugins will be registered as tap listeners
2360 by stats_tree_stat.c and need to registered before that */
2363 register_all_plugin_tap_listeners();
2366 register_all_tap_listeners();
2368 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2370 /* Now register the preferences for any non-dissector modules.
2371 We must do that before we read the preferences as well. */
2372 prefs_register_modules();
2374 prefs_p = read_configuration_files (&gdp_path, &dp_path);
2376 /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2377 #if !defined(_WIN32) && defined(G_THREADS_ENABLED) && defined USE_THREADS
2380 g_thread_init(NULL);
2382 ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2383 g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2385 #else /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2386 /* this is to keep tap extensions updating once every 3 seconds */
2387 tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2388 #endif /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2390 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2393 /* Read the profile dependent (static part) of the recent file. */
2394 /* Only the static part of it will be read, as we don't have the gui now to fill the */
2395 /* recent lists which is done in the dynamic part. */
2396 /* We have to do this already here, so command line parameters can overwrite these values. */
2397 recent_read_profile_static(&rf_path, &rf_open_errno);
2398 if (rf_path != NULL && rf_open_errno != 0) {
2399 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2400 "Could not open recent file\n\"%s\": %s.",
2401 rf_path, strerror(rf_open_errno));
2404 cap_file_init(&cfile);
2406 /* Fill in capture options with values from the preferences */
2407 prefs_to_capture_opts();
2409 /* Now get our args */
2410 while ((opt = getopt(argc, argv, optstring)) != -1) {
2412 /*** capture option specific ***/
2413 case 'a': /* autostop criteria */
2414 case 'b': /* Ringbuffer option */
2415 case 'c': /* Capture xxx packets */
2416 case 'f': /* capture filter */
2417 case 'k': /* Start capture immediately */
2418 case 'H': /* Hide capture info dialog box */
2419 case 'i': /* Use interface xxx */
2420 case 'p': /* Don't capture in promiscuous mode */
2421 #ifdef HAVE_PCAP_CREATE
2422 case 'I': /* Capture in monitor mode, if available */
2424 case 'Q': /* Quit after capture (just capture to file) */
2425 case 's': /* Set the snapshot (capture) length */
2426 case 'S': /* "Sync" mode: used for following file ala tail -f */
2427 case 'w': /* Write to capture file xxx */
2428 case 'y': /* Set the pcap data link type */
2429 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2430 case 'B': /* Buffer size */
2431 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2433 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2439 capture_option_specified = TRUE;
2444 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2445 case 'K': /* Kerberos keytab file */
2446 read_keytab_file(optarg);
2450 /*** all non capture option specific ***/
2452 /* Configuration profile settings were already processed just ignore them this time*/
2454 case 'D': /* Print a list of capture devices and exit */
2456 if_list = capture_interface_list(&err, &err_str);
2457 if (if_list == NULL) {
2459 case CANT_GET_INTERFACE_LIST:
2460 cmdarg_err("%s", err_str);
2464 case NO_INTERFACES_FOUND:
2465 cmdarg_err("There are no interfaces on which a capture can be done");
2470 capture_opts_print_interfaces(if_list);
2471 free_interface_list(if_list);
2474 capture_option_specified = TRUE;
2478 case 'j': /* Search backwards for a matching packet from filter in option J */
2479 jump_backwards = TRUE;
2481 case 'g': /* Go to packet with the given packet number */
2482 go_to_packet = get_positive_int(optarg, "go to packet");
2484 case 'J': /* Jump to the first packet which matches the filter criteria */
2487 case 'l': /* Automatic scrolling in live capture mode */
2489 auto_scroll_live = TRUE;
2491 capture_option_specified = TRUE;
2495 case 'L': /* Print list of link-layer types and exit */
2497 list_link_layer_types = TRUE;
2499 capture_option_specified = TRUE;
2503 case 'm': /* Fixed-width font for the display */
2504 g_free(prefs_p->gui_font_name);
2505 prefs_p->gui_font_name = g_strdup(optarg);
2507 case 'n': /* No name resolution */
2508 g_resolv_flags = RESOLV_NONE;
2510 case 'N': /* Select what types of addresses/port #s to resolve */
2511 if (g_resolv_flags == RESOLV_ALL)
2512 g_resolv_flags = RESOLV_NONE;
2513 badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2514 if (badopt != '\0') {
2515 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2520 case 'o': /* Override preference from command line */
2521 switch (prefs_set_pref(optarg)) {
2524 case PREFS_SET_SYNTAX_ERR:
2525 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2528 case PREFS_SET_NO_SUCH_PREF:
2529 /* not a preference, might be a recent setting */
2530 switch (recent_set_arg(optarg)) {
2533 case PREFS_SET_SYNTAX_ERR:
2534 /* shouldn't happen, checked already above */
2535 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2538 case PREFS_SET_NO_SUCH_PREF:
2539 case PREFS_SET_OBSOLETE:
2540 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2545 g_assert_not_reached();
2548 case PREFS_SET_OBSOLETE:
2549 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2554 g_assert_not_reached();
2558 /* Path settings were already processed just ignore them this time*/
2560 case 'r': /* Read capture file xxx */
2561 /* We may set "last_open_dir" to "cf_name", and if we change
2562 "last_open_dir" later, we free the old value, so we have to
2563 set "cf_name" to something that's been allocated. */
2564 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2565 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2566 cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2568 cf_name = g_strdup(optarg);
2571 case 'R': /* Read file filter */
2574 case 't': /* Time stamp type */
2575 if (strcmp(optarg, "r") == 0)
2576 timestamp_set_type(TS_RELATIVE);
2577 else if (strcmp(optarg, "a") == 0)
2578 timestamp_set_type(TS_ABSOLUTE);
2579 else if (strcmp(optarg, "ad") == 0)
2580 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2581 else if (strcmp(optarg, "d") == 0)
2582 timestamp_set_type(TS_DELTA);
2583 else if (strcmp(optarg, "dd") == 0)
2584 timestamp_set_type(TS_DELTA_DIS);
2585 else if (strcmp(optarg, "e") == 0)
2586 timestamp_set_type(TS_EPOCH);
2588 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2589 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2590 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2594 case 'u': /* Seconds type */
2595 if (strcmp(optarg, "s") == 0)
2596 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
2597 else if (strcmp(optarg, "hms") == 0)
2598 timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
2600 cmdarg_err("Invalid seconds type \"%s\"", optarg);
2601 cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
2606 /* ext ops were already processed just ignore them this time*/
2609 /* We won't call the init function for the stat this soon
2610 as it would disallow MATE's fields (which are registered
2611 by the preferences set callback) from being used as
2612 part of a tap filter. Instead, we just add the argument
2613 to a list of stat arguments. */
2614 if (!process_stat_cmd_arg(optarg)) {
2615 cmdarg_err("Invalid -z argument.");
2616 cmdarg_err_cont(" -z argument must be one of :");
2617 list_stat_cmd_args();
2622 case '?': /* Bad flag - print usage message */
2630 if (cf_name != NULL) {
2632 * Input file name specified with "-r" *and* specified as a regular
2633 * command-line argument.
2635 cmdarg_err("File name specified both with -r and regular argument");
2639 * Input file name not specified with "-r", and a command-line argument
2640 * was specified; treat it as the input file name.
2642 * Yes, this is different from tshark, where non-flag command-line
2643 * arguments are a filter, but this works better on GUI desktops
2644 * where a command can be specified to be run to open a particular
2645 * file - yes, you could have "-r" as the last part of the command,
2646 * but that's a bit ugly.
2648 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2649 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2650 cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2652 cf_name = g_strdup(argv[0]);
2663 * Extra command line arguments were specified; complain.
2665 cmdarg_err("Invalid argument: %s", argv[0]);
2670 #ifndef HAVE_LIBPCAP
2671 if (capture_option_specified) {
2672 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2680 if (start_capture && list_link_layer_types) {
2681 /* Specifying *both* is bogus. */
2682 cmdarg_err("You can't specify both -L and a live capture.");
2686 if (list_link_layer_types) {
2687 /* We're supposed to list the link-layer types for an interface;
2688 did the user also specify a capture file to be read? */
2690 /* Yes - that's bogus. */
2691 cmdarg_err("You can't specify -L and a capture file to be read.");
2694 /* No - did they specify a ring buffer option? */
2695 if (global_capture_opts.multi_files_on) {
2696 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2700 /* We're supposed to do a live capture; did the user also specify
2701 a capture file to be read? */
2702 if (start_capture && cf_name) {
2703 /* Yes - that's bogus. */
2704 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2708 /* No - was the ring buffer option specified and, if so, does it make
2710 if (global_capture_opts.multi_files_on) {
2711 /* Ring buffer works only under certain conditions:
2712 a) ring buffer does not work with temporary files;
2713 b) real_time_mode and multi_files_on are mutually exclusive -
2714 real_time_mode takes precedence;
2715 c) it makes no sense to enable the ring buffer if the maximum
2716 file size is set to "infinite". */
2717 if (global_capture_opts.save_file == NULL) {
2718 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2719 global_capture_opts.multi_files_on = FALSE;
2721 /* if (global_capture_opts.real_time_mode) {
2722 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2723 global_capture_opts.multi_files_on = FALSE;
2725 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2726 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2727 /* XXX - this must be redesigned as the conditions changed */
2728 /* global_capture_opts.multi_files_on = FALSE;*/
2733 if (start_capture || list_link_layer_types) {
2734 /* Did the user specify an interface to use? */
2735 if (!capture_opts_trim_iface(&global_capture_opts,
2736 (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
2741 if (list_link_layer_types) {
2742 /* Get the list of link-layer types for the capture device. */
2743 if_capabilities_t *caps;
2745 caps = capture_get_if_capabilities(global_capture_opts.iface,
2746 global_capture_opts.monitor_mode,
2749 cmdarg_err("%s", err_str);
2753 if (caps->data_link_types == NULL) {
2754 cmdarg_err("The capture device \"%s\" has no data link types.", global_capture_opts.iface);
2757 capture_opts_print_if_capabilities(caps, global_capture_opts.monitor_mode);
2758 free_if_capabilities(caps);
2762 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2763 capture_opts_trim_ring_num_files(&global_capture_opts);
2764 #endif /* HAVE_LIBPCAP */
2766 /* Notify all registered modules that have had any of their preferences
2767 changed either from one of the preferences file or from the command
2768 line that their preferences have changed. */
2771 /* disabled protocols as per configuration file */
2772 if (gdp_path == NULL && dp_path == NULL) {
2773 set_disabled_protos_list();
2776 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2778 /* read in rc file from global and personal configuration paths. */
2779 rc_file = get_datafile_path(RC_FILE);
2780 gtk_rc_parse(rc_file);
2782 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2783 gtk_rc_parse(rc_file);
2790 /* close the splash screen, as we are going to open the main window now */
2791 splash_destroy(splash_win);
2793 /************************************************************************/
2794 /* Everything is prepared now, preferences and command line was read in */
2796 /* Pop up the main window. */
2797 create_main_window(pl_size, tv_size, bv_size, prefs_p);
2799 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2800 recent_read_dynamic(&rf_path, &rf_open_errno);
2801 if (rf_path != NULL && rf_open_errno != 0) {
2802 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2803 "Could not open recent file\n\"%s\": %s.",
2804 rf_path, strerror(rf_open_errno));
2807 color_filters_enable(recent.packet_list_colorize);
2809 /* rearrange all the widgets as we now have all recent settings ready for this */
2810 main_widgets_rearrange();
2812 /* Fill in column titles. This must be done after the top level window
2815 XXX - is that still true, with fixed-width columns? */
2816 #ifndef NEW_PACKET_LIST
2817 packet_list_set_column_titles();
2820 menu_recent_read_finished();
2822 menu_auto_scroll_live_changed(auto_scroll_live);
2825 switch (user_font_apply()) {
2828 case FA_FONT_NOT_RESIZEABLE:
2829 /* "user_font_apply()" popped up an alert box. */
2830 /* turn off zooming - font can't be resized */
2831 case FA_FONT_NOT_AVAILABLE:
2832 /* XXX - did we successfully load the un-zoomed version earlier?
2833 If so, this *probably* means the font is available, but not at
2834 this particular zoom level, but perhaps some other failure
2835 occurred; I'm not sure you can determine which is the case,
2837 /* turn off zooming - zoom level is unavailable */
2839 /* in any other case than FA_SUCCESS, turn off zooming */
2840 recent.gui_zoom_level = 0;
2841 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2844 dnd_init(top_level);
2846 color_filters_init();
2849 /* the window can be sized only, if it's not already shown, so do it now! */
2850 main_load_window_geometry(top_level);
2852 g_timeout_add(info_update_freq, resolv_update_cb, NULL);
2855 /* If we were given the name of a capture file, read it in now;
2856 we defer it until now, so that, if we can't open it, and pop
2857 up an alert box, the alert box is more likely to come up on
2858 top of the main window - but before the preference-file-error
2859 alert box, so, if we get one of those, it's more likely to come
2862 show_main_window(TRUE);
2863 check_and_warn_user_startup(cf_name);
2864 if (rfilter != NULL) {
2865 if (!dfilter_compile(rfilter, &rfcode)) {
2866 bad_dfilter_alert_box(rfilter);
2867 rfilter_parse_failed = TRUE;
2870 if (!rfilter_parse_failed) {
2871 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2872 /* "cf_open()" succeeded, so it closed the previous
2873 capture file, and thus destroyed any previous read filter
2874 attached to "cf". */
2876 cfile.rfcode = rfcode;
2877 /* Open stat windows; we do so after creating the main window,
2878 to avoid GTK warnings, and after successfully opening the
2879 capture file, so we know we have something to compute stats
2880 on, and after registering all dissectors, so that MATE will
2881 have registered its field array and we can have a tap filter
2882 with one of MATE's late-registered fields as part of the
2884 start_requested_stats();
2886 /* Read the capture file. */
2887 switch (cf_read(&cfile, FALSE)) {
2891 /* Just because we got an error, that doesn't mean we were unable
2892 to read any of the file; we handle what we could get from the
2894 /* if the user told us to jump to a specific packet, do it now */
2895 if(go_to_packet != 0) {
2896 /* Jump to the specified frame number, kept for backward
2898 cf_goto_frame(&cfile, go_to_packet);
2899 } else if (jfilter != NULL) {
2900 /* try to compile given filter */
2901 if (!dfilter_compile(jfilter, &jump_to_filter)) {
2902 bad_dfilter_alert_box(jfilter);
2905 /* Filter ok, jump to the first packet matching the filter
2906 conditions. Default search direction is forward, but if
2907 option d was given, search backwards */
2908 saved_bw = cfile.sbackward;
2909 cfile.sbackward = jump_backwards;
2910 cf_find_packet_dfilter(&cfile, jump_to_filter);
2911 cfile.sbackward = saved_bw;
2916 case CF_READ_ABORTED:
2921 /* Save the name of the containing directory specified in the
2922 path name, if any; we can write over cf_name, which is a
2923 good thing, given that "get_dirname()" does write over its
2925 s = get_dirname(cf_name);
2926 set_last_open_dir(s);
2931 dfilter_free(rfcode);
2932 cfile.rfcode = NULL;
2933 show_main_window(FALSE);
2934 /* Don't call check_and_warn_user_startup(): we did it above */
2935 set_menus_for_capture_in_progress(FALSE);
2936 set_capture_if_dialog_for_capture_in_progress(FALSE);
2941 if (start_capture) {
2942 if (global_capture_opts.save_file != NULL) {
2943 /* Save the directory name for future file dialogs. */
2944 /* (get_dirname overwrites filename) */
2945 s = get_dirname(g_strdup(global_capture_opts.save_file));
2946 set_last_open_dir(s);
2949 /* "-k" was specified; start a capture. */
2950 show_main_window(TRUE);
2951 check_and_warn_user_startup(cf_name);
2952 if (capture_start(&global_capture_opts)) {
2953 /* The capture started. Open stat windows; we do so after creating
2954 the main window, to avoid GTK warnings, and after successfully
2955 opening the capture file, so we know we have something to compute
2956 stats on, and after registering all dissectors, so that MATE will
2957 have registered its field array and we can have a tap filter with
2958 one of MATE's late-registered fields as part of the filter. */
2959 start_requested_stats();
2963 show_main_window(FALSE);
2964 check_and_warn_user_startup(cf_name);
2965 set_menus_for_capture_in_progress(FALSE);
2966 set_capture_if_dialog_for_capture_in_progress(FALSE);
2969 /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2970 if (!start_capture && strlen(global_capture_opts.cfilter) == 0) {
2971 g_free(global_capture_opts.cfilter);
2972 global_capture_opts.cfilter = g_strdup(get_conn_cfilter());
2974 #else /* HAVE_LIBPCAP */
2975 show_main_window(FALSE);
2976 check_and_warn_user_startup(cf_name);
2977 set_menus_for_capture_in_progress(FALSE);
2978 set_capture_if_dialog_for_capture_in_progress(FALSE);
2979 #endif /* HAVE_LIBPCAP */
2982 /* register our pid if we are being run from a U3 device */
2985 profile_store_persconffiles (FALSE);
2987 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
2989 /* we'll enter the GTK loop now and hand the control over to GTK ... */
2991 /* ... back from GTK, we're going down now! */
2993 /* deregister our pid */
2994 u3_deregister_pid();
2998 #ifdef HAVE_AIRPDCAP
2999 AirPDcapDestroyContext(&airpdcap_ctx);
3003 /* hide the (unresponsive) main window, while asking the user to close the console window */
3004 gtk_widget_hide(top_level);
3006 /* Shutdown windows sockets */
3009 /* For some unknown reason, the "atexit()" call in "create_console()"
3010 doesn't arrange that "destroy_console()" be called when we exit,
3011 so we call it here if a console was created. */
3020 /* We build this as a GUI subsystem application on Win32, so
3021 "WinMain()", not "main()", gets called.
3023 Hack shamelessly stolen from the Win32 port of the GIMP. */
3025 #define _stdcall __attribute__((stdcall))
3029 WinMain (struct HINSTANCE__ *hInstance,
3030 struct HINSTANCE__ *hPrevInstance,
3034 INITCOMMONCONTROLSEX comm_ctrl;
3036 /* Initialize our controls. Required for native Windows file dialogs. */
3037 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3038 comm_ctrl.dwSize = sizeof(comm_ctrl);
3039 /* Includes the animate, header, hot key, list view, progress bar,
3040 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3043 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3044 InitCommonControlsEx(&comm_ctrl);
3046 /* RichEd20.DLL is needed for filter entries. */
3047 LoadLibrary(_T("riched20.dll"));
3049 has_console = FALSE;
3050 return main (__argc, __argv);
3053 /* The code to create and desstroy console windows should not be necessary,
3054 at least as I read the GLib source code, as it looks as if GLib is, on
3055 Win32, *supposed* to create a console window into which to display its
3058 That doesn't happen, however. I suspect there's something completely
3059 broken about that code in GLib-for-Win32, and that it may be related
3060 to the breakage that forces us to just call "printf()" on the message
3061 rather than passing the message on to "g_log_default_handler()"
3062 (which is the routine that does the aforementioned non-functional
3063 console window creation). */
3066 * If this application has no console window to which its standard output
3067 * would go, create one.
3070 create_console(void)
3072 if (stdin_capture) {
3073 /* We've been handed "-i -". Don't mess with stdio. */
3078 /* We have no console to which to print the version string, so
3079 create one and make it the standard input, output, and error. */
3080 if (!AllocConsole())
3081 return; /* couldn't create console */
3083 ws_freopen("CONIN$", "r", stdin);
3084 ws_freopen("CONOUT$", "w", stdout);
3085 ws_freopen("CONOUT$", "w", stderr);
3087 /* Well, we have a console now. */
3090 /* Now register "destroy_console()" as a routine to be called just
3091 before the application exits, so that we can destroy the console
3092 after the user has typed a key (so that the console doesn't just
3093 disappear out from under them, giving the user no chance to see
3094 the message(s) we put in there). */
3095 atexit(destroy_console);
3097 SetConsoleTitle(_T("Wireshark Debug Console"));
3102 destroy_console(void)
3105 printf("\n\nPress any key to exit\n");
3114 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3115 const char *message, gpointer user_data _U_)
3122 /* ignore log message, if log_level isn't interesting based
3123 upon the console log preferences.
3124 If the preferences haven't been loaded loaded yet, display the
3127 The default console_log_level preference value is such that only
3128 ERROR, CRITICAL and WARNING level messages are processed;
3129 MESSAGE, INFO and DEBUG level messages are ignored. */
3130 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3131 prefs.console_log_level != 0) {
3136 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3137 /* the user wants a console or the application will terminate immediately */
3141 /* For some unknown reason, the above doesn't appear to actually cause
3142 anything to be sent to the standard output, so we'll just splat the
3143 message out directly, just to make sure it gets out. */
3145 switch(log_level & G_LOG_LEVEL_MASK) {
3146 case G_LOG_LEVEL_ERROR:
3149 case G_LOG_LEVEL_CRITICAL:
3152 case G_LOG_LEVEL_WARNING:
3155 case G_LOG_LEVEL_MESSAGE:
3158 case G_LOG_LEVEL_INFO:
3161 case G_LOG_LEVEL_DEBUG:
3165 fprintf(stderr, "unknown log_level %u\n", log_level);
3167 g_assert_not_reached();
3170 /* create a "timestamp" */
3172 today = localtime(&curr);
3174 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3175 today->tm_hour, today->tm_min, today->tm_sec,
3176 log_domain != NULL ? log_domain : "",
3179 if(log_level & G_LOG_LEVEL_ERROR) {
3180 /* wait for a key press before the following error handler will terminate the program
3181 this way the user at least can read the error message */
3182 printf("\n\nPress any key to exit\n");
3186 /* XXX - on UN*X, should we just use g_log_default_handler()?
3187 We want the error messages to go to the standard output;
3188 on Mac OS X, that will cause them to show up in various
3189 per-user logs accessible through Console (details depend
3190 on whether you're running 10.0 through 10.4 or running
3191 10.5 and later), and, on other UN*X desktop environments,
3192 if they don't show up in some form of console log, that's
3193 a deficiency in that desktop environment. (Too bad
3194 Windows doesn't set the standard output and error for
3195 GUI apps to something that shows up in such a log.) */
3196 g_log_default_handler(log_domain, log_level, message, user_data);
3203 * Helper for main_widgets_rearrange()
3205 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3206 gtk_container_remove(GTK_CONTAINER(data), widget);
3209 static GtkWidget *main_widget_layout(gint layout_content)
3211 switch(layout_content) {
3212 case(layout_pane_content_none):
3214 case(layout_pane_content_plist):
3216 case(layout_pane_content_pdetails):
3218 case(layout_pane_content_pbytes):
3219 return byte_nb_ptr_gbl;
3221 g_assert_not_reached();
3228 * Rearrange the main window widgets
3230 void main_widgets_rearrange(void) {
3231 GtkWidget *first_pane_widget1, *first_pane_widget2;
3232 GtkWidget *second_pane_widget1, *second_pane_widget2;
3233 gboolean split_top_left;
3235 /* be a bit faster */
3236 gtk_widget_hide(main_vbox);
3238 /* be sure we don't lose a widget while rearranging */
3239 g_object_ref(G_OBJECT(menubar));
3240 g_object_ref(G_OBJECT(main_tb));
3241 g_object_ref(G_OBJECT(filter_tb));
3243 g_object_ref(G_OBJECT(airpcap_tb));
3245 g_object_ref(G_OBJECT(pkt_scrollw));
3246 g_object_ref(G_OBJECT(tv_scrollw));
3247 g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3248 g_object_ref(G_OBJECT(statusbar));
3249 g_object_ref(G_OBJECT(main_pane_v1));
3250 g_object_ref(G_OBJECT(main_pane_v2));
3251 g_object_ref(G_OBJECT(main_pane_h1));
3252 g_object_ref(G_OBJECT(main_pane_h2));
3253 g_object_ref(G_OBJECT(welcome_pane));
3255 /* empty all containers participating */
3256 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
3257 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
3258 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
3259 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
3260 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
3262 statusbar_widgets_emptying(statusbar);
3264 /* add the menubar always at the top */
3265 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3268 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3270 /* filter toolbar in toolbar area */
3271 if (!prefs.filter_toolbar_show_in_statusbar) {
3272 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3276 /* airpcap toolbar */
3277 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3280 /* fill the main layout panes */
3281 switch(prefs.gui_layout_type) {
3282 case(layout_type_5):
3283 main_first_pane = main_pane_v1;
3284 main_second_pane = main_pane_v2;
3285 split_top_left = FALSE;
3287 case(layout_type_2):
3288 main_first_pane = main_pane_v1;
3289 main_second_pane = main_pane_h1;
3290 split_top_left = FALSE;
3292 case(layout_type_1):
3293 main_first_pane = main_pane_v1;
3294 main_second_pane = main_pane_h1;
3295 split_top_left = TRUE;
3297 case(layout_type_4):
3298 main_first_pane = main_pane_h1;
3299 main_second_pane = main_pane_v1;
3300 split_top_left = FALSE;
3302 case(layout_type_3):
3303 main_first_pane = main_pane_h1;
3304 main_second_pane = main_pane_v1;
3305 split_top_left = TRUE;
3307 case(layout_type_6):
3308 main_first_pane = main_pane_h1;
3309 main_second_pane = main_pane_h2;
3310 split_top_left = FALSE;
3313 main_first_pane = NULL;
3314 main_second_pane = NULL;
3315 split_top_left = FALSE;
3316 g_assert_not_reached();
3318 if (split_top_left) {
3319 first_pane_widget1 = main_second_pane;
3320 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3321 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3322 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3324 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3325 first_pane_widget2 = main_second_pane;
3326 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3327 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3329 if (first_pane_widget1 != NULL)
3330 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3331 if (first_pane_widget2 != NULL)
3332 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3333 if (second_pane_widget1 != NULL)
3334 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3335 if (second_pane_widget2 != NULL)
3336 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3338 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3341 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3344 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3346 /* filter toolbar in statusbar hbox */
3347 if (prefs.filter_toolbar_show_in_statusbar) {
3348 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3352 /* airpcap toolbar */
3353 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3356 /* statusbar widgets */
3357 statusbar_widgets_pack(statusbar);
3359 /* hide widgets on users recent settings */
3360 main_widgets_show_or_hide();
3362 gtk_widget_show(main_vbox);
3366 is_widget_visible(GtkWidget *widget, gpointer data)
3368 gboolean *is_visible = data;
3371 if (GTK_WIDGET_VISIBLE(widget))
3378 main_widgets_show_or_hide(void)
3380 gboolean main_second_pane_show;
3382 if (recent.main_toolbar_show) {
3383 gtk_widget_show(main_tb);
3385 gtk_widget_hide(main_tb);
3388 statusbar_widgets_show_or_hide(statusbar);
3390 if (recent.filter_toolbar_show) {
3391 gtk_widget_show(filter_tb);
3393 gtk_widget_hide(filter_tb);
3397 if (recent.airpcap_toolbar_show) {
3398 gtk_widget_show(airpcap_tb);
3400 gtk_widget_hide(airpcap_tb);
3404 if (recent.packet_list_show && have_capture_file) {
3405 gtk_widget_show(pkt_scrollw);
3407 gtk_widget_hide(pkt_scrollw);
3410 if (recent.tree_view_show && have_capture_file) {
3411 gtk_widget_show(tv_scrollw);
3413 gtk_widget_hide(tv_scrollw);
3416 if (recent.byte_view_show && have_capture_file) {
3417 gtk_widget_show(byte_nb_ptr_gbl);
3419 gtk_widget_hide(byte_nb_ptr_gbl);
3422 if (have_capture_file) {
3423 gtk_widget_show(main_first_pane);
3425 gtk_widget_hide(main_first_pane);
3429 * Is anything in "main_second_pane" visible?
3430 * If so, show it, otherwise hide it.
3432 main_second_pane_show = FALSE;
3433 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3434 &main_second_pane_show);
3435 if (main_second_pane_show) {
3436 gtk_widget_show(main_second_pane);
3438 gtk_widget_hide(main_second_pane);
3441 if (!have_capture_file) {
3443 gtk_widget_show(welcome_pane);
3446 gtk_widget_hide(welcome_pane);
3449 /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3450 #ifndef NEW_PACKET_LIST
3451 packet_list_freeze ();
3452 packet_list_thaw ();
3457 /* called, when the window state changes (minimized, maximized, ...) */
3459 window_state_event_cb (GtkWidget *widget _U_,
3463 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3465 if( (event->type) == (GDK_WINDOW_STATE)) {
3466 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3467 /* we might have dialogs popped up while we where iconified,
3469 display_queued_messages();
3477 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3479 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3481 if (event->keyval == GDK_F8) {
3482 #ifdef NEW_PACKET_LIST
3483 new_packet_list_next();
3488 } else if (event->keyval == GDK_F7) {
3489 #ifdef NEW_PACKET_LIST
3490 new_packet_list_prev();
3495 } else if (event->state & NO_SHIFT_MOD_MASK) {
3496 return FALSE; /* Skip control, alt, and other modifiers */
3498 * A comment in gdkkeysyms.h says that it's autogenerated from
3499 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3500 * don't explicitly say so, isprint() should work as expected
3503 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3504 /* Forward the keypress on to the display filter entry */
3505 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3506 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3507 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3515 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
3517 GtkAccelGroup *accel;
3520 /* use user-defined title if preference is set */
3521 title = create_user_window_title("The Wireshark Network Analyzer");
3524 top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
3527 gtk_widget_set_name(top_level, "main window");
3528 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3530 g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3531 G_CALLBACK(window_state_event_cb), NULL);
3532 g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3533 G_CALLBACK(top_level_key_pressed_cb), NULL );
3535 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3536 main_vbox = gtk_vbox_new(FALSE, 1);
3537 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
3538 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3539 gtk_widget_show(main_vbox);
3542 menubar = main_menu_new(&accel);
3544 #ifdef HAVE_IGE_MAC_INTEGRATION
3545 /* MacOS X native menus are created and displayed by main_menu_new() */
3546 if(!prefs_p->gui_macosx_style) {
3548 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3549 gtk_widget_show(menubar);
3550 #ifdef HAVE_IGE_MAC_INTEGRATION
3555 main_tb = toolbar_new();
3556 gtk_widget_show (main_tb);
3558 /* Filter toolbar */
3559 filter_tb = filter_toolbar_new();
3562 #ifdef NEW_PACKET_LIST
3563 pkt_scrollw = new_packet_list_create();
3564 gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3565 gtk_widget_show_all(pkt_scrollw);
3567 pkt_scrollw = packet_list_new(prefs_p);
3568 gtk_widget_set_size_request(packet_list, -1, pl_size);
3569 gtk_widget_show(pkt_scrollw);
3573 tv_scrollw = main_tree_view_new(prefs_p, &tree_view_gbl);
3574 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3575 gtk_widget_show(tv_scrollw);
3577 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3578 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3579 g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3580 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3581 gtk_widget_show(tree_view_gbl);
3584 byte_nb_ptr_gbl = byte_view_new();
3585 gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3586 gtk_widget_show(byte_nb_ptr_gbl);
3588 g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3589 g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3591 /* Panes for the packet list, tree, and byte view */
3592 main_pane_v1 = gtk_vpaned_new();
3593 gtk_widget_show(main_pane_v1);
3594 main_pane_v2 = gtk_vpaned_new();
3595 gtk_widget_show(main_pane_v2);
3596 main_pane_h1 = gtk_hpaned_new();
3597 gtk_widget_show(main_pane_h1);
3598 main_pane_h2 = gtk_hpaned_new();
3599 gtk_widget_show(main_pane_h2);
3601 airpcap_tb = airpcap_toolbar_new();
3602 gtk_widget_show(airpcap_tb);
3605 statusbar = statusbar_new();
3606 gtk_widget_show(statusbar);
3608 /* Pane for the welcome screen */
3609 welcome_pane = welcome_new();
3610 gtk_widget_show(welcome_pane);
3614 show_main_window(gboolean doing_work)
3616 main_set_for_capture_file(doing_work);
3618 /*** we have finished all init things, show the main window ***/
3619 gtk_widget_show(top_level);
3621 /* the window can be maximized only, if it's visible, so do it after show! */
3622 main_load_window_geometry(top_level);
3624 /* process all pending GUI events before continue */
3625 while (gtk_events_pending()) gtk_main_iteration();
3627 /* Pop up any queued-up alert boxes. */
3628 display_queued_messages();
3630 /* Move the main window to the front, in case it isn't already there */
3631 gdk_window_raise(top_level->window);
3634 airpcap_toolbar_show(airpcap_tb);
3635 #endif /* HAVE_AIRPCAP */
3638 /* Fill in capture options with values from the preferences */
3640 prefs_to_capture_opts(void)
3643 /* Set promiscuous mode from the preferences setting. */
3644 /* the same applies to other preferences settings as well. */
3645 global_capture_opts.promisc_mode = prefs.capture_prom_mode;
3646 global_capture_opts.use_pcapng = prefs.capture_pcap_ng;
3647 global_capture_opts.show_info = prefs.capture_show_info;
3648 global_capture_opts.real_time_mode = prefs.capture_real_time;
3649 auto_scroll_live = prefs.capture_auto_scroll;
3650 #endif /* HAVE_LIBPCAP */
3652 /* Set the name resolution code's flags from the preferences. */
3653 g_resolv_flags = prefs.name_resolve;
3657 /* Change configuration profile */
3658 void change_configuration_profile (const gchar *profile_name)
3660 char *gdp_path, *dp_path;
3664 /* First check if profile exists */
3665 if (!profile_exists(profile_name)) {
3669 /* Get the current geometry, before writing it to disk */
3670 main_save_window_geometry(top_level);
3672 if (profile_exists(get_profile_name())) {
3673 /* Write recent file for profile we are leaving, if it still exists */
3674 write_profile_recent();
3677 /* Set profile name and update the status bar */
3678 set_profile_name (profile_name);
3679 profile_bar_update ();
3681 /* Reset current preferences and apply the new */
3685 (void) read_configuration_files (&gdp_path, &dp_path);
3687 recent_read_profile_static(&rf_path, &rf_open_errno);
3688 if (rf_path != NULL && rf_open_errno != 0) {
3689 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3690 "Could not open common recent file\n\"%s\": %s.",
3691 rf_path, strerror(rf_open_errno));
3693 timestamp_set_type (recent.gui_time_format);
3694 timestamp_set_seconds_type (recent.gui_seconds_format);
3695 color_filters_enable(recent.packet_list_colorize);
3697 prefs_to_capture_opts();
3700 /* Update window view and redraw the toolbar */
3701 update_main_window_name();
3702 toolbar_redraw_all();
3704 /* Enable all protocols and disable from the disabled list */
3706 if (gdp_path == NULL && dp_path == NULL) {
3707 set_disabled_protos_list();
3710 /* Reload color filters */
3711 color_filters_reload();
3713 /* Reload list of interfaces on welcome page */
3714 welcome_if_panel_reload();
3716 /* Recreate the packet list according to new preferences */
3717 #ifdef NEW_PACKET_LIST
3718 new_packet_list_recreate ();
3720 packet_list_recreate ();
3722 cfile.cinfo.columns_changed = FALSE; /* Reset value */
3725 /* Update menus with new recent values */
3726 menu_recent_read_finished();
3728 /* Reload pane geometry, must be done after recreating the list */
3729 main_pane_load_window_geometry();
3732 /** redissect packets and update UI */
3733 void redissect_packets(void)
3735 cf_redissect_packets(&cfile);
3736 status_expert_update();