5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * Richard Sharpe, 13-Feb-1999, added support for initializing structures
10 * needed by dissect routines
11 * Jeff Foster, 2001/03/12, added support tabbed hex display windowss
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include <gdk/gdkkeysyms.h>
44 #ifdef NEED_STRERROR_H
54 #ifdef _WIN32 /* Needed for console I/O */
59 #ifdef HAVE_LIBPORTAUDIO
60 #include <portaudio.h>
61 #endif /* HAVE_LIBPORTAUDIO */
63 #include <epan/epan.h>
64 #include <epan/filesystem.h>
65 #include <wsutil/privileges.h>
66 #include <epan/epan_dissect.h>
67 #include <epan/timestamp.h>
68 #include <epan/packet.h>
69 #include <epan/plugins.h>
70 #include <epan/dfilter/dfilter.h>
71 #include <epan/strutil.h>
72 #include <epan/addr_resolv.h>
73 #include <epan/emem.h>
74 #include <epan/ex-opt.h>
75 #include <epan/funnel.h>
76 #include <epan/expert.h>
77 #include <epan/frequency-utils.h>
78 #include <epan/prefs.h>
79 #include <epan/prefs-int.h>
81 #include <epan/stat_cmd_args.h>
83 #include <epan/emem.h>
84 #include <epan/column.h>
86 /* general (not GTK specific) */
88 #include "../summary.h"
89 #include "../filters.h"
90 #include "../disabled_protos.h"
92 #include "../color_filters.h"
94 #include "../simple_dialog.h"
95 #include "../register.h"
96 #include "../ringbuffer.h"
97 #include "../ui_util.h"
99 #include "../clopts_common.h"
100 #include "../console_io.h"
101 #include "../cmdarg_err.h"
102 #include "../version_info.h"
103 #include "../merge.h"
104 #include "../alert_box.h"
106 #include <wsutil/file_util.h>
109 #include "../capture_ui_utils.h"
110 #include "../capture-pcap-util.h"
111 #include "../capture_ifinfo.h"
112 #include "../capture.h"
113 #include "../capture_sync.h"
117 #include "../capture-wpcap.h"
118 #include "../capture_wpcap_packet.h"
119 #include <tchar.h> /* Needed for Unicode */
120 #include <commctrl.h>
124 #include "gtk/file_dlg.h"
125 #include "gtk/gtkglobals.h"
126 #include "gtk/color_utils.h"
127 #include "gtk/gui_utils.h"
128 #include "gtk/color_dlg.h"
129 #include "gtk/filter_dlg.h"
130 #include "gtk/uat_gui.h"
132 #include "gtk/main.h"
133 #include "gtk/main_airpcap_toolbar.h"
134 #include "gtk/main_filter_toolbar.h"
135 #include "gtk/menus.h"
136 #include "gtk/main_packet_list.h"
137 #include "gtk/main_statusbar.h"
138 #include "gtk/main_statusbar_private.h"
139 #include "gtk/main_toolbar.h"
140 #include "gtk/main_welcome.h"
141 #include "gtk/drag_and_drop.h"
142 #include "gtk/capture_file_dlg.h"
143 #include "gtk/main_proto_draw.h"
144 #include "gtk/keys.h"
145 #include "gtk/packet_win.h"
146 #include "gtk/stock_icons.h"
147 #include "gtk/find_dlg.h"
148 #include "gtk/recent.h"
149 #include "gtk/follow_tcp.h"
150 #include "gtk/font_utils.h"
151 #include "gtk/about_dlg.h"
152 #include "gtk/help_dlg.h"
153 #include "gtk/decode_as_dlg.h"
154 #include "gtk/webbrowser.h"
155 #include "gtk/capture_dlg.h"
156 #include "gtk/capture_if_dlg.h"
157 #include "gtk/tap_dfilter_dlg.h"
158 #include "gtk/prefs_column.h"
159 #include "gtk/prefs_dlg.h"
162 #include "../image/wsicon16.xpm"
163 #include "../image/wsicon32.xpm"
164 #include "../image/wsicon48.xpm"
165 #include "../image/wsicon64.xpm"
166 #include "../image/wsiconcap16.xpm"
167 #include "../image/wsiconcap32.xpm"
168 #include "../image/wsiconcap48.xpm"
173 #include "airpcap_loader.h"
174 #include "airpcap_dlg.h"
175 #include "airpcap_gui_utils.h"
179 #include <epan/crypt/airpdcap_ws.h>
182 #ifdef NEW_PACKET_LIST
183 #include "gtk/new_packet_list.h"
186 #ifdef HAVE_GTKOSXAPPLICATION
187 #include <igemacintegration/gtkosxapplication.h>
191 * Files under personal and global preferences directories in which
192 * GTK settings for Wireshark are stored.
194 #define RC_FILE "gtkrc"
198 /* "exported" main widgets */
199 GtkWidget *top_level = NULL, *pkt_scrollw, *tree_view_gbl, *byte_nb_ptr_gbl;
201 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
202 static GtkWidget *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
203 static GtkWidget *main_first_pane, *main_second_pane;
205 /* internally used widgets */
206 static GtkWidget *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
209 GtkWidget *airpcap_tb;
210 int airpcap_dll_ret_val = -1;
213 GString *comp_info_str, *runtime_info_str;
214 gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
216 guint tap_update_timer_id;
219 static gboolean has_console; /* TRUE if app has console */
220 static void destroy_console(void);
221 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
223 static void console_log_handler(const char *log_domain,
224 GLogLevelFlags log_level, const char *message, gpointer user_data);
227 capture_options global_capture_opts;
231 static void create_main_window(gint, gint, gint, e_prefs*);
232 static void show_main_window(gboolean);
233 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
234 static void main_save_window_geometry(GtkWidget *widget);
237 /* Match selected byte pattern */
239 match_selected_cb_do(gpointer data, int action, gchar *text)
241 GtkWidget *filter_te;
242 char *cur_filter, *new_filter;
244 if ((!text) || (0 == strlen(text))) {
245 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
250 filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
253 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
255 switch (action&MATCH_SELECTED_MASK) {
257 case MATCH_SELECTED_REPLACE:
258 new_filter = g_strdup(text);
261 case MATCH_SELECTED_AND:
262 if ((!cur_filter) || (0 == strlen(cur_filter)))
263 new_filter = g_strdup(text);
265 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
268 case MATCH_SELECTED_OR:
269 if ((!cur_filter) || (0 == strlen(cur_filter)))
270 new_filter = g_strdup(text);
272 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
275 case MATCH_SELECTED_NOT:
276 new_filter = g_strconcat("!(", text, ")", NULL);
279 case MATCH_SELECTED_AND_NOT:
280 if ((!cur_filter) || (0 == strlen(cur_filter)))
281 new_filter = g_strconcat("!(", text, ")", NULL);
283 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
286 case MATCH_SELECTED_OR_NOT:
287 if ((!cur_filter) || (0 == strlen(cur_filter)))
288 new_filter = g_strconcat("!(", text, ")", NULL);
290 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
294 g_assert_not_reached();
299 /* Free up the copy we got of the old filter text. */
302 /* Don't change the current display filter if we only want to copy the filter */
303 if (action&MATCH_SELECTED_COPY_ONLY) {
304 GString *gtk_text_str = g_string_new("");
305 g_string_append(gtk_text_str, new_filter);
306 copy_to_clipboard(gtk_text_str);
307 g_string_free(gtk_text_str, TRUE);
309 /* create a new one and set the display filter entry accordingly */
310 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
312 /* Run the display filter so it goes in effect. */
313 if (action&MATCH_SELECTED_APPLY_NOW)
314 main_filter_packets(&cfile, new_filter, FALSE);
317 /* Free up the new filter text. */
322 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
326 if (cfile.finfo_selected) {
327 filter = proto_construct_match_selected_string(cfile.finfo_selected,
329 match_selected_cb_do((data ? data : w), action, filter);
334 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
338 if (cfile.finfo_selected) {
339 filter = proto_construct_match_selected_string(cfile.finfo_selected,
341 if ((!filter) || (0 == strlen(filter))) {
342 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
343 "Could not acquire information to build a filter!\n"
344 "Try expanding or choosing another item.");
349 color_display_with_filter(filter);
352 color_filters_reset_tmp();
354 color_filters_set_tmp(filt_nr,filter, FALSE);
356 cf_colorize_packets(&cfile);
362 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
364 gchar *selected_proto_url;
365 gchar *proto_abbrev = data;
370 if (cfile.finfo_selected) {
371 /* open wiki page using the protocol abbreviation */
372 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
373 browser_open_url(selected_proto_url);
374 g_free(selected_proto_url);
377 case(ESD_BTN_CANCEL):
380 g_assert_not_reached();
386 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
389 const gchar *proto_abbrev;
393 if (cfile.finfo_selected) {
394 /* convert selected field to protocol abbreviation */
395 /* XXX - could this conversion be simplified? */
396 field_id = cfile.finfo_selected->hfinfo->id;
397 /* if the selected field isn't a protocol, get it's parent */
398 if(!proto_registrar_is_protocol(field_id)) {
399 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
402 proto_abbrev = proto_registrar_get_abbrev(field_id);
404 if (!proto_is_private(field_id)) {
405 /* ask the user if the wiki page really should be opened */
406 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
407 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
409 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
411 "The Wireshark Wiki is a collaborative approach to provide information "
412 "about Wireshark in several ways (not limited to protocol specifics).\n"
414 "This Wiki is new, so the page of the selected protocol "
415 "may not exist and/or may not contain valuable information.\n"
417 "As everyone can edit the Wiki and add new content (or extend existing), "
418 "you are encouraged to add information if you can.\n"
420 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
422 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
423 "which will save you a lot of editing and will give a consistent look over the pages.",
424 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
425 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
427 /* appologize to the user that the wiki page cannot be opened */
428 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
429 "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
431 "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
433 "Since this is a private protocol, such information is not available in "
434 "a public wiki. Therefore this wiki entry is blocked.\n"
436 "Sorry for the inconvenience.\n",
437 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
442 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
444 gchar *selected_proto_url;
445 gchar *proto_abbrev = data;
449 if (cfile.finfo_selected) {
450 /* open reference page using the protocol abbreviation */
451 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
452 browser_open_url(selected_proto_url);
453 g_free(selected_proto_url);
456 case(ESD_BTN_CANCEL):
459 g_assert_not_reached();
464 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
467 const gchar *proto_abbrev;
471 if (cfile.finfo_selected) {
472 /* convert selected field to protocol abbreviation */
473 /* XXX - could this conversion be simplified? */
474 field_id = cfile.finfo_selected->hfinfo->id;
475 /* if the selected field isn't a protocol, get it's parent */
476 if(!proto_registrar_is_protocol(field_id)) {
477 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
480 proto_abbrev = proto_registrar_get_abbrev(field_id);
482 if (!proto_is_private(field_id)) {
483 /* ask the user if the wiki page really should be opened */
484 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
485 "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
487 "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
489 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
490 simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
492 /* appologize to the user that the wiki page cannot be opened */
493 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
494 "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
496 "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
498 "Since this is a private protocol, such information is not available on "
499 "a public website. Therefore this filter entry is blocked.\n"
501 "Sorry for the inconvenience.\n",
502 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
508 is_address_column (gint column)
510 if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) ||
511 (cfile.cinfo.col_fmt[column] == COL_RES_SRC) ||
512 (cfile.cinfo.col_fmt[column] == COL_DEF_DST) ||
513 (cfile.cinfo.col_fmt[column] == COL_RES_DST)) &&
514 strlen(cfile.cinfo.col_expr.col_expr_val[column]))
523 get_ip_address_list_from_packet_list_row(gpointer data)
525 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
526 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
529 GList *addr_list = NULL;
533 #ifdef NEW_PACKET_LIST
534 fdata = (frame_data *) new_packet_list_get_row_data(row);
536 fdata = (frame_data *) packet_list_get_row_data(row);
542 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
543 cfile.pd, fdata->cap_len, &err, &err_info))
545 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
546 cf_read_error_message(err, err_info), cfile.filename);
550 epan_dissect_init(&edt, FALSE, FALSE);
551 col_custom_prime_edt(&edt, &cfile.cinfo);
553 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo);
554 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
556 /* First check selected column */
557 if (is_address_column (column)) {
558 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column]));
561 for (col = 0; col < cfile.cinfo.num_cols; col++) {
562 /* Then check all columns except the selected */
563 if ((col != column) && (is_address_column (col))) {
564 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col]));
568 epan_dissect_cleanup(&edt);
575 get_filter_from_packet_list_row_and_column(gpointer data)
577 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
578 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
584 #ifdef NEW_PACKET_LIST
585 fdata = (frame_data *) new_packet_list_get_row_data(row);
587 fdata = (frame_data *) packet_list_get_row_data(row);
593 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
594 cfile.pd, fdata->cap_len, &err, &err_info)) {
595 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
596 cf_read_error_message(err, err_info), cfile.filename);
599 /* proto tree, visible. We need a proto tree if there's custom columns */
600 epan_dissect_init(&edt, have_custom_cols(&cfile.cinfo), FALSE);
601 col_custom_prime_edt(&edt, &cfile.cinfo);
603 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata,
605 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
607 if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
608 strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
609 /* leak a little but safer than ep_ here */
610 if (cfile.cinfo.col_fmt[column] == COL_CUSTOM) {
611 header_field_info *hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[column]);
612 if (hfi->parent == -1) {
614 buf = se_strdup(cfile.cinfo.col_expr.col_expr[column]);
615 } else if (hfi->type == FT_STRING) {
616 /* Custom string, add quotes */
617 buf = se_strdup_printf("%s == \"%s\"", cfile.cinfo.col_expr.col_expr[column],
618 cfile.cinfo.col_expr.col_expr_val[column]);
622 buf = se_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
623 cfile.cinfo.col_expr.col_expr_val[column]);
627 epan_dissect_cleanup(&edt);
634 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
636 match_selected_cb_do(data,
638 get_filter_from_packet_list_row_and_column(data));
641 /* This function allows users to right click in the details window and copy the text
642 * information to the operating systems clipboard.
644 * We first check to see if a string representation is setup in the tree and then
645 * read the string. If not available then we try to grab the value. If all else
646 * fails we display a message to the user to indicate the copy could not be completed.
649 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
651 GString *gtk_text_str = g_string_new("");
652 char labelstring[256];
653 char *stringpointer = labelstring;
657 case COPY_SELECTED_DESCRIPTION:
658 if (cfile.finfo_selected->rep->representation != 0) {
659 g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
662 case COPY_SELECTED_FIELDNAME:
663 if (cfile.finfo_selected->hfinfo->abbrev != 0) {
664 g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
667 case COPY_SELECTED_VALUE:
668 if (cfile.edt !=0 ) {
669 g_string_append(gtk_text_str,
670 get_node_field_value(cfile.finfo_selected, cfile.edt));
677 if (gtk_text_str->len == 0) {
678 /* If no representation then... Try to read the value */
679 proto_item_fill_label(cfile.finfo_selected, stringpointer);
680 g_string_append(gtk_text_str, stringpointer);
683 if (gtk_text_str->len == 0) {
684 /* Could not get item so display error msg */
685 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
687 /* Copy string to clipboard */
688 copy_to_clipboard(gtk_text_str);
690 g_string_free(gtk_text_str, TRUE); /* Free the memory */
694 /* mark as reference time frame */
696 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
700 frame->flags.ref_time=1;
702 frame->flags.ref_time=0;
704 cf_reftime_packets(&cfile);
705 #ifdef NEW_PACKET_LIST
706 new_packet_list_queue_draw();
711 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
715 timestamp_set_type(TS_RELATIVE);
716 recent.gui_time_format = TS_RELATIVE;
717 #ifdef NEW_PACKET_LIST
718 cf_timestamp_auto_precision(&cfile);
719 new_packet_list_queue_draw();
721 cf_change_time_formats(&cfile);
727 g_assert_not_reached();
730 if (cfile.current_frame) {
731 set_frame_reftime(!cfile.current_frame->flags.ref_time,
732 cfile.current_frame, cfile.current_row);
738 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
740 static GtkWidget *reftime_dialog = NULL;
744 if (cfile.current_frame) {
745 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
746 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
747 "%sSwitch to the appropriate Time Display Format?%s\n\n"
748 "Time References don't work well with the currently selected Time Display Format.\n\n"
749 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
750 simple_dialog_primary_start(), simple_dialog_primary_end());
751 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
753 set_frame_reftime(!cfile.current_frame->flags.ref_time,
754 cfile.current_frame, cfile.current_row);
758 case REFTIME_FIND_NEXT:
759 find_previous_next_frame_with_filter("frame.ref_time", FALSE);
761 case REFTIME_FIND_PREV:
762 find_previous_next_frame_with_filter("frame.ref_time", TRUE);
768 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
770 find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
774 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
776 find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
780 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
783 gchar *help_str = NULL;
784 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
786 gboolean has_blurb = FALSE;
787 guint length = 0, byte_len;
788 GtkWidget *byte_view;
789 const guint8 *byte_data;
794 /* if nothing is selected */
795 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
798 * Which byte view is displaying the current protocol tree
801 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
802 if (byte_view == NULL)
805 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
806 if (byte_data == NULL)
809 cf_unselect_field(&cfile);
810 packet_hex_print(byte_view, byte_data,
811 cfile.current_frame, NULL, byte_len);
814 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
817 set_notebook_page(byte_nb_ptr_gbl, finfo->ds_tvb);
819 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
820 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
821 g_assert(byte_data != NULL);
823 cfile.finfo_selected = finfo;
824 set_menus_for_selected_tree_row(&cfile);
827 if (finfo->hfinfo->blurb != NULL &&
828 finfo->hfinfo->blurb[0] != '\0') {
830 length = (guint) strlen(finfo->hfinfo->blurb);
832 length = (guint) strlen(finfo->hfinfo->name);
834 finfo_length = finfo->length + finfo->appendix_length;
836 if (finfo_length == 0) {
838 } else if (finfo_length == 1) {
839 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
841 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
843 statusbar_pop_field_msg(); /* get rid of current help msg */
845 help_str = g_strdup_printf(" %s (%s)%s",
846 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
847 finfo->hfinfo->abbrev, len_str);
848 statusbar_push_field_msg(help_str);
852 * Don't show anything if the field name is zero-length;
853 * the pseudo-field for "proto_tree_add_text()" is such
854 * a field, and we don't want "Text (text)" showing up
855 * on the status line if you've selected such a field.
857 * XXX - there are zero-length fields for which we *do*
858 * want to show the field name.
860 * XXX - perhaps the name and abbrev field should be null
861 * pointers rather than null strings for that pseudo-field,
862 * but we'd have to add checks for null pointers in some
863 * places if we did that.
865 * Or perhaps protocol tree items added with
866 * "proto_tree_add_text()" should have -1 as the field index,
867 * with no pseudo-field being used, but that might also
868 * require special checks for -1 to be added.
870 statusbar_push_field_msg("");
873 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
877 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
879 collapse_all_tree(cfile.edt->tree, tree_view_gbl);
882 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
884 expand_all_tree(cfile.edt->tree, tree_view_gbl);
887 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
889 if (cfile.finfo_selected) {
890 column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
891 cfile.finfo_selected->hfinfo->abbrev);
892 /* Recreate the packet list according to new preferences */
893 #ifdef NEW_PACKET_LIST
894 new_packet_list_recreate ();
896 packet_list_recreate ();
898 if (!prefs.gui_use_pref_save) {
901 cfile.cinfo.columns_changed = FALSE; /* Reset value */
905 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
908 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
910 /* the mouse position is at an entry, expand that one */
911 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
912 gtk_tree_path_free(path);
916 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
917 if (cfile.edt->tree) {
918 guint32 tmp = g_resolv_flags;
919 g_resolv_flags = RESOLV_ALL;
920 proto_tree_draw(cfile.edt->tree, tree_view_gbl);
921 g_resolv_flags = tmp;
926 main_set_for_capture_file(gboolean have_capture_file_in)
928 have_capture_file = have_capture_file_in;
930 main_widgets_show_or_hide();
936 /* get the current geometry, before writing it to disk */
937 main_save_window_geometry(top_level);
939 /* write user's recent file to disk
940 * It is no problem to write this file, even if we do not quit */
941 write_profile_recent();
944 /* XXX - should we check whether the capture file is an
945 unsaved temporary file for a live capture and, if so,
946 pop up a "do you want to exit without saving the capture
947 file?" dialog, and then just return, leaving said dialog
948 box to forcibly quit if the user clicks "OK"?
950 If so, note that this should be done in a subroutine that
951 returns TRUE if we do so, and FALSE otherwise, and if it
952 returns TRUE we should return TRUE without nuking anything.
954 Note that, if we do that, we might also want to check if
955 an "Update list of packets in real time" capture is in
956 progress and, if so, ask whether they want to terminate
957 the capture and discard it, and return TRUE, before nuking
958 any child capture, if they say they don't want to do so. */
961 /* Nuke any child capture in progress. */
962 capture_kill_child(&global_capture_opts);
965 /* Are we in the middle of reading a capture? */
966 if (cfile.state == FILE_READ_IN_PROGRESS) {
967 /* Yes, so we can't just close the file and quit, as
968 that may yank the rug out from under the read in
969 progress; instead, just set the state to
970 "FILE_READ_ABORTED" and return - the code doing the read
971 will check for that and, if it sees that, will clean
973 cfile.state = FILE_READ_ABORTED;
975 /* Say that the window should *not* be deleted;
976 that'll be done by the code that cleans up. */
979 /* Close any capture file we have open; on some OSes, you
980 can't unlink a temporary capture file if you have it
982 "cf_close()" will unlink it after closing it if
983 it's a temporary file.
985 We do this here, rather than after the main loop returns,
986 as, after the main loop returns, the main window may have
987 been destroyed (if this is called due to a "destroy"
988 even on the main window rather than due to the user
989 selecting a menu item), and there may be a crash
990 or other problem when "cf_close()" tries to
991 clean up stuff in the main window.
993 XXX - is there a better place to put this?
994 Or should we have a routine that *just* closes the
995 capture file, and doesn't do anything with the UI,
996 which we'd call here, and another routine that
997 calls that routine and also cleans up the UI, which
998 we'd call elsewhere? */
1001 /* Exit by leaving the main loop, so that any quit functions
1002 we registered get called. */
1005 /* Say that the window should be deleted. */
1011 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1015 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1016 gtk_window_present(GTK_WINDOW(top_level));
1017 /* user didn't saved his current file, ask him */
1018 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1019 "%sSave capture file before program quit?%s\n\n"
1020 "If you quit the program without saving, your capture data will be discarded.",
1021 simple_dialog_primary_start(), simple_dialog_primary_end());
1022 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1025 /* unchanged file, just exit */
1026 /* "main_do_quit()" indicates whether the main window should be deleted. */
1027 return main_do_quit();
1033 main_pane_load_window_geometry(void)
1035 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1036 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1037 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
1038 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1044 main_load_window_geometry(GtkWidget *widget)
1046 window_geometry_t geom;
1048 geom.set_pos = prefs.gui_geometry_save_position;
1049 geom.x = recent.gui_geometry_main_x;
1050 geom.y = recent.gui_geometry_main_y;
1051 geom.set_size = prefs.gui_geometry_save_size;
1052 if (recent.gui_geometry_main_width > 0 &&
1053 recent.gui_geometry_main_height > 0) {
1054 geom.width = recent.gui_geometry_main_width;
1055 geom.height = recent.gui_geometry_main_height;
1056 geom.set_maximized = prefs.gui_geometry_save_maximized;
1058 /* We assume this means the width and height weren't set in
1059 the "recent" file (or that there is no "recent" file),
1060 and weren't set to a default value, so we don't set the
1061 size. (The "recent" file code rejects non-positive width
1062 and height values.) */
1063 geom.set_size = FALSE;
1065 geom.maximized = recent.gui_geometry_main_maximized;
1067 window_set_geometry(widget, &geom);
1069 main_pane_load_window_geometry();
1070 statusbar_load_window_geometry();
1075 main_save_window_geometry(GtkWidget *widget)
1077 window_geometry_t geom;
1079 window_get_geometry(widget, &geom);
1081 if (prefs.gui_geometry_save_position) {
1082 recent.gui_geometry_main_x = geom.x;
1083 recent.gui_geometry_main_y = geom.y;
1086 if (prefs.gui_geometry_save_size) {
1087 recent.gui_geometry_main_width = geom.width;
1088 recent.gui_geometry_main_height = geom.height;
1091 if(prefs.gui_geometry_save_maximized) {
1092 recent.gui_geometry_main_maximized = geom.maximized;
1095 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
1096 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
1097 statusbar_save_window_geometry();
1100 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1104 /* save file first */
1105 file_save_as_cmd(after_save_exit, NULL);
1107 case(ESD_BTN_QUIT_DONT_SAVE):
1110 case(ESD_BTN_CANCEL):
1113 g_assert_not_reached();
1118 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1122 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1123 /* user didn't saved his current file, ask him */
1124 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1125 "%sSave capture file before program quit?%s\n\n"
1126 "If you quit the program without saving, your capture data will be discarded.",
1127 simple_dialog_primary_start(), simple_dialog_primary_end());
1128 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1130 /* unchanged file, just exit */
1136 print_usage(gboolean print_ver) {
1146 fprintf(output, "Wireshark " VERSION "%s\n"
1147 "Interactively dump and analyze network traffic.\n"
1148 "See http://www.wireshark.org for more information.\n"
1151 wireshark_svnversion, get_copyright_info());
1155 fprintf(output, "\n");
1156 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1157 fprintf(output, "\n");
1160 fprintf(output, "Capture interface:\n");
1161 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1162 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1163 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1164 fprintf(output, " -p don't capture in promiscuous mode\n");
1165 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1166 fprintf(output, " -Q quit Wireshark after capturing\n");
1167 fprintf(output, " -S update packet display when new packets are captured\n");
1168 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1169 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
1170 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1172 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1173 fprintf(output, " -D print list of interfaces and exit\n");
1174 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1175 fprintf(output, "\n");
1176 fprintf(output, "Capture stop conditions:\n");
1177 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1178 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1179 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1180 fprintf(output, " files:NUM - stop after NUM files\n");
1181 /*fprintf(output, "\n");*/
1182 fprintf(output, "Capture output:\n");
1183 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1184 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1185 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1186 #endif /* HAVE_LIBPCAP */
1188 /*fprintf(output, "\n");*/
1189 fprintf(output, "Input file:\n");
1190 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1192 fprintf(output, "\n");
1193 fprintf(output, "Processing:\n");
1194 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1195 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1196 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1198 fprintf(output, "\n");
1199 fprintf(output, "User interface:\n");
1200 fprintf(output, " -C <config profile> start with specified configuration profile\n");
1201 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1202 fprintf(output, " -J <jump filter> jump to the first packet matching the (display) filter\n");
1203 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
1204 fprintf(output, " -m <font> set the font name used for most text\n");
1205 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1206 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
1207 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1208 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1210 fprintf(output, "\n");
1211 fprintf(output, "Output:\n");
1212 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1214 fprintf(output, "\n");
1215 fprintf(output, "Miscellaneous:\n");
1216 fprintf(output, " -h display this help and exit\n");
1217 fprintf(output, " -v display version info and exit\n");
1218 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1219 fprintf(output, " persdata:path - personal data files\n");
1220 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1221 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1223 fprintf(output, " --display=DISPLAY X display to use\n");
1238 printf(PACKAGE " " VERSION "%s\n"
1245 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1246 runtime_info_str->str);
1254 * Print to the standard error. On Windows, create a console for the
1255 * standard error to show up on, if necessary.
1256 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1257 * terminal isn't the standard error?
1260 vfprintf_stderr(const char *fmt, va_list ap)
1265 vfprintf(stderr, fmt, ap);
1269 fprintf_stderr(const char *fmt, ...)
1274 vfprintf_stderr(fmt, ap);
1279 * Report an error in command-line arguments.
1280 * Creates a console on Windows.
1283 cmdarg_err(const char *fmt, ...)
1287 fprintf_stderr("wireshark: ");
1289 vfprintf_stderr(fmt, ap);
1291 fprintf_stderr("\n");
1295 * Report additional information for an error in command-line arguments.
1296 * Creates a console on Windows.
1297 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1298 * terminal isn't the standard error?
1301 cmdarg_err_cont(const char *fmt, ...)
1306 vfprintf_stderr(fmt, ap);
1307 fprintf_stderr("\n");
1311 #if defined(_WIN32) || ! defined USE_THREADS
1313 Once every 3 seconds we get a callback here which we use to update
1314 the tap extensions. Since Gtk1 is single threaded we dont have to
1315 worry about any locking or critical regions.
1318 tap_update_cb(gpointer data _U_)
1320 draw_tap_listeners(FALSE);
1324 /* Restart the tap update display timer with new configured interval */
1325 void reset_tap_update_timer(void)
1327 g_source_remove(tap_update_timer_id);
1328 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, tap_update_cb, NULL);
1333 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1334 use threads all update_thread_mutex can be dropped and protect/unprotect
1335 would just be empty functions.
1337 This allows gtk2-rpcstat.c and friends to be copied unmodified to
1338 gtk1-wireshark and it will just work.
1340 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1342 update_thread(gpointer data _U_)
1346 g_get_current_time(&tv1);
1347 g_static_mutex_lock(&update_thread_mutex);
1348 gdk_threads_enter();
1349 draw_tap_listeners(FALSE);
1350 gdk_threads_leave();
1351 g_static_mutex_unlock(&update_thread_mutex);
1353 g_get_current_time(&tv2);
1355 /* Assuming it took less than configured time to update tap listeners... */
1356 if( (tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) >
1357 (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1358 /* Wait for remainder of configured time */
1359 g_usleep((tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) -
1360 (tv2.tv_sec * 1000000 + tv2.tv_usec));
1367 protect_thread_critical_region(void)
1369 #if !defined(_WIN32) && defined USE_THREADS
1370 g_static_mutex_lock(&update_thread_mutex);
1374 unprotect_thread_critical_region(void)
1376 #if !defined(_WIN32) && defined USE_THREADS
1377 g_static_mutex_unlock(&update_thread_mutex);
1382 * Periodically process outstanding hostname lookups. If we have new items,
1383 * redraw the packet list and tree view.
1387 resolv_update_cb(gpointer data _U_)
1389 /* Anything new show up? */
1390 if (host_name_lookup_process(NULL)) {
1391 if (pkt_scrollw->window)
1392 gdk_window_invalidate_rect(pkt_scrollw->window, NULL, TRUE);
1393 if (tv_scrollw->window)
1394 gdk_window_invalidate_rect(tv_scrollw->window, NULL, TRUE);
1397 /* Always check. Even if we don't do async lookups we could still get
1398 passive updates, e.g. from DNS packets. */
1403 /* Set the file name in the name for the main window and in the name for the main window's icon. */
1405 set_display_filename(capture_file *cf)
1409 if (!cf->is_tempfile && cf->filename) {
1410 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1411 add_menu_recent_capture_file(cf->filename);
1415 win_name = g_strdup_printf("%s - Wireshark", cf_get_display_name(cf));
1416 set_main_window_name(win_name);
1420 GtkWidget *close_dlg = NULL;
1423 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1425 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1430 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1432 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1437 main_cf_cb_file_closing(capture_file *cf)
1440 /* if we have more than 10000 packets, show a splash screen while closing */
1441 /* XXX - don't know a better way to decide whether to show or not,
1442 * as most of the time is spend in a single eth_clist_clear function,
1443 * so we can't use a progress bar here! */
1444 if(cf->count > 10000) {
1445 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1446 "%sClosing file!%s\n\nPlease wait ...",
1447 simple_dialog_primary_start(),
1448 simple_dialog_primary_end());
1449 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1452 /* Destroy all windows, which refer to the
1453 capture file we're closing. */
1454 destroy_packet_wins();
1455 file_save_as_destroy();
1457 /* Restore the standard title bar message. */
1458 set_main_window_name("The Wireshark Network Analyzer");
1460 /* Disable all menu items that make sense only if you have a capture. */
1461 set_menus_for_capture_file(NULL);
1462 set_menus_for_captured_packets(FALSE);
1463 set_menus_for_selected_packet(cf);
1464 set_menus_for_capture_in_progress(FALSE);
1465 set_capture_if_dialog_for_capture_in_progress(FALSE);
1466 set_menus_for_selected_tree_row(cf);
1468 /* Set up main window for no capture file. */
1469 main_set_for_capture_file(FALSE);
1471 main_window_update();
1475 main_cf_cb_file_closed(capture_file *cf _U_)
1477 if(close_dlg != NULL) {
1478 splash_destroy(close_dlg);
1485 main_cf_cb_file_read_started(capture_file *cf _U_)
1487 tap_dfilter_dlg_update();
1489 /* Set up main window for a capture file. */
1490 main_set_for_capture_file(TRUE);
1494 main_cf_cb_file_read_finished(capture_file *cf)
1496 set_display_filename(cf);
1498 /* Enable menu items that make sense if you have a capture file you've
1499 finished reading. */
1500 set_menus_for_capture_file(cf);
1502 /* Enable menu items that make sense if you have some captured packets. */
1503 set_menus_for_captured_packets(TRUE);
1507 static GList *icon_list_create(
1508 const char **icon16_xpm,
1509 const char **icon32_xpm,
1510 const char **icon48_xpm,
1511 const char **icon64_xpm)
1513 GList *icon_list = NULL;
1514 GdkPixbuf * pixbuf16;
1515 GdkPixbuf * pixbuf32;
1516 GdkPixbuf * pixbuf48;
1517 GdkPixbuf * pixbuf64;
1520 if(icon16_xpm != NULL) {
1521 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1523 icon_list = g_list_append(icon_list, pixbuf16);
1526 if(icon32_xpm != NULL) {
1527 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1529 icon_list = g_list_append(icon_list, pixbuf32);
1532 if(icon48_xpm != NULL) {
1533 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1535 icon_list = g_list_append(icon_list, pixbuf48);
1538 if(icon64_xpm != NULL) {
1539 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1541 icon_list = g_list_append(icon_list, pixbuf64);
1548 main_capture_set_main_window_title(capture_options *capture_opts)
1550 GString *title = g_string_new("");
1552 g_string_append(title, "Capturing ");
1553 if(capture_opts->iface) {
1554 g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
1556 g_string_append(title, "- Wireshark");
1558 set_main_window_name(title->str);
1559 g_string_free(title, TRUE);
1563 main_capture_cb_capture_prepared(capture_options *capture_opts)
1565 static GList *icon_list = NULL;
1567 main_capture_set_main_window_title(capture_opts);
1569 if(icon_list == NULL) {
1570 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1572 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1574 /* Disable menu items that make no sense if you're currently running
1576 set_menus_for_capture_in_progress(TRUE);
1577 set_capture_if_dialog_for_capture_in_progress(TRUE);
1579 /* Don't set up main window for a capture file. */
1580 main_set_for_capture_file(FALSE);
1584 main_capture_cb_capture_update_started(capture_options *capture_opts)
1586 /* We've done this in "prepared" above, but it will be cleared while
1587 switching to the next multiple file. */
1588 main_capture_set_main_window_title(capture_opts);
1590 set_menus_for_capture_in_progress(TRUE);
1591 set_capture_if_dialog_for_capture_in_progress(TRUE);
1593 /* Enable menu items that make sense if you have some captured
1594 packets (yes, I know, we don't have any *yet*). */
1595 set_menus_for_captured_packets(TRUE);
1597 /* Set up main window for a capture file. */
1598 main_set_for_capture_file(TRUE);
1602 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1604 capture_file *cf = capture_opts->cf;
1605 static GList *icon_list = NULL;
1607 set_display_filename(cf);
1609 /* Enable menu items that make sense if you're not currently running
1611 set_menus_for_capture_in_progress(FALSE);
1612 set_capture_if_dialog_for_capture_in_progress(FALSE);
1614 /* Enable menu items that make sense if you have a capture file
1615 you've finished reading. */
1616 set_menus_for_capture_file(cf);
1618 /* Set up main window for a capture file. */
1619 main_set_for_capture_file(TRUE);
1621 if(icon_list == NULL) {
1622 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1624 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1626 if(global_capture_opts.quit_after_cap) {
1627 /* command line asked us to quit after the capture */
1628 /* don't pop up a dialog to ask for unsaved files etc. */
1634 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1636 /* Don't set up main window for a capture file. */
1637 main_set_for_capture_file(FALSE);
1641 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1644 capture_file *cf = capture_opts->cf;
1646 static GList *icon_list = NULL;
1648 /*set_display_filename(cf);*/
1650 /* Enable menu items that make sense if you're not currently running
1652 set_menus_for_capture_in_progress(FALSE);
1653 set_capture_if_dialog_for_capture_in_progress(FALSE);
1655 /* Restore the standard title bar message */
1656 /* (just in case we have trouble opening the capture file). */
1657 set_main_window_name("The Wireshark Network Analyzer");
1659 if(icon_list == NULL) {
1660 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1662 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1664 /* We don't have loaded the capture file, this will be done later.
1665 * For now we still have simply a blank screen. */
1667 if(global_capture_opts.quit_after_cap) {
1668 /* command line asked us to quit after the capture */
1669 /* don't pop up a dialog to ask for unsaved files etc. */
1674 #endif /* HAVE_LIBPCAP */
1677 main_cf_cb_packet_selected(gpointer data)
1679 capture_file *cf = data;
1681 /* Display the GUI protocol tree and packet bytes.
1682 XXX - why do we dump core if we call "proto_tree_draw()"
1683 before calling "add_byte_views()"? */
1684 add_main_byte_views(cf->edt);
1685 main_proto_tree_draw(cf->edt->tree);
1687 /* The user is searching for a string in the data or a hex value,
1688 * highlight the field that is found in the tree and hex displays. */
1689 if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1690 highlight_field(cf->edt->tvb, cfile.search_pos,
1691 (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1692 cfile.search_pos = 0; /* Reset the position */
1695 /* A packet is selected. */
1696 set_menus_for_selected_packet(cf);
1700 main_cf_cb_packet_unselected(capture_file *cf)
1702 /* Clear out the display of that packet. */
1703 clear_tree_and_hex_views();
1705 /* No packet is selected. */
1706 set_menus_for_selected_packet(cf);
1710 main_cf_cb_field_unselected(capture_file *cf)
1712 set_menus_for_selected_tree_row(cf);
1716 main_cf_cb_file_save_reload_finished(gpointer data _U_)
1718 set_display_filename(&cfile);
1719 set_menus_for_capture_file(&cfile);
1723 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1726 case(cf_cb_file_closing):
1727 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1728 main_cf_cb_file_closing(data);
1730 case(cf_cb_file_closed):
1731 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1732 main_cf_cb_file_closed(data);
1734 case(cf_cb_file_read_started):
1735 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1736 main_cf_cb_file_read_started(data);
1738 case(cf_cb_file_read_finished):
1739 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1740 main_cf_cb_file_read_finished(data);
1742 case(cf_cb_packet_selected):
1743 main_cf_cb_packet_selected(data);
1745 case(cf_cb_packet_unselected):
1746 main_cf_cb_packet_unselected(data);
1748 case(cf_cb_field_unselected):
1749 main_cf_cb_field_unselected(data);
1751 case(cf_cb_file_save_started):
1752 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1754 case(cf_cb_file_save_finished):
1755 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1757 case(cf_cb_file_save_reload_finished):
1758 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1759 main_cf_cb_file_save_reload_finished(data);
1761 case(cf_cb_file_save_failed):
1762 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1765 g_warning("main_cf_callback: event %u unknown", event);
1766 g_assert_not_reached();
1772 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1774 #ifdef HAVE_GTKOSXAPPLICATION
1775 GtkOSXApplication *theApp;
1778 case(capture_cb_capture_prepared):
1779 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1780 main_capture_cb_capture_prepared(capture_opts);
1782 case(capture_cb_capture_update_started):
1783 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1784 main_capture_cb_capture_update_started(capture_opts);
1785 #ifdef HAVE_GTKOSXAPPLICATION
1786 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1787 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsiconcap48_xpm));
1790 case(capture_cb_capture_update_continue):
1791 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1793 case(capture_cb_capture_update_finished):
1794 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1795 main_capture_cb_capture_update_finished(capture_opts);
1797 case(capture_cb_capture_fixed_started):
1798 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1799 main_capture_cb_capture_fixed_started(capture_opts);
1801 case(capture_cb_capture_fixed_continue):
1802 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1804 case(capture_cb_capture_fixed_finished):
1805 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1806 main_capture_cb_capture_fixed_finished(capture_opts);
1808 case(capture_cb_capture_stopping):
1809 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1810 /* Beware: this state won't be called, if the capture child
1811 * closes the capturing on it's own! */
1812 #ifdef HAVE_GTKOSXAPPLICATION
1813 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1814 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
1818 g_warning("main_capture_callback: event %u unknown", event);
1819 g_assert_not_reached();
1825 get_gui_compiled_info(GString *str)
1827 get_epan_compiled_version_info(str);
1829 g_string_append(str, ", ");
1830 #ifdef HAVE_LIBPORTAUDIO
1831 #ifdef PORTAUDIO_API_1
1832 g_string_append(str, "with PortAudio <= V18");
1833 #else /* PORTAUDIO_API_1 */
1834 g_string_append(str, "with ");
1835 g_string_append(str, Pa_GetVersionText());
1836 #endif /* PORTAUDIO_API_1 */
1837 #else /* HAVE_LIBPORTAUDIO */
1838 g_string_append(str, "without PortAudio");
1839 #endif /* HAVE_LIBPORTAUDIO */
1841 g_string_append(str, ", ");
1843 get_compiled_airpcap_version(str);
1845 g_string_append(str, "without AirPcap");
1847 #ifdef NEW_PACKET_LIST
1848 g_string_append(str, ", with new_packet_list");
1853 get_gui_runtime_info(GString *str)
1856 g_string_append(str, ", ");
1857 get_runtime_airpcap_version(str);
1861 g_string_append(str, ", ");
1862 u3_runtime_info(str);
1868 read_configuration_files(char **gdp_path, char **dp_path)
1870 int gpf_open_errno, gpf_read_errno;
1871 int cf_open_errno, df_open_errno;
1872 int gdp_open_errno, gdp_read_errno;
1873 int dp_open_errno, dp_read_errno;
1874 char *gpf_path, *pf_path;
1875 char *cf_path, *df_path;
1876 int pf_open_errno, pf_read_errno;
1879 /* Read the preference files. */
1880 prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1881 &pf_open_errno, &pf_read_errno, &pf_path);
1883 if (gpf_path != NULL) {
1884 if (gpf_open_errno != 0) {
1885 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1886 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1887 strerror(gpf_open_errno));
1889 if (gpf_read_errno != 0) {
1890 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1891 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1892 strerror(gpf_read_errno));
1895 if (pf_path != NULL) {
1896 if (pf_open_errno != 0) {
1897 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1898 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1899 strerror(pf_open_errno));
1901 if (pf_read_errno != 0) {
1902 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1903 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1904 strerror(pf_read_errno));
1911 /* if the user wants a console to be always there, well, we should open one for him */
1912 if (prefs_p->gui_console_open == console_open_always) {
1917 /* Read the capture filter file. */
1918 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1919 if (cf_path != NULL) {
1920 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1921 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1922 strerror(cf_open_errno));
1926 /* Read the display filter file. */
1927 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1928 if (df_path != NULL) {
1929 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1930 "Could not open your display filter file\n\"%s\": %s.", df_path,
1931 strerror(df_open_errno));
1935 /* Read the disabled protocols file. */
1936 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1937 dp_path, &dp_open_errno, &dp_read_errno);
1938 if (*gdp_path != NULL) {
1939 if (gdp_open_errno != 0) {
1940 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1941 "Could not open global disabled protocols file\n\"%s\": %s.",
1942 *gdp_path, strerror(gdp_open_errno));
1944 if (gdp_read_errno != 0) {
1945 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1946 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1947 *gdp_path, strerror(gdp_read_errno));
1952 if (*dp_path != NULL) {
1953 if (dp_open_errno != 0) {
1954 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1955 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1956 strerror(dp_open_errno));
1958 if (dp_read_errno != 0) {
1959 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1960 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1961 strerror(dp_read_errno));
1970 /* Check if there's something important to tell the user during startup.
1971 * We want to do this *after* showing the main window so that any windows
1972 * we pop up will be above the main window.
1976 check_and_warn_user_startup(gchar *cf_name)
1978 check_and_warn_user_startup(gchar *cf_name _U_)
1981 gchar *cur_user, *cur_group;
1982 gpointer priv_warning_dialog;
1984 /* Tell the user not to run as root. */
1985 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
1986 cur_user = get_cur_username();
1987 cur_group = get_cur_groupname();
1988 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1989 "Running as user \"%s\" and group \"%s\".\n"
1990 "This could be dangerous.", cur_user, cur_group);
1993 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
1994 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
1998 /* Warn the user if npf.sys isn't loaded. */
1999 if (!stdin_capture && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
2000 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2001 "The NPF driver isn't running. You may have trouble\n"
2002 "capturing or listing interfaces.");
2003 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2004 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
2011 /* And now our feature presentation... [ fade to music ] */
2013 main(int argc, char *argv[])
2015 char *init_progfile_dir_error;
2018 gboolean arg_error = FALSE;
2020 extern int info_update_freq; /* Found in about_dlg.c. */
2021 const gchar *filter;
2029 char *gdp_path, *dp_path;
2032 gboolean start_capture = FALSE;
2033 gboolean list_link_layer_types = FALSE;
2037 gboolean capture_option_specified = FALSE;
2044 gint pl_size = 280, tv_size = 95, bv_size = 75;
2045 gchar *rc_file, *cf_name = NULL, *rfilter = NULL, *jfilter = NULL;
2046 dfilter_t *rfcode = NULL;
2047 gboolean rfilter_parse_failed = FALSE;
2050 GtkWidget *splash_win = NULL;
2051 GLogLevelFlags log_flags;
2052 guint go_to_packet = 0;
2053 gboolean jump_backwards = FALSE, saved_bw = FALSE;
2054 dfilter_t *jump_to_filter = NULL;
2057 #ifdef HAVE_GTKOSXAPPLICATION
2058 GtkOSXApplication *theApp;
2062 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2063 #define OPTSTRING_B "B:"
2065 #define OPTSTRING_B ""
2066 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2067 #else /* HAVE_LIBPCAP */
2068 #define OPTSTRING_B ""
2069 #endif /* HAVE_LIBPCAP */
2071 #ifdef HAVE_PCAP_CREATE
2072 #define OPTSTRING_I "I"
2074 #define OPTSTRING_I ""
2077 #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:"
2079 static const char optstring[] = OPTSTRING;
2082 * Get credential information for later use, and drop privileges
2083 * before doing anything else.
2084 * Let the user know if anything happened.
2086 get_credential_info();
2087 relinquish_special_privs_perm();
2090 * Attempt to get the pathname of the executable file.
2092 init_progfile_dir_error = init_progfile_dir(argv[0], main);
2094 /* initialize the funnel mini-api */
2095 initialize_funnel_ops();
2097 #ifdef HAVE_AIRPDCAP
2098 AirPDcapInitContext(&airpdcap_ctx);
2102 /* Load wpcap if possible. Do this before collecting the run-time version information */
2105 /* ... and also load the packet.dll from wpcap */
2106 wpcap_packet_load();
2109 /* Load the airpcap.dll. This must also be done before collecting
2110 * run-time version information. */
2111 airpcap_dll_ret_val = load_airpcap();
2113 switch (airpcap_dll_ret_val) {
2114 case AIRPCAP_DLL_OK:
2115 /* load the airpcap interfaces */
2116 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2118 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2119 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2120 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2123 airpcap_if_active = NULL;
2127 /* select the first ad default (THIS SHOULD BE CHANGED) */
2128 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2133 * XXX - Maybe we need to warn the user if one of the following happens???
2135 case AIRPCAP_DLL_OLD:
2136 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2139 case AIRPCAP_DLL_ERROR:
2140 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2143 case AIRPCAP_DLL_NOT_FOUND:
2144 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2148 #endif /* HAVE_AIRPCAP */
2150 /* Start windows sockets */
2151 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2154 profile_store_persconffiles (TRUE);
2156 /* Assemble the compile-time version information string */
2157 comp_info_str = g_string_new("Compiled ");
2159 g_string_append(comp_info_str, "with ");
2160 g_string_append_printf(comp_info_str,
2161 #ifdef GTK_MAJOR_VERSION
2162 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
2165 "GTK+ (version unknown)");
2167 g_string_append(comp_info_str, ", ");
2169 get_compiled_version_info(comp_info_str, get_gui_compiled_info);
2171 /* Assemble the run-time version information string */
2172 runtime_info_str = g_string_new("Running ");
2173 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2175 /* Read the profile independent recent file. We have to do this here so we can */
2176 /* set the profile before it can be set from the command line parameterts */
2177 recent_read_static(&rf_path, &rf_open_errno);
2178 if (rf_path != NULL && rf_open_errno != 0) {
2179 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2180 "Could not open common recent file\n\"%s\": %s.",
2181 rf_path, strerror(rf_open_errno));
2184 /* "pre-scan" the command line parameters, if we have "console only"
2185 parameters. We do this so we don't start GTK+ if we're only showing
2186 command-line help or version information.
2188 XXX - this pre-scan is done before we start GTK+, so we haven't
2189 run gtk_init() on the arguments. That means that GTK+ arguments
2190 have not been removed from the argument list; those arguments
2191 begin with "--", and will be treated as an error by getopt().
2193 We thus ignore errors - *and* set "opterr" to 0 to suppress the
2196 optind_initial = optind;
2197 while ((opt = getopt(argc, argv, optstring)) != -1) {
2199 case 'C': /* Configuration Profile */
2200 if (profile_exists (optarg)) {
2201 set_profile_name (optarg);
2203 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2207 case 'h': /* Print help and exit */
2213 if (strcmp(optarg, "-") == 0)
2214 stdin_capture = TRUE;
2217 case 'P': /* Path settings - change these before the Preferences and alike are processed */
2218 status = filesystem_opt(opt, optarg);
2220 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2224 case 'v': /* Show version and exit */
2230 * Extension command line options have to be processed before
2231 * we call epan_init() as they are supposed to be used by dissectors
2232 * or taps very early in the registration process.
2236 case '?': /* Ignore errors - the "real" scan will catch them. */
2241 /* Init the "Open file" dialog directory */
2242 /* (do this after the path settings are processed) */
2243 set_last_open_dir(get_persdatafile_dir());
2245 /* Set getopt index back to initial value, so it will start with the
2246 first command line parameter again. Also reset opterr to 1, so that
2247 error messages are printed by getopt().
2249 XXX - this seems to work on most platforms, but time will tell.
2250 The Single UNIX Specification says "The getopt() function need
2251 not be reentrant", so this isn't guaranteed to work. The Mac
2252 OS X 10.4[.x] getopt() man page says
2254 In order to use getopt() to evaluate multiple sets of arguments, or to
2255 evaluate a single set of arguments multiple times, the variable optreset
2256 must be set to 1 before the second and each additional set of calls to
2257 getopt(), and the variable optind must be reinitialized.
2261 The optreset variable was added to make it possible to call the getopt()
2262 function multiple times. This is an extension to the IEEE Std 1003.2
2263 (``POSIX.2'') specification.
2265 which I think comes from one of the other BSDs.
2267 XXX - if we want to control all the command-line option errors, so
2268 that we can display them where we choose (e.g., in a window), we'd
2269 want to leave opterr as 0, and produce our own messages using optopt.
2270 We'd have to check the value of optopt to see if it's a valid option
2271 letter, in which case *presumably* the error is "this option requires
2272 an argument but none was specified", or not a valid option letter,
2273 in which case *presumably* the error is "this option isn't valid".
2274 Some versions of getopt() let you supply a option string beginning
2275 with ':', which means that getopt() will return ':' rather than '?'
2276 for "this option requires an argument but none was specified", but
2278 optind = optind_initial;
2281 /* Set the current locale according to the program environment.
2282 * We haven't localized anything, but some GTK widgets are localized
2283 * (the file selection dialogue, for example).
2284 * This also sets the C-language locale to the native environment. */
2287 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2288 gtk_init (&argc, &argv);
2290 cf_callback_add(main_cf_callback, NULL);
2292 capture_callback_add(main_capture_callback, NULL);
2294 cf_callback_add(statusbar_cf_callback, NULL);
2296 capture_callback_add(statusbar_capture_callback, NULL);
2299 /* Arrange that if we have no console window, and a GLib message logging
2300 routine is called to log a message, we pop up a console window.
2302 We do that by inserting our own handler for all messages logged
2303 to the default domain; that handler pops up a console if necessary,
2304 and then calls the default handler. */
2306 /* We might want to have component specific log levels later ... */
2310 G_LOG_LEVEL_CRITICAL|
2311 G_LOG_LEVEL_WARNING|
2312 G_LOG_LEVEL_MESSAGE|
2315 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2317 g_log_set_handler(NULL,
2319 console_log_handler, NULL /* user_data */);
2320 g_log_set_handler(LOG_DOMAIN_MAIN,
2322 console_log_handler, NULL /* user_data */);
2325 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2327 console_log_handler, NULL /* user_data */);
2328 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2330 console_log_handler, NULL /* user_data */);
2332 /* Set the initial values in the capture options. This might be overwritten
2333 by preference settings and then again by the command line parameters. */
2334 capture_opts_init(&global_capture_opts, &cfile);
2336 global_capture_opts.snaplen = MIN_PACKET_SIZE;
2337 global_capture_opts.has_ring_num_files = TRUE;
2340 /* Initialize whatever we need to allocate colors for GTK+ */
2343 /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2344 filter = get_conn_cfilter();
2345 if ( *filter != '\0' ) {
2346 info_update_freq = 1000; /* Milliseconds */
2349 /* We won't come till here, if we had a "console only" command line parameter. */
2350 splash_win = splash_new("Loading Wireshark ...");
2351 if (init_progfile_dir_error != NULL) {
2352 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2353 "Can't get pathname of Wireshark: %s.\n"
2354 "It won't be possible to capture traffic.\n"
2355 "Report this to the Wireshark developers.",
2356 init_progfile_dir_error);
2357 g_free(init_progfile_dir_error);
2360 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2362 /* Register all dissectors; we must do this before checking for the
2363 "-G" flag, as the "-G" flag dumps information registered by the
2364 dissectors, and we must do it before we read the preferences, in
2365 case any dissectors register preferences. */
2366 epan_init(register_all_protocols,register_all_protocol_handoffs,
2367 splash_update, (gpointer) splash_win,
2368 failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2369 write_failure_alert_box);
2371 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2373 /* Register all tap listeners; we do this before we parse the arguments,
2374 as the "-z" argument can specify a registered tap. */
2376 /* we register the plugin taps before the other taps because
2377 stats_tree taps plugins will be registered as tap listeners
2378 by stats_tree_stat.c and need to registered before that */
2381 register_all_plugin_tap_listeners();
2384 register_all_tap_listeners();
2386 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2388 /* Now register the preferences for any non-dissector modules.
2389 We must do that before we read the preferences as well. */
2390 prefs_register_modules();
2392 prefs_p = read_configuration_files (&gdp_path, &dp_path);
2394 /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2395 #if !defined(_WIN32) && defined(G_THREADS_ENABLED) && defined USE_THREADS
2398 g_thread_init(NULL);
2400 ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2401 g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2403 #else /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2404 /* this is to keep tap extensions updating once every 3 seconds */
2405 tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2406 #endif /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2408 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2411 /* Read the profile dependent (static part) of the recent file. */
2412 /* Only the static part of it will be read, as we don't have the gui now to fill the */
2413 /* recent lists which is done in the dynamic part. */
2414 /* We have to do this already here, so command line parameters can overwrite these values. */
2415 recent_read_profile_static(&rf_path, &rf_open_errno);
2416 if (rf_path != NULL && rf_open_errno != 0) {
2417 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2418 "Could not open recent file\n\"%s\": %s.",
2419 rf_path, strerror(rf_open_errno));
2422 cap_file_init(&cfile);
2424 /* Fill in capture options with values from the preferences */
2425 prefs_to_capture_opts();
2427 /* Now get our args */
2428 while ((opt = getopt(argc, argv, optstring)) != -1) {
2430 /*** capture option specific ***/
2431 case 'a': /* autostop criteria */
2432 case 'b': /* Ringbuffer option */
2433 case 'c': /* Capture xxx packets */
2434 case 'f': /* capture filter */
2435 case 'k': /* Start capture immediately */
2436 case 'H': /* Hide capture info dialog box */
2437 case 'i': /* Use interface xxx */
2438 case 'p': /* Don't capture in promiscuous mode */
2439 #ifdef HAVE_PCAP_CREATE
2440 case 'I': /* Capture in monitor mode, if available */
2442 case 'Q': /* Quit after capture (just capture to file) */
2443 case 's': /* Set the snapshot (capture) length */
2444 case 'S': /* "Sync" mode: used for following file ala tail -f */
2445 case 'w': /* Write to capture file xxx */
2446 case 'y': /* Set the pcap data link type */
2447 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2448 case 'B': /* Buffer size */
2449 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2451 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2457 capture_option_specified = TRUE;
2462 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2463 case 'K': /* Kerberos keytab file */
2464 read_keytab_file(optarg);
2468 /*** all non capture option specific ***/
2470 /* Configuration profile settings were already processed just ignore them this time*/
2472 case 'D': /* Print a list of capture devices and exit */
2474 if_list = capture_interface_list(&err, &err_str);
2475 if (if_list == NULL) {
2477 case CANT_GET_INTERFACE_LIST:
2478 cmdarg_err("%s", err_str);
2482 case NO_INTERFACES_FOUND:
2483 cmdarg_err("There are no interfaces on which a capture can be done");
2488 capture_opts_print_interfaces(if_list);
2489 free_interface_list(if_list);
2492 capture_option_specified = TRUE;
2496 case 'j': /* Search backwards for a matching packet from filter in option J */
2497 jump_backwards = TRUE;
2499 case 'g': /* Go to packet with the given packet number */
2500 go_to_packet = get_positive_int(optarg, "go to packet");
2502 case 'J': /* Jump to the first packet which matches the filter criteria */
2505 case 'l': /* Automatic scrolling in live capture mode */
2507 auto_scroll_live = TRUE;
2509 capture_option_specified = TRUE;
2513 case 'L': /* Print list of link-layer types and exit */
2515 list_link_layer_types = TRUE;
2517 capture_option_specified = TRUE;
2521 case 'm': /* Fixed-width font for the display */
2522 g_free(prefs_p->gui_font_name);
2523 prefs_p->gui_font_name = g_strdup(optarg);
2525 case 'n': /* No name resolution */
2526 g_resolv_flags = RESOLV_NONE;
2528 case 'N': /* Select what types of addresses/port #s to resolve */
2529 if (g_resolv_flags == RESOLV_ALL)
2530 g_resolv_flags = RESOLV_NONE;
2531 badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2532 if (badopt != '\0') {
2533 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2538 case 'o': /* Override preference from command line */
2539 switch (prefs_set_pref(optarg)) {
2542 case PREFS_SET_SYNTAX_ERR:
2543 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2546 case PREFS_SET_NO_SUCH_PREF:
2547 /* not a preference, might be a recent setting */
2548 switch (recent_set_arg(optarg)) {
2551 case PREFS_SET_SYNTAX_ERR:
2552 /* shouldn't happen, checked already above */
2553 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2556 case PREFS_SET_NO_SUCH_PREF:
2557 case PREFS_SET_OBSOLETE:
2558 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2563 g_assert_not_reached();
2566 case PREFS_SET_OBSOLETE:
2567 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2572 g_assert_not_reached();
2576 /* Path settings were already processed just ignore them this time*/
2578 case 'r': /* Read capture file xxx */
2579 /* We may set "last_open_dir" to "cf_name", and if we change
2580 "last_open_dir" later, we free the old value, so we have to
2581 set "cf_name" to something that's been allocated. */
2582 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2583 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2584 cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2586 cf_name = g_strdup(optarg);
2589 case 'R': /* Read file filter */
2592 case 't': /* Time stamp type */
2593 if (strcmp(optarg, "r") == 0)
2594 timestamp_set_type(TS_RELATIVE);
2595 else if (strcmp(optarg, "a") == 0)
2596 timestamp_set_type(TS_ABSOLUTE);
2597 else if (strcmp(optarg, "ad") == 0)
2598 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2599 else if (strcmp(optarg, "d") == 0)
2600 timestamp_set_type(TS_DELTA);
2601 else if (strcmp(optarg, "dd") == 0)
2602 timestamp_set_type(TS_DELTA_DIS);
2603 else if (strcmp(optarg, "e") == 0)
2604 timestamp_set_type(TS_EPOCH);
2606 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2607 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2608 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2612 case 'u': /* Seconds type */
2613 if (strcmp(optarg, "s") == 0)
2614 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
2615 else if (strcmp(optarg, "hms") == 0)
2616 timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
2618 cmdarg_err("Invalid seconds type \"%s\"", optarg);
2619 cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
2624 /* ext ops were already processed just ignore them this time*/
2627 /* We won't call the init function for the stat this soon
2628 as it would disallow MATE's fields (which are registered
2629 by the preferences set callback) from being used as
2630 part of a tap filter. Instead, we just add the argument
2631 to a list of stat arguments. */
2632 if (!process_stat_cmd_arg(optarg)) {
2633 cmdarg_err("Invalid -z argument.");
2634 cmdarg_err_cont(" -z argument must be one of :");
2635 list_stat_cmd_args();
2640 case '?': /* Bad flag - print usage message */
2648 if (cf_name != NULL) {
2650 * Input file name specified with "-r" *and* specified as a regular
2651 * command-line argument.
2653 cmdarg_err("File name specified both with -r and regular argument");
2657 * Input file name not specified with "-r", and a command-line argument
2658 * was specified; treat it as the input file name.
2660 * Yes, this is different from tshark, where non-flag command-line
2661 * arguments are a filter, but this works better on GUI desktops
2662 * where a command can be specified to be run to open a particular
2663 * file - yes, you could have "-r" as the last part of the command,
2664 * but that's a bit ugly.
2666 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2667 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2668 cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2670 cf_name = g_strdup(argv[0]);
2681 * Extra command line arguments were specified; complain.
2683 cmdarg_err("Invalid argument: %s", argv[0]);
2688 #ifndef HAVE_LIBPCAP
2689 if (capture_option_specified) {
2690 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2698 if (start_capture && list_link_layer_types) {
2699 /* Specifying *both* is bogus. */
2700 cmdarg_err("You can't specify both -L and a live capture.");
2704 if (list_link_layer_types) {
2705 /* We're supposed to list the link-layer types for an interface;
2706 did the user also specify a capture file to be read? */
2708 /* Yes - that's bogus. */
2709 cmdarg_err("You can't specify -L and a capture file to be read.");
2712 /* No - did they specify a ring buffer option? */
2713 if (global_capture_opts.multi_files_on) {
2714 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2718 /* We're supposed to do a live capture; did the user also specify
2719 a capture file to be read? */
2720 if (start_capture && cf_name) {
2721 /* Yes - that's bogus. */
2722 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2726 /* No - was the ring buffer option specified and, if so, does it make
2728 if (global_capture_opts.multi_files_on) {
2729 /* Ring buffer works only under certain conditions:
2730 a) ring buffer does not work with temporary files;
2731 b) real_time_mode and multi_files_on are mutually exclusive -
2732 real_time_mode takes precedence;
2733 c) it makes no sense to enable the ring buffer if the maximum
2734 file size is set to "infinite". */
2735 if (global_capture_opts.save_file == NULL) {
2736 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2737 global_capture_opts.multi_files_on = FALSE;
2739 /* if (global_capture_opts.real_time_mode) {
2740 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2741 global_capture_opts.multi_files_on = FALSE;
2743 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2744 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2745 /* XXX - this must be redesigned as the conditions changed */
2746 /* global_capture_opts.multi_files_on = FALSE;*/
2751 if (start_capture || list_link_layer_types) {
2752 /* Did the user specify an interface to use? */
2753 if (!capture_opts_trim_iface(&global_capture_opts,
2754 (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
2759 if (list_link_layer_types) {
2760 /* Get the list of link-layer types for the capture device. */
2761 if_capabilities_t *caps;
2763 caps = capture_get_if_capabilities(global_capture_opts.iface,
2764 global_capture_opts.monitor_mode,
2767 cmdarg_err("%s", err_str);
2771 if (caps->data_link_types == NULL) {
2772 cmdarg_err("The capture device \"%s\" has no data link types.", global_capture_opts.iface);
2775 capture_opts_print_if_capabilities(caps, global_capture_opts.monitor_mode);
2776 free_if_capabilities(caps);
2780 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2781 capture_opts_trim_ring_num_files(&global_capture_opts);
2782 #endif /* HAVE_LIBPCAP */
2784 /* Notify all registered modules that have had any of their preferences
2785 changed either from one of the preferences file or from the command
2786 line that their preferences have changed. */
2789 /* disabled protocols as per configuration file */
2790 if (gdp_path == NULL && dp_path == NULL) {
2791 set_disabled_protos_list();
2794 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2796 /* read in rc file from global and personal configuration paths. */
2797 rc_file = get_datafile_path(RC_FILE);
2798 gtk_rc_parse(rc_file);
2800 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2801 gtk_rc_parse(rc_file);
2808 /* close the splash screen, as we are going to open the main window now */
2809 splash_destroy(splash_win);
2811 /************************************************************************/
2812 /* Everything is prepared now, preferences and command line was read in */
2814 /* Pop up the main window. */
2815 create_main_window(pl_size, tv_size, bv_size, prefs_p);
2817 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2818 recent_read_dynamic(&rf_path, &rf_open_errno);
2819 if (rf_path != NULL && rf_open_errno != 0) {
2820 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2821 "Could not open recent file\n\"%s\": %s.",
2822 rf_path, strerror(rf_open_errno));
2825 color_filters_enable(recent.packet_list_colorize);
2827 /* rearrange all the widgets as we now have all recent settings ready for this */
2828 main_widgets_rearrange();
2830 /* Fill in column titles. This must be done after the top level window
2833 XXX - is that still true, with fixed-width columns? */
2834 #ifndef NEW_PACKET_LIST
2835 packet_list_set_column_titles();
2838 menu_recent_read_finished();
2840 menu_auto_scroll_live_changed(auto_scroll_live);
2843 switch (user_font_apply()) {
2846 case FA_FONT_NOT_RESIZEABLE:
2847 /* "user_font_apply()" popped up an alert box. */
2848 /* turn off zooming - font can't be resized */
2849 case FA_FONT_NOT_AVAILABLE:
2850 /* XXX - did we successfully load the un-zoomed version earlier?
2851 If so, this *probably* means the font is available, but not at
2852 this particular zoom level, but perhaps some other failure
2853 occurred; I'm not sure you can determine which is the case,
2855 /* turn off zooming - zoom level is unavailable */
2857 /* in any other case than FA_SUCCESS, turn off zooming */
2858 recent.gui_zoom_level = 0;
2859 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2862 dnd_init(top_level);
2864 color_filters_init();
2867 /* the window can be sized only, if it's not already shown, so do it now! */
2868 main_load_window_geometry(top_level);
2870 g_timeout_add(info_update_freq, resolv_update_cb, NULL);
2873 /* If we were given the name of a capture file, read it in now;
2874 we defer it until now, so that, if we can't open it, and pop
2875 up an alert box, the alert box is more likely to come up on
2876 top of the main window - but before the preference-file-error
2877 alert box, so, if we get one of those, it's more likely to come
2880 show_main_window(TRUE);
2881 check_and_warn_user_startup(cf_name);
2882 if (rfilter != NULL) {
2883 if (!dfilter_compile(rfilter, &rfcode)) {
2884 bad_dfilter_alert_box(rfilter);
2885 rfilter_parse_failed = TRUE;
2888 if (!rfilter_parse_failed) {
2889 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2890 /* "cf_open()" succeeded, so it closed the previous
2891 capture file, and thus destroyed any previous read filter
2892 attached to "cf". */
2894 cfile.rfcode = rfcode;
2895 /* Open stat windows; we do so after creating the main window,
2896 to avoid GTK warnings, and after successfully opening the
2897 capture file, so we know we have something to compute stats
2898 on, and after registering all dissectors, so that MATE will
2899 have registered its field array and we can have a tap filter
2900 with one of MATE's late-registered fields as part of the
2902 start_requested_stats();
2904 /* Read the capture file. */
2905 switch (cf_read(&cfile, FALSE)) {
2909 /* Just because we got an error, that doesn't mean we were unable
2910 to read any of the file; we handle what we could get from the
2912 /* if the user told us to jump to a specific packet, do it now */
2913 if(go_to_packet != 0) {
2914 /* Jump to the specified frame number, kept for backward
2916 cf_goto_frame(&cfile, go_to_packet);
2917 } else if (jfilter != NULL) {
2918 /* try to compile given filter */
2919 if (!dfilter_compile(jfilter, &jump_to_filter)) {
2920 bad_dfilter_alert_box(jfilter);
2923 /* Filter ok, jump to the first packet matching the filter
2924 conditions. Default search direction is forward, but if
2925 option d was given, search backwards */
2926 saved_bw = cfile.sbackward;
2927 cfile.sbackward = jump_backwards;
2928 cf_find_packet_dfilter(&cfile, jump_to_filter);
2929 cfile.sbackward = saved_bw;
2934 case CF_READ_ABORTED:
2939 /* Save the name of the containing directory specified in the
2940 path name, if any; we can write over cf_name, which is a
2941 good thing, given that "get_dirname()" does write over its
2943 s = get_dirname(cf_name);
2944 set_last_open_dir(s);
2949 dfilter_free(rfcode);
2950 cfile.rfcode = NULL;
2951 show_main_window(FALSE);
2952 /* Don't call check_and_warn_user_startup(): we did it above */
2953 set_menus_for_capture_in_progress(FALSE);
2954 set_capture_if_dialog_for_capture_in_progress(FALSE);
2959 if (start_capture) {
2960 if (global_capture_opts.save_file != NULL) {
2961 /* Save the directory name for future file dialogs. */
2962 /* (get_dirname overwrites filename) */
2963 s = get_dirname(g_strdup(global_capture_opts.save_file));
2964 set_last_open_dir(s);
2967 /* "-k" was specified; start a capture. */
2968 show_main_window(TRUE);
2969 check_and_warn_user_startup(cf_name);
2970 if (capture_start(&global_capture_opts)) {
2971 /* The capture started. Open stat windows; we do so after creating
2972 the main window, to avoid GTK warnings, and after successfully
2973 opening the capture file, so we know we have something to compute
2974 stats on, and after registering all dissectors, so that MATE will
2975 have registered its field array and we can have a tap filter with
2976 one of MATE's late-registered fields as part of the filter. */
2977 start_requested_stats();
2981 show_main_window(FALSE);
2982 check_and_warn_user_startup(cf_name);
2983 set_menus_for_capture_in_progress(FALSE);
2984 set_capture_if_dialog_for_capture_in_progress(FALSE);
2987 /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2988 if (!start_capture && strlen(global_capture_opts.cfilter) == 0) {
2989 g_free(global_capture_opts.cfilter);
2990 global_capture_opts.cfilter = g_strdup(get_conn_cfilter());
2992 #else /* HAVE_LIBPCAP */
2993 show_main_window(FALSE);
2994 check_and_warn_user_startup(cf_name);
2995 set_menus_for_capture_in_progress(FALSE);
2996 set_capture_if_dialog_for_capture_in_progress(FALSE);
2997 #endif /* HAVE_LIBPCAP */
3000 /* register our pid if we are being run from a U3 device */
3003 profile_store_persconffiles (FALSE);
3005 #ifdef HAVE_GTKOSXAPPLICATION
3006 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
3007 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
3008 gtk_osxapplication_ready(theApp);
3011 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
3013 /* we'll enter the GTK loop now and hand the control over to GTK ... */
3015 /* ... back from GTK, we're going down now! */
3017 /* deregister our pid */
3018 u3_deregister_pid();
3022 #ifdef HAVE_AIRPDCAP
3023 AirPDcapDestroyContext(&airpdcap_ctx);
3027 /* hide the (unresponsive) main window, while asking the user to close the console window */
3028 gtk_widget_hide(top_level);
3030 #ifdef HAVE_GTKOSXAPPLICATION
3031 g_object_unref(theApp);
3034 /* Shutdown windows sockets */
3037 /* For some unknown reason, the "atexit()" call in "create_console()"
3038 doesn't arrange that "destroy_console()" be called when we exit,
3039 so we call it here if a console was created. */
3048 /* We build this as a GUI subsystem application on Win32, so
3049 "WinMain()", not "main()", gets called.
3051 Hack shamelessly stolen from the Win32 port of the GIMP. */
3053 #define _stdcall __attribute__((stdcall))
3057 WinMain (struct HINSTANCE__ *hInstance,
3058 struct HINSTANCE__ *hPrevInstance,
3062 INITCOMMONCONTROLSEX comm_ctrl;
3064 /* Initialize our controls. Required for native Windows file dialogs. */
3065 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3066 comm_ctrl.dwSize = sizeof(comm_ctrl);
3067 /* Includes the animate, header, hot key, list view, progress bar,
3068 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3071 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3072 InitCommonControlsEx(&comm_ctrl);
3074 /* RichEd20.DLL is needed for filter entries. */
3075 LoadLibrary(_T("riched20.dll"));
3077 has_console = FALSE;
3078 return main (__argc, __argv);
3081 /* The code to create and desstroy console windows should not be necessary,
3082 at least as I read the GLib source code, as it looks as if GLib is, on
3083 Win32, *supposed* to create a console window into which to display its
3086 That doesn't happen, however. I suspect there's something completely
3087 broken about that code in GLib-for-Win32, and that it may be related
3088 to the breakage that forces us to just call "printf()" on the message
3089 rather than passing the message on to "g_log_default_handler()"
3090 (which is the routine that does the aforementioned non-functional
3091 console window creation). */
3094 * If this application has no console window to which its standard output
3095 * would go, create one.
3098 create_console(void)
3100 if (stdin_capture) {
3101 /* We've been handed "-i -". Don't mess with stdio. */
3106 /* We have no console to which to print the version string, so
3107 create one and make it the standard input, output, and error. */
3108 if (!AllocConsole())
3109 return; /* couldn't create console */
3111 ws_freopen("CONIN$", "r", stdin);
3112 ws_freopen("CONOUT$", "w", stdout);
3113 ws_freopen("CONOUT$", "w", stderr);
3115 /* Well, we have a console now. */
3118 /* Now register "destroy_console()" as a routine to be called just
3119 before the application exits, so that we can destroy the console
3120 after the user has typed a key (so that the console doesn't just
3121 disappear out from under them, giving the user no chance to see
3122 the message(s) we put in there). */
3123 atexit(destroy_console);
3125 SetConsoleTitle(_T("Wireshark Debug Console"));
3130 destroy_console(void)
3133 printf("\n\nPress any key to exit\n");
3142 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3143 const char *message, gpointer user_data _U_)
3150 /* ignore log message, if log_level isn't interesting based
3151 upon the console log preferences.
3152 If the preferences haven't been loaded loaded yet, display the
3155 The default console_log_level preference value is such that only
3156 ERROR, CRITICAL and WARNING level messages are processed;
3157 MESSAGE, INFO and DEBUG level messages are ignored. */
3158 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3159 prefs.console_log_level != 0) {
3164 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3165 /* the user wants a console or the application will terminate immediately */
3169 /* For some unknown reason, the above doesn't appear to actually cause
3170 anything to be sent to the standard output, so we'll just splat the
3171 message out directly, just to make sure it gets out. */
3173 switch(log_level & G_LOG_LEVEL_MASK) {
3174 case G_LOG_LEVEL_ERROR:
3177 case G_LOG_LEVEL_CRITICAL:
3180 case G_LOG_LEVEL_WARNING:
3183 case G_LOG_LEVEL_MESSAGE:
3186 case G_LOG_LEVEL_INFO:
3189 case G_LOG_LEVEL_DEBUG:
3193 fprintf(stderr, "unknown log_level %u\n", log_level);
3195 g_assert_not_reached();
3198 /* create a "timestamp" */
3200 today = localtime(&curr);
3202 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3203 today->tm_hour, today->tm_min, today->tm_sec,
3204 log_domain != NULL ? log_domain : "",
3207 if(log_level & G_LOG_LEVEL_ERROR) {
3208 /* wait for a key press before the following error handler will terminate the program
3209 this way the user at least can read the error message */
3210 printf("\n\nPress any key to exit\n");
3214 /* XXX - on UN*X, should we just use g_log_default_handler()?
3215 We want the error messages to go to the standard output;
3216 on Mac OS X, that will cause them to show up in various
3217 per-user logs accessible through Console (details depend
3218 on whether you're running 10.0 through 10.4 or running
3219 10.5 and later), and, on other UN*X desktop environments,
3220 if they don't show up in some form of console log, that's
3221 a deficiency in that desktop environment. (Too bad
3222 Windows doesn't set the standard output and error for
3223 GUI apps to something that shows up in such a log.) */
3224 g_log_default_handler(log_domain, log_level, message, user_data);
3231 * Helper for main_widgets_rearrange()
3233 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3234 gtk_container_remove(GTK_CONTAINER(data), widget);
3237 static GtkWidget *main_widget_layout(gint layout_content)
3239 switch(layout_content) {
3240 case(layout_pane_content_none):
3242 case(layout_pane_content_plist):
3244 case(layout_pane_content_pdetails):
3246 case(layout_pane_content_pbytes):
3247 return byte_nb_ptr_gbl;
3249 g_assert_not_reached();
3256 * Rearrange the main window widgets
3258 void main_widgets_rearrange(void) {
3259 GtkWidget *first_pane_widget1, *first_pane_widget2;
3260 GtkWidget *second_pane_widget1, *second_pane_widget2;
3261 gboolean split_top_left;
3263 /* be a bit faster */
3264 gtk_widget_hide(main_vbox);
3266 /* be sure we don't lose a widget while rearranging */
3267 g_object_ref(G_OBJECT(menubar));
3268 g_object_ref(G_OBJECT(main_tb));
3269 g_object_ref(G_OBJECT(filter_tb));
3271 g_object_ref(G_OBJECT(airpcap_tb));
3273 g_object_ref(G_OBJECT(pkt_scrollw));
3274 g_object_ref(G_OBJECT(tv_scrollw));
3275 g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3276 g_object_ref(G_OBJECT(statusbar));
3277 g_object_ref(G_OBJECT(main_pane_v1));
3278 g_object_ref(G_OBJECT(main_pane_v2));
3279 g_object_ref(G_OBJECT(main_pane_h1));
3280 g_object_ref(G_OBJECT(main_pane_h2));
3281 g_object_ref(G_OBJECT(welcome_pane));
3283 /* empty all containers participating */
3284 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
3285 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
3286 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
3287 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
3288 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
3290 statusbar_widgets_emptying(statusbar);
3292 /* add the menubar always at the top */
3293 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3296 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3298 /* filter toolbar in toolbar area */
3299 if (!prefs.filter_toolbar_show_in_statusbar) {
3300 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3304 /* airpcap toolbar */
3305 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3308 /* fill the main layout panes */
3309 switch(prefs.gui_layout_type) {
3310 case(layout_type_5):
3311 main_first_pane = main_pane_v1;
3312 main_second_pane = main_pane_v2;
3313 split_top_left = FALSE;
3315 case(layout_type_2):
3316 main_first_pane = main_pane_v1;
3317 main_second_pane = main_pane_h1;
3318 split_top_left = FALSE;
3320 case(layout_type_1):
3321 main_first_pane = main_pane_v1;
3322 main_second_pane = main_pane_h1;
3323 split_top_left = TRUE;
3325 case(layout_type_4):
3326 main_first_pane = main_pane_h1;
3327 main_second_pane = main_pane_v1;
3328 split_top_left = FALSE;
3330 case(layout_type_3):
3331 main_first_pane = main_pane_h1;
3332 main_second_pane = main_pane_v1;
3333 split_top_left = TRUE;
3335 case(layout_type_6):
3336 main_first_pane = main_pane_h1;
3337 main_second_pane = main_pane_h2;
3338 split_top_left = FALSE;
3341 main_first_pane = NULL;
3342 main_second_pane = NULL;
3343 split_top_left = FALSE;
3344 g_assert_not_reached();
3346 if (split_top_left) {
3347 first_pane_widget1 = main_second_pane;
3348 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3349 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3350 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3352 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3353 first_pane_widget2 = main_second_pane;
3354 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3355 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3357 if (first_pane_widget1 != NULL)
3358 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3359 if (first_pane_widget2 != NULL)
3360 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3361 if (second_pane_widget1 != NULL)
3362 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3363 if (second_pane_widget2 != NULL)
3364 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3366 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3369 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3372 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3374 /* filter toolbar in statusbar hbox */
3375 if (prefs.filter_toolbar_show_in_statusbar) {
3376 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3380 /* airpcap toolbar */
3381 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3384 /* statusbar widgets */
3385 statusbar_widgets_pack(statusbar);
3387 /* hide widgets on users recent settings */
3388 main_widgets_show_or_hide();
3390 gtk_widget_show(main_vbox);
3394 is_widget_visible(GtkWidget *widget, gpointer data)
3396 gboolean *is_visible = data;
3399 if (GTK_WIDGET_VISIBLE(widget))
3406 main_widgets_show_or_hide(void)
3408 gboolean main_second_pane_show;
3410 if (recent.main_toolbar_show) {
3411 gtk_widget_show(main_tb);
3413 gtk_widget_hide(main_tb);
3416 statusbar_widgets_show_or_hide(statusbar);
3418 if (recent.filter_toolbar_show) {
3419 gtk_widget_show(filter_tb);
3421 gtk_widget_hide(filter_tb);
3425 if (recent.airpcap_toolbar_show) {
3426 gtk_widget_show(airpcap_tb);
3428 gtk_widget_hide(airpcap_tb);
3432 if (recent.packet_list_show && have_capture_file) {
3433 gtk_widget_show(pkt_scrollw);
3435 gtk_widget_hide(pkt_scrollw);
3438 if (recent.tree_view_show && have_capture_file) {
3439 gtk_widget_show(tv_scrollw);
3441 gtk_widget_hide(tv_scrollw);
3444 if (recent.byte_view_show && have_capture_file) {
3445 gtk_widget_show(byte_nb_ptr_gbl);
3447 gtk_widget_hide(byte_nb_ptr_gbl);
3450 if (have_capture_file) {
3451 gtk_widget_show(main_first_pane);
3453 gtk_widget_hide(main_first_pane);
3457 * Is anything in "main_second_pane" visible?
3458 * If so, show it, otherwise hide it.
3460 main_second_pane_show = FALSE;
3461 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3462 &main_second_pane_show);
3463 if (main_second_pane_show) {
3464 gtk_widget_show(main_second_pane);
3466 gtk_widget_hide(main_second_pane);
3469 if (!have_capture_file) {
3471 gtk_widget_show(welcome_pane);
3474 gtk_widget_hide(welcome_pane);
3477 /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3478 #ifndef NEW_PACKET_LIST
3479 packet_list_freeze ();
3480 packet_list_thaw ();
3485 /* called, when the window state changes (minimized, maximized, ...) */
3487 window_state_event_cb (GtkWidget *widget _U_,
3491 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3493 if( (event->type) == (GDK_WINDOW_STATE)) {
3494 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3495 /* we might have dialogs popped up while we where iconified,
3497 display_queued_messages();
3505 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3507 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3509 if (event->keyval == GDK_F8) {
3510 #ifdef NEW_PACKET_LIST
3511 new_packet_list_next();
3516 } else if (event->keyval == GDK_F7) {
3517 #ifdef NEW_PACKET_LIST
3518 new_packet_list_prev();
3523 } else if (event->state & NO_SHIFT_MOD_MASK) {
3524 return FALSE; /* Skip control, alt, and other modifiers */
3526 * A comment in gdkkeysyms.h says that it's autogenerated from
3527 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3528 * don't explicitly say so, isprint() should work as expected
3531 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3532 /* Forward the keypress on to the display filter entry */
3533 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3534 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3535 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3543 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
3545 GtkAccelGroup *accel;
3548 /* use user-defined title if preference is set */
3549 title = create_user_window_title("The Wireshark Network Analyzer");
3552 top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
3555 gtk_widget_set_name(top_level, "main window");
3556 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3558 g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3559 G_CALLBACK(window_state_event_cb), NULL);
3560 g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3561 G_CALLBACK(top_level_key_pressed_cb), NULL );
3563 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3564 main_vbox = gtk_vbox_new(FALSE, 1);
3565 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
3566 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3567 gtk_widget_show(main_vbox);
3570 menubar = main_menu_new(&accel);
3572 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined (HAVE_GTKOSXAPPLICATION)
3573 /* Mac OS X native menus are created and displayed by main_menu_new() */
3574 if(!prefs_p->gui_macosx_style) {
3576 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3577 gtk_widget_show(menubar);
3578 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined(HAVE_GTKOSXAPPLICATION)
3583 main_tb = toolbar_new();
3584 gtk_widget_show (main_tb);
3586 /* Filter toolbar */
3587 filter_tb = filter_toolbar_new();
3590 #ifdef NEW_PACKET_LIST
3591 pkt_scrollw = new_packet_list_create();
3592 gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3593 gtk_widget_show_all(pkt_scrollw);
3595 pkt_scrollw = packet_list_new(prefs_p);
3596 gtk_widget_set_size_request(packet_list, -1, pl_size);
3597 gtk_widget_show(pkt_scrollw);
3601 tv_scrollw = main_tree_view_new(prefs_p, &tree_view_gbl);
3602 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3603 gtk_widget_show(tv_scrollw);
3605 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3606 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3607 g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3608 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3609 gtk_widget_show(tree_view_gbl);
3612 byte_nb_ptr_gbl = byte_view_new();
3613 gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3614 gtk_widget_show(byte_nb_ptr_gbl);
3616 g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3617 g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3619 /* Panes for the packet list, tree, and byte view */
3620 main_pane_v1 = gtk_vpaned_new();
3621 gtk_widget_show(main_pane_v1);
3622 main_pane_v2 = gtk_vpaned_new();
3623 gtk_widget_show(main_pane_v2);
3624 main_pane_h1 = gtk_hpaned_new();
3625 gtk_widget_show(main_pane_h1);
3626 main_pane_h2 = gtk_hpaned_new();
3627 gtk_widget_show(main_pane_h2);
3629 airpcap_tb = airpcap_toolbar_new();
3630 gtk_widget_show(airpcap_tb);
3633 statusbar = statusbar_new();
3634 gtk_widget_show(statusbar);
3636 /* Pane for the welcome screen */
3637 welcome_pane = welcome_new();
3638 gtk_widget_show(welcome_pane);
3642 show_main_window(gboolean doing_work)
3644 main_set_for_capture_file(doing_work);
3646 /*** we have finished all init things, show the main window ***/
3647 gtk_widget_show(top_level);
3649 /* the window can be maximized only, if it's visible, so do it after show! */
3650 main_load_window_geometry(top_level);
3652 /* process all pending GUI events before continue */
3653 while (gtk_events_pending()) gtk_main_iteration();
3655 /* Pop up any queued-up alert boxes. */
3656 display_queued_messages();
3658 /* Move the main window to the front, in case it isn't already there */
3659 gdk_window_raise(top_level->window);
3662 airpcap_toolbar_show(airpcap_tb);
3663 #endif /* HAVE_AIRPCAP */
3666 /* Fill in capture options with values from the preferences */
3668 prefs_to_capture_opts(void)
3671 /* Set promiscuous mode from the preferences setting. */
3672 /* the same applies to other preferences settings as well. */
3673 global_capture_opts.promisc_mode = prefs.capture_prom_mode;
3674 global_capture_opts.use_pcapng = prefs.capture_pcap_ng;
3675 global_capture_opts.show_info = prefs.capture_show_info;
3676 global_capture_opts.real_time_mode = prefs.capture_real_time;
3677 auto_scroll_live = prefs.capture_auto_scroll;
3678 #endif /* HAVE_LIBPCAP */
3680 /* Set the name resolution code's flags from the preferences. */
3681 g_resolv_flags = prefs.name_resolve;
3685 /* Change configuration profile */
3686 void change_configuration_profile (const gchar *profile_name)
3688 char *gdp_path, *dp_path;
3692 /* First check if profile exists */
3693 if (!profile_exists(profile_name)) {
3697 /* Get the current geometry, before writing it to disk */
3698 main_save_window_geometry(top_level);
3700 if (profile_exists(get_profile_name())) {
3701 /* Write recent file for profile we are leaving, if it still exists */
3702 write_profile_recent();
3705 /* Set profile name and update the status bar */
3706 set_profile_name (profile_name);
3707 profile_bar_update ();
3709 /* Reset current preferences and apply the new */
3713 (void) read_configuration_files (&gdp_path, &dp_path);
3715 recent_read_profile_static(&rf_path, &rf_open_errno);
3716 if (rf_path != NULL && rf_open_errno != 0) {
3717 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3718 "Could not open common recent file\n\"%s\": %s.",
3719 rf_path, strerror(rf_open_errno));
3721 timestamp_set_type (recent.gui_time_format);
3722 timestamp_set_seconds_type (recent.gui_seconds_format);
3723 color_filters_enable(recent.packet_list_colorize);
3725 prefs_to_capture_opts();
3728 /* Update window view and redraw the toolbar */
3729 update_main_window_name();
3730 toolbar_redraw_all();
3732 /* Enable all protocols and disable from the disabled list */
3734 if (gdp_path == NULL && dp_path == NULL) {
3735 set_disabled_protos_list();
3738 /* Reload color filters */
3739 color_filters_reload();
3741 /* Reload list of interfaces on welcome page */
3742 welcome_if_panel_reload();
3744 /* Recreate the packet list according to new preferences */
3745 #ifdef NEW_PACKET_LIST
3746 new_packet_list_recreate ();
3748 packet_list_recreate ();
3750 cfile.cinfo.columns_changed = FALSE; /* Reset value */
3753 /* Update menus with new recent values */
3754 menu_recent_read_finished();
3756 /* Reload pane geometry, must be done after recreating the list */
3757 main_pane_load_window_geometry();
3760 /** redissect packets and update UI */
3761 void redissect_packets(void)
3763 cf_redissect_packets(&cfile);
3764 status_expert_update();