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
45 #include "wsutil/strerror.h"
51 #include "wsutil/wsgetopt.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 <wsutil/unicode-utils.h>
121 #include <commctrl.h>
122 #include <shellapi.h>
126 #include "gtk/file_dlg.h"
127 #include "gtk/gtkglobals.h"
128 #include "gtk/color_utils.h"
129 #include "gtk/gui_utils.h"
130 #include "gtk/color_dlg.h"
131 #include "gtk/filter_dlg.h"
132 #include "gtk/uat_gui.h"
134 #include "gtk/main.h"
135 #include "gtk/main_airpcap_toolbar.h"
136 #include "gtk/main_filter_toolbar.h"
137 #include "gtk/menus.h"
138 #include "gtk/macros_dlg.h"
139 #include "gtk/main_packet_list.h"
140 #include "gtk/main_statusbar.h"
141 #include "gtk/main_statusbar_private.h"
142 #include "gtk/main_toolbar.h"
143 #include "gtk/main_welcome.h"
144 #include "gtk/drag_and_drop.h"
145 #include "gtk/capture_file_dlg.h"
146 #include "gtk/main_proto_draw.h"
147 #include "gtk/keys.h"
148 #include "gtk/packet_win.h"
149 #include "gtk/stock_icons.h"
150 #include "gtk/find_dlg.h"
151 #include "gtk/recent.h"
152 #include "gtk/follow_tcp.h"
153 #include "gtk/font_utils.h"
154 #include "gtk/about_dlg.h"
155 #include "gtk/help_dlg.h"
156 #include "gtk/decode_as_dlg.h"
157 #include "gtk/webbrowser.h"
158 #include "gtk/capture_dlg.h"
159 #include "gtk/capture_if_dlg.h"
160 #include "gtk/tap_dfilter_dlg.h"
161 #include "gtk/prefs_column.h"
162 #include "gtk/prefs_dlg.h"
163 #include "gtk/proto_help.h"
166 #include "../image/wsicon16.xpm"
167 #include "../image/wsicon32.xpm"
168 #include "../image/wsicon48.xpm"
169 #include "../image/wsicon64.xpm"
170 #include "../image/wsiconcap16.xpm"
171 #include "../image/wsiconcap32.xpm"
172 #include "../image/wsiconcap48.xpm"
177 #include "airpcap_loader.h"
178 #include "airpcap_dlg.h"
179 #include "airpcap_gui_utils.h"
183 #include <epan/crypt/airpdcap_ws.h>
186 #ifdef NEW_PACKET_LIST
187 #include "gtk/new_packet_list.h"
190 #ifdef HAVE_GTKOSXAPPLICATION
191 #include <igemacintegration/gtkosxapplication.h>
195 * Files under personal and global preferences directories in which
196 * GTK settings for Wireshark are stored.
198 #define RC_FILE "gtkrc"
202 /* "exported" main widgets */
203 GtkWidget *top_level = NULL, *pkt_scrollw, *tree_view_gbl, *byte_nb_ptr_gbl;
205 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
206 static GtkWidget *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
207 static GtkWidget *main_first_pane, *main_second_pane;
209 /* internally used widgets */
210 static GtkWidget *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
213 GtkWidget *airpcap_tb;
214 int airpcap_dll_ret_val = -1;
217 GString *comp_info_str, *runtime_info_str;
219 static gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
221 static guint tap_update_timer_id;
224 static gboolean has_console; /* TRUE if app has console */
225 static void destroy_console(void);
226 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
228 static void console_log_handler(const char *log_domain,
229 GLogLevelFlags log_level, const char *message, gpointer user_data);
232 capture_options global_capture_opts;
236 static void create_main_window(gint, gint, gint, e_prefs*);
237 static void show_main_window(gboolean);
238 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
239 static void main_save_window_geometry(GtkWidget *widget);
242 /* Match selected byte pattern */
244 match_selected_cb_do(gpointer data, int action, gchar *text)
246 GtkWidget *filter_te;
247 char *cur_filter, *new_filter;
249 if ((!text) || (0 == strlen(text))) {
250 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
255 filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
258 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
260 switch (action&MATCH_SELECTED_MASK) {
262 case MATCH_SELECTED_REPLACE:
263 new_filter = g_strdup(text);
266 case MATCH_SELECTED_AND:
267 if ((!cur_filter) || (0 == strlen(cur_filter)))
268 new_filter = g_strdup(text);
270 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
273 case MATCH_SELECTED_OR:
274 if ((!cur_filter) || (0 == strlen(cur_filter)))
275 new_filter = g_strdup(text);
277 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
280 case MATCH_SELECTED_NOT:
281 new_filter = g_strconcat("!(", text, ")", NULL);
284 case MATCH_SELECTED_AND_NOT:
285 if ((!cur_filter) || (0 == strlen(cur_filter)))
286 new_filter = g_strconcat("!(", text, ")", NULL);
288 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
291 case MATCH_SELECTED_OR_NOT:
292 if ((!cur_filter) || (0 == strlen(cur_filter)))
293 new_filter = g_strconcat("!(", text, ")", NULL);
295 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
299 g_assert_not_reached();
304 /* Free up the copy we got of the old filter text. */
307 /* Don't change the current display filter if we only want to copy the filter */
308 if (action&MATCH_SELECTED_COPY_ONLY) {
309 GString *gtk_text_str = g_string_new("");
310 g_string_append(gtk_text_str, new_filter);
311 copy_to_clipboard(gtk_text_str);
312 g_string_free(gtk_text_str, TRUE);
314 /* create a new one and set the display filter entry accordingly */
315 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
317 /* Run the display filter so it goes in effect. */
318 if (action&MATCH_SELECTED_APPLY_NOW)
319 main_filter_packets(&cfile, new_filter, FALSE);
322 /* Free up the new filter text. */
327 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
331 if (cfile.finfo_selected) {
332 filter = proto_construct_match_selected_string(cfile.finfo_selected,
334 match_selected_cb_do((data ? data : w), action, filter);
339 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
343 if (cfile.finfo_selected) {
344 filter = proto_construct_match_selected_string(cfile.finfo_selected,
346 if ((!filter) || (0 == strlen(filter))) {
347 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
348 "Could not acquire information to build a filter!\n"
349 "Try expanding or choosing another item.");
354 color_display_with_filter(filter);
357 color_filters_reset_tmp();
359 color_filters_set_tmp(filt_nr,filter, FALSE);
361 cf_colorize_packets(&cfile);
367 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
369 gchar *selected_proto_url;
370 gchar *proto_abbrev = data;
375 if (cfile.finfo_selected) {
376 /* open wiki page using the protocol abbreviation */
377 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
378 browser_open_url(selected_proto_url);
379 g_free(selected_proto_url);
382 case(ESD_BTN_CANCEL):
385 g_assert_not_reached();
391 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
394 const gchar *proto_abbrev;
398 if (cfile.finfo_selected) {
399 /* convert selected field to protocol abbreviation */
400 /* XXX - could this conversion be simplified? */
401 field_id = cfile.finfo_selected->hfinfo->id;
402 /* if the selected field isn't a protocol, get it's parent */
403 if(!proto_registrar_is_protocol(field_id)) {
404 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
407 proto_abbrev = proto_registrar_get_abbrev(field_id);
409 if (!proto_is_private(field_id)) {
410 /* ask the user if the wiki page really should be opened */
411 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
412 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
414 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
416 "The Wireshark Wiki is a collaborative approach to provide information "
417 "about Wireshark in several ways (not limited to protocol specifics).\n"
419 "This Wiki is new, so the page of the selected protocol "
420 "may not exist and/or may not contain valuable information.\n"
422 "As everyone can edit the Wiki and add new content (or extend existing), "
423 "you are encouraged to add information if you can.\n"
425 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
427 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
428 "which will save you a lot of editing and will give a consistent look over the pages.",
429 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
430 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
432 /* appologize to the user that the wiki page cannot be opened */
433 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
434 "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
436 "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
438 "Since this is a private protocol, such information is not available in "
439 "a public wiki. Therefore this wiki entry is blocked.\n"
441 "Sorry for the inconvenience.\n",
442 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
447 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
449 gchar *selected_proto_url;
450 gchar *proto_abbrev = data;
454 if (cfile.finfo_selected) {
455 /* open reference page using the protocol abbreviation */
456 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
457 browser_open_url(selected_proto_url);
458 g_free(selected_proto_url);
461 case(ESD_BTN_CANCEL):
464 g_assert_not_reached();
469 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
472 const gchar *proto_abbrev;
476 if (cfile.finfo_selected) {
477 /* convert selected field to protocol abbreviation */
478 /* XXX - could this conversion be simplified? */
479 field_id = cfile.finfo_selected->hfinfo->id;
480 /* if the selected field isn't a protocol, get it's parent */
481 if(!proto_registrar_is_protocol(field_id)) {
482 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
485 proto_abbrev = proto_registrar_get_abbrev(field_id);
487 if (!proto_is_private(field_id)) {
488 /* ask the user if the wiki page really should be opened */
489 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
490 "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
492 "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
494 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
495 simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
497 /* appologize to the user that the wiki page cannot be opened */
498 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
499 "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
501 "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
503 "Since this is a private protocol, such information is not available on "
504 "a public website. Therefore this filter entry is blocked.\n"
506 "Sorry for the inconvenience.\n",
507 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
513 is_address_column (gint column)
515 if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) ||
516 (cfile.cinfo.col_fmt[column] == COL_RES_SRC) ||
517 (cfile.cinfo.col_fmt[column] == COL_DEF_DST) ||
518 (cfile.cinfo.col_fmt[column] == COL_RES_DST)) &&
519 strlen(cfile.cinfo.col_expr.col_expr_val[column]))
528 get_ip_address_list_from_packet_list_row(gpointer data)
530 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
531 #ifdef NEW_PACKET_LIST
532 gint column = new_packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
534 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
538 GList *addr_list = NULL;
540 #ifdef NEW_PACKET_LIST
541 fdata = (frame_data *) new_packet_list_get_row_data(row);
543 fdata = (frame_data *) packet_list_get_row_data(row);
549 if (!cf_read_frame (&cfile, fdata))
550 return NULL; /* error reading the frame */
552 epan_dissect_init(&edt, FALSE, FALSE);
553 col_custom_prime_edt(&edt, &cfile.cinfo);
555 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo);
556 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
558 /* First check selected column */
559 if (is_address_column (column)) {
560 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column]));
563 for (col = 0; col < cfile.cinfo.num_cols; col++) {
564 /* Then check all columns except the selected */
565 if ((col != column) && (is_address_column (col))) {
566 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col]));
570 epan_dissect_cleanup(&edt);
577 get_filter_from_packet_list_row_and_column(gpointer data)
579 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
580 #ifdef NEW_PACKET_LIST
581 gint column = new_packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
583 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
588 #ifdef NEW_PACKET_LIST
589 fdata = (frame_data *) new_packet_list_get_row_data(row);
591 fdata = (frame_data *) packet_list_get_row_data(row);
597 if (!cf_read_frame(&cfile, fdata))
598 return NULL; /* error reading the frame */
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 ((cfile.cinfo.col_custom_occurrence[column]) ||
608 (strchr (cfile.cinfo.col_expr.col_expr_val[column], ',') == NULL))
610 /* Only construct the filter when a single occurrence is displayed
611 * otherwise we might end up with a filter like "ip.proto==1,6".
613 * Or do we want to be able to filter on multiple occurrences so that
614 * the filter might be calculated as "ip.proto==1 && ip.proto==6"
617 if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
618 strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
619 /* leak a little but safer than ep_ here */
620 if (cfile.cinfo.col_fmt[column] == COL_CUSTOM) {
621 header_field_info *hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[column]);
622 if (hfi->parent == -1) {
624 buf = se_strdup(cfile.cinfo.col_expr.col_expr[column]);
625 } else if (hfi->type == FT_STRING) {
626 /* Custom string, add quotes */
627 buf = se_strdup_printf("%s == \"%s\"", cfile.cinfo.col_expr.col_expr[column],
628 cfile.cinfo.col_expr.col_expr_val[column]);
632 buf = se_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
633 cfile.cinfo.col_expr.col_expr_val[column]);
638 epan_dissect_cleanup(&edt);
645 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
647 match_selected_cb_do(data,
649 get_filter_from_packet_list_row_and_column(data));
652 /* This function allows users to right click in the details window and copy the text
653 * information to the operating systems clipboard.
655 * We first check to see if a string representation is setup in the tree and then
656 * read the string. If not available then we try to grab the value. If all else
657 * fails we display a message to the user to indicate the copy could not be completed.
660 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
662 GString *gtk_text_str = g_string_new("");
663 char labelstring[256];
664 char *stringpointer = labelstring;
668 case COPY_SELECTED_DESCRIPTION:
669 if (cfile.finfo_selected->rep->representation != 0) {
670 g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
673 case COPY_SELECTED_FIELDNAME:
674 if (cfile.finfo_selected->hfinfo->abbrev != 0) {
675 g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
678 case COPY_SELECTED_VALUE:
679 if (cfile.edt !=0 ) {
680 g_string_append(gtk_text_str,
681 get_node_field_value(cfile.finfo_selected, cfile.edt));
688 if (gtk_text_str->len == 0) {
689 /* If no representation then... Try to read the value */
690 proto_item_fill_label(cfile.finfo_selected, stringpointer);
691 g_string_append(gtk_text_str, stringpointer);
694 if (gtk_text_str->len == 0) {
695 /* Could not get item so display error msg */
696 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
698 /* Copy string to clipboard */
699 copy_to_clipboard(gtk_text_str);
701 g_string_free(gtk_text_str, TRUE); /* Free the memory */
705 /* mark as reference time frame */
707 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
711 frame->flags.ref_time=1;
712 cfile.ref_time_count++;
714 frame->flags.ref_time=0;
715 cfile.ref_time_count--;
717 cf_reftime_packets(&cfile);
718 #ifdef NEW_PACKET_LIST
719 if (!frame->flags.ref_time && !frame->flags.passed_dfilter) {
720 new_packet_list_freeze();
721 cfile.displayed_count--;
722 new_packet_list_recreate_visible_rows();
723 new_packet_list_thaw();
725 new_packet_list_queue_draw();
730 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
734 timestamp_set_type(TS_RELATIVE);
735 recent.gui_time_format = TS_RELATIVE;
736 #ifdef NEW_PACKET_LIST
737 cf_timestamp_auto_precision(&cfile);
738 new_packet_list_queue_draw();
740 cf_change_time_formats(&cfile);
746 g_assert_not_reached();
749 if (cfile.current_frame) {
750 set_frame_reftime(!cfile.current_frame->flags.ref_time,
751 cfile.current_frame, cfile.current_row);
757 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
759 static GtkWidget *reftime_dialog = NULL;
763 if (cfile.current_frame) {
764 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
765 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
766 "%sSwitch to the appropriate Time Display Format?%s\n\n"
767 "Time References don't work well with the currently selected Time Display Format.\n\n"
768 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
769 simple_dialog_primary_start(), simple_dialog_primary_end());
770 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
772 set_frame_reftime(!cfile.current_frame->flags.ref_time,
773 cfile.current_frame, cfile.current_row);
777 case REFTIME_FIND_NEXT:
778 cf_find_packet_time_reference(&cfile, SD_FORWARD);
780 case REFTIME_FIND_PREV:
781 cf_find_packet_time_reference(&cfile, SD_BACKWARD);
787 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
789 cf_find_packet_marked(&cfile, SD_FORWARD);
793 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
795 cf_find_packet_marked(&cfile, SD_BACKWARD);
799 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
802 gchar *help_str = NULL;
803 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
805 gboolean has_blurb = FALSE;
806 guint length = 0, byte_len;
807 GtkWidget *byte_view;
808 const guint8 *byte_data;
813 /* if nothing is selected */
814 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
817 * Which byte view is displaying the current protocol tree
820 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
821 if (byte_view == NULL)
824 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
825 if (byte_data == NULL)
828 cf_unselect_field(&cfile);
829 packet_hex_print(byte_view, byte_data,
830 cfile.current_frame, NULL, byte_len);
831 proto_help_menu_modify(sel, &cfile);
834 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
837 set_notebook_page(byte_nb_ptr_gbl, finfo->ds_tvb);
839 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
840 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
841 g_assert(byte_data != NULL);
843 cfile.finfo_selected = finfo;
844 set_menus_for_selected_tree_row(&cfile);
847 if (finfo->hfinfo->blurb != NULL &&
848 finfo->hfinfo->blurb[0] != '\0') {
850 length = (guint) strlen(finfo->hfinfo->blurb);
852 length = (guint) strlen(finfo->hfinfo->name);
854 finfo_length = finfo->length + finfo->appendix_length;
856 if (finfo_length == 0) {
858 } else if (finfo_length == 1) {
859 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
861 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
863 statusbar_pop_field_msg(); /* get rid of current help msg */
865 help_str = g_strdup_printf(" %s (%s)%s",
866 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
867 finfo->hfinfo->abbrev, len_str);
868 statusbar_push_field_msg(help_str);
872 * Don't show anything if the field name is zero-length;
873 * the pseudo-field for "proto_tree_add_text()" is such
874 * a field, and we don't want "Text (text)" showing up
875 * on the status line if you've selected such a field.
877 * XXX - there are zero-length fields for which we *do*
878 * want to show the field name.
880 * XXX - perhaps the name and abbrev field should be null
881 * pointers rather than null strings for that pseudo-field,
882 * but we'd have to add checks for null pointers in some
883 * places if we did that.
885 * Or perhaps protocol tree items added with
886 * "proto_tree_add_text()" should have -1 as the field index,
887 * with no pseudo-field being used, but that might also
888 * require special checks for -1 to be added.
890 statusbar_push_field_msg("");
893 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
895 proto_help_menu_modify(sel, &cfile);
898 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
900 collapse_all_tree(cfile.edt->tree, tree_view_gbl);
903 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
905 expand_all_tree(cfile.edt->tree, tree_view_gbl);
908 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
910 if (cfile.finfo_selected) {
911 column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
912 cfile.finfo_selected->hfinfo->abbrev,0);
913 /* Recreate the packet list according to new preferences */
914 #ifdef NEW_PACKET_LIST
915 new_packet_list_recreate ();
917 packet_list_recreate ();
919 if (!prefs.gui_use_pref_save) {
922 cfile.cinfo.columns_changed = FALSE; /* Reset value */
926 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
929 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
931 /* the mouse position is at an entry, expand that one */
932 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
933 gtk_tree_path_free(path);
937 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
938 if (cfile.edt->tree) {
939 guint32 tmp = gbl_resolv_flags;
940 gbl_resolv_flags = RESOLV_ALL;
941 proto_tree_draw(cfile.edt->tree, tree_view_gbl);
942 gbl_resolv_flags = tmp;
947 main_set_for_capture_file(gboolean have_capture_file_in)
949 have_capture_file = have_capture_file_in;
951 main_widgets_show_or_hide();
957 /* get the current geometry, before writing it to disk */
958 main_save_window_geometry(top_level);
960 /* write user's recent file to disk
961 * It is no problem to write this file, even if we do not quit */
962 write_profile_recent();
965 /* XXX - should we check whether the capture file is an
966 unsaved temporary file for a live capture and, if so,
967 pop up a "do you want to exit without saving the capture
968 file?" dialog, and then just return, leaving said dialog
969 box to forcibly quit if the user clicks "OK"?
971 If so, note that this should be done in a subroutine that
972 returns TRUE if we do so, and FALSE otherwise, and if it
973 returns TRUE we should return TRUE without nuking anything.
975 Note that, if we do that, we might also want to check if
976 an "Update list of packets in real time" capture is in
977 progress and, if so, ask whether they want to terminate
978 the capture and discard it, and return TRUE, before nuking
979 any child capture, if they say they don't want to do so. */
982 /* Nuke any child capture in progress. */
983 capture_kill_child(&global_capture_opts);
986 /* Are we in the middle of reading a capture? */
987 if (cfile.state == FILE_READ_IN_PROGRESS) {
988 /* Yes, so we can't just close the file and quit, as
989 that may yank the rug out from under the read in
990 progress; instead, just set the state to
991 "FILE_READ_ABORTED" and return - the code doing the read
992 will check for that and, if it sees that, will clean
994 cfile.state = FILE_READ_ABORTED;
996 /* Say that the window should *not* be deleted;
997 that'll be done by the code that cleans up. */
1000 /* Close any capture file we have open; on some OSes, you
1001 can't unlink a temporary capture file if you have it
1003 "cf_close()" will unlink it after closing it if
1004 it's a temporary file.
1006 We do this here, rather than after the main loop returns,
1007 as, after the main loop returns, the main window may have
1008 been destroyed (if this is called due to a "destroy"
1009 even on the main window rather than due to the user
1010 selecting a menu item), and there may be a crash
1011 or other problem when "cf_close()" tries to
1012 clean up stuff in the main window.
1014 XXX - is there a better place to put this?
1015 Or should we have a routine that *just* closes the
1016 capture file, and doesn't do anything with the UI,
1017 which we'd call here, and another routine that
1018 calls that routine and also cleans up the UI, which
1019 we'd call elsewhere? */
1022 /* Exit by leaving the main loop, so that any quit functions
1023 we registered get called. */
1026 /* Say that the window should be deleted. */
1032 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1036 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1037 gtk_window_present(GTK_WINDOW(top_level));
1038 /* user didn't saved his current file, ask him */
1039 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1040 "%sSave capture file before program quit?%s\n\n"
1041 "If you quit the program without saving, your capture data will be discarded.",
1042 simple_dialog_primary_start(), simple_dialog_primary_end());
1043 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1046 /* unchanged file, just exit */
1047 /* "main_do_quit()" indicates whether the main window should be deleted. */
1048 return main_do_quit();
1054 main_pane_load_window_geometry(void)
1056 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1057 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1058 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
1059 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1065 main_load_window_geometry(GtkWidget *widget)
1067 window_geometry_t geom;
1069 geom.set_pos = prefs.gui_geometry_save_position;
1070 geom.x = recent.gui_geometry_main_x;
1071 geom.y = recent.gui_geometry_main_y;
1072 geom.set_size = prefs.gui_geometry_save_size;
1073 if (recent.gui_geometry_main_width > 0 &&
1074 recent.gui_geometry_main_height > 0) {
1075 geom.width = recent.gui_geometry_main_width;
1076 geom.height = recent.gui_geometry_main_height;
1077 geom.set_maximized = prefs.gui_geometry_save_maximized;
1079 /* We assume this means the width and height weren't set in
1080 the "recent" file (or that there is no "recent" file),
1081 and weren't set to a default value, so we don't set the
1082 size. (The "recent" file code rejects non-positive width
1083 and height values.) */
1084 geom.set_size = FALSE;
1086 geom.maximized = recent.gui_geometry_main_maximized;
1088 window_set_geometry(widget, &geom);
1090 main_pane_load_window_geometry();
1091 statusbar_load_window_geometry();
1096 main_save_window_geometry(GtkWidget *widget)
1098 window_geometry_t geom;
1100 window_get_geometry(widget, &geom);
1102 if (prefs.gui_geometry_save_position) {
1103 recent.gui_geometry_main_x = geom.x;
1104 recent.gui_geometry_main_y = geom.y;
1107 if (prefs.gui_geometry_save_size) {
1108 recent.gui_geometry_main_width = geom.width;
1109 recent.gui_geometry_main_height = geom.height;
1112 if(prefs.gui_geometry_save_maximized) {
1113 recent.gui_geometry_main_maximized = geom.maximized;
1116 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
1117 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
1118 statusbar_save_window_geometry();
1121 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1125 /* save file first */
1126 file_save_as_cmd(after_save_exit, NULL);
1128 case(ESD_BTN_QUIT_DONT_SAVE):
1131 case(ESD_BTN_CANCEL):
1134 g_assert_not_reached();
1139 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1143 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1144 /* user didn't saved his current file, ask him */
1145 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_QUIT_DONTSAVE_CANCEL,
1146 "%sSave capture file before program quit?%s\n\n"
1147 "If you quit the program without saving, your capture data will be discarded.",
1148 simple_dialog_primary_start(), simple_dialog_primary_end());
1149 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1151 /* unchanged file, just exit */
1157 print_usage(gboolean print_ver) {
1167 fprintf(output, "Wireshark " VERSION "%s\n"
1168 "Interactively dump and analyze network traffic.\n"
1169 "See http://www.wireshark.org for more information.\n"
1172 wireshark_svnversion, get_copyright_info());
1176 fprintf(output, "\n");
1177 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1178 fprintf(output, "\n");
1181 fprintf(output, "Capture interface:\n");
1182 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1183 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1184 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1185 fprintf(output, " -p don't capture in promiscuous mode\n");
1186 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1187 fprintf(output, " -Q quit Wireshark after capturing\n");
1188 fprintf(output, " -S update packet display when new packets are captured\n");
1189 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1190 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
1191 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1193 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1194 fprintf(output, " -D print list of interfaces and exit\n");
1195 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1196 fprintf(output, "\n");
1197 fprintf(output, "Capture stop conditions:\n");
1198 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1199 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1200 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1201 fprintf(output, " files:NUM - stop after NUM files\n");
1202 /*fprintf(output, "\n");*/
1203 fprintf(output, "Capture output:\n");
1204 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1205 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1206 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1207 #endif /* HAVE_LIBPCAP */
1209 /*fprintf(output, "\n");*/
1210 fprintf(output, "Input file:\n");
1211 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1213 fprintf(output, "\n");
1214 fprintf(output, "Processing:\n");
1215 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1216 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1217 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1219 fprintf(output, "\n");
1220 fprintf(output, "User interface:\n");
1221 fprintf(output, " -C <config profile> start with specified configuration profile\n");
1222 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1223 fprintf(output, " -J <jump filter> jump to the first packet matching the (display) filter\n");
1224 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
1225 fprintf(output, " -m <font> set the font name used for most text\n");
1226 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1227 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
1228 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1229 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1231 fprintf(output, "\n");
1232 fprintf(output, "Output:\n");
1233 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1235 fprintf(output, "\n");
1236 fprintf(output, "Miscellaneous:\n");
1237 fprintf(output, " -h display this help and exit\n");
1238 fprintf(output, " -v display version info and exit\n");
1239 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1240 fprintf(output, " persdata:path - personal data files\n");
1241 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1242 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1244 fprintf(output, " --display=DISPLAY X display to use\n");
1259 printf(PACKAGE " " VERSION "%s\n"
1266 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1267 runtime_info_str->str);
1275 * Print to the standard error. On Windows, create a console for the
1276 * standard error to show up on, if necessary.
1277 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1278 * terminal isn't the standard error?
1281 vfprintf_stderr(const char *fmt, va_list ap)
1286 vfprintf(stderr, fmt, ap);
1290 fprintf_stderr(const char *fmt, ...)
1295 vfprintf_stderr(fmt, ap);
1300 * Report an error in command-line arguments.
1301 * Creates a console on Windows.
1304 cmdarg_err(const char *fmt, ...)
1308 fprintf_stderr("wireshark: ");
1310 vfprintf_stderr(fmt, ap);
1312 fprintf_stderr("\n");
1316 * Report additional information for an error in command-line arguments.
1317 * Creates a console on Windows.
1318 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1319 * terminal isn't the standard error?
1322 cmdarg_err_cont(const char *fmt, ...)
1327 vfprintf_stderr(fmt, ap);
1328 fprintf_stderr("\n");
1333 Once every 3 seconds we get a callback here which we use to update
1337 tap_update_cb(gpointer data _U_)
1339 draw_tap_listeners(FALSE);
1343 /* Restart the tap update display timer with new configured interval */
1344 void reset_tap_update_timer(void)
1346 g_source_remove(tap_update_timer_id);
1347 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, tap_update_cb, NULL);
1351 protect_thread_critical_region(void)
1353 /* Threading support for TAP:s removed
1354 * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
1358 unprotect_thread_critical_region(void)
1360 /* Threading support for TAP:s removed
1361 * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
1367 * Periodically process outstanding hostname lookups. If we have new items,
1368 * redraw the packet list and tree view.
1372 resolv_update_cb(gpointer data _U_)
1374 /* Anything new show up? */
1375 if (host_name_lookup_process(NULL)) {
1376 if (pkt_scrollw->window)
1377 gdk_window_invalidate_rect(pkt_scrollw->window, NULL, TRUE);
1378 if (tv_scrollw->window)
1379 gdk_window_invalidate_rect(tv_scrollw->window, NULL, TRUE);
1382 /* Always check. Even if we don't do async lookups we could still get
1383 passive updates, e.g. from DNS packets. */
1388 /* Set main_window_name and it's icon title to the capture filename */
1390 set_display_filename(capture_file *cf)
1395 window_name = g_strdup_printf("%s", cf_get_display_name(cf));
1396 set_main_window_name(window_name);
1397 g_free(window_name);
1399 set_main_window_name("The Wireshark Network Analyzer");
1403 static GtkWidget *close_dlg = NULL;
1406 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1408 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1413 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1415 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1420 main_cf_cb_file_closing(capture_file *cf)
1423 /* if we have more than 10000 packets, show a splash screen while closing */
1424 /* XXX - don't know a better way to decide whether to show or not,
1425 * as most of the time is spend in a single eth_clist_clear function,
1426 * so we can't use a progress bar here! */
1427 if(cf->count > 10000) {
1428 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1429 "%sClosing file!%s\n\nPlease wait ...",
1430 simple_dialog_primary_start(),
1431 simple_dialog_primary_end());
1432 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1435 /* Destroy all windows, which refer to the
1436 capture file we're closing. */
1437 destroy_packet_wins();
1438 file_save_as_destroy();
1440 /* Restore the standard title bar message. */
1441 set_main_window_name("The Wireshark Network Analyzer");
1443 /* Disable all menu items that make sense only if you have a capture. */
1444 set_menus_for_capture_file(NULL);
1445 set_menus_for_captured_packets(FALSE);
1446 set_menus_for_selected_packet(cf);
1447 set_menus_for_capture_in_progress(FALSE);
1448 set_capture_if_dialog_for_capture_in_progress(FALSE);
1449 set_menus_for_selected_tree_row(cf);
1451 /* Set up main window for no capture file. */
1452 main_set_for_capture_file(FALSE);
1454 main_window_update();
1458 main_cf_cb_file_closed(capture_file *cf _U_)
1460 if(close_dlg != NULL) {
1461 splash_destroy(close_dlg);
1468 main_cf_cb_file_read_started(capture_file *cf _U_)
1470 tap_dfilter_dlg_update();
1472 /* Set up main window for a capture file. */
1473 main_set_for_capture_file(TRUE);
1477 main_cf_cb_file_read_finished(capture_file *cf)
1481 if (!cf->is_tempfile && cf->filename) {
1482 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1483 add_menu_recent_capture_file(cf->filename);
1485 /* Remember folder for next Open dialog and save it in recent */
1486 dir_path = get_dirname(g_strdup(cf->filename));
1487 set_last_open_dir(dir_path);
1490 set_display_filename(cf);
1492 /* Enable menu items that make sense if you have a capture file you've
1493 finished reading. */
1494 set_menus_for_capture_file(cf);
1496 /* Enable menu items that make sense if you have some captured packets. */
1497 set_menus_for_captured_packets(TRUE);
1501 static GList *icon_list_create(
1502 const char **icon16_xpm,
1503 const char **icon32_xpm,
1504 const char **icon48_xpm,
1505 const char **icon64_xpm)
1507 GList *icon_list = NULL;
1508 GdkPixbuf * pixbuf16;
1509 GdkPixbuf * pixbuf32;
1510 GdkPixbuf * pixbuf48;
1511 GdkPixbuf * pixbuf64;
1514 if(icon16_xpm != NULL) {
1515 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1517 icon_list = g_list_append(icon_list, pixbuf16);
1520 if(icon32_xpm != NULL) {
1521 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1523 icon_list = g_list_append(icon_list, pixbuf32);
1526 if(icon48_xpm != NULL) {
1527 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1529 icon_list = g_list_append(icon_list, pixbuf48);
1532 if(icon64_xpm != NULL) {
1533 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1535 icon_list = g_list_append(icon_list, pixbuf64);
1542 main_capture_set_main_window_title(capture_options *capture_opts)
1544 GString *title = g_string_new("");
1546 g_string_append(title, "Capturing ");
1547 if(capture_opts->iface) {
1548 g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
1550 set_main_window_name(title->str);
1551 g_string_free(title, TRUE);
1555 main_capture_cb_capture_prepared(capture_options *capture_opts)
1557 static GList *icon_list = NULL;
1559 main_capture_set_main_window_title(capture_opts);
1561 if(icon_list == NULL) {
1562 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1564 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1566 /* Disable menu items that make no sense if you're currently running
1568 set_menus_for_capture_in_progress(TRUE);
1569 set_capture_if_dialog_for_capture_in_progress(TRUE);
1571 /* Don't set up main window for a capture file. */
1572 main_set_for_capture_file(FALSE);
1576 main_capture_cb_capture_update_started(capture_options *capture_opts)
1578 /* We've done this in "prepared" above, but it will be cleared while
1579 switching to the next multiple file. */
1580 main_capture_set_main_window_title(capture_opts);
1582 set_menus_for_capture_in_progress(TRUE);
1583 set_capture_if_dialog_for_capture_in_progress(TRUE);
1585 /* Enable menu items that make sense if you have some captured
1586 packets (yes, I know, we don't have any *yet*). */
1587 set_menus_for_captured_packets(TRUE);
1589 /* Set up main window for a capture file. */
1590 main_set_for_capture_file(TRUE);
1594 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1596 capture_file *cf = capture_opts->cf;
1597 static GList *icon_list = NULL;
1599 if (!cf->is_tempfile && cf->filename) {
1600 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1601 add_menu_recent_capture_file(cf->filename);
1603 set_display_filename(cf);
1605 /* Enable menu items that make sense if you're not currently running
1607 set_menus_for_capture_in_progress(FALSE);
1608 set_capture_if_dialog_for_capture_in_progress(FALSE);
1610 /* Enable menu items that make sense if you have a capture file
1611 you've finished reading. */
1612 set_menus_for_capture_file(cf);
1614 /* Set up main window for a capture file. */
1615 main_set_for_capture_file(TRUE);
1617 if(icon_list == NULL) {
1618 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1620 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1622 if(global_capture_opts.quit_after_cap) {
1623 /* command line asked us to quit after the capture */
1624 /* don't pop up a dialog to ask for unsaved files etc. */
1630 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1632 /* Don't set up main window for a capture file. */
1633 main_set_for_capture_file(FALSE);
1637 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1640 capture_file *cf = capture_opts->cf;
1642 static GList *icon_list = NULL;
1644 /*set_display_filename(cf);*/
1646 /* Enable menu items that make sense if you're not currently running
1648 set_menus_for_capture_in_progress(FALSE);
1649 set_capture_if_dialog_for_capture_in_progress(FALSE);
1651 /* Restore the standard title bar message */
1652 /* (just in case we have trouble opening the capture file). */
1653 set_main_window_name("The Wireshark Network Analyzer");
1655 if(icon_list == NULL) {
1656 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1658 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1660 /* We don't have loaded the capture file, this will be done later.
1661 * For now we still have simply a blank screen. */
1663 if(global_capture_opts.quit_after_cap) {
1664 /* command line asked us to quit after the capture */
1665 /* don't pop up a dialog to ask for unsaved files etc. */
1670 #endif /* HAVE_LIBPCAP */
1673 main_cf_cb_packet_selected(gpointer data)
1675 capture_file *cf = data;
1677 /* Display the GUI protocol tree and packet bytes.
1678 XXX - why do we dump core if we call "proto_tree_draw()"
1679 before calling "add_byte_views()"? */
1680 add_main_byte_views(cf->edt);
1681 main_proto_tree_draw(cf->edt->tree);
1683 /* The user is searching for a string in the data or a hex value,
1684 * highlight the field that is found in the tree and hex displays. */
1685 if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1686 highlight_field(cf->edt->tvb, cfile.search_pos,
1687 (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1688 cfile.search_pos = 0; /* Reset the position */
1691 /* A packet is selected. */
1692 set_menus_for_selected_packet(cf);
1696 main_cf_cb_packet_unselected(capture_file *cf)
1698 /* Clear out the display of that packet. */
1699 clear_tree_and_hex_views();
1701 /* No packet is selected. */
1702 set_menus_for_selected_packet(cf);
1706 main_cf_cb_field_unselected(capture_file *cf)
1708 set_menus_for_selected_tree_row(cf);
1712 main_cf_cb_file_save_reload_finished(gpointer data _U_)
1714 set_display_filename(&cfile);
1715 set_menus_for_capture_file(&cfile);
1719 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1722 case(cf_cb_file_closing):
1723 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1724 main_cf_cb_file_closing(data);
1726 case(cf_cb_file_closed):
1727 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1728 main_cf_cb_file_closed(data);
1730 case(cf_cb_file_read_started):
1731 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1732 main_cf_cb_file_read_started(data);
1734 case(cf_cb_file_read_finished):
1735 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1736 main_cf_cb_file_read_finished(data);
1738 case(cf_cb_packet_selected):
1739 main_cf_cb_packet_selected(data);
1741 case(cf_cb_packet_unselected):
1742 main_cf_cb_packet_unselected(data);
1744 case(cf_cb_field_unselected):
1745 main_cf_cb_field_unselected(data);
1747 case(cf_cb_file_save_started):
1748 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1750 case(cf_cb_file_save_finished):
1751 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1753 case(cf_cb_file_save_reload_finished):
1754 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1755 main_cf_cb_file_save_reload_finished(data);
1757 case(cf_cb_file_save_failed):
1758 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1761 g_warning("main_cf_callback: event %u unknown", event);
1762 g_assert_not_reached();
1768 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1770 #ifdef HAVE_GTKOSXAPPLICATION
1771 GtkOSXApplication *theApp;
1774 case(capture_cb_capture_prepared):
1775 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1776 main_capture_cb_capture_prepared(capture_opts);
1778 case(capture_cb_capture_update_started):
1779 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1780 main_capture_cb_capture_update_started(capture_opts);
1781 #ifdef HAVE_GTKOSXAPPLICATION
1782 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1783 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsiconcap48_xpm));
1786 case(capture_cb_capture_update_continue):
1787 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1789 case(capture_cb_capture_update_finished):
1790 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1791 main_capture_cb_capture_update_finished(capture_opts);
1793 case(capture_cb_capture_fixed_started):
1794 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1795 main_capture_cb_capture_fixed_started(capture_opts);
1797 case(capture_cb_capture_fixed_continue):
1798 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1800 case(capture_cb_capture_fixed_finished):
1801 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1802 main_capture_cb_capture_fixed_finished(capture_opts);
1804 case(capture_cb_capture_stopping):
1805 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1806 /* Beware: this state won't be called, if the capture child
1807 * closes the capturing on it's own! */
1808 #ifdef HAVE_GTKOSXAPPLICATION
1809 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1810 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
1814 g_warning("main_capture_callback: event %u unknown", event);
1815 g_assert_not_reached();
1821 get_gtk_compiled_info(GString *str)
1823 g_string_append(str, "with ");
1824 g_string_append_printf(str,
1825 #ifdef GTK_MAJOR_VERSION
1826 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1829 "GTK+ (version unknown)");
1831 g_string_append(str, ", ");
1835 get_gui_compiled_info(GString *str)
1837 epan_get_compiled_version_info(str);
1839 g_string_append(str, ", ");
1840 #ifdef HAVE_LIBPORTAUDIO
1841 #ifdef PORTAUDIO_API_1
1842 g_string_append(str, "with PortAudio <= V18");
1843 #else /* PORTAUDIO_API_1 */
1844 g_string_append(str, "with ");
1845 g_string_append(str, Pa_GetVersionText());
1846 #endif /* PORTAUDIO_API_1 */
1847 #else /* HAVE_LIBPORTAUDIO */
1848 g_string_append(str, "without PortAudio");
1849 #endif /* HAVE_LIBPORTAUDIO */
1851 g_string_append(str, ", ");
1853 get_compiled_airpcap_version(str);
1855 g_string_append(str, "without AirPcap");
1857 #ifndef NEW_PACKET_LIST
1858 g_string_append(str, ", with old_packet_list");
1863 get_gui_runtime_info(GString *str)
1865 epan_get_runtime_version_info(str);
1868 g_string_append(str, ", ");
1869 get_runtime_airpcap_version(str);
1873 g_string_append(str, ", ");
1874 u3_runtime_info(str);
1879 read_configuration_files(char **gdp_path, char **dp_path)
1881 int gpf_open_errno, gpf_read_errno;
1882 int cf_open_errno, df_open_errno;
1883 int gdp_open_errno, gdp_read_errno;
1884 int dp_open_errno, dp_read_errno;
1885 char *gpf_path, *pf_path;
1886 char *cf_path, *df_path;
1887 int pf_open_errno, pf_read_errno;
1890 /* Read the preference files. */
1891 prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1892 &pf_open_errno, &pf_read_errno, &pf_path);
1894 if (gpf_path != NULL) {
1895 if (gpf_open_errno != 0) {
1896 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1897 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1898 strerror(gpf_open_errno));
1900 if (gpf_read_errno != 0) {
1901 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1902 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1903 strerror(gpf_read_errno));
1906 if (pf_path != NULL) {
1907 if (pf_open_errno != 0) {
1908 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1909 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1910 strerror(pf_open_errno));
1912 if (pf_read_errno != 0) {
1913 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1914 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1915 strerror(pf_read_errno));
1922 /* if the user wants a console to be always there, well, we should open one for him */
1923 if (prefs_p->gui_console_open == console_open_always) {
1928 /* Read the capture filter file. */
1929 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1930 if (cf_path != NULL) {
1931 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1932 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1933 strerror(cf_open_errno));
1937 /* Read the display filter file. */
1938 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1939 if (df_path != NULL) {
1940 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1941 "Could not open your display filter file\n\"%s\": %s.", df_path,
1942 strerror(df_open_errno));
1946 /* Read the disabled protocols file. */
1947 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1948 dp_path, &dp_open_errno, &dp_read_errno);
1949 if (*gdp_path != NULL) {
1950 if (gdp_open_errno != 0) {
1951 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1952 "Could not open global disabled protocols file\n\"%s\": %s.",
1953 *gdp_path, strerror(gdp_open_errno));
1955 if (gdp_read_errno != 0) {
1956 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1957 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1958 *gdp_path, strerror(gdp_read_errno));
1963 if (*dp_path != NULL) {
1964 if (dp_open_errno != 0) {
1965 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1966 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1967 strerror(dp_open_errno));
1969 if (dp_read_errno != 0) {
1970 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1971 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1972 strerror(dp_read_errno));
1981 /* Check if there's something important to tell the user during startup.
1982 * We want to do this *after* showing the main window so that any windows
1983 * we pop up will be above the main window.
1987 check_and_warn_user_startup(gchar *cf_name)
1989 check_and_warn_user_startup(gchar *cf_name _U_)
1992 gchar *cur_user, *cur_group;
1993 gpointer priv_warning_dialog;
1995 /* Tell the user not to run as root. */
1996 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
1997 cur_user = get_cur_username();
1998 cur_group = get_cur_groupname();
1999 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2000 "Running as user \"%s\" and group \"%s\".\n"
2001 "This could be dangerous.", cur_user, cur_group);
2004 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2005 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
2009 /* Warn the user if npf.sys isn't loaded. */
2010 if (!stdin_capture && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
2011 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2012 "The NPF driver isn't running. You may have trouble\n"
2013 "capturing or listing interfaces.");
2014 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2015 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
2022 /* And now our feature presentation... [ fade to music ] */
2024 main(int argc, char *argv[])
2026 char *init_progfile_dir_error;
2029 gboolean arg_error = FALSE;
2031 extern int info_update_freq; /* Found in about_dlg.c. */
2032 const gchar *filter;
2042 char *gdp_path, *dp_path;
2045 gboolean start_capture = FALSE;
2046 gboolean list_link_layer_types = FALSE;
2050 gboolean capture_option_specified = FALSE;
2057 gint pl_size = 280, tv_size = 95, bv_size = 75;
2058 gchar *rc_file, *cf_name = NULL, *rfilter = NULL, *jfilter = NULL;
2059 dfilter_t *rfcode = NULL;
2060 gboolean rfilter_parse_failed = FALSE;
2063 GtkWidget *splash_win = NULL;
2064 GLogLevelFlags log_flags;
2065 guint go_to_packet = 0;
2066 gboolean jump_backwards = FALSE;
2067 dfilter_t *jump_to_filter = NULL;
2070 #ifdef HAVE_GTKOSXAPPLICATION
2071 GtkOSXApplication *theApp;
2075 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2076 #define OPTSTRING_B "B:"
2078 #define OPTSTRING_B ""
2079 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2080 #else /* HAVE_LIBPCAP */
2081 #define OPTSTRING_B ""
2082 #endif /* HAVE_LIBPCAP */
2084 #ifdef HAVE_PCAP_CREATE
2085 #define OPTSTRING_I "I"
2087 #define OPTSTRING_I ""
2090 #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:"
2092 static const char optstring[] = OPTSTRING;
2095 /* Convert our arg list to UTF-8. */
2096 wc_argv = CommandLineToArgvW(GetCommandLineW(), &wc_argc);
2097 if (wc_argv && wc_argc == argc) {
2098 for (i = 0; i < argc; i++) {
2099 argv[i] = g_strdup(utf_16to8(wc_argv[i]));
2101 } /* XXX else bail because something is horribly, horribly wrong? */
2105 * Get credential information for later use, and drop privileges
2106 * before doing anything else.
2107 * Let the user know if anything happened.
2109 init_process_policies();
2110 relinquish_special_privs_perm();
2113 * Attempt to get the pathname of the executable file.
2115 init_progfile_dir_error = init_progfile_dir(argv[0], main);
2117 /* initialize the funnel mini-api */
2118 initialize_funnel_ops();
2120 #ifdef HAVE_AIRPDCAP
2121 AirPDcapInitContext(&airpdcap_ctx);
2125 /* Load wpcap if possible. Do this before collecting the run-time version information */
2128 /* ... and also load the packet.dll from wpcap */
2129 wpcap_packet_load();
2132 /* Load the airpcap.dll. This must also be done before collecting
2133 * run-time version information. */
2134 airpcap_dll_ret_val = load_airpcap();
2136 switch (airpcap_dll_ret_val) {
2137 case AIRPCAP_DLL_OK:
2138 /* load the airpcap interfaces */
2139 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2141 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2142 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2143 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2146 airpcap_if_active = NULL;
2150 /* select the first ad default (THIS SHOULD BE CHANGED) */
2151 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2156 * XXX - Maybe we need to warn the user if one of the following happens???
2158 case AIRPCAP_DLL_OLD:
2159 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2162 case AIRPCAP_DLL_ERROR:
2163 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2166 case AIRPCAP_DLL_NOT_FOUND:
2167 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2171 #endif /* HAVE_AIRPCAP */
2173 /* Start windows sockets */
2174 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2177 profile_store_persconffiles (TRUE);
2179 /* Assemble the compile-time version information string */
2180 comp_info_str = g_string_new("Compiled ");
2182 get_compiled_version_info(comp_info_str, get_gtk_compiled_info, get_gui_compiled_info);
2184 /* Assemble the run-time version information string */
2185 runtime_info_str = g_string_new("Running ");
2186 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2188 /* Read the profile independent recent file. We have to do this here so we can */
2189 /* set the profile before it can be set from the command line parameterts */
2190 recent_read_static(&rf_path, &rf_open_errno);
2191 if (rf_path != NULL && rf_open_errno != 0) {
2192 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2193 "Could not open common recent file\n\"%s\": %s.",
2194 rf_path, strerror(rf_open_errno));
2197 /* "pre-scan" the command line parameters, if we have "console only"
2198 parameters. We do this so we don't start GTK+ if we're only showing
2199 command-line help or version information.
2201 XXX - this pre-scan is done before we start GTK+, so we haven't
2202 run gtk_init() on the arguments. That means that GTK+ arguments
2203 have not been removed from the argument list; those arguments
2204 begin with "--", and will be treated as an error by getopt().
2206 We thus ignore errors - *and* set "opterr" to 0 to suppress the
2209 optind_initial = optind;
2210 while ((opt = getopt(argc, argv, optstring)) != -1) {
2212 case 'C': /* Configuration Profile */
2213 if (profile_exists (optarg)) {
2214 set_profile_name (optarg);
2216 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2220 case 'h': /* Print help and exit */
2226 if (strcmp(optarg, "-") == 0)
2227 stdin_capture = TRUE;
2230 case 'P': /* Path settings - change these before the Preferences and alike are processed */
2231 status = filesystem_opt(opt, optarg);
2233 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2237 case 'v': /* Show version and exit */
2243 * Extension command line options have to be processed before
2244 * we call epan_init() as they are supposed to be used by dissectors
2245 * or taps very early in the registration process.
2249 case '?': /* Ignore errors - the "real" scan will catch them. */
2254 /* Init the "Open file" dialog directory */
2255 /* (do this after the path settings are processed) */
2257 /* Read the profile dependent (static part) of the recent file. */
2258 /* Only the static part of it will be read, as we don't have the gui now to fill the */
2259 /* recent lists which is done in the dynamic part. */
2260 /* We have to do this already here, so command line parameters can overwrite these values. */
2261 recent_read_profile_static(&rf_path, &rf_open_errno);
2262 if (rf_path != NULL && rf_open_errno != 0) {
2263 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2264 "Could not open recent file\n\"%s\": %s.",
2265 rf_path, strerror(rf_open_errno));
2268 if (recent.gui_fileopen_remembered_dir &&
2269 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
2270 set_last_open_dir(recent.gui_fileopen_remembered_dir);
2272 set_last_open_dir(get_persdatafile_dir());
2275 /* Set getopt index back to initial value, so it will start with the
2276 first command line parameter again. Also reset opterr to 1, so that
2277 error messages are printed by getopt().
2279 XXX - this seems to work on most platforms, but time will tell.
2280 The Single UNIX Specification says "The getopt() function need
2281 not be reentrant", so this isn't guaranteed to work. The Mac
2282 OS X 10.4[.x] getopt() man page says
2284 In order to use getopt() to evaluate multiple sets of arguments, or to
2285 evaluate a single set of arguments multiple times, the variable optreset
2286 must be set to 1 before the second and each additional set of calls to
2287 getopt(), and the variable optind must be reinitialized.
2291 The optreset variable was added to make it possible to call the getopt()
2292 function multiple times. This is an extension to the IEEE Std 1003.2
2293 (``POSIX.2'') specification.
2295 which I think comes from one of the other BSDs.
2297 XXX - if we want to control all the command-line option errors, so
2298 that we can display them where we choose (e.g., in a window), we'd
2299 want to leave opterr as 0, and produce our own messages using optopt.
2300 We'd have to check the value of optopt to see if it's a valid option
2301 letter, in which case *presumably* the error is "this option requires
2302 an argument but none was specified", or not a valid option letter,
2303 in which case *presumably* the error is "this option isn't valid".
2304 Some versions of getopt() let you supply a option string beginning
2305 with ':', which means that getopt() will return ':' rather than '?'
2306 for "this option requires an argument but none was specified", but
2308 optind = optind_initial;
2311 /* Set the current locale according to the program environment.
2312 * We haven't localized anything, but some GTK widgets are localized
2313 * (the file selection dialogue, for example).
2314 * This also sets the C-language locale to the native environment. */
2317 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2318 gtk_init (&argc, &argv);
2320 cf_callback_add(main_cf_callback, NULL);
2322 capture_callback_add(main_capture_callback, NULL);
2324 cf_callback_add(statusbar_cf_callback, NULL);
2326 capture_callback_add(statusbar_capture_callback, NULL);
2329 /* Arrange that if we have no console window, and a GLib message logging
2330 routine is called to log a message, we pop up a console window.
2332 We do that by inserting our own handler for all messages logged
2333 to the default domain; that handler pops up a console if necessary,
2334 and then calls the default handler. */
2336 /* We might want to have component specific log levels later ... */
2340 G_LOG_LEVEL_CRITICAL|
2341 G_LOG_LEVEL_WARNING|
2342 G_LOG_LEVEL_MESSAGE|
2345 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2347 g_log_set_handler(NULL,
2349 console_log_handler, NULL /* user_data */);
2350 g_log_set_handler(LOG_DOMAIN_MAIN,
2352 console_log_handler, NULL /* user_data */);
2355 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2357 console_log_handler, NULL /* user_data */);
2358 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2360 console_log_handler, NULL /* user_data */);
2362 /* Set the initial values in the capture options. This might be overwritten
2363 by preference settings and then again by the command line parameters. */
2364 capture_opts_init(&global_capture_opts, &cfile);
2367 /* Initialize whatever we need to allocate colors for GTK+ */
2370 /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2371 filter = get_conn_cfilter();
2372 if ( *filter != '\0' ) {
2373 info_update_freq = 1000; /* Milliseconds */
2376 /* We won't come till here, if we had a "console only" command line parameter. */
2377 splash_win = splash_new("Loading Wireshark ...");
2378 if (init_progfile_dir_error != NULL) {
2379 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2380 "Can't get pathname of Wireshark: %s.\n"
2381 "It won't be possible to capture traffic.\n"
2382 "Report this to the Wireshark developers.",
2383 init_progfile_dir_error);
2384 g_free(init_progfile_dir_error);
2387 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2389 /* Register all dissectors; we must do this before checking for the
2390 "-G" flag, as the "-G" flag dumps information registered by the
2391 dissectors, and we must do it before we read the preferences, in
2392 case any dissectors register preferences. */
2393 epan_init(register_all_protocols,register_all_protocol_handoffs,
2394 splash_update, (gpointer) splash_win,
2395 failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2396 write_failure_alert_box);
2398 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2400 /* Register all tap listeners; we do this before we parse the arguments,
2401 as the "-z" argument can specify a registered tap. */
2403 /* we register the plugin taps before the other taps because
2404 stats_tree taps plugins will be registered as tap listeners
2405 by stats_tree_stat.c and need to registered before that */
2408 register_all_plugin_tap_listeners();
2411 register_all_tap_listeners();
2413 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2415 /* Now register the preferences for any non-dissector modules.
2416 We must do that before we read the preferences as well. */
2417 prefs_register_modules();
2419 prefs_p = read_configuration_files (&gdp_path, &dp_path);
2421 /* this is to keep tap extensions updating once every 3 seconds */
2422 tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2424 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2426 cap_file_init(&cfile);
2428 /* Fill in capture options with values from the preferences */
2429 prefs_to_capture_opts();
2431 /* Now get our args */
2432 while ((opt = getopt(argc, argv, optstring)) != -1) {
2434 /*** capture option specific ***/
2435 case 'a': /* autostop criteria */
2436 case 'b': /* Ringbuffer option */
2437 case 'c': /* Capture xxx packets */
2438 case 'f': /* capture filter */
2439 case 'k': /* Start capture immediately */
2440 case 'H': /* Hide capture info dialog box */
2441 case 'i': /* Use interface xxx */
2442 case 'p': /* Don't capture in promiscuous mode */
2443 #ifdef HAVE_PCAP_CREATE
2444 case 'I': /* Capture in monitor mode, if available */
2446 case 'Q': /* Quit after capture (just capture to file) */
2447 case 's': /* Set the snapshot (capture) length */
2448 case 'S': /* "Sync" mode: used for following file ala tail -f */
2449 case 'w': /* Write to capture file xxx */
2450 case 'y': /* Set the pcap data link type */
2451 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2452 case 'B': /* Buffer size */
2453 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2455 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2461 capture_option_specified = TRUE;
2466 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2467 case 'K': /* Kerberos keytab file */
2468 read_keytab_file(optarg);
2472 /*** all non capture option specific ***/
2474 /* Configuration profile settings were already processed just ignore them this time*/
2476 case 'D': /* Print a list of capture devices and exit */
2478 if_list = capture_interface_list(&err, &err_str);
2479 if (if_list == NULL) {
2481 case CANT_GET_INTERFACE_LIST:
2482 cmdarg_err("%s", err_str);
2486 case NO_INTERFACES_FOUND:
2487 cmdarg_err("There are no interfaces on which a capture can be done");
2492 capture_opts_print_interfaces(if_list);
2493 free_interface_list(if_list);
2496 capture_option_specified = TRUE;
2500 case 'j': /* Search backwards for a matching packet from filter in option J */
2501 jump_backwards = TRUE;
2503 case 'g': /* Go to packet with the given packet number */
2504 go_to_packet = get_positive_int(optarg, "go to packet");
2506 case 'J': /* Jump to the first packet which matches the filter criteria */
2509 case 'l': /* Automatic scrolling in live capture mode */
2511 auto_scroll_live = TRUE;
2513 capture_option_specified = TRUE;
2517 case 'L': /* Print list of link-layer types and exit */
2519 list_link_layer_types = TRUE;
2521 capture_option_specified = TRUE;
2525 case 'm': /* Fixed-width font for the display */
2526 g_free(prefs_p->gui_font_name);
2527 prefs_p->gui_font_name = g_strdup(optarg);
2529 case 'n': /* No name resolution */
2530 gbl_resolv_flags = RESOLV_NONE;
2532 case 'N': /* Select what types of addresses/port #s to resolve */
2533 if (gbl_resolv_flags == RESOLV_ALL)
2534 gbl_resolv_flags = RESOLV_NONE;
2535 badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
2536 if (badopt != '\0') {
2537 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2542 case 'o': /* Override preference from command line */
2543 switch (prefs_set_pref(optarg)) {
2546 case PREFS_SET_SYNTAX_ERR:
2547 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2550 case PREFS_SET_NO_SUCH_PREF:
2551 /* not a preference, might be a recent setting */
2552 switch (recent_set_arg(optarg)) {
2555 case PREFS_SET_SYNTAX_ERR:
2556 /* shouldn't happen, checked already above */
2557 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2560 case PREFS_SET_NO_SUCH_PREF:
2561 case PREFS_SET_OBSOLETE:
2562 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2567 g_assert_not_reached();
2570 case PREFS_SET_OBSOLETE:
2571 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2576 g_assert_not_reached();
2580 /* Path settings were already processed just ignore them this time*/
2582 case 'r': /* Read capture file xxx */
2583 /* We may set "last_open_dir" to "cf_name", and if we change
2584 "last_open_dir" later, we free the old value, so we have to
2585 set "cf_name" to something that's been allocated. */
2586 cf_name = g_strdup(optarg);
2588 case 'R': /* Read file filter */
2591 case 't': /* Time stamp type */
2592 if (strcmp(optarg, "r") == 0)
2593 timestamp_set_type(TS_RELATIVE);
2594 else if (strcmp(optarg, "a") == 0)
2595 timestamp_set_type(TS_ABSOLUTE);
2596 else if (strcmp(optarg, "ad") == 0)
2597 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2598 else if (strcmp(optarg, "d") == 0)
2599 timestamp_set_type(TS_DELTA);
2600 else if (strcmp(optarg, "dd") == 0)
2601 timestamp_set_type(TS_DELTA_DIS);
2602 else if (strcmp(optarg, "e") == 0)
2603 timestamp_set_type(TS_EPOCH);
2605 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2606 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2607 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2611 case 'u': /* Seconds type */
2612 if (strcmp(optarg, "s") == 0)
2613 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
2614 else if (strcmp(optarg, "hms") == 0)
2615 timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
2617 cmdarg_err("Invalid seconds type \"%s\"", optarg);
2618 cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
2623 /* ext ops were already processed just ignore them this time*/
2626 /* We won't call the init function for the stat this soon
2627 as it would disallow MATE's fields (which are registered
2628 by the preferences set callback) from being used as
2629 part of a tap filter. Instead, we just add the argument
2630 to a list of stat arguments. */
2631 if (!process_stat_cmd_arg(optarg)) {
2632 cmdarg_err("Invalid -z argument.");
2633 cmdarg_err_cont(" -z argument must be one of :");
2634 list_stat_cmd_args();
2639 case '?': /* Bad flag - print usage message */
2647 if (cf_name != NULL) {
2649 * Input file name specified with "-r" *and* specified as a regular
2650 * command-line argument.
2652 cmdarg_err("File name specified both with -r and regular argument");
2656 * Input file name not specified with "-r", and a command-line argument
2657 * was specified; treat it as the input file name.
2659 * Yes, this is different from tshark, where non-flag command-line
2660 * arguments are a filter, but this works better on GUI desktops
2661 * where a command can be specified to be run to open a particular
2662 * file - yes, you could have "-r" as the last part of the command,
2663 * but that's a bit ugly.
2665 cf_name = g_strdup(argv[0]);
2673 * Extra command line arguments were specified; complain.
2675 cmdarg_err("Invalid argument: %s", argv[0]);
2680 #ifndef HAVE_LIBPCAP
2681 if (capture_option_specified) {
2682 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2690 if (start_capture && list_link_layer_types) {
2691 /* Specifying *both* is bogus. */
2692 cmdarg_err("You can't specify both -L and a live capture.");
2696 if (list_link_layer_types) {
2697 /* We're supposed to list the link-layer types for an interface;
2698 did the user also specify a capture file to be read? */
2700 /* Yes - that's bogus. */
2701 cmdarg_err("You can't specify -L and a capture file to be read.");
2704 /* No - did they specify a ring buffer option? */
2705 if (global_capture_opts.multi_files_on) {
2706 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2710 /* We're supposed to do a live capture; did the user also specify
2711 a capture file to be read? */
2712 if (start_capture && cf_name) {
2713 /* Yes - that's bogus. */
2714 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2718 /* No - was the ring buffer option specified and, if so, does it make
2720 if (global_capture_opts.multi_files_on) {
2721 /* Ring buffer works only under certain conditions:
2722 a) ring buffer does not work with temporary files;
2723 b) real_time_mode and multi_files_on are mutually exclusive -
2724 real_time_mode takes precedence;
2725 c) it makes no sense to enable the ring buffer if the maximum
2726 file size is set to "infinite". */
2727 if (global_capture_opts.save_file == NULL) {
2728 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2729 global_capture_opts.multi_files_on = FALSE;
2731 /* if (global_capture_opts.real_time_mode) {
2732 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2733 global_capture_opts.multi_files_on = FALSE;
2735 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2736 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2737 /* XXX - this must be redesigned as the conditions changed */
2738 /* global_capture_opts.multi_files_on = FALSE;*/
2743 if (start_capture || list_link_layer_types) {
2744 /* Did the user specify an interface to use? */
2745 if (!capture_opts_trim_iface(&global_capture_opts,
2746 (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
2751 if (list_link_layer_types) {
2752 /* Get the list of link-layer types for the capture device. */
2753 if_capabilities_t *caps;
2755 caps = capture_get_if_capabilities(global_capture_opts.iface,
2756 global_capture_opts.monitor_mode,
2759 cmdarg_err("%s", err_str);
2763 if (caps->data_link_types == NULL) {
2764 cmdarg_err("The capture device \"%s\" has no data link types.", global_capture_opts.iface);
2767 capture_opts_print_if_capabilities(caps, global_capture_opts.monitor_mode);
2768 free_if_capabilities(caps);
2772 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2773 capture_opts_trim_ring_num_files(&global_capture_opts);
2774 #endif /* HAVE_LIBPCAP */
2776 /* Notify all registered modules that have had any of their preferences
2777 changed either from one of the preferences file or from the command
2778 line that their preferences have changed. */
2781 /* disabled protocols as per configuration file */
2782 if (gdp_path == NULL && dp_path == NULL) {
2783 set_disabled_protos_list();
2786 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2788 /* read in rc file from global and personal configuration paths. */
2789 rc_file = get_datafile_path(RC_FILE);
2790 gtk_rc_parse(rc_file);
2792 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2793 gtk_rc_parse(rc_file);
2802 /* close the splash screen, as we are going to open the main window now */
2803 splash_destroy(splash_win);
2805 /************************************************************************/
2806 /* Everything is prepared now, preferences and command line was read in */
2808 /* Pop up the main window. */
2809 create_main_window(pl_size, tv_size, bv_size, prefs_p);
2811 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2812 recent_read_dynamic(&rf_path, &rf_open_errno);
2813 if (rf_path != NULL && rf_open_errno != 0) {
2814 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2815 "Could not open recent file\n\"%s\": %s.",
2816 rf_path, strerror(rf_open_errno));
2819 color_filters_enable(recent.packet_list_colorize);
2821 /* rearrange all the widgets as we now have all recent settings ready for this */
2822 main_widgets_rearrange();
2824 /* Fill in column titles. This must be done after the top level window
2827 XXX - is that still true, with fixed-width columns? */
2828 #ifndef NEW_PACKET_LIST
2829 packet_list_set_column_titles();
2832 menu_recent_read_finished();
2834 menu_auto_scroll_live_changed(auto_scroll_live);
2837 switch (user_font_apply()) {
2840 case FA_FONT_NOT_RESIZEABLE:
2841 /* "user_font_apply()" popped up an alert box. */
2842 /* turn off zooming - font can't be resized */
2843 case FA_FONT_NOT_AVAILABLE:
2844 /* XXX - did we successfully load the un-zoomed version earlier?
2845 If so, this *probably* means the font is available, but not at
2846 this particular zoom level, but perhaps some other failure
2847 occurred; I'm not sure you can determine which is the case,
2849 /* turn off zooming - zoom level is unavailable */
2851 /* in any other case than FA_SUCCESS, turn off zooming */
2852 recent.gui_zoom_level = 0;
2853 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2856 dnd_init(top_level);
2858 color_filters_init();
2861 /* the window can be sized only, if it's not already shown, so do it now! */
2862 main_load_window_geometry(top_level);
2864 g_timeout_add(info_update_freq, resolv_update_cb, NULL);
2867 /* If we were given the name of a capture file, read it in now;
2868 we defer it until now, so that, if we can't open it, and pop
2869 up an alert box, the alert box is more likely to come up on
2870 top of the main window - but before the preference-file-error
2871 alert box, so, if we get one of those, it's more likely to come
2874 show_main_window(TRUE);
2875 check_and_warn_user_startup(cf_name);
2876 if (rfilter != NULL) {
2877 if (!dfilter_compile(rfilter, &rfcode)) {
2878 bad_dfilter_alert_box(rfilter);
2879 rfilter_parse_failed = TRUE;
2882 if (!rfilter_parse_failed) {
2883 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2884 /* "cf_open()" succeeded, so it closed the previous
2885 capture file, and thus destroyed any previous read filter
2886 attached to "cf". */
2888 cfile.rfcode = rfcode;
2889 /* Open stat windows; we do so after creating the main window,
2890 to avoid GTK warnings, and after successfully opening the
2891 capture file, so we know we have something to compute stats
2892 on, and after registering all dissectors, so that MATE will
2893 have registered its field array and we can have a tap filter
2894 with one of MATE's late-registered fields as part of the
2896 start_requested_stats();
2898 /* Read the capture file. */
2899 switch (cf_read(&cfile, FALSE)) {
2903 /* Just because we got an error, that doesn't mean we were unable
2904 to read any of the file; we handle what we could get from the
2906 /* if the user told us to jump to a specific packet, do it now */
2907 if(go_to_packet != 0) {
2908 /* Jump to the specified frame number, kept for backward
2910 cf_goto_frame(&cfile, go_to_packet);
2911 } else if (jfilter != NULL) {
2912 /* try to compile given filter */
2913 if (!dfilter_compile(jfilter, &jump_to_filter)) {
2914 bad_dfilter_alert_box(jfilter);
2916 /* Filter ok, jump to the first packet matching the filter
2917 conditions. Default search direction is forward, but if
2918 option d was given, search backwards */
2919 cf_find_packet_dfilter(&cfile, jump_to_filter, jump_backwards);
2924 case CF_READ_ABORTED:
2930 /* If the filename is not the absolute path, prepend the current dir. This happens
2931 when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */
2932 if (!g_path_is_absolute(cf_name)) {
2933 char *old_cf_name = cf_name;
2934 char *pwd = g_get_current_dir();
2935 cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, cf_name);
2936 g_free(old_cf_name);
2940 /* Save the name of the containing directory specified in the
2941 path name, if any; we can write over cf_name, which is a
2942 good thing, given that "get_dirname()" does write over its
2944 s = get_dirname(cf_name);
2945 set_last_open_dir(s);
2950 dfilter_free(rfcode);
2951 cfile.rfcode = NULL;
2952 show_main_window(FALSE);
2953 /* Don't call check_and_warn_user_startup(): we did it above */
2954 set_menus_for_capture_in_progress(FALSE);
2955 set_capture_if_dialog_for_capture_in_progress(FALSE);
2960 if (start_capture) {
2961 if (global_capture_opts.save_file != NULL) {
2962 /* Save the directory name for future file dialogs. */
2963 /* (get_dirname overwrites filename) */
2964 s = get_dirname(g_strdup(global_capture_opts.save_file));
2965 set_last_open_dir(s);
2968 /* "-k" was specified; start a capture. */
2969 show_main_window(TRUE);
2970 check_and_warn_user_startup(cf_name);
2971 if (capture_start(&global_capture_opts)) {
2972 /* The capture started. Open stat windows; we do so after creating
2973 the main window, to avoid GTK warnings, and after successfully
2974 opening the capture file, so we know we have something to compute
2975 stats on, and after registering all dissectors, so that MATE will
2976 have registered its field array and we can have a tap filter with
2977 one of MATE's late-registered fields as part of the filter. */
2978 start_requested_stats();
2982 show_main_window(FALSE);
2983 check_and_warn_user_startup(cf_name);
2984 set_menus_for_capture_in_progress(FALSE);
2985 set_capture_if_dialog_for_capture_in_progress(FALSE);
2988 /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2989 if (!start_capture && strlen(global_capture_opts.cfilter) == 0) {
2990 g_free(global_capture_opts.cfilter);
2991 global_capture_opts.cfilter = g_strdup(get_conn_cfilter());
2993 #else /* HAVE_LIBPCAP */
2994 show_main_window(FALSE);
2995 check_and_warn_user_startup(cf_name);
2996 set_menus_for_capture_in_progress(FALSE);
2997 set_capture_if_dialog_for_capture_in_progress(FALSE);
2998 #endif /* HAVE_LIBPCAP */
3001 /* register our pid if we are being run from a U3 device */
3004 profile_store_persconffiles (FALSE);
3006 #ifdef HAVE_GTKOSXAPPLICATION
3007 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
3008 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
3009 gtk_osxapplication_ready(theApp);
3012 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
3014 /* we'll enter the GTK loop now and hand the control over to GTK ... */
3016 /* ... back from GTK, we're going down now! */
3018 /* deregister our pid */
3019 u3_deregister_pid();
3023 #ifdef HAVE_AIRPDCAP
3024 AirPDcapDestroyContext(&airpdcap_ctx);
3028 /* hide the (unresponsive) main window, while asking the user to close the console window */
3029 gtk_widget_hide(top_level);
3031 #ifdef HAVE_GTKOSXAPPLICATION
3032 g_object_unref(theApp);
3035 /* Shutdown windows sockets */
3038 /* For some unknown reason, the "atexit()" call in "create_console()"
3039 doesn't arrange that "destroy_console()" be called when we exit,
3040 so we call it here if a console was created. */
3049 /* We build this as a GUI subsystem application on Win32, so
3050 "WinMain()", not "main()", gets called.
3052 Hack shamelessly stolen from the Win32 port of the GIMP. */
3054 #define _stdcall __attribute__((stdcall))
3058 WinMain (struct HINSTANCE__ *hInstance,
3059 struct HINSTANCE__ *hPrevInstance,
3063 INITCOMMONCONTROLSEX comm_ctrl;
3066 * Initialize our DLL search path. MUST be called before LoadLibrary
3069 ws_init_dll_search_path();
3071 /* Initialize our controls. Required for native Windows file dialogs. */
3072 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3073 comm_ctrl.dwSize = sizeof(comm_ctrl);
3074 /* Includes the animate, header, hot key, list view, progress bar,
3075 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3078 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3079 InitCommonControlsEx(&comm_ctrl);
3081 /* RichEd20.DLL is needed for filter entries. */
3082 ws_load_library("riched20.dll");
3084 has_console = FALSE;
3085 return main (__argc, __argv);
3088 /* The code to create and desstroy console windows should not be necessary,
3089 at least as I read the GLib source code, as it looks as if GLib is, on
3090 Win32, *supposed* to create a console window into which to display its
3093 That doesn't happen, however. I suspect there's something completely
3094 broken about that code in GLib-for-Win32, and that it may be related
3095 to the breakage that forces us to just call "printf()" on the message
3096 rather than passing the message on to "g_log_default_handler()"
3097 (which is the routine that does the aforementioned non-functional
3098 console window creation). */
3101 * If this application has no console window to which its standard output
3102 * would go, create one.
3105 create_console(void)
3107 if (stdin_capture) {
3108 /* We've been handed "-i -". Don't mess with stdio. */
3113 /* We have no console to which to print the version string, so
3114 create one and make it the standard input, output, and error. */
3115 if (!AllocConsole())
3116 return; /* couldn't create console */
3118 ws_freopen("CONIN$", "r", stdin);
3119 ws_freopen("CONOUT$", "w", stdout);
3120 ws_freopen("CONOUT$", "w", stderr);
3122 /* Well, we have a console now. */
3125 /* Now register "destroy_console()" as a routine to be called just
3126 before the application exits, so that we can destroy the console
3127 after the user has typed a key (so that the console doesn't just
3128 disappear out from under them, giving the user no chance to see
3129 the message(s) we put in there). */
3130 atexit(destroy_console);
3132 SetConsoleTitle(_T("Wireshark Debug Console"));
3137 destroy_console(void)
3140 printf("\n\nPress any key to exit\n");
3149 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3150 const char *message, gpointer user_data _U_)
3157 /* ignore log message, if log_level isn't interesting based
3158 upon the console log preferences.
3159 If the preferences haven't been loaded loaded yet, display the
3162 The default console_log_level preference value is such that only
3163 ERROR, CRITICAL and WARNING level messages are processed;
3164 MESSAGE, INFO and DEBUG level messages are ignored. */
3165 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3166 prefs.console_log_level != 0) {
3171 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3172 /* the user wants a console or the application will terminate immediately */
3176 /* For some unknown reason, the above doesn't appear to actually cause
3177 anything to be sent to the standard output, so we'll just splat the
3178 message out directly, just to make sure it gets out. */
3180 switch(log_level & G_LOG_LEVEL_MASK) {
3181 case G_LOG_LEVEL_ERROR:
3184 case G_LOG_LEVEL_CRITICAL:
3187 case G_LOG_LEVEL_WARNING:
3190 case G_LOG_LEVEL_MESSAGE:
3193 case G_LOG_LEVEL_INFO:
3196 case G_LOG_LEVEL_DEBUG:
3200 fprintf(stderr, "unknown log_level %u\n", log_level);
3202 g_assert_not_reached();
3205 /* create a "timestamp" */
3207 today = localtime(&curr);
3209 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3210 today->tm_hour, today->tm_min, today->tm_sec,
3211 log_domain != NULL ? log_domain : "",
3214 if(log_level & G_LOG_LEVEL_ERROR) {
3215 /* wait for a key press before the following error handler will terminate the program
3216 this way the user at least can read the error message */
3217 printf("\n\nPress any key to exit\n");
3221 /* XXX - on UN*X, should we just use g_log_default_handler()?
3222 We want the error messages to go to the standard output;
3223 on Mac OS X, that will cause them to show up in various
3224 per-user logs accessible through Console (details depend
3225 on whether you're running 10.0 through 10.4 or running
3226 10.5 and later), and, on other UN*X desktop environments,
3227 if they don't show up in some form of console log, that's
3228 a deficiency in that desktop environment. (Too bad
3229 Windows doesn't set the standard output and error for
3230 GUI apps to something that shows up in such a log.) */
3231 g_log_default_handler(log_domain, log_level, message, user_data);
3238 * Helper for main_widgets_rearrange()
3240 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3241 gtk_container_remove(GTK_CONTAINER(data), widget);
3244 static GtkWidget *main_widget_layout(gint layout_content)
3246 switch(layout_content) {
3247 case(layout_pane_content_none):
3249 case(layout_pane_content_plist):
3251 case(layout_pane_content_pdetails):
3253 case(layout_pane_content_pbytes):
3254 return byte_nb_ptr_gbl;
3256 g_assert_not_reached();
3263 * Rearrange the main window widgets
3265 void main_widgets_rearrange(void) {
3266 GtkWidget *first_pane_widget1, *first_pane_widget2;
3267 GtkWidget *second_pane_widget1, *second_pane_widget2;
3268 gboolean split_top_left;
3270 /* be a bit faster */
3271 gtk_widget_hide(main_vbox);
3273 /* be sure we don't lose a widget while rearranging */
3274 g_object_ref(G_OBJECT(menubar));
3275 g_object_ref(G_OBJECT(main_tb));
3276 g_object_ref(G_OBJECT(filter_tb));
3278 g_object_ref(G_OBJECT(airpcap_tb));
3280 g_object_ref(G_OBJECT(pkt_scrollw));
3281 g_object_ref(G_OBJECT(tv_scrollw));
3282 g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3283 g_object_ref(G_OBJECT(statusbar));
3284 g_object_ref(G_OBJECT(main_pane_v1));
3285 g_object_ref(G_OBJECT(main_pane_v2));
3286 g_object_ref(G_OBJECT(main_pane_h1));
3287 g_object_ref(G_OBJECT(main_pane_h2));
3288 g_object_ref(G_OBJECT(welcome_pane));
3290 /* empty all containers participating */
3291 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
3292 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
3293 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
3294 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
3295 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
3297 statusbar_widgets_emptying(statusbar);
3299 /* add the menubar always at the top */
3300 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3303 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3305 /* filter toolbar in toolbar area */
3306 if (!prefs.filter_toolbar_show_in_statusbar) {
3307 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3311 /* airpcap toolbar */
3312 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3315 /* fill the main layout panes */
3316 switch(prefs.gui_layout_type) {
3317 case(layout_type_5):
3318 main_first_pane = main_pane_v1;
3319 main_second_pane = main_pane_v2;
3320 split_top_left = FALSE;
3322 case(layout_type_2):
3323 main_first_pane = main_pane_v1;
3324 main_second_pane = main_pane_h1;
3325 split_top_left = FALSE;
3327 case(layout_type_1):
3328 main_first_pane = main_pane_v1;
3329 main_second_pane = main_pane_h1;
3330 split_top_left = TRUE;
3332 case(layout_type_4):
3333 main_first_pane = main_pane_h1;
3334 main_second_pane = main_pane_v1;
3335 split_top_left = FALSE;
3337 case(layout_type_3):
3338 main_first_pane = main_pane_h1;
3339 main_second_pane = main_pane_v1;
3340 split_top_left = TRUE;
3342 case(layout_type_6):
3343 main_first_pane = main_pane_h1;
3344 main_second_pane = main_pane_h2;
3345 split_top_left = FALSE;
3348 main_first_pane = NULL;
3349 main_second_pane = NULL;
3350 split_top_left = FALSE;
3351 g_assert_not_reached();
3353 if (split_top_left) {
3354 first_pane_widget1 = main_second_pane;
3355 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3356 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3357 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3359 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3360 first_pane_widget2 = main_second_pane;
3361 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3362 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3364 if (first_pane_widget1 != NULL)
3365 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3366 if (first_pane_widget2 != NULL)
3367 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3368 if (second_pane_widget1 != NULL)
3369 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3370 if (second_pane_widget2 != NULL)
3371 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3373 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3376 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3379 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3381 /* filter toolbar in statusbar hbox */
3382 if (prefs.filter_toolbar_show_in_statusbar) {
3383 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3387 /* airpcap toolbar */
3388 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3391 /* statusbar widgets */
3392 statusbar_widgets_pack(statusbar);
3394 /* hide widgets on users recent settings */
3395 main_widgets_show_or_hide();
3397 gtk_widget_show(main_vbox);
3401 is_widget_visible(GtkWidget *widget, gpointer data)
3403 gboolean *is_visible = data;
3406 if (GTK_WIDGET_VISIBLE(widget))
3413 main_widgets_show_or_hide(void)
3415 gboolean main_second_pane_show;
3417 if (recent.main_toolbar_show) {
3418 gtk_widget_show(main_tb);
3420 gtk_widget_hide(main_tb);
3423 statusbar_widgets_show_or_hide(statusbar);
3425 if (recent.filter_toolbar_show) {
3426 gtk_widget_show(filter_tb);
3428 gtk_widget_hide(filter_tb);
3432 if (recent.airpcap_toolbar_show) {
3433 gtk_widget_show(airpcap_tb);
3435 gtk_widget_hide(airpcap_tb);
3439 if (recent.packet_list_show && have_capture_file) {
3440 gtk_widget_show(pkt_scrollw);
3442 gtk_widget_hide(pkt_scrollw);
3445 if (recent.tree_view_show && have_capture_file) {
3446 gtk_widget_show(tv_scrollw);
3448 gtk_widget_hide(tv_scrollw);
3451 if (recent.byte_view_show && have_capture_file) {
3452 gtk_widget_show(byte_nb_ptr_gbl);
3454 gtk_widget_hide(byte_nb_ptr_gbl);
3457 if (have_capture_file) {
3458 gtk_widget_show(main_first_pane);
3460 gtk_widget_hide(main_first_pane);
3464 * Is anything in "main_second_pane" visible?
3465 * If so, show it, otherwise hide it.
3467 main_second_pane_show = FALSE;
3468 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3469 &main_second_pane_show);
3470 if (main_second_pane_show) {
3471 gtk_widget_show(main_second_pane);
3473 gtk_widget_hide(main_second_pane);
3476 if (!have_capture_file) {
3478 gtk_widget_show(welcome_pane);
3481 gtk_widget_hide(welcome_pane);
3484 /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3485 #ifndef NEW_PACKET_LIST
3486 packet_list_freeze ();
3487 packet_list_thaw ();
3492 /* called, when the window state changes (minimized, maximized, ...) */
3494 window_state_event_cb (GtkWidget *widget _U_,
3498 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3500 if( (event->type) == (GDK_WINDOW_STATE)) {
3501 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3502 /* we might have dialogs popped up while we where iconified,
3504 display_queued_messages();
3512 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3514 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3516 if (event->keyval == GDK_F8) {
3517 #ifdef NEW_PACKET_LIST
3518 new_packet_list_next();
3523 } else if (event->keyval == GDK_F7) {
3524 #ifdef NEW_PACKET_LIST
3525 new_packet_list_prev();
3530 } else if (event->state & NO_SHIFT_MOD_MASK) {
3531 return FALSE; /* Skip control, alt, and other modifiers */
3533 * A comment in gdkkeysyms.h says that it's autogenerated from
3534 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3535 * don't explicitly say so, isprint() should work as expected
3538 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3539 /* Forward the keypress on to the display filter entry */
3540 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3541 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3542 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3550 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
3552 GtkAccelGroup *accel;
3555 top_level = window_new(GTK_WINDOW_TOPLEVEL, "");
3556 set_main_window_name("The Wireshark Network Analyzer");
3558 gtk_widget_set_name(top_level, "main window");
3559 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3561 g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3562 G_CALLBACK(window_state_event_cb), NULL);
3563 g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3564 G_CALLBACK(top_level_key_pressed_cb), NULL );
3566 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3567 main_vbox = gtk_vbox_new(FALSE, 1);
3568 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 0);
3569 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3570 gtk_widget_show(main_vbox);
3573 menubar = main_menu_new(&accel);
3575 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined (HAVE_GTKOSXAPPLICATION)
3576 /* Mac OS X native menus are created and displayed by main_menu_new() */
3577 if(!prefs_p->gui_macosx_style) {
3579 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3580 gtk_widget_show(menubar);
3581 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined(HAVE_GTKOSXAPPLICATION)
3586 main_tb = toolbar_new();
3587 gtk_widget_show (main_tb);
3589 /* Filter toolbar */
3590 filter_tb = filter_toolbar_new();
3593 #ifdef NEW_PACKET_LIST
3594 pkt_scrollw = new_packet_list_create();
3595 gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3596 gtk_widget_show_all(pkt_scrollw);
3598 pkt_scrollw = packet_list_new(prefs_p);
3599 gtk_widget_set_size_request(packet_list, -1, pl_size);
3600 gtk_widget_show(pkt_scrollw);
3604 tv_scrollw = main_tree_view_new(prefs_p, &tree_view_gbl);
3605 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3606 gtk_widget_show(tv_scrollw);
3608 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3609 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3610 g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3611 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3612 gtk_widget_show(tree_view_gbl);
3615 byte_nb_ptr_gbl = byte_view_new();
3616 gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3617 gtk_widget_show(byte_nb_ptr_gbl);
3619 g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3620 g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3622 /* Panes for the packet list, tree, and byte view */
3623 main_pane_v1 = gtk_vpaned_new();
3624 gtk_widget_show(main_pane_v1);
3625 main_pane_v2 = gtk_vpaned_new();
3626 gtk_widget_show(main_pane_v2);
3627 main_pane_h1 = gtk_hpaned_new();
3628 gtk_widget_show(main_pane_h1);
3629 main_pane_h2 = gtk_hpaned_new();
3630 gtk_widget_show(main_pane_h2);
3632 airpcap_tb = airpcap_toolbar_new();
3633 gtk_widget_show(airpcap_tb);
3636 statusbar = statusbar_new();
3637 gtk_widget_show(statusbar);
3639 /* Pane for the welcome screen */
3640 welcome_pane = welcome_new();
3641 gtk_widget_show(welcome_pane);
3645 show_main_window(gboolean doing_work)
3647 main_set_for_capture_file(doing_work);
3649 /*** we have finished all init things, show the main window ***/
3650 gtk_widget_show(top_level);
3652 /* the window can be maximized only, if it's visible, so do it after show! */
3653 main_load_window_geometry(top_level);
3655 /* process all pending GUI events before continue */
3656 while (gtk_events_pending()) gtk_main_iteration();
3658 /* Pop up any queued-up alert boxes. */
3659 display_queued_messages();
3661 /* Move the main window to the front, in case it isn't already there */
3662 gdk_window_raise(top_level->window);
3665 airpcap_toolbar_show(airpcap_tb);
3666 #endif /* HAVE_AIRPCAP */
3669 /* Fill in capture options with values from the preferences */
3671 prefs_to_capture_opts(void)
3674 /* Set promiscuous mode from the preferences setting. */
3675 /* the same applies to other preferences settings as well. */
3676 global_capture_opts.promisc_mode = prefs.capture_prom_mode;
3677 global_capture_opts.use_pcapng = prefs.capture_pcap_ng;
3678 global_capture_opts.show_info = prefs.capture_show_info;
3679 global_capture_opts.real_time_mode = prefs.capture_real_time;
3680 auto_scroll_live = prefs.capture_auto_scroll;
3681 #endif /* HAVE_LIBPCAP */
3683 /* Set the name resolution code's flags from the preferences. */
3684 gbl_resolv_flags = prefs.name_resolve;
3688 /* Change configuration profile */
3689 void change_configuration_profile (const gchar *profile_name)
3691 char *gdp_path, *dp_path;
3695 /* First check if profile exists */
3696 if (!profile_exists(profile_name)) {
3700 /* Get the current geometry, before writing it to disk */
3701 main_save_window_geometry(top_level);
3703 if (profile_exists(get_profile_name())) {
3704 /* Write recent file for profile we are leaving, if it still exists */
3705 write_profile_recent();
3708 /* Set profile name and update the status bar */
3709 set_profile_name (profile_name);
3710 profile_bar_update ();
3712 /* Reset current preferences and apply the new */
3716 (void) read_configuration_files (&gdp_path, &dp_path);
3718 recent_read_profile_static(&rf_path, &rf_open_errno);
3719 if (rf_path != NULL && rf_open_errno != 0) {
3720 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3721 "Could not open common recent file\n\"%s\": %s.",
3722 rf_path, strerror(rf_open_errno));
3724 if (recent.gui_fileopen_remembered_dir &&
3725 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
3726 set_last_open_dir(recent.gui_fileopen_remembered_dir);
3728 timestamp_set_type (recent.gui_time_format);
3729 timestamp_set_seconds_type (recent.gui_seconds_format);
3730 color_filters_enable(recent.packet_list_colorize);
3732 prefs_to_capture_opts();
3734 macros_post_update();
3736 /* Update window view and redraw the toolbar */
3737 update_main_window_title();
3738 toolbar_redraw_all();
3740 /* Enable all protocols and disable from the disabled list */
3742 if (gdp_path == NULL && dp_path == NULL) {
3743 set_disabled_protos_list();
3746 /* Reload color filters */
3747 color_filters_reload();
3749 /* Reload list of interfaces on welcome page */
3750 welcome_if_panel_reload();
3752 /* Recreate the packet list according to new preferences */
3753 #ifdef NEW_PACKET_LIST
3754 new_packet_list_recreate ();
3756 packet_list_recreate ();
3758 cfile.cinfo.columns_changed = FALSE; /* Reset value */
3761 /* Update menus with new recent values */
3762 menu_recent_read_finished();
3764 /* Reload pane geometry, must be done after recreating the list */
3765 main_pane_load_window_geometry();
3768 /** redissect packets and update UI */
3769 void redissect_packets(void)
3771 cf_redissect_packets(&cfile);
3772 status_expert_update();