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"
105 #include "../capture_ui_utils.h"
107 #include <wsutil/file_util.h>
111 #include "../capture-pcap-util.h"
112 #include "../capture_ifinfo.h"
113 #include "../capture.h"
114 #include "../capture_sync.h"
118 #include "../capture-wpcap.h"
119 #include "../capture_wpcap_packet.h"
120 #include <tchar.h> /* Needed for Unicode */
121 #include <commctrl.h>
125 #include "gtk/file_dlg.h"
126 #include "gtk/gtkglobals.h"
127 #include "gtk/color_utils.h"
128 #include "gtk/gui_utils.h"
129 #include "gtk/color_dlg.h"
130 #include "gtk/filter_dlg.h"
131 #include "gtk/uat_gui.h"
133 #include "gtk/main.h"
134 #include "gtk/main_airpcap_toolbar.h"
135 #include "gtk/main_filter_toolbar.h"
136 #include "gtk/menus.h"
137 #include "gtk/main_packet_list.h"
138 #include "gtk/main_statusbar.h"
139 #include "gtk/main_statusbar_private.h"
140 #include "gtk/main_toolbar.h"
141 #include "gtk/main_welcome.h"
142 #include "gtk/drag_and_drop.h"
143 #include "gtk/capture_file_dlg.h"
144 #include "gtk/main_proto_draw.h"
145 #include "gtk/keys.h"
146 #include "gtk/packet_win.h"
147 #include "gtk/stock_icons.h"
148 #include "gtk/find_dlg.h"
149 #include "gtk/recent.h"
150 #include "gtk/follow_tcp.h"
151 #include "gtk/font_utils.h"
152 #include "gtk/about_dlg.h"
153 #include "gtk/help_dlg.h"
154 #include "gtk/decode_as_dlg.h"
155 #include "gtk/webbrowser.h"
156 #include "gtk/capture_dlg.h"
157 #include "gtk/capture_if_dlg.h"
158 #include "gtk/tap_dfilter_dlg.h"
159 #include "gtk/prefs_column.h"
160 #include "gtk/prefs_dlg.h"
163 #include "../image/wsicon16.xpm"
164 #include "../image/wsicon32.xpm"
165 #include "../image/wsicon48.xpm"
166 #include "../image/wsicon64.xpm"
167 #include "../image/wsiconcap16.xpm"
168 #include "../image/wsiconcap32.xpm"
169 #include "../image/wsiconcap48.xpm"
174 #include "airpcap_loader.h"
175 #include "airpcap_dlg.h"
176 #include "airpcap_gui_utils.h"
180 #include <epan/crypt/airpdcap_ws.h>
183 #ifdef NEW_PACKET_LIST
184 #include "gtk/new_packet_list.h"
188 * Files under personal and global preferences directories in which
189 * GTK settings for Wireshark are stored.
191 #define RC_FILE "gtkrc"
195 /* "exported" main widgets */
196 GtkWidget *top_level = NULL, *pkt_scrollw, *tree_view_gbl, *byte_nb_ptr_gbl;
198 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
199 static GtkWidget *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
200 static GtkWidget *main_first_pane, *main_second_pane;
202 /* internally used widgets */
203 static GtkWidget *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
206 GtkWidget *airpcap_tb;
207 int airpcap_dll_ret_val = -1;
210 GString *comp_info_str, *runtime_info_str;
211 gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
213 guint tap_update_timer_id;
216 static gboolean has_console; /* TRUE if app has console */
217 static void destroy_console(void);
218 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
220 static void console_log_handler(const char *log_domain,
221 GLogLevelFlags log_level, const char *message, gpointer user_data);
224 capture_options global_capture_opts;
228 static void create_main_window(gint, gint, gint, e_prefs*);
229 static void show_main_window(gboolean);
230 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
231 static void main_save_window_geometry(GtkWidget *widget);
234 /* Match selected byte pattern */
236 match_selected_cb_do(gpointer data, int action, gchar *text)
238 GtkWidget *filter_te;
239 char *cur_filter, *new_filter;
241 if ((!text) || (0 == strlen(text))) {
242 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
247 filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
250 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
252 switch (action&MATCH_SELECTED_MASK) {
254 case MATCH_SELECTED_REPLACE:
255 new_filter = g_strdup(text);
258 case MATCH_SELECTED_AND:
259 if ((!cur_filter) || (0 == strlen(cur_filter)))
260 new_filter = g_strdup(text);
262 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
265 case MATCH_SELECTED_OR:
266 if ((!cur_filter) || (0 == strlen(cur_filter)))
267 new_filter = g_strdup(text);
269 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
272 case MATCH_SELECTED_NOT:
273 new_filter = g_strconcat("!(", text, ")", NULL);
276 case MATCH_SELECTED_AND_NOT:
277 if ((!cur_filter) || (0 == strlen(cur_filter)))
278 new_filter = g_strconcat("!(", text, ")", NULL);
280 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
283 case MATCH_SELECTED_OR_NOT:
284 if ((!cur_filter) || (0 == strlen(cur_filter)))
285 new_filter = g_strconcat("!(", text, ")", NULL);
287 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
291 g_assert_not_reached();
296 /* Free up the copy we got of the old filter text. */
299 /* Don't change the current display filter if we only want to copy the filter */
300 if (action&MATCH_SELECTED_COPY_ONLY) {
301 GString *gtk_text_str = g_string_new("");
302 g_string_append(gtk_text_str, new_filter);
303 copy_to_clipboard(gtk_text_str);
304 g_string_free(gtk_text_str, TRUE);
306 /* create a new one and set the display filter entry accordingly */
307 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
309 /* Run the display filter so it goes in effect. */
310 if (action&MATCH_SELECTED_APPLY_NOW)
311 main_filter_packets(&cfile, new_filter, FALSE);
314 /* Free up the new filter text. */
319 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
323 if (cfile.finfo_selected) {
324 filter = proto_construct_match_selected_string(cfile.finfo_selected,
326 match_selected_cb_do((data ? data : w), action, filter);
331 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
335 if (cfile.finfo_selected) {
336 filter = proto_construct_match_selected_string(cfile.finfo_selected,
338 if ((!filter) || (0 == strlen(filter))) {
339 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
340 "Could not acquire information to build a filter!\n"
341 "Try expanding or choosing another item.");
346 color_display_with_filter(filter);
349 color_filters_reset_tmp();
351 color_filters_set_tmp(filt_nr,filter, FALSE);
353 cf_colorize_packets(&cfile);
359 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
361 gchar *selected_proto_url;
362 gchar *proto_abbrev = data;
367 if (cfile.finfo_selected) {
368 /* open wiki page using the protocol abbreviation */
369 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
370 browser_open_url(selected_proto_url);
371 g_free(selected_proto_url);
374 case(ESD_BTN_CANCEL):
377 g_assert_not_reached();
383 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
386 const gchar *proto_abbrev;
390 if (cfile.finfo_selected) {
391 /* convert selected field to protocol abbreviation */
392 /* XXX - could this conversion be simplified? */
393 field_id = cfile.finfo_selected->hfinfo->id;
394 /* if the selected field isn't a protocol, get it's parent */
395 if(!proto_registrar_is_protocol(field_id)) {
396 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
399 proto_abbrev = proto_registrar_get_abbrev(field_id);
401 if (!proto_is_private(field_id)) {
402 /* ask the user if the wiki page really should be opened */
403 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
404 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
406 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
408 "The Wireshark Wiki is a collaborative approach to provide information "
409 "about Wireshark in several ways (not limited to protocol specifics).\n"
411 "This Wiki is new, so the page of the selected protocol "
412 "may not exist and/or may not contain valuable information.\n"
414 "As everyone can edit the Wiki and add new content (or extend existing), "
415 "you are encouraged to add information if you can.\n"
417 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
419 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
420 "which will save you a lot of editing and will give a consistent look over the pages.",
421 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
422 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
424 /* appologize to the user that the wiki page cannot be opened */
425 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
426 "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
428 "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
430 "Since this is a private protocol, such information is not available in "
431 "a public wiki. Therefore this wiki entry is blocked.\n"
433 "Sorry for the inconvenience.\n",
434 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
439 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
441 gchar *selected_proto_url;
442 gchar *proto_abbrev = data;
446 if (cfile.finfo_selected) {
447 /* open reference page using the protocol abbreviation */
448 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
449 browser_open_url(selected_proto_url);
450 g_free(selected_proto_url);
453 case(ESD_BTN_CANCEL):
456 g_assert_not_reached();
461 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
464 const gchar *proto_abbrev;
468 if (cfile.finfo_selected) {
469 /* convert selected field to protocol abbreviation */
470 /* XXX - could this conversion be simplified? */
471 field_id = cfile.finfo_selected->hfinfo->id;
472 /* if the selected field isn't a protocol, get it's parent */
473 if(!proto_registrar_is_protocol(field_id)) {
474 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
477 proto_abbrev = proto_registrar_get_abbrev(field_id);
479 if (!proto_is_private(field_id)) {
480 /* ask the user if the wiki page really should be opened */
481 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
482 "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
484 "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
486 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
487 simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
489 /* appologize to the user that the wiki page cannot be opened */
490 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
491 "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
493 "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
495 "Since this is a private protocol, such information is not available on "
496 "a public website. Therefore this filter entry is blocked.\n"
498 "Sorry for the inconvenience.\n",
499 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
505 is_address_column (gint column)
507 if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) ||
508 (cfile.cinfo.col_fmt[column] == COL_RES_SRC) ||
509 (cfile.cinfo.col_fmt[column] == COL_DEF_DST) ||
510 (cfile.cinfo.col_fmt[column] == COL_RES_DST)) &&
511 strlen(cfile.cinfo.col_expr.col_expr_val[column]))
520 get_ip_address_list_from_packet_list_row(gpointer data)
522 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
523 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
526 GList *addr_list = NULL;
530 #ifdef NEW_PACKET_LIST
531 fdata = (frame_data *) new_packet_list_get_row_data(row);
533 fdata = (frame_data *) packet_list_get_row_data(row);
539 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
540 cfile.pd, fdata->cap_len, &err, &err_info))
542 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
543 cf_read_error_message(err, err_info), cfile.filename);
547 epan_dissect_init(&edt, FALSE, FALSE);
548 col_custom_prime_edt(&edt, &cfile.cinfo);
550 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo);
551 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
553 /* First check selected column */
554 if (is_address_column (column)) {
555 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column]));
558 for (col = 0; col < cfile.cinfo.num_cols; col++) {
559 /* Then check all columns except the selected */
560 if ((col != column) && (is_address_column (col))) {
561 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col]));
565 epan_dissect_cleanup(&edt);
572 get_filter_from_packet_list_row_and_column(gpointer data)
574 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
575 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
581 #ifdef NEW_PACKET_LIST
582 fdata = (frame_data *) new_packet_list_get_row_data(row);
584 fdata = (frame_data *) packet_list_get_row_data(row);
590 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
591 cfile.pd, fdata->cap_len, &err, &err_info)) {
592 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
593 cf_read_error_message(err, err_info), cfile.filename);
596 /* proto tree, visible. We need a proto tree if there's custom columns */
597 epan_dissect_init(&edt, have_custom_cols(&cfile.cinfo), FALSE);
598 col_custom_prime_edt(&edt, &cfile.cinfo);
600 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata,
602 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
604 if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
605 strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
606 /* leak a little but safer than ep_ here */
607 if (cfile.cinfo.col_fmt[column] == COL_CUSTOM) {
608 header_field_info *hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[column]);
609 if (hfi->parent == -1) {
611 buf = se_strdup(cfile.cinfo.col_expr.col_expr[column]);
612 } else if (hfi->type == FT_STRING) {
613 /* Custom string, add quotes */
614 buf = se_strdup_printf("%s == \"%s\"", cfile.cinfo.col_expr.col_expr[column],
615 cfile.cinfo.col_expr.col_expr_val[column]);
619 buf = se_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
620 cfile.cinfo.col_expr.col_expr_val[column]);
624 epan_dissect_cleanup(&edt);
631 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
633 match_selected_cb_do(data,
635 get_filter_from_packet_list_row_and_column(data));
638 /* This function allows users to right click in the details window and copy the text
639 * information to the operating systems clipboard.
641 * We first check to see if a string representation is setup in the tree and then
642 * read the string. If not available then we try to grab the value. If all else
643 * fails we display a message to the user to indicate the copy could not be completed.
646 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
648 GString *gtk_text_str = g_string_new("");
649 char labelstring[256];
650 char *stringpointer = labelstring;
654 case COPY_SELECTED_DESCRIPTION:
655 if (cfile.finfo_selected->rep->representation != 0) {
656 g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
659 case COPY_SELECTED_FIELDNAME:
660 if (cfile.finfo_selected->hfinfo->abbrev != 0) {
661 g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
664 case COPY_SELECTED_VALUE:
665 if (cfile.edt !=0 ) {
666 g_string_append(gtk_text_str,
667 get_node_field_value(cfile.finfo_selected, cfile.edt));
674 if (gtk_text_str->len == 0) {
675 /* If no representation then... Try to read the value */
676 proto_item_fill_label(cfile.finfo_selected, stringpointer);
677 g_string_append(gtk_text_str, stringpointer);
680 if (gtk_text_str->len == 0) {
681 /* Could not get item so display error msg */
682 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
684 /* Copy string to clipboard */
685 copy_to_clipboard(gtk_text_str);
687 g_string_free(gtk_text_str, TRUE); /* Free the memory */
691 /* mark as reference time frame */
693 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
697 frame->flags.ref_time=1;
699 frame->flags.ref_time=0;
701 cf_reftime_packets(&cfile);
702 #ifdef NEW_PACKET_LIST
703 new_packet_list_queue_draw();
708 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
712 timestamp_set_type(TS_RELATIVE);
713 recent.gui_time_format = TS_RELATIVE;
714 #ifdef NEW_PACKET_LIST
715 cf_timestamp_auto_precision(&cfile);
716 new_packet_list_queue_draw();
718 cf_change_time_formats(&cfile);
724 g_assert_not_reached();
727 if (cfile.current_frame) {
728 set_frame_reftime(!cfile.current_frame->flags.ref_time,
729 cfile.current_frame, cfile.current_row);
735 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
737 static GtkWidget *reftime_dialog = NULL;
741 if (cfile.current_frame) {
742 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
743 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
744 "%sSwitch to the appropriate Time Display Format?%s\n\n"
745 "Time References don't work well with the currently selected Time Display Format.\n\n"
746 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
747 simple_dialog_primary_start(), simple_dialog_primary_end());
748 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
750 set_frame_reftime(!cfile.current_frame->flags.ref_time,
751 cfile.current_frame, cfile.current_row);
755 case REFTIME_FIND_NEXT:
756 find_previous_next_frame_with_filter("frame.ref_time", FALSE);
758 case REFTIME_FIND_PREV:
759 find_previous_next_frame_with_filter("frame.ref_time", TRUE);
765 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
767 find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
771 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
773 find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
777 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
780 gchar *help_str = NULL;
781 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
783 gboolean has_blurb = FALSE;
784 guint length = 0, byte_len;
785 GtkWidget *byte_view;
786 const guint8 *byte_data;
791 /* if nothing is selected */
792 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
795 * Which byte view is displaying the current protocol tree
798 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
799 if (byte_view == NULL)
802 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
803 if (byte_data == NULL)
806 cf_unselect_field(&cfile);
807 packet_hex_print(byte_view, byte_data,
808 cfile.current_frame, NULL, byte_len);
811 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
814 set_notebook_page(byte_nb_ptr_gbl, finfo->ds_tvb);
816 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
817 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
818 g_assert(byte_data != NULL);
820 cfile.finfo_selected = finfo;
821 set_menus_for_selected_tree_row(&cfile);
824 if (finfo->hfinfo->blurb != NULL &&
825 finfo->hfinfo->blurb[0] != '\0') {
827 length = (guint) strlen(finfo->hfinfo->blurb);
829 length = (guint) strlen(finfo->hfinfo->name);
831 finfo_length = finfo->length + finfo->appendix_length;
833 if (finfo_length == 0) {
835 } else if (finfo_length == 1) {
836 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
838 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
840 statusbar_pop_field_msg(); /* get rid of current help msg */
842 help_str = g_strdup_printf(" %s (%s)%s",
843 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
844 finfo->hfinfo->abbrev, len_str);
845 statusbar_push_field_msg(help_str);
849 * Don't show anything if the field name is zero-length;
850 * the pseudo-field for "proto_tree_add_text()" is such
851 * a field, and we don't want "Text (text)" showing up
852 * on the status line if you've selected such a field.
854 * XXX - there are zero-length fields for which we *do*
855 * want to show the field name.
857 * XXX - perhaps the name and abbrev field should be null
858 * pointers rather than null strings for that pseudo-field,
859 * but we'd have to add checks for null pointers in some
860 * places if we did that.
862 * Or perhaps protocol tree items added with
863 * "proto_tree_add_text()" should have -1 as the field index,
864 * with no pseudo-field being used, but that might also
865 * require special checks for -1 to be added.
867 statusbar_push_field_msg("");
870 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
874 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
876 collapse_all_tree(cfile.edt->tree, tree_view_gbl);
879 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
881 expand_all_tree(cfile.edt->tree, tree_view_gbl);
884 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
886 if (cfile.finfo_selected) {
887 column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
888 cfile.finfo_selected->hfinfo->abbrev);
889 /* Recreate the packet list according to new preferences */
890 #ifdef NEW_PACKET_LIST
891 new_packet_list_recreate ();
893 packet_list_recreate ();
895 if (!prefs.gui_use_pref_save) {
898 cfile.cinfo.columns_changed = FALSE; /* Reset value */
902 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
905 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
907 /* the mouse position is at an entry, expand that one */
908 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
909 gtk_tree_path_free(path);
913 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
914 if (cfile.edt->tree) {
915 guint32 tmp = g_resolv_flags;
916 g_resolv_flags = RESOLV_ALL;
917 proto_tree_draw(cfile.edt->tree, tree_view_gbl);
918 g_resolv_flags = tmp;
923 main_set_for_capture_file(gboolean have_capture_file_in)
925 have_capture_file = have_capture_file_in;
927 main_widgets_show_or_hide();
933 /* get the current geometry, before writing it to disk */
934 main_save_window_geometry(top_level);
936 /* write user's recent file to disk
937 * It is no problem to write this file, even if we do not quit */
938 write_profile_recent();
941 /* XXX - should we check whether the capture file is an
942 unsaved temporary file for a live capture and, if so,
943 pop up a "do you want to exit without saving the capture
944 file?" dialog, and then just return, leaving said dialog
945 box to forcibly quit if the user clicks "OK"?
947 If so, note that this should be done in a subroutine that
948 returns TRUE if we do so, and FALSE otherwise, and if it
949 returns TRUE we should return TRUE without nuking anything.
951 Note that, if we do that, we might also want to check if
952 an "Update list of packets in real time" capture is in
953 progress and, if so, ask whether they want to terminate
954 the capture and discard it, and return TRUE, before nuking
955 any child capture, if they say they don't want to do so. */
958 /* Nuke any child capture in progress. */
959 capture_kill_child(&global_capture_opts);
962 /* Are we in the middle of reading a capture? */
963 if (cfile.state == FILE_READ_IN_PROGRESS) {
964 /* Yes, so we can't just close the file and quit, as
965 that may yank the rug out from under the read in
966 progress; instead, just set the state to
967 "FILE_READ_ABORTED" and return - the code doing the read
968 will check for that and, if it sees that, will clean
970 cfile.state = FILE_READ_ABORTED;
972 /* Say that the window should *not* be deleted;
973 that'll be done by the code that cleans up. */
976 /* Close any capture file we have open; on some OSes, you
977 can't unlink a temporary capture file if you have it
979 "cf_close()" will unlink it after closing it if
980 it's a temporary file.
982 We do this here, rather than after the main loop returns,
983 as, after the main loop returns, the main window may have
984 been destroyed (if this is called due to a "destroy"
985 even on the main window rather than due to the user
986 selecting a menu item), and there may be a crash
987 or other problem when "cf_close()" tries to
988 clean up stuff in the main window.
990 XXX - is there a better place to put this?
991 Or should we have a routine that *just* closes the
992 capture file, and doesn't do anything with the UI,
993 which we'd call here, and another routine that
994 calls that routine and also cleans up the UI, which
995 we'd call elsewhere? */
998 /* Exit by leaving the main loop, so that any quit functions
999 we registered get called. */
1002 /* Say that the window should be deleted. */
1008 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1012 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1013 gtk_window_present(GTK_WINDOW(top_level));
1014 /* user didn't saved his current file, ask him */
1015 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1016 "%sSave capture file before program quit?%s\n\n"
1017 "If you quit the program without saving, your capture data will be discarded.",
1018 simple_dialog_primary_start(), simple_dialog_primary_end());
1019 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1022 /* unchanged file, just exit */
1023 /* "main_do_quit()" indicates whether the main window should be deleted. */
1024 return main_do_quit();
1030 main_pane_load_window_geometry(void)
1032 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1033 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1034 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
1035 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1041 main_load_window_geometry(GtkWidget *widget)
1043 window_geometry_t geom;
1045 geom.set_pos = prefs.gui_geometry_save_position;
1046 geom.x = recent.gui_geometry_main_x;
1047 geom.y = recent.gui_geometry_main_y;
1048 geom.set_size = prefs.gui_geometry_save_size;
1049 if (recent.gui_geometry_main_width > 0 &&
1050 recent.gui_geometry_main_height > 0) {
1051 geom.width = recent.gui_geometry_main_width;
1052 geom.height = recent.gui_geometry_main_height;
1053 geom.set_maximized = prefs.gui_geometry_save_maximized;
1055 /* We assume this means the width and height weren't set in
1056 the "recent" file (or that there is no "recent" file),
1057 and weren't set to a default value, so we don't set the
1058 size. (The "recent" file code rejects non-positive width
1059 and height values.) */
1060 geom.set_size = FALSE;
1062 geom.maximized = recent.gui_geometry_main_maximized;
1064 window_set_geometry(widget, &geom);
1066 main_pane_load_window_geometry();
1067 statusbar_load_window_geometry();
1072 main_save_window_geometry(GtkWidget *widget)
1074 window_geometry_t geom;
1076 window_get_geometry(widget, &geom);
1078 if (prefs.gui_geometry_save_position) {
1079 recent.gui_geometry_main_x = geom.x;
1080 recent.gui_geometry_main_y = geom.y;
1083 if (prefs.gui_geometry_save_size) {
1084 recent.gui_geometry_main_width = geom.width;
1085 recent.gui_geometry_main_height = geom.height;
1088 if(prefs.gui_geometry_save_maximized) {
1089 recent.gui_geometry_main_maximized = geom.maximized;
1092 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
1093 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
1094 statusbar_save_window_geometry();
1097 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1101 /* save file first */
1102 file_save_as_cmd(after_save_exit, NULL);
1104 case(ESD_BTN_QUIT_DONT_SAVE):
1107 case(ESD_BTN_CANCEL):
1110 g_assert_not_reached();
1115 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1119 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1120 /* user didn't saved his current file, ask him */
1121 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1122 "%sSave capture file before program quit?%s\n\n"
1123 "If you quit the program without saving, your capture data will be discarded.",
1124 simple_dialog_primary_start(), simple_dialog_primary_end());
1125 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1127 /* unchanged file, just exit */
1133 print_usage(gboolean print_ver) {
1143 fprintf(output, "Wireshark " VERSION "%s\n"
1144 "Interactively dump and analyze network traffic.\n"
1145 "See http://www.wireshark.org for more information.\n"
1148 wireshark_svnversion, get_copyright_info());
1152 fprintf(output, "\n");
1153 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1154 fprintf(output, "\n");
1157 fprintf(output, "Capture interface:\n");
1158 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1159 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1160 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1161 fprintf(output, " -p don't capture in promiscuous mode\n");
1162 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1163 fprintf(output, " -Q quit Wireshark after capturing\n");
1164 fprintf(output, " -S update packet display when new packets are captured\n");
1165 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1166 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
1167 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1169 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1170 fprintf(output, " -D print list of interfaces and exit\n");
1171 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1172 fprintf(output, "\n");
1173 fprintf(output, "Capture stop conditions:\n");
1174 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1175 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1176 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1177 fprintf(output, " files:NUM - stop after NUM files\n");
1178 /*fprintf(output, "\n");*/
1179 fprintf(output, "Capture output:\n");
1180 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1181 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1182 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1183 #endif /* HAVE_LIBPCAP */
1185 /*fprintf(output, "\n");*/
1186 fprintf(output, "Input file:\n");
1187 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1189 fprintf(output, "\n");
1190 fprintf(output, "Processing:\n");
1191 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1192 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1193 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1195 fprintf(output, "\n");
1196 fprintf(output, "User interface:\n");
1197 fprintf(output, " -C <config profile> start with specified configuration profile\n");
1198 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1199 fprintf(output, " -J <jump filter> jump to the first packet matching the (display) filter\n");
1200 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
1201 fprintf(output, " -m <font> set the font name used for most text\n");
1202 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1203 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
1204 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1205 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1207 fprintf(output, "\n");
1208 fprintf(output, "Output:\n");
1209 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1211 fprintf(output, "\n");
1212 fprintf(output, "Miscellaneous:\n");
1213 fprintf(output, " -h display this help and exit\n");
1214 fprintf(output, " -v display version info and exit\n");
1215 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1216 fprintf(output, " persdata:path - personal data files\n");
1217 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1218 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1220 fprintf(output, " --display=DISPLAY X display to use\n");
1235 printf(PACKAGE " " VERSION "%s\n"
1242 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1243 runtime_info_str->str);
1251 * Print to the standard error. On Windows, create a console for the
1252 * standard error to show up on, if necessary.
1253 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1254 * terminal isn't the standard error?
1257 vfprintf_stderr(const char *fmt, va_list ap)
1262 vfprintf(stderr, fmt, ap);
1266 fprintf_stderr(const char *fmt, ...)
1271 vfprintf_stderr(fmt, ap);
1276 * Report an error in command-line arguments.
1277 * Creates a console on Windows.
1280 cmdarg_err(const char *fmt, ...)
1284 fprintf_stderr("wireshark: ");
1286 vfprintf_stderr(fmt, ap);
1288 fprintf_stderr("\n");
1292 * Report additional information for an error in command-line arguments.
1293 * Creates a console on Windows.
1294 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1295 * terminal isn't the standard error?
1298 cmdarg_err_cont(const char *fmt, ...)
1303 vfprintf_stderr(fmt, ap);
1304 fprintf_stderr("\n");
1308 #if defined(_WIN32) || ! defined USE_THREADS
1310 Once every 3 seconds we get a callback here which we use to update
1311 the tap extensions. Since Gtk1 is single threaded we dont have to
1312 worry about any locking or critical regions.
1315 tap_update_cb(gpointer data _U_)
1317 draw_tap_listeners(FALSE);
1321 /* Restart the tap update display timer with new configured interval */
1322 void reset_tap_update_timer(void)
1324 g_source_remove(tap_update_timer_id);
1325 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, tap_update_cb, NULL);
1330 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1331 use threads all update_thread_mutex can be dropped and protect/unprotect
1332 would just be empty functions.
1334 This allows gtk2-rpcstat.c and friends to be copied unmodified to
1335 gtk1-wireshark and it will just work.
1337 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1339 update_thread(gpointer data _U_)
1343 g_get_current_time(&tv1);
1344 g_static_mutex_lock(&update_thread_mutex);
1345 gdk_threads_enter();
1346 draw_tap_listeners(FALSE);
1347 gdk_threads_leave();
1348 g_static_mutex_unlock(&update_thread_mutex);
1350 g_get_current_time(&tv2);
1352 /* Assuming it took less than configured time to update tap listeners... */
1353 if( (tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) >
1354 (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1355 /* Wait for remainder of configured time */
1356 g_usleep((tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) -
1357 (tv2.tv_sec * 1000000 + tv2.tv_usec));
1364 protect_thread_critical_region(void)
1366 #if !defined(_WIN32) && defined USE_THREADS
1367 g_static_mutex_lock(&update_thread_mutex);
1371 unprotect_thread_critical_region(void)
1373 #if !defined(_WIN32) && defined USE_THREADS
1374 g_static_mutex_unlock(&update_thread_mutex);
1379 * Periodically process outstanding hostname lookups. If we have new items,
1380 * redraw the packet list and tree view.
1384 resolv_update_cb(gpointer data _U_)
1386 /* Anything new show up? */
1387 if (host_name_lookup_process(NULL)) {
1388 if (pkt_scrollw->window)
1389 gdk_window_invalidate_rect(pkt_scrollw->window, NULL, TRUE);
1390 if (tv_scrollw->window)
1391 gdk_window_invalidate_rect(tv_scrollw->window, NULL, TRUE);
1394 /* Always check. Even if we don't do async lookups we could still get
1395 passive updates, e.g. from DNS packets. */
1400 /* Set the file name in the name for the main window and in the name for the main window's icon. */
1402 set_display_filename(capture_file *cf)
1406 if (!cf->is_tempfile && cf->filename) {
1407 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1408 add_menu_recent_capture_file(cf->filename);
1412 win_name = g_strdup_printf("%s - Wireshark", cf_get_display_name(cf));
1413 set_main_window_name(win_name);
1417 GtkWidget *close_dlg = NULL;
1420 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1422 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1427 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1429 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1434 main_cf_cb_file_closing(capture_file *cf)
1437 /* if we have more than 10000 packets, show a splash screen while closing */
1438 /* XXX - don't know a better way to decide whether to show or not,
1439 * as most of the time is spend in a single eth_clist_clear function,
1440 * so we can't use a progress bar here! */
1441 if(cf->count > 10000) {
1442 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1443 "%sClosing file!%s\n\nPlease wait ...",
1444 simple_dialog_primary_start(),
1445 simple_dialog_primary_end());
1446 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1449 /* Destroy all windows, which refer to the
1450 capture file we're closing. */
1451 destroy_packet_wins();
1452 file_save_as_destroy();
1454 /* Restore the standard title bar message. */
1455 set_main_window_name("The Wireshark Network Analyzer");
1457 /* Disable all menu items that make sense only if you have a capture. */
1458 set_menus_for_capture_file(NULL);
1459 set_menus_for_captured_packets(FALSE);
1460 set_menus_for_selected_packet(cf);
1461 set_menus_for_capture_in_progress(FALSE);
1462 set_capture_if_dialog_for_capture_in_progress(FALSE);
1463 set_menus_for_selected_tree_row(cf);
1465 /* Set up main window for no capture file. */
1466 main_set_for_capture_file(FALSE);
1468 main_window_update();
1472 main_cf_cb_file_closed(capture_file *cf _U_)
1474 if(close_dlg != NULL) {
1475 splash_destroy(close_dlg);
1482 main_cf_cb_file_read_started(capture_file *cf _U_)
1484 tap_dfilter_dlg_update();
1486 /* Set up main window for a capture file. */
1487 main_set_for_capture_file(TRUE);
1491 main_cf_cb_file_read_finished(capture_file *cf)
1493 set_display_filename(cf);
1495 /* Enable menu items that make sense if you have a capture file you've
1496 finished reading. */
1497 set_menus_for_capture_file(cf);
1499 /* Enable menu items that make sense if you have some captured packets. */
1500 set_menus_for_captured_packets(TRUE);
1504 static GList *icon_list_create(
1505 const char **icon16_xpm,
1506 const char **icon32_xpm,
1507 const char **icon48_xpm,
1508 const char **icon64_xpm)
1510 GList *icon_list = NULL;
1511 GdkPixbuf * pixbuf16;
1512 GdkPixbuf * pixbuf32;
1513 GdkPixbuf * pixbuf48;
1514 GdkPixbuf * pixbuf64;
1517 if(icon16_xpm != NULL) {
1518 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1520 icon_list = g_list_append(icon_list, pixbuf16);
1523 if(icon32_xpm != NULL) {
1524 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1526 icon_list = g_list_append(icon_list, pixbuf32);
1529 if(icon48_xpm != NULL) {
1530 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1532 icon_list = g_list_append(icon_list, pixbuf48);
1535 if(icon64_xpm != NULL) {
1536 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1538 icon_list = g_list_append(icon_list, pixbuf64);
1545 main_capture_set_main_window_title(capture_options *capture_opts)
1547 GString *title = g_string_new("");
1549 g_string_append(title, "Capturing ");
1550 if(capture_opts->iface) {
1551 g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
1553 g_string_append(title, "- Wireshark");
1555 set_main_window_name(title->str);
1556 g_string_free(title, TRUE);
1560 main_capture_cb_capture_prepared(capture_options *capture_opts)
1562 static GList *icon_list = NULL;
1564 main_capture_set_main_window_title(capture_opts);
1566 if(icon_list == NULL) {
1567 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1569 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1571 /* Disable menu items that make no sense if you're currently running
1573 set_menus_for_capture_in_progress(TRUE);
1574 set_capture_if_dialog_for_capture_in_progress(TRUE);
1576 /* Don't set up main window for a capture file. */
1577 main_set_for_capture_file(FALSE);
1581 main_capture_cb_capture_update_started(capture_options *capture_opts)
1583 /* We've done this in "prepared" above, but it will be cleared while
1584 switching to the next multiple file. */
1585 main_capture_set_main_window_title(capture_opts);
1587 set_menus_for_capture_in_progress(TRUE);
1588 set_capture_if_dialog_for_capture_in_progress(TRUE);
1590 /* Enable menu items that make sense if you have some captured
1591 packets (yes, I know, we don't have any *yet*). */
1592 set_menus_for_captured_packets(TRUE);
1594 /* Set up main window for a capture file. */
1595 main_set_for_capture_file(TRUE);
1599 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1601 capture_file *cf = capture_opts->cf;
1602 static GList *icon_list = NULL;
1604 set_display_filename(cf);
1606 /* Enable menu items that make sense if you're not currently running
1608 set_menus_for_capture_in_progress(FALSE);
1609 set_capture_if_dialog_for_capture_in_progress(FALSE);
1611 /* Enable menu items that make sense if you have a capture file
1612 you've finished reading. */
1613 set_menus_for_capture_file(cf);
1615 /* Set up main window for a capture file. */
1616 main_set_for_capture_file(TRUE);
1618 if(icon_list == NULL) {
1619 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1621 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1623 if(global_capture_opts.quit_after_cap) {
1624 /* command line asked us to quit after the capture */
1625 /* don't pop up a dialog to ask for unsaved files etc. */
1631 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1633 /* Don't set up main window for a capture file. */
1634 main_set_for_capture_file(FALSE);
1638 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1641 capture_file *cf = capture_opts->cf;
1643 static GList *icon_list = NULL;
1645 /*set_display_filename(cf);*/
1647 /* Enable menu items that make sense if you're not currently running
1649 set_menus_for_capture_in_progress(FALSE);
1650 set_capture_if_dialog_for_capture_in_progress(FALSE);
1652 /* Restore the standard title bar message */
1653 /* (just in case we have trouble opening the capture file). */
1654 set_main_window_name("The Wireshark Network Analyzer");
1656 if(icon_list == NULL) {
1657 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1659 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1661 /* We don't have loaded the capture file, this will be done later.
1662 * For now we still have simply a blank screen. */
1664 if(global_capture_opts.quit_after_cap) {
1665 /* command line asked us to quit after the capture */
1666 /* don't pop up a dialog to ask for unsaved files etc. */
1671 #endif /* HAVE_LIBPCAP */
1674 main_cf_cb_packet_selected(gpointer data)
1676 capture_file *cf = data;
1678 /* Display the GUI protocol tree and packet bytes.
1679 XXX - why do we dump core if we call "proto_tree_draw()"
1680 before calling "add_byte_views()"? */
1681 add_main_byte_views(cf->edt);
1682 main_proto_tree_draw(cf->edt->tree);
1684 /* The user is searching for a string in the data or a hex value,
1685 * highlight the field that is found in the tree and hex displays. */
1686 if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1687 highlight_field(cf->edt->tvb, cfile.search_pos,
1688 (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1689 cfile.search_pos = 0; /* Reset the position */
1692 /* A packet is selected. */
1693 set_menus_for_selected_packet(cf);
1697 main_cf_cb_packet_unselected(capture_file *cf)
1699 /* Clear out the display of that packet. */
1700 clear_tree_and_hex_views();
1702 /* No packet is selected. */
1703 set_menus_for_selected_packet(cf);
1707 main_cf_cb_field_unselected(capture_file *cf)
1709 set_menus_for_selected_tree_row(cf);
1713 main_cf_cb_file_save_reload_finished(gpointer data _U_)
1715 set_display_filename(&cfile);
1716 set_menus_for_capture_file(&cfile);
1720 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1723 case(cf_cb_file_closing):
1724 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1725 main_cf_cb_file_closing(data);
1727 case(cf_cb_file_closed):
1728 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1729 main_cf_cb_file_closed(data);
1731 case(cf_cb_file_read_started):
1732 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1733 main_cf_cb_file_read_started(data);
1735 case(cf_cb_file_read_finished):
1736 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1737 main_cf_cb_file_read_finished(data);
1739 case(cf_cb_packet_selected):
1740 main_cf_cb_packet_selected(data);
1742 case(cf_cb_packet_unselected):
1743 main_cf_cb_packet_unselected(data);
1745 case(cf_cb_field_unselected):
1746 main_cf_cb_field_unselected(data);
1748 case(cf_cb_file_save_started):
1749 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1751 case(cf_cb_file_save_finished):
1752 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1754 case(cf_cb_file_save_reload_finished):
1755 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1756 main_cf_cb_file_save_reload_finished(data);
1758 case(cf_cb_file_save_failed):
1759 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1762 g_warning("main_cf_callback: event %u unknown", event);
1763 g_assert_not_reached();
1769 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1772 case(capture_cb_capture_prepared):
1773 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1774 main_capture_cb_capture_prepared(capture_opts);
1776 case(capture_cb_capture_update_started):
1777 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1778 main_capture_cb_capture_update_started(capture_opts);
1780 case(capture_cb_capture_update_continue):
1781 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1783 case(capture_cb_capture_update_finished):
1784 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1785 main_capture_cb_capture_update_finished(capture_opts);
1787 case(capture_cb_capture_fixed_started):
1788 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1789 main_capture_cb_capture_fixed_started(capture_opts);
1791 case(capture_cb_capture_fixed_continue):
1792 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1794 case(capture_cb_capture_fixed_finished):
1795 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1796 main_capture_cb_capture_fixed_finished(capture_opts);
1798 case(capture_cb_capture_stopping):
1799 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1800 /* Beware: this state won't be called, if the capture child
1801 * closes the capturing on it's own! */
1804 g_warning("main_capture_callback: event %u unknown", event);
1805 g_assert_not_reached();
1811 get_gui_compiled_info(GString *str)
1813 get_epan_compiled_version_info(str);
1815 g_string_append(str, ", ");
1816 #ifdef HAVE_LIBPORTAUDIO
1817 #ifdef PORTAUDIO_API_1
1818 g_string_append(str, "with PortAudio <= V18");
1819 #else /* PORTAUDIO_API_1 */
1820 g_string_append(str, "with ");
1821 g_string_append(str, Pa_GetVersionText());
1822 #endif /* PORTAUDIO_API_1 */
1823 #else /* HAVE_LIBPORTAUDIO */
1824 g_string_append(str, "without PortAudio");
1825 #endif /* HAVE_LIBPORTAUDIO */
1827 g_string_append(str, ", ");
1829 get_compiled_airpcap_version(str);
1831 g_string_append(str, "without AirPcap");
1833 #ifdef NEW_PACKET_LIST
1834 g_string_append(str, ", with new_packet_list");
1839 get_gui_runtime_info(GString *str)
1842 g_string_append(str, ", ");
1843 get_runtime_airpcap_version(str);
1847 g_string_append(str, ", ");
1848 u3_runtime_info(str);
1854 read_configuration_files(char **gdp_path, char **dp_path)
1856 int gpf_open_errno, gpf_read_errno;
1857 int cf_open_errno, df_open_errno;
1858 int gdp_open_errno, gdp_read_errno;
1859 int dp_open_errno, dp_read_errno;
1860 char *gpf_path, *pf_path;
1861 char *cf_path, *df_path;
1862 int pf_open_errno, pf_read_errno;
1865 /* Read the preference files. */
1866 prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1867 &pf_open_errno, &pf_read_errno, &pf_path);
1869 if (gpf_path != NULL) {
1870 if (gpf_open_errno != 0) {
1871 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1872 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1873 strerror(gpf_open_errno));
1875 if (gpf_read_errno != 0) {
1876 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1877 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1878 strerror(gpf_read_errno));
1881 if (pf_path != NULL) {
1882 if (pf_open_errno != 0) {
1883 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1884 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1885 strerror(pf_open_errno));
1887 if (pf_read_errno != 0) {
1888 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1889 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1890 strerror(pf_read_errno));
1897 /* if the user wants a console to be always there, well, we should open one for him */
1898 if (prefs_p->gui_console_open == console_open_always) {
1903 /* Read the capture filter file. */
1904 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1905 if (cf_path != NULL) {
1906 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1907 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1908 strerror(cf_open_errno));
1912 /* Read the display filter file. */
1913 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1914 if (df_path != NULL) {
1915 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1916 "Could not open your display filter file\n\"%s\": %s.", df_path,
1917 strerror(df_open_errno));
1921 /* Read the disabled protocols file. */
1922 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1923 dp_path, &dp_open_errno, &dp_read_errno);
1924 if (*gdp_path != NULL) {
1925 if (gdp_open_errno != 0) {
1926 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1927 "Could not open global disabled protocols file\n\"%s\": %s.",
1928 *gdp_path, strerror(gdp_open_errno));
1930 if (gdp_read_errno != 0) {
1931 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1932 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1933 *gdp_path, strerror(gdp_read_errno));
1938 if (*dp_path != NULL) {
1939 if (dp_open_errno != 0) {
1940 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1941 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1942 strerror(dp_open_errno));
1944 if (dp_read_errno != 0) {
1945 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1946 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1947 strerror(dp_read_errno));
1956 /* Check if there's something important to tell the user during startup.
1957 * We want to do this *after* showing the main window so that any windows
1958 * we pop up will be above the main window.
1962 check_and_warn_user_startup(gchar *cf_name)
1964 check_and_warn_user_startup(gchar *cf_name _U_)
1967 gchar *cur_user, *cur_group;
1968 gpointer priv_warning_dialog;
1970 /* Tell the user not to run as root. */
1971 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
1972 cur_user = get_cur_username();
1973 cur_group = get_cur_groupname();
1974 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1975 "Running as user \"%s\" and group \"%s\".\n"
1976 "This could be dangerous.", cur_user, cur_group);
1979 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
1980 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
1984 /* Warn the user if npf.sys isn't loaded. */
1985 if (!stdin_capture && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
1986 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1987 "The NPF driver isn't running. You may have trouble\n"
1988 "capturing or listing interfaces.");
1989 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
1990 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
1997 /* And now our feature presentation... [ fade to music ] */
1999 main(int argc, char *argv[])
2001 char *init_progfile_dir_error;
2004 gboolean arg_error = FALSE;
2006 extern int info_update_freq; /* Found in about_dlg.c. */
2007 const gchar *filter;
2015 char *gdp_path, *dp_path;
2018 gboolean start_capture = FALSE;
2019 gboolean list_link_layer_types = FALSE;
2023 gboolean capture_option_specified = FALSE;
2030 gint pl_size = 280, tv_size = 95, bv_size = 75;
2031 gchar *rc_file, *cf_name = NULL, *rfilter = NULL, *jfilter = NULL;
2032 dfilter_t *rfcode = NULL;
2033 gboolean rfilter_parse_failed = FALSE;
2036 GtkWidget *splash_win = NULL;
2037 GLogLevelFlags log_flags;
2038 guint go_to_packet = 0;
2039 gboolean jump_backwards = FALSE, saved_bw = FALSE;
2040 dfilter_t *jump_to_filter = NULL;
2045 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2046 #define OPTSTRING_B "B:"
2048 #define OPTSTRING_B ""
2049 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2050 #else /* HAVE_LIBPCAP */
2051 #define OPTSTRING_B ""
2052 #endif /* HAVE_LIBPCAP */
2054 #ifdef HAVE_PCAP_CREATE
2055 #define OPTSTRING_I "I"
2057 #define OPTSTRING_I ""
2060 #define OPTSTRING "a:b:" OPTSTRING_B "c:C:Df:g:Hhi:" OPTSTRING_I "jJ:kK:lLm:nN:o:P:pQr:R:Ss:t:u:vw:X:y:z:"
2062 static const char optstring[] = OPTSTRING;
2065 * Get credential information for later use, and drop privileges
2066 * before doing anything else.
2067 * Let the user know if anything happened.
2069 get_credential_info();
2070 relinquish_special_privs_perm();
2073 * Attempt to get the pathname of the executable file.
2075 init_progfile_dir_error = init_progfile_dir(argv[0], main);
2077 /* initialize the funnel mini-api */
2078 initialize_funnel_ops();
2080 #ifdef HAVE_AIRPDCAP
2081 AirPDcapInitContext(&airpdcap_ctx);
2085 /* Load wpcap if possible. Do this before collecting the run-time version information */
2088 /* ... and also load the packet.dll from wpcap */
2089 wpcap_packet_load();
2092 /* Load the airpcap.dll. This must also be done before collecting
2093 * run-time version information. */
2094 airpcap_dll_ret_val = load_airpcap();
2096 switch (airpcap_dll_ret_val) {
2097 case AIRPCAP_DLL_OK:
2098 /* load the airpcap interfaces */
2099 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2101 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2102 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2103 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2106 airpcap_if_active = NULL;
2110 /* select the first ad default (THIS SHOULD BE CHANGED) */
2111 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2116 * XXX - Maybe we need to warn the user if one of the following happens???
2118 case AIRPCAP_DLL_OLD:
2119 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2122 case AIRPCAP_DLL_ERROR:
2123 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2126 case AIRPCAP_DLL_NOT_FOUND:
2127 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2131 #endif /* HAVE_AIRPCAP */
2133 /* Start windows sockets */
2134 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2137 profile_store_persconffiles (TRUE);
2139 /* Assemble the compile-time version information string */
2140 comp_info_str = g_string_new("Compiled ");
2142 g_string_append(comp_info_str, "with ");
2143 g_string_append_printf(comp_info_str,
2144 #ifdef GTK_MAJOR_VERSION
2145 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
2148 "GTK+ (version unknown)");
2150 g_string_append(comp_info_str, ", ");
2152 get_compiled_version_info(comp_info_str, get_gui_compiled_info);
2154 /* Assemble the run-time version information string */
2155 runtime_info_str = g_string_new("Running ");
2156 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2158 /* Read the profile independent recent file. We have to do this here so we can */
2159 /* set the profile before it can be set from the command line parameterts */
2160 recent_read_static(&rf_path, &rf_open_errno);
2161 if (rf_path != NULL && rf_open_errno != 0) {
2162 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2163 "Could not open common recent file\n\"%s\": %s.",
2164 rf_path, strerror(rf_open_errno));
2167 /* "pre-scan" the command line parameters, if we have "console only"
2168 parameters. We do this so we don't start GTK+ if we're only showing
2169 command-line help or version information.
2171 XXX - this pre-scan is done before we start GTK+, so we haven't
2172 run gtk_init() on the arguments. That means that GTK+ arguments
2173 have not been removed from the argument list; those arguments
2174 begin with "--", and will be treated as an error by getopt().
2176 We thus ignore errors - *and* set "opterr" to 0 to suppress the
2179 optind_initial = optind;
2180 while ((opt = getopt(argc, argv, optstring)) != -1) {
2182 case 'C': /* Configuration Profile */
2183 if (profile_exists (optarg)) {
2184 set_profile_name (optarg);
2186 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2190 case 'h': /* Print help and exit */
2196 if (strcmp(optarg, "-") == 0)
2197 stdin_capture = TRUE;
2200 case 'P': /* Path settings - change these before the Preferences and alike are processed */
2201 status = filesystem_opt(opt, optarg);
2203 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2207 case 'v': /* Show version and exit */
2213 * Extension command line options have to be processed before
2214 * we call epan_init() as they are supposed to be used by dissectors
2215 * or taps very early in the registration process.
2219 case '?': /* Ignore errors - the "real" scan will catch them. */
2224 /* Init the "Open file" dialog directory */
2225 /* (do this after the path settings are processed) */
2226 set_last_open_dir(get_persdatafile_dir());
2228 /* Set getopt index back to initial value, so it will start with the
2229 first command line parameter again. Also reset opterr to 1, so that
2230 error messages are printed by getopt().
2232 XXX - this seems to work on most platforms, but time will tell.
2233 The Single UNIX Specification says "The getopt() function need
2234 not be reentrant", so this isn't guaranteed to work. The Mac
2235 OS X 10.4[.x] getopt() man page says
2237 In order to use getopt() to evaluate multiple sets of arguments, or to
2238 evaluate a single set of arguments multiple times, the variable optreset
2239 must be set to 1 before the second and each additional set of calls to
2240 getopt(), and the variable optind must be reinitialized.
2244 The optreset variable was added to make it possible to call the getopt()
2245 function multiple times. This is an extension to the IEEE Std 1003.2
2246 (``POSIX.2'') specification.
2248 which I think comes from one of the other BSDs.
2250 XXX - if we want to control all the command-line option errors, so
2251 that we can display them where we choose (e.g., in a window), we'd
2252 want to leave opterr as 0, and produce our own messages using optopt.
2253 We'd have to check the value of optopt to see if it's a valid option
2254 letter, in which case *presumably* the error is "this option requires
2255 an argument but none was specified", or not a valid option letter,
2256 in which case *presumably* the error is "this option isn't valid".
2257 Some versions of getopt() let you supply a option string beginning
2258 with ':', which means that getopt() will return ':' rather than '?'
2259 for "this option requires an argument but none was specified", but
2261 optind = optind_initial;
2264 /* Set the current locale according to the program environment.
2265 * We haven't localized anything, but some GTK widgets are localized
2266 * (the file selection dialogue, for example).
2267 * This also sets the C-language locale to the native environment. */
2270 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2271 gtk_init (&argc, &argv);
2273 cf_callback_add(main_cf_callback, NULL);
2275 capture_callback_add(main_capture_callback, NULL);
2277 cf_callback_add(statusbar_cf_callback, NULL);
2279 capture_callback_add(statusbar_capture_callback, NULL);
2282 /* Arrange that if we have no console window, and a GLib message logging
2283 routine is called to log a message, we pop up a console window.
2285 We do that by inserting our own handler for all messages logged
2286 to the default domain; that handler pops up a console if necessary,
2287 and then calls the default handler. */
2289 /* We might want to have component specific log levels later ... */
2293 G_LOG_LEVEL_CRITICAL|
2294 G_LOG_LEVEL_WARNING|
2295 G_LOG_LEVEL_MESSAGE|
2298 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2300 g_log_set_handler(NULL,
2302 console_log_handler, NULL /* user_data */);
2303 g_log_set_handler(LOG_DOMAIN_MAIN,
2305 console_log_handler, NULL /* user_data */);
2308 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2310 console_log_handler, NULL /* user_data */);
2311 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2313 console_log_handler, NULL /* user_data */);
2315 /* Set the initial values in the capture options. This might be overwritten
2316 by preference settings and then again by the command line parameters. */
2317 capture_opts_init(&global_capture_opts, &cfile);
2319 global_capture_opts.snaplen = MIN_PACKET_SIZE;
2320 global_capture_opts.has_ring_num_files = TRUE;
2323 /* Initialize whatever we need to allocate colors for GTK+ */
2326 /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2327 filter = get_conn_cfilter();
2328 if ( *filter != '\0' ) {
2329 info_update_freq = 1000; /* Milliseconds */
2332 /* We won't come till here, if we had a "console only" command line parameter. */
2333 splash_win = splash_new("Loading Wireshark ...");
2334 if (init_progfile_dir_error != NULL) {
2335 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2336 "Can't get pathname of Wireshark: %s.\n"
2337 "It won't be possible to capture traffic.\n"
2338 "Report this to the Wireshark developers.",
2339 init_progfile_dir_error);
2340 g_free(init_progfile_dir_error);
2343 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2345 /* Register all dissectors; we must do this before checking for the
2346 "-G" flag, as the "-G" flag dumps information registered by the
2347 dissectors, and we must do it before we read the preferences, in
2348 case any dissectors register preferences. */
2349 epan_init(register_all_protocols,register_all_protocol_handoffs,
2350 splash_update, (gpointer) splash_win,
2351 failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2352 write_failure_alert_box);
2354 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2356 /* Register all tap listeners; we do this before we parse the arguments,
2357 as the "-z" argument can specify a registered tap. */
2359 /* we register the plugin taps before the other taps because
2360 stats_tree taps plugins will be registered as tap listeners
2361 by stats_tree_stat.c and need to registered before that */
2364 register_all_plugin_tap_listeners();
2367 register_all_tap_listeners();
2369 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2371 /* Now register the preferences for any non-dissector modules.
2372 We must do that before we read the preferences as well. */
2373 prefs_register_modules();
2375 prefs_p = read_configuration_files (&gdp_path, &dp_path);
2377 /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2378 #if !defined(_WIN32) && defined(G_THREADS_ENABLED) && defined USE_THREADS
2381 g_thread_init(NULL);
2383 ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2384 g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2386 #else /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2387 /* this is to keep tap extensions updating once every 3 seconds */
2388 tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2389 #endif /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2391 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2394 /* Read the profile dependent (static part) of the recent file. */
2395 /* Only the static part of it will be read, as we don't have the gui now to fill the */
2396 /* recent lists which is done in the dynamic part. */
2397 /* We have to do this already here, so command line parameters can overwrite these values. */
2398 recent_read_profile_static(&rf_path, &rf_open_errno);
2399 if (rf_path != NULL && rf_open_errno != 0) {
2400 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2401 "Could not open recent file\n\"%s\": %s.",
2402 rf_path, strerror(rf_open_errno));
2405 cap_file_init(&cfile);
2407 /* Fill in capture options with values from the preferences */
2408 prefs_to_capture_opts();
2410 /* Now get our args */
2411 while ((opt = getopt(argc, argv, optstring)) != -1) {
2413 /*** capture option specific ***/
2414 case 'a': /* autostop criteria */
2415 case 'b': /* Ringbuffer option */
2416 case 'c': /* Capture xxx packets */
2417 case 'f': /* capture filter */
2418 case 'k': /* Start capture immediately */
2419 case 'H': /* Hide capture info dialog box */
2420 case 'i': /* Use interface xxx */
2421 case 'p': /* Don't capture in promiscuous mode */
2422 #ifdef HAVE_PCAP_CREATE
2423 case 'I': /* Capture in monitor mode, if available */
2425 case 'Q': /* Quit after capture (just capture to file) */
2426 case 's': /* Set the snapshot (capture) length */
2427 case 'S': /* "Sync" mode: used for following file ala tail -f */
2428 case 'w': /* Write to capture file xxx */
2429 case 'y': /* Set the pcap data link type */
2430 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2431 case 'B': /* Buffer size */
2432 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2434 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2440 capture_option_specified = TRUE;
2445 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2446 case 'K': /* Kerberos keytab file */
2447 read_keytab_file(optarg);
2451 /*** all non capture option specific ***/
2453 /* Configuration profile settings were already processed just ignore them this time*/
2455 case 'D': /* Print a list of capture devices and exit */
2457 if_list = capture_interface_list(&err, &err_str);
2458 if (if_list == NULL) {
2460 case CANT_GET_INTERFACE_LIST:
2461 cmdarg_err("%s", err_str);
2465 case NO_INTERFACES_FOUND:
2466 cmdarg_err("There are no interfaces on which a capture can be done");
2471 capture_opts_print_interfaces(if_list);
2472 free_interface_list(if_list);
2475 capture_option_specified = TRUE;
2479 case 'j': /* Search backwards for a matching packet from filter in option J */
2480 jump_backwards = TRUE;
2482 case 'g': /* Go to packet with the given packet number */
2483 go_to_packet = get_positive_int(optarg, "go to packet");
2485 case 'J': /* Jump to the first packet which matches the filter criteria */
2488 case 'l': /* Automatic scrolling in live capture mode */
2490 auto_scroll_live = TRUE;
2492 capture_option_specified = TRUE;
2496 case 'L': /* Print list of link-layer types and exit */
2498 list_link_layer_types = TRUE;
2500 capture_option_specified = TRUE;
2504 case 'm': /* Fixed-width font for the display */
2505 g_free(prefs_p->gui_font_name);
2506 prefs_p->gui_font_name = g_strdup(optarg);
2508 case 'n': /* No name resolution */
2509 g_resolv_flags = RESOLV_NONE;
2511 case 'N': /* Select what types of addresses/port #s to resolve */
2512 if (g_resolv_flags == RESOLV_ALL)
2513 g_resolv_flags = RESOLV_NONE;
2514 badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2515 if (badopt != '\0') {
2516 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2521 case 'o': /* Override preference from command line */
2522 switch (prefs_set_pref(optarg)) {
2525 case PREFS_SET_SYNTAX_ERR:
2526 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2529 case PREFS_SET_NO_SUCH_PREF:
2530 /* not a preference, might be a recent setting */
2531 switch (recent_set_arg(optarg)) {
2534 case PREFS_SET_SYNTAX_ERR:
2535 /* shouldn't happen, checked already above */
2536 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2539 case PREFS_SET_NO_SUCH_PREF:
2540 case PREFS_SET_OBSOLETE:
2541 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2546 g_assert_not_reached();
2549 case PREFS_SET_OBSOLETE:
2550 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2555 g_assert_not_reached();
2559 /* Path settings were already processed just ignore them this time*/
2561 case 'r': /* Read capture file xxx */
2562 /* We may set "last_open_dir" to "cf_name", and if we change
2563 "last_open_dir" later, we free the old value, so we have to
2564 set "cf_name" to something that's been allocated. */
2565 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2566 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2567 cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2569 cf_name = g_strdup(optarg);
2572 case 'R': /* Read file filter */
2575 case 't': /* Time stamp type */
2576 if (strcmp(optarg, "r") == 0)
2577 timestamp_set_type(TS_RELATIVE);
2578 else if (strcmp(optarg, "a") == 0)
2579 timestamp_set_type(TS_ABSOLUTE);
2580 else if (strcmp(optarg, "ad") == 0)
2581 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2582 else if (strcmp(optarg, "d") == 0)
2583 timestamp_set_type(TS_DELTA);
2584 else if (strcmp(optarg, "dd") == 0)
2585 timestamp_set_type(TS_DELTA_DIS);
2586 else if (strcmp(optarg, "e") == 0)
2587 timestamp_set_type(TS_EPOCH);
2589 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2590 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2591 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2595 case 'u': /* Seconds type */
2596 if (strcmp(optarg, "s") == 0)
2597 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
2598 else if (strcmp(optarg, "hms") == 0)
2599 timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
2601 cmdarg_err("Invalid seconds type \"%s\"", optarg);
2602 cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
2607 /* ext ops were already processed just ignore them this time*/
2610 /* We won't call the init function for the stat this soon
2611 as it would disallow MATE's fields (which are registered
2612 by the preferences set callback) from being used as
2613 part of a tap filter. Instead, we just add the argument
2614 to a list of stat arguments. */
2615 if (!process_stat_cmd_arg(optarg)) {
2616 cmdarg_err("Invalid -z argument.");
2617 cmdarg_err_cont(" -z argument must be one of :");
2618 list_stat_cmd_args();
2623 case '?': /* Bad flag - print usage message */
2631 if (cf_name != NULL) {
2633 * Input file name specified with "-r" *and* specified as a regular
2634 * command-line argument.
2636 cmdarg_err("File name specified both with -r and regular argument");
2640 * Input file name not specified with "-r", and a command-line argument
2641 * was specified; treat it as the input file name.
2643 * Yes, this is different from tshark, where non-flag command-line
2644 * arguments are a filter, but this works better on GUI desktops
2645 * where a command can be specified to be run to open a particular
2646 * file - yes, you could have "-r" as the last part of the command,
2647 * but that's a bit ugly.
2649 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2650 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2651 cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2653 cf_name = g_strdup(argv[0]);
2664 * Extra command line arguments were specified; complain.
2666 cmdarg_err("Invalid argument: %s", argv[0]);
2671 #ifndef HAVE_LIBPCAP
2672 if (capture_option_specified) {
2673 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2681 if (start_capture && list_link_layer_types) {
2682 /* Specifying *both* is bogus. */
2683 cmdarg_err("You can't specify both -L and a live capture.");
2687 if (list_link_layer_types) {
2688 /* We're supposed to list the link-layer types for an interface;
2689 did the user also specify a capture file to be read? */
2691 /* Yes - that's bogus. */
2692 cmdarg_err("You can't specify -L and a capture file to be read.");
2695 /* No - did they specify a ring buffer option? */
2696 if (global_capture_opts.multi_files_on) {
2697 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2701 /* We're supposed to do a live capture; did the user also specify
2702 a capture file to be read? */
2703 if (start_capture && cf_name) {
2704 /* Yes - that's bogus. */
2705 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2709 /* No - was the ring buffer option specified and, if so, does it make
2711 if (global_capture_opts.multi_files_on) {
2712 /* Ring buffer works only under certain conditions:
2713 a) ring buffer does not work with temporary files;
2714 b) real_time_mode and multi_files_on are mutually exclusive -
2715 real_time_mode takes precedence;
2716 c) it makes no sense to enable the ring buffer if the maximum
2717 file size is set to "infinite". */
2718 if (global_capture_opts.save_file == NULL) {
2719 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2720 global_capture_opts.multi_files_on = FALSE;
2722 /* if (global_capture_opts.real_time_mode) {
2723 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2724 global_capture_opts.multi_files_on = FALSE;
2726 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2727 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2728 /* XXX - this must be redesigned as the conditions changed */
2729 /* global_capture_opts.multi_files_on = FALSE;*/
2734 if (start_capture || list_link_layer_types) {
2735 /* Did the user specify an interface to use? */
2736 if (!capture_opts_trim_iface(&global_capture_opts,
2737 (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
2742 if (list_link_layer_types) {
2743 /* Get the list of link-layer types for the capture device. */
2745 gchar *error_string;
2747 lt_list = capture_pcap_linktype_list(global_capture_opts.iface, &error_string);
2748 if (lt_list == NULL) {
2749 if (error_string != NULL) {
2750 cmdarg_err("The list of data link types for the capture device \"%s\" could not be obtained (%s)."
2751 "Please check to make sure you have sufficient permissions, and that\n"
2752 "you have the proper interface or pipe specified.\n", global_capture_opts.iface, error_string);
2753 g_free(error_string);
2755 cmdarg_err("The capture device \"%s\" has no data link types.", global_capture_opts.iface);
2758 capture_opts_print_link_layer_types(lt_list);
2759 free_pcap_linktype_list(lt_list);
2763 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2764 capture_opts_trim_ring_num_files(&global_capture_opts);
2765 #endif /* HAVE_LIBPCAP */
2767 /* Notify all registered modules that have had any of their preferences
2768 changed either from one of the preferences file or from the command
2769 line that their preferences have changed. */
2772 /* disabled protocols as per configuration file */
2773 if (gdp_path == NULL && dp_path == NULL) {
2774 set_disabled_protos_list();
2777 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2779 /* read in rc file from global and personal configuration paths. */
2780 rc_file = get_datafile_path(RC_FILE);
2781 gtk_rc_parse(rc_file);
2783 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2784 gtk_rc_parse(rc_file);
2791 /* close the splash screen, as we are going to open the main window now */
2792 splash_destroy(splash_win);
2794 /************************************************************************/
2795 /* Everything is prepared now, preferences and command line was read in */
2797 /* Pop up the main window. */
2798 create_main_window(pl_size, tv_size, bv_size, prefs_p);
2800 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2801 recent_read_dynamic(&rf_path, &rf_open_errno);
2802 if (rf_path != NULL && rf_open_errno != 0) {
2803 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2804 "Could not open recent file\n\"%s\": %s.",
2805 rf_path, strerror(rf_open_errno));
2808 color_filters_enable(recent.packet_list_colorize);
2810 /* rearrange all the widgets as we now have all recent settings ready for this */
2811 main_widgets_rearrange();
2813 /* Fill in column titles. This must be done after the top level window
2816 XXX - is that still true, with fixed-width columns? */
2817 #ifndef NEW_PACKET_LIST
2818 packet_list_set_column_titles();
2821 menu_recent_read_finished();
2823 menu_auto_scroll_live_changed(auto_scroll_live);
2826 switch (user_font_apply()) {
2829 case FA_FONT_NOT_RESIZEABLE:
2830 /* "user_font_apply()" popped up an alert box. */
2831 /* turn off zooming - font can't be resized */
2832 case FA_FONT_NOT_AVAILABLE:
2833 /* XXX - did we successfully load the un-zoomed version earlier?
2834 If so, this *probably* means the font is available, but not at
2835 this particular zoom level, but perhaps some other failure
2836 occurred; I'm not sure you can determine which is the case,
2838 /* turn off zooming - zoom level is unavailable */
2840 /* in any other case than FA_SUCCESS, turn off zooming */
2841 recent.gui_zoom_level = 0;
2842 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2845 dnd_init(top_level);
2847 color_filters_init();
2850 /* the window can be sized only, if it's not already shown, so do it now! */
2851 main_load_window_geometry(top_level);
2853 g_timeout_add(info_update_freq, resolv_update_cb, NULL);
2856 /* If we were given the name of a capture file, read it in now;
2857 we defer it until now, so that, if we can't open it, and pop
2858 up an alert box, the alert box is more likely to come up on
2859 top of the main window - but before the preference-file-error
2860 alert box, so, if we get one of those, it's more likely to come
2863 show_main_window(TRUE);
2864 check_and_warn_user_startup(cf_name);
2865 if (rfilter != NULL) {
2866 if (!dfilter_compile(rfilter, &rfcode)) {
2867 bad_dfilter_alert_box(rfilter);
2868 rfilter_parse_failed = TRUE;
2871 if (!rfilter_parse_failed) {
2872 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2873 /* "cf_open()" succeeded, so it closed the previous
2874 capture file, and thus destroyed any previous read filter
2875 attached to "cf". */
2877 cfile.rfcode = rfcode;
2878 /* Open stat windows; we do so after creating the main window,
2879 to avoid GTK warnings, and after successfully opening the
2880 capture file, so we know we have something to compute stats
2881 on, and after registering all dissectors, so that MATE will
2882 have registered its field array and we can have a tap filter
2883 with one of MATE's late-registered fields as part of the
2885 start_requested_stats();
2887 /* Read the capture file. */
2888 switch (cf_read(&cfile, FALSE)) {
2892 /* Just because we got an error, that doesn't mean we were unable
2893 to read any of the file; we handle what we could get from the
2895 /* if the user told us to jump to a specific packet, do it now */
2896 if(go_to_packet != 0) {
2897 /* Jump to the specified frame number, kept for backward
2899 cf_goto_frame(&cfile, go_to_packet);
2900 } else if (jfilter != NULL) {
2901 /* try to compile given filter */
2902 if (!dfilter_compile(jfilter, &jump_to_filter)) {
2903 bad_dfilter_alert_box(jfilter);
2906 /* Filter ok, jump to the first packet matching the filter
2907 conditions. Default search direction is forward, but if
2908 option d was given, search backwards */
2909 saved_bw = cfile.sbackward;
2910 cfile.sbackward = jump_backwards;
2911 cf_find_packet_dfilter(&cfile, jump_to_filter);
2912 cfile.sbackward = saved_bw;
2917 case CF_READ_ABORTED:
2922 /* Save the name of the containing directory specified in the
2923 path name, if any; we can write over cf_name, which is a
2924 good thing, given that "get_dirname()" does write over its
2926 s = get_dirname(cf_name);
2927 set_last_open_dir(s);
2932 dfilter_free(rfcode);
2933 cfile.rfcode = NULL;
2934 show_main_window(FALSE);
2935 /* Don't call check_and_warn_user_startup(): we did it above */
2936 set_menus_for_capture_in_progress(FALSE);
2937 set_capture_if_dialog_for_capture_in_progress(FALSE);
2942 if (start_capture) {
2943 if (global_capture_opts.save_file != NULL) {
2944 /* Save the directory name for future file dialogs. */
2945 /* (get_dirname overwrites filename) */
2946 s = get_dirname(g_strdup(global_capture_opts.save_file));
2947 set_last_open_dir(s);
2950 /* "-k" was specified; start a capture. */
2951 show_main_window(TRUE);
2952 check_and_warn_user_startup(cf_name);
2953 if (capture_start(&global_capture_opts)) {
2954 /* The capture started. Open stat windows; we do so after creating
2955 the main window, to avoid GTK warnings, and after successfully
2956 opening the capture file, so we know we have something to compute
2957 stats on, and after registering all dissectors, so that MATE will
2958 have registered its field array and we can have a tap filter with
2959 one of MATE's late-registered fields as part of the filter. */
2960 start_requested_stats();
2964 show_main_window(FALSE);
2965 check_and_warn_user_startup(cf_name);
2966 set_menus_for_capture_in_progress(FALSE);
2967 set_capture_if_dialog_for_capture_in_progress(FALSE);
2970 /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2971 if (!start_capture && strlen(global_capture_opts.cfilter) == 0) {
2972 g_free(global_capture_opts.cfilter);
2973 global_capture_opts.cfilter = g_strdup(get_conn_cfilter());
2975 #else /* HAVE_LIBPCAP */
2976 show_main_window(FALSE);
2977 check_and_warn_user_startup(cf_name);
2978 set_menus_for_capture_in_progress(FALSE);
2979 set_capture_if_dialog_for_capture_in_progress(FALSE);
2980 #endif /* HAVE_LIBPCAP */
2983 /* register our pid if we are being run from a U3 device */
2986 profile_store_persconffiles (FALSE);
2988 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
2990 /* we'll enter the GTK loop now and hand the control over to GTK ... */
2992 /* ... back from GTK, we're going down now! */
2994 /* deregister our pid */
2995 u3_deregister_pid();
2999 #ifdef HAVE_AIRPDCAP
3000 AirPDcapDestroyContext(&airpdcap_ctx);
3004 /* hide the (unresponsive) main window, while asking the user to close the console window */
3005 gtk_widget_hide(top_level);
3007 /* Shutdown windows sockets */
3010 /* For some unknown reason, the "atexit()" call in "create_console()"
3011 doesn't arrange that "destroy_console()" be called when we exit,
3012 so we call it here if a console was created. */
3021 /* We build this as a GUI subsystem application on Win32, so
3022 "WinMain()", not "main()", gets called.
3024 Hack shamelessly stolen from the Win32 port of the GIMP. */
3026 #define _stdcall __attribute__((stdcall))
3030 WinMain (struct HINSTANCE__ *hInstance,
3031 struct HINSTANCE__ *hPrevInstance,
3035 INITCOMMONCONTROLSEX comm_ctrl;
3037 /* Initialize our controls. Required for native Windows file dialogs. */
3038 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3039 comm_ctrl.dwSize = sizeof(comm_ctrl);
3040 /* Includes the animate, header, hot key, list view, progress bar,
3041 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3044 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3045 InitCommonControlsEx(&comm_ctrl);
3047 /* RichEd20.DLL is needed for filter entries. */
3048 LoadLibrary(_T("riched20.dll"));
3050 has_console = FALSE;
3051 return main (__argc, __argv);
3054 /* The code to create and desstroy console windows should not be necessary,
3055 at least as I read the GLib source code, as it looks as if GLib is, on
3056 Win32, *supposed* to create a console window into which to display its
3059 That doesn't happen, however. I suspect there's something completely
3060 broken about that code in GLib-for-Win32, and that it may be related
3061 to the breakage that forces us to just call "printf()" on the message
3062 rather than passing the message on to "g_log_default_handler()"
3063 (which is the routine that does the aforementioned non-functional
3064 console window creation). */
3067 * If this application has no console window to which its standard output
3068 * would go, create one.
3071 create_console(void)
3073 if (stdin_capture) {
3074 /* We've been handed "-i -". Don't mess with stdio. */
3079 /* We have no console to which to print the version string, so
3080 create one and make it the standard input, output, and error. */
3081 if (!AllocConsole())
3082 return; /* couldn't create console */
3084 ws_freopen("CONIN$", "r", stdin);
3085 ws_freopen("CONOUT$", "w", stdout);
3086 ws_freopen("CONOUT$", "w", stderr);
3088 /* Well, we have a console now. */
3091 /* Now register "destroy_console()" as a routine to be called just
3092 before the application exits, so that we can destroy the console
3093 after the user has typed a key (so that the console doesn't just
3094 disappear out from under them, giving the user no chance to see
3095 the message(s) we put in there). */
3096 atexit(destroy_console);
3098 SetConsoleTitle(_T("Wireshark Debug Console"));
3103 destroy_console(void)
3106 printf("\n\nPress any key to exit\n");
3115 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3116 const char *message, gpointer user_data _U_)
3123 /* ignore log message, if log_level isn't interesting based
3124 upon the console log preferences.
3125 If the preferences haven't been loaded loaded yet, display the
3128 The default console_log_level preference value is such that only
3129 ERROR, CRITICAL and WARNING level messages are processed;
3130 MESSAGE, INFO and DEBUG level messages are ignored. */
3131 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3132 prefs.console_log_level != 0) {
3137 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3138 /* the user wants a console or the application will terminate immediately */
3142 /* For some unknown reason, the above doesn't appear to actually cause
3143 anything to be sent to the standard output, so we'll just splat the
3144 message out directly, just to make sure it gets out. */
3146 switch(log_level & G_LOG_LEVEL_MASK) {
3147 case G_LOG_LEVEL_ERROR:
3150 case G_LOG_LEVEL_CRITICAL:
3153 case G_LOG_LEVEL_WARNING:
3156 case G_LOG_LEVEL_MESSAGE:
3159 case G_LOG_LEVEL_INFO:
3162 case G_LOG_LEVEL_DEBUG:
3166 fprintf(stderr, "unknown log_level %u\n", log_level);
3168 g_assert_not_reached();
3171 /* create a "timestamp" */
3173 today = localtime(&curr);
3175 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3176 today->tm_hour, today->tm_min, today->tm_sec,
3177 log_domain != NULL ? log_domain : "",
3180 if(log_level & G_LOG_LEVEL_ERROR) {
3181 /* wait for a key press before the following error handler will terminate the program
3182 this way the user at least can read the error message */
3183 printf("\n\nPress any key to exit\n");
3187 /* XXX - on UN*X, should we just use g_log_default_handler()?
3188 We want the error messages to go to the standard output;
3189 on Mac OS X, that will cause them to show up in various
3190 per-user logs accessible through Console (details depend
3191 on whether you're running 10.0 through 10.4 or running
3192 10.5 and later), and, on other UN*X desktop environments,
3193 if they don't show up in some form of console log, that's
3194 a deficiency in that desktop environment. (Too bad
3195 Windows doesn't set the standard output and error for
3196 GUI apps to something that shows up in such a log.) */
3197 g_log_default_handler(log_domain, log_level, message, user_data);
3204 * Helper for main_widgets_rearrange()
3206 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3207 gtk_container_remove(GTK_CONTAINER(data), widget);
3210 static GtkWidget *main_widget_layout(gint layout_content)
3212 switch(layout_content) {
3213 case(layout_pane_content_none):
3215 case(layout_pane_content_plist):
3217 case(layout_pane_content_pdetails):
3219 case(layout_pane_content_pbytes):
3220 return byte_nb_ptr_gbl;
3222 g_assert_not_reached();
3229 * Rearrange the main window widgets
3231 void main_widgets_rearrange(void) {
3232 GtkWidget *first_pane_widget1, *first_pane_widget2;
3233 GtkWidget *second_pane_widget1, *second_pane_widget2;
3234 gboolean split_top_left;
3236 /* be a bit faster */
3237 gtk_widget_hide(main_vbox);
3239 /* be sure we don't lose a widget while rearranging */
3240 g_object_ref(G_OBJECT(menubar));
3241 g_object_ref(G_OBJECT(main_tb));
3242 g_object_ref(G_OBJECT(filter_tb));
3244 g_object_ref(G_OBJECT(airpcap_tb));
3246 g_object_ref(G_OBJECT(pkt_scrollw));
3247 g_object_ref(G_OBJECT(tv_scrollw));
3248 g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3249 g_object_ref(G_OBJECT(statusbar));
3250 g_object_ref(G_OBJECT(main_pane_v1));
3251 g_object_ref(G_OBJECT(main_pane_v2));
3252 g_object_ref(G_OBJECT(main_pane_h1));
3253 g_object_ref(G_OBJECT(main_pane_h2));
3254 g_object_ref(G_OBJECT(welcome_pane));
3256 /* empty all containers participating */
3257 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
3258 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
3259 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
3260 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
3261 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
3263 statusbar_widgets_emptying(statusbar);
3265 /* add the menubar always at the top */
3266 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3269 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3271 /* filter toolbar in toolbar area */
3272 if (!prefs.filter_toolbar_show_in_statusbar) {
3273 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3277 /* airpcap toolbar */
3278 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3281 /* fill the main layout panes */
3282 switch(prefs.gui_layout_type) {
3283 case(layout_type_5):
3284 main_first_pane = main_pane_v1;
3285 main_second_pane = main_pane_v2;
3286 split_top_left = FALSE;
3288 case(layout_type_2):
3289 main_first_pane = main_pane_v1;
3290 main_second_pane = main_pane_h1;
3291 split_top_left = FALSE;
3293 case(layout_type_1):
3294 main_first_pane = main_pane_v1;
3295 main_second_pane = main_pane_h1;
3296 split_top_left = TRUE;
3298 case(layout_type_4):
3299 main_first_pane = main_pane_h1;
3300 main_second_pane = main_pane_v1;
3301 split_top_left = FALSE;
3303 case(layout_type_3):
3304 main_first_pane = main_pane_h1;
3305 main_second_pane = main_pane_v1;
3306 split_top_left = TRUE;
3308 case(layout_type_6):
3309 main_first_pane = main_pane_h1;
3310 main_second_pane = main_pane_h2;
3311 split_top_left = FALSE;
3314 main_first_pane = NULL;
3315 main_second_pane = NULL;
3316 split_top_left = FALSE;
3317 g_assert_not_reached();
3319 if (split_top_left) {
3320 first_pane_widget1 = main_second_pane;
3321 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3322 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3323 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3325 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3326 first_pane_widget2 = main_second_pane;
3327 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3328 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3330 if (first_pane_widget1 != NULL)
3331 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3332 if (first_pane_widget2 != NULL)
3333 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3334 if (second_pane_widget1 != NULL)
3335 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3336 if (second_pane_widget2 != NULL)
3337 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3339 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3342 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3345 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3347 /* filter toolbar in statusbar hbox */
3348 if (prefs.filter_toolbar_show_in_statusbar) {
3349 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3353 /* airpcap toolbar */
3354 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3357 /* statusbar widgets */
3358 statusbar_widgets_pack(statusbar);
3360 /* hide widgets on users recent settings */
3361 main_widgets_show_or_hide();
3363 gtk_widget_show(main_vbox);
3367 is_widget_visible(GtkWidget *widget, gpointer data)
3369 gboolean *is_visible = data;
3372 if (GTK_WIDGET_VISIBLE(widget))
3379 main_widgets_show_or_hide(void)
3381 gboolean main_second_pane_show;
3383 if (recent.main_toolbar_show) {
3384 gtk_widget_show(main_tb);
3386 gtk_widget_hide(main_tb);
3389 statusbar_widgets_show_or_hide(statusbar);
3391 if (recent.filter_toolbar_show) {
3392 gtk_widget_show(filter_tb);
3394 gtk_widget_hide(filter_tb);
3398 if (recent.airpcap_toolbar_show) {
3399 gtk_widget_show(airpcap_tb);
3401 gtk_widget_hide(airpcap_tb);
3405 if (recent.packet_list_show && have_capture_file) {
3406 gtk_widget_show(pkt_scrollw);
3408 gtk_widget_hide(pkt_scrollw);
3411 if (recent.tree_view_show && have_capture_file) {
3412 gtk_widget_show(tv_scrollw);
3414 gtk_widget_hide(tv_scrollw);
3417 if (recent.byte_view_show && have_capture_file) {
3418 gtk_widget_show(byte_nb_ptr_gbl);
3420 gtk_widget_hide(byte_nb_ptr_gbl);
3423 if (have_capture_file) {
3424 gtk_widget_show(main_first_pane);
3426 gtk_widget_hide(main_first_pane);
3430 * Is anything in "main_second_pane" visible?
3431 * If so, show it, otherwise hide it.
3433 main_second_pane_show = FALSE;
3434 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3435 &main_second_pane_show);
3436 if (main_second_pane_show) {
3437 gtk_widget_show(main_second_pane);
3439 gtk_widget_hide(main_second_pane);
3442 if (!have_capture_file) {
3444 gtk_widget_show(welcome_pane);
3447 gtk_widget_hide(welcome_pane);
3450 /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3451 #ifndef NEW_PACKET_LIST
3452 packet_list_freeze ();
3453 packet_list_thaw ();
3458 /* called, when the window state changes (minimized, maximized, ...) */
3460 window_state_event_cb (GtkWidget *widget _U_,
3464 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3466 if( (event->type) == (GDK_WINDOW_STATE)) {
3467 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3468 /* we might have dialogs popped up while we where iconified,
3470 display_queued_messages();
3478 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3480 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3482 if (event->keyval == GDK_F8) {
3483 #ifdef NEW_PACKET_LIST
3484 new_packet_list_next();
3489 } else if (event->keyval == GDK_F7) {
3490 #ifdef NEW_PACKET_LIST
3491 new_packet_list_prev();
3496 } else if (event->state & NO_SHIFT_MOD_MASK) {
3497 return FALSE; /* Skip control, alt, and other modifiers */
3499 * A comment in gdkkeysyms.h says that it's autogenerated from
3500 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3501 * don't explicitly say so, isprint() should work as expected
3504 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3505 /* Forward the keypress on to the display filter entry */
3506 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3507 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3508 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3516 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
3518 GtkAccelGroup *accel;
3521 /* use user-defined title if preference is set */
3522 title = create_user_window_title("The Wireshark Network Analyzer");
3525 top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
3528 gtk_widget_set_name(top_level, "main window");
3529 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3531 g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3532 G_CALLBACK(window_state_event_cb), NULL);
3533 g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3534 G_CALLBACK(top_level_key_pressed_cb), NULL );
3536 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3537 main_vbox = gtk_vbox_new(FALSE, 1);
3538 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
3539 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3540 gtk_widget_show(main_vbox);
3543 menubar = main_menu_new(&accel);
3545 #ifdef HAVE_IGE_MAC_INTEGRATION
3546 /* MacOS X native menus are created and displayed by main_menu_new() */
3547 if(!prefs_p->gui_macosx_style) {
3549 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3550 gtk_widget_show(menubar);
3551 #ifdef HAVE_IGE_MAC_INTEGRATION
3556 main_tb = toolbar_new();
3557 gtk_widget_show (main_tb);
3559 /* Filter toolbar */
3560 filter_tb = filter_toolbar_new();
3563 #ifdef NEW_PACKET_LIST
3564 pkt_scrollw = new_packet_list_create();
3565 gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3566 gtk_widget_show_all(pkt_scrollw);
3568 pkt_scrollw = packet_list_new(prefs_p);
3569 gtk_widget_set_size_request(packet_list, -1, pl_size);
3570 gtk_widget_show(pkt_scrollw);
3574 tv_scrollw = main_tree_view_new(prefs_p, &tree_view_gbl);
3575 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3576 gtk_widget_show(tv_scrollw);
3578 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3579 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3580 g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3581 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3582 gtk_widget_show(tree_view_gbl);
3585 byte_nb_ptr_gbl = byte_view_new();
3586 gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3587 gtk_widget_show(byte_nb_ptr_gbl);
3589 g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3590 g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3592 /* Panes for the packet list, tree, and byte view */
3593 main_pane_v1 = gtk_vpaned_new();
3594 gtk_widget_show(main_pane_v1);
3595 main_pane_v2 = gtk_vpaned_new();
3596 gtk_widget_show(main_pane_v2);
3597 main_pane_h1 = gtk_hpaned_new();
3598 gtk_widget_show(main_pane_h1);
3599 main_pane_h2 = gtk_hpaned_new();
3600 gtk_widget_show(main_pane_h2);
3602 airpcap_tb = airpcap_toolbar_new();
3603 gtk_widget_show(airpcap_tb);
3606 statusbar = statusbar_new();
3607 gtk_widget_show(statusbar);
3609 /* Pane for the welcome screen */
3610 welcome_pane = welcome_new();
3611 gtk_widget_show(welcome_pane);
3615 show_main_window(gboolean doing_work)
3617 main_set_for_capture_file(doing_work);
3619 /*** we have finished all init things, show the main window ***/
3620 gtk_widget_show(top_level);
3622 /* the window can be maximized only, if it's visible, so do it after show! */
3623 main_load_window_geometry(top_level);
3625 /* process all pending GUI events before continue */
3626 while (gtk_events_pending()) gtk_main_iteration();
3628 /* Pop up any queued-up alert boxes. */
3629 display_queued_messages();
3631 /* Move the main window to the front, in case it isn't already there */
3632 gdk_window_raise(top_level->window);
3635 airpcap_toolbar_show(airpcap_tb);
3636 #endif /* HAVE_AIRPCAP */
3639 /* Fill in capture options with values from the preferences */
3641 prefs_to_capture_opts(void)
3644 /* Set promiscuous mode from the preferences setting. */
3645 /* the same applies to other preferences settings as well. */
3646 global_capture_opts.promisc_mode = prefs.capture_prom_mode;
3647 global_capture_opts.use_pcapng = prefs.capture_pcap_ng;
3648 global_capture_opts.show_info = prefs.capture_show_info;
3649 global_capture_opts.real_time_mode = prefs.capture_real_time;
3650 auto_scroll_live = prefs.capture_auto_scroll;
3651 #endif /* HAVE_LIBPCAP */
3653 /* Set the name resolution code's flags from the preferences. */
3654 g_resolv_flags = prefs.name_resolve;
3658 /* Change configuration profile */
3659 void change_configuration_profile (const gchar *profile_name)
3661 char *gdp_path, *dp_path;
3665 /* First check if profile exists */
3666 if (!profile_exists(profile_name)) {
3670 /* Get the current geometry, before writing it to disk */
3671 main_save_window_geometry(top_level);
3673 if (profile_exists(get_profile_name())) {
3674 /* Write recent file for profile we are leaving, if it still exists */
3675 write_profile_recent();
3678 /* Set profile name and update the status bar */
3679 set_profile_name (profile_name);
3680 profile_bar_update ();
3682 /* Reset current preferences and apply the new */
3686 (void) read_configuration_files (&gdp_path, &dp_path);
3688 recent_read_profile_static(&rf_path, &rf_open_errno);
3689 if (rf_path != NULL && rf_open_errno != 0) {
3690 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3691 "Could not open common recent file\n\"%s\": %s.",
3692 rf_path, strerror(rf_open_errno));
3694 timestamp_set_type (recent.gui_time_format);
3695 timestamp_set_seconds_type (recent.gui_seconds_format);
3696 color_filters_enable(recent.packet_list_colorize);
3698 prefs_to_capture_opts();
3701 /* Update window view and redraw the toolbar */
3702 update_main_window_name();
3703 toolbar_redraw_all();
3705 /* Enable all protocols and disable from the disabled list */
3707 if (gdp_path == NULL && dp_path == NULL) {
3708 set_disabled_protos_list();
3711 /* Reload color filters */
3712 color_filters_reload();
3714 /* Reload list of interfaces on welcome page */
3715 welcome_if_panel_reload();
3717 /* Recreate the packet list according to new preferences */
3718 #ifdef NEW_PACKET_LIST
3719 new_packet_list_recreate ();
3721 packet_list_recreate ();
3723 cfile.cinfo.columns_changed = FALSE; /* Reset value */
3726 /* Update menus with new recent values */
3727 menu_recent_read_finished();
3729 /* Reload pane geometry, must be done after recreating the list */
3730 main_pane_load_window_geometry();
3733 /** redissect packets and update UI */
3734 void redissect_packets(void)
3736 cf_redissect_packets(&cfile);
3737 status_expert_update();