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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
34 #include <gdk/gdkkeysyms.h>
35 #if GTK_CHECK_VERSION(3,0,0)
36 # include <gdk/gdkkeysyms-compat.h>
49 #include "wsutil/wsgetopt.h"
52 #ifdef _WIN32 /* Needed for console I/O */
54 /* AttachConsole() needs this #define! */
55 #define _WIN32_WINNT 0x0501
61 #ifdef HAVE_LIBPORTAUDIO
62 #include <portaudio.h>
63 #endif /* HAVE_LIBPORTAUDIO */
65 #include <epan/epan.h>
66 #include <epan/filesystem.h>
67 #include <wsutil/privileges.h>
68 #include <epan/epan_dissect.h>
69 #include <epan/timestamp.h>
70 #include <epan/plugins.h>
71 #include <epan/dfilter/dfilter.h>
72 #include <epan/strutil.h>
73 #include <epan/addr_resolv.h>
74 #include <epan/emem.h>
75 #include <epan/ex-opt.h>
76 #include <epan/funnel.h>
77 #include <epan/expert.h>
78 #include <epan/frequency-utils.h>
79 #include <epan/prefs.h>
80 #include <epan/prefs-int.h>
82 #include <epan/stat_cmd_args.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 "../register.h"
95 #include "../ringbuffer.h"
97 #include "../clopts_common.h"
98 #include "../console_io.h"
99 #include "../cmdarg_err.h"
100 #include "../version_info.h"
101 #include "../merge.h"
105 #include "gtk_iface_monitor.h"
107 #include "ui/alert_box.h"
108 #include "ui/main_statusbar.h"
109 #include "ui/recent.h"
110 #include "ui/recent_utils.h"
111 #include "ui/simple_dialog.h"
112 #include "ui/ui_util.h"
114 #include <wsutil/file_util.h>
117 #include "../capture_ui_utils.h"
118 #include "../capture-pcap-util.h"
119 #include "../capture_ifinfo.h"
120 #include "../capture.h"
121 #include "../capture_sync.h"
125 #include "../capture-wpcap.h"
126 #include "../capture_wpcap_packet.h"
127 #include <tchar.h> /* Needed for Unicode */
128 #include <wsutil/unicode-utils.h>
129 #include <commctrl.h>
130 #include <shellapi.h>
134 #include "ui/gtk/file_dlg.h"
135 #include "ui/gtk/gtkglobals.h"
136 #include "ui/gtk/color_utils.h"
137 #include "ui/gtk/gui_utils.h"
138 #include "ui/gtk/color_dlg.h"
139 #include "ui/gtk/filter_dlg.h"
140 #include "ui/gtk/uat_gui.h"
141 #include "ui/gtk/main.h"
142 #include "ui/gtk/main_80211_toolbar.h"
143 #include "ui/gtk/main_airpcap_toolbar.h"
144 #include "ui/gtk/main_filter_toolbar.h"
145 #include "ui/gtk/main_titlebar.h"
146 #include "ui/gtk/menus.h"
147 #include "ui/gtk/main_menubar_private.h"
148 #include "ui/gtk/macros_dlg.h"
149 #include "ui/gtk/main_statusbar_private.h"
150 #include "ui/gtk/main_toolbar.h"
151 #include "ui/gtk/main_toolbar_private.h"
152 #include "ui/gtk/main_welcome.h"
153 #include "ui/gtk/drag_and_drop.h"
154 #include "ui/gtk/capture_file_dlg.h"
155 #include "ui/gtk/packet_panes.h"
156 #include "ui/gtk/keys.h"
157 #include "ui/gtk/packet_win.h"
158 #include "ui/gtk/stock_icons.h"
159 #include "ui/gtk/find_dlg.h"
160 #include "ui/gtk/follow_tcp.h"
161 #include "ui/gtk/font_utils.h"
162 #include "ui/gtk/about_dlg.h"
163 #include "ui/gtk/help_dlg.h"
164 #include "ui/gtk/decode_as_dlg.h"
165 #include "ui/gtk/webbrowser.h"
166 #include "ui/gtk/capture_dlg.h"
167 #include "ui/gtk/capture_if_dlg.h"
168 #include "ui/gtk/capture_globals.h"
169 #include "ui/gtk/tap_param_dlg.h"
170 #include "ui/gtk/prefs_column.h"
171 #include "ui/gtk/prefs_dlg.h"
172 #include "ui/gtk/proto_help.h"
173 #include "ui/gtk/new_packet_list.h"
174 #include "ui/gtk/filter_expression_save_dlg.h"
177 #include "ui/gtk/iface_lists.h"
180 #include "ui/gtk/old-gtk-compat.h"
183 #include "../../image/wsicon16.xpm"
184 #include "../../image/wsicon32.xpm"
185 #include "../../image/wsicon48.xpm"
186 #include "../../image/wsicon64.xpm"
187 #include "../../image/wsiconcap16.xpm"
188 #include "../../image/wsiconcap32.xpm"
189 #include "../../image/wsiconcap48.xpm"
194 #include "airpcap_loader.h"
195 #include "airpcap_dlg.h"
196 #include "airpcap_gui_utils.h"
199 #include <epan/crypt/airpdcap_ws.h>
202 #ifdef HAVE_GTKOSXAPPLICATION
203 #include <igemacintegration/gtkosxapplication.h>
207 * Files under personal and global preferences directories in which
208 * GTK settings for Wireshark are stored.
210 #define RC_FILE "gtkrc"
214 static gboolean capture_stopping;
216 /* "exported" main widgets */
217 GtkWidget *top_level = NULL, *pkt_scrollw, *tree_view_gbl, *byte_nb_ptr_gbl;
219 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
220 static GtkWidget *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
221 static GtkWidget *main_first_pane, *main_second_pane;
223 /* internally used widgets */
224 static GtkWidget *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
226 GtkWidget *wireless_tb;
228 int airpcap_dll_ret_val = -1;
231 GString *comp_info_str, *runtime_info_str;
233 static gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
235 static guint tap_update_timer_id;
238 static gboolean has_console; /* TRUE if app has console */
239 static gboolean console_wait; /* "Press any key..." */
240 static void destroy_console(void);
241 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
243 static void console_log_handler(const char *log_domain,
244 GLogLevelFlags log_level, const char *message, gpointer user_data);
246 static void create_main_window(gint, gint, gint, e_prefs*);
247 static void show_main_window(gboolean);
248 static void main_save_window_geometry(GtkWidget *widget);
251 /* Match selected byte pattern */
253 match_selected_cb_do(gpointer data, int action, gchar *text)
255 GtkWidget *filter_te;
256 char *cur_filter, *new_filter;
258 if ((!text) || (0 == strlen(text))) {
259 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
264 filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
267 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
269 switch (action&MATCH_SELECTED_MASK) {
271 case MATCH_SELECTED_REPLACE:
272 new_filter = g_strdup(text);
275 case MATCH_SELECTED_AND:
276 if ((!cur_filter) || (0 == strlen(cur_filter)))
277 new_filter = g_strdup(text);
279 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
282 case MATCH_SELECTED_OR:
283 if ((!cur_filter) || (0 == strlen(cur_filter)))
284 new_filter = g_strdup(text);
286 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
289 case MATCH_SELECTED_NOT:
290 new_filter = g_strconcat("!(", text, ")", NULL);
293 case MATCH_SELECTED_AND_NOT:
294 if ((!cur_filter) || (0 == strlen(cur_filter)))
295 new_filter = g_strconcat("!(", text, ")", NULL);
297 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
300 case MATCH_SELECTED_OR_NOT:
301 if ((!cur_filter) || (0 == strlen(cur_filter)))
302 new_filter = g_strconcat("!(", text, ")", NULL);
304 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
308 g_assert_not_reached();
313 /* Free up the copy we got of the old filter text. */
316 /* Don't change the current display filter if we only want to copy the filter */
317 if (action&MATCH_SELECTED_COPY_ONLY) {
318 GString *gtk_text_str = g_string_new("");
319 g_string_append(gtk_text_str, new_filter);
320 copy_to_clipboard(gtk_text_str);
321 g_string_free(gtk_text_str, TRUE);
323 /* create a new one and set the display filter entry accordingly */
324 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
326 /* Run the display filter so it goes in effect. */
327 if (action&MATCH_SELECTED_APPLY_NOW)
328 main_filter_packets(&cfile, new_filter, FALSE);
331 /* Free up the new filter text. */
336 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
340 if (cfile.finfo_selected) {
341 filter = proto_construct_match_selected_string(cfile.finfo_selected,
343 match_selected_cb_do((data ? data : w), action, filter);
348 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
352 if (cfile.finfo_selected) {
353 filter = proto_construct_match_selected_string(cfile.finfo_selected,
355 if ((!filter) || (0 == strlen(filter))) {
356 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
357 "Could not acquire information to build a filter!\n"
358 "Try expanding or choosing another item.");
363 color_display_with_filter(filter);
366 color_filters_reset_tmp();
368 color_filters_set_tmp(filt_nr,filter, FALSE);
370 new_packet_list_colorize_packets();
376 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
378 gchar *selected_proto_url;
379 gchar *proto_abbrev = data;
384 if (cfile.finfo_selected) {
385 /* open wiki page using the protocol abbreviation */
386 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
387 browser_open_url(selected_proto_url);
388 g_free(selected_proto_url);
391 case(ESD_BTN_CANCEL):
394 g_assert_not_reached();
400 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
403 const gchar *proto_abbrev;
407 if (cfile.finfo_selected) {
408 /* convert selected field to protocol abbreviation */
409 /* XXX - could this conversion be simplified? */
410 field_id = cfile.finfo_selected->hfinfo->id;
411 /* if the selected field isn't a protocol, get it's parent */
412 if(!proto_registrar_is_protocol(field_id)) {
413 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
416 proto_abbrev = proto_registrar_get_abbrev(field_id);
418 if (!proto_is_private(field_id)) {
419 /* ask the user if the wiki page really should be opened */
420 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
421 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
423 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
425 "The Wireshark Wiki is a collaborative approach to provide information "
426 "about Wireshark in several ways (not limited to protocol specifics).\n"
428 "This Wiki is new, so the page of the selected protocol "
429 "may not exist and/or may not contain valuable information.\n"
431 "As everyone can edit the Wiki and add new content (or extend existing), "
432 "you are encouraged to add information if you can.\n"
434 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
436 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
437 "which will save you a lot of editing and will give a consistent look over the pages.",
438 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
439 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
441 /* appologize to the user that the wiki page cannot be opened */
442 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
443 "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
445 "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
447 "Since this is a private protocol, such information is not available in "
448 "a public wiki. Therefore this wiki entry is blocked.\n"
450 "Sorry for the inconvenience.\n",
451 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
456 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
458 gchar *selected_proto_url;
459 gchar *proto_abbrev = data;
463 if (cfile.finfo_selected) {
464 /* open reference page using the protocol abbreviation */
465 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
466 browser_open_url(selected_proto_url);
467 g_free(selected_proto_url);
470 case(ESD_BTN_CANCEL):
473 g_assert_not_reached();
478 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
481 const gchar *proto_abbrev;
485 if (cfile.finfo_selected) {
486 /* convert selected field to protocol abbreviation */
487 /* XXX - could this conversion be simplified? */
488 field_id = cfile.finfo_selected->hfinfo->id;
489 /* if the selected field isn't a protocol, get it's parent */
490 if(!proto_registrar_is_protocol(field_id)) {
491 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
494 proto_abbrev = proto_registrar_get_abbrev(field_id);
496 if (!proto_is_private(field_id)) {
497 /* ask the user if the wiki page really should be opened */
498 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
499 "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
501 "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
503 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
504 simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
506 /* appologize to the user that the wiki page cannot be opened */
507 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
508 "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
510 "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
512 "Since this is a private protocol, such information is not available on "
513 "a public website. Therefore this filter entry is blocked.\n"
515 "Sorry for the inconvenience.\n",
516 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
522 is_address_column (gint column)
524 if (((cfile.cinfo.col_fmt[column] == COL_DEF_SRC) ||
525 (cfile.cinfo.col_fmt[column] == COL_RES_SRC) ||
526 (cfile.cinfo.col_fmt[column] == COL_DEF_DST) ||
527 (cfile.cinfo.col_fmt[column] == COL_RES_DST)) &&
528 strlen(cfile.cinfo.col_expr.col_expr_val[column]))
537 get_ip_address_list_from_packet_list_row(gpointer data)
539 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
540 gint column = new_packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
543 GList *addr_list = NULL;
545 fdata = (frame_data *) new_packet_list_get_row_data(row);
550 if (!cf_read_frame (&cfile, fdata))
551 return NULL; /* error reading the frame */
553 epan_dissect_init(&edt, FALSE, FALSE);
554 col_custom_prime_edt(&edt, &cfile.cinfo);
556 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata, &cfile.cinfo);
557 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
559 /* First check selected column */
560 if (is_address_column (column)) {
561 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[column]));
564 for (col = 0; col < cfile.cinfo.num_cols; col++) {
565 /* Then check all columns except the selected */
566 if ((col != column) && (is_address_column (col))) {
567 addr_list = g_list_append (addr_list, se_strdup_printf("%s", cfile.cinfo.col_expr.col_expr_val[col]));
571 epan_dissect_cleanup(&edt);
578 get_filter_from_packet_list_row_and_column(gpointer data)
580 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
581 gint column = new_packet_list_get_column_id (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY)));
585 fdata = (frame_data *) new_packet_list_get_row_data(row);
590 if (!cf_read_frame(&cfile, fdata))
591 return NULL; /* error reading the frame */
592 /* proto tree, visible. We need a proto tree if there's custom columns */
593 epan_dissect_init(&edt, have_custom_cols(&cfile.cinfo), FALSE);
594 col_custom_prime_edt(&edt, &cfile.cinfo);
596 epan_dissect_run(&edt, &cfile.pseudo_header, cfile.pd, fdata,
598 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
600 if ((cfile.cinfo.col_custom_occurrence[column]) ||
601 (strchr (cfile.cinfo.col_expr.col_expr_val[column], ',') == NULL))
603 /* Only construct the filter when a single occurrence is displayed
604 * otherwise we might end up with a filter like "ip.proto==1,6".
606 * Or do we want to be able to filter on multiple occurrences so that
607 * the filter might be calculated as "ip.proto==1 && ip.proto==6"
610 if (strlen(cfile.cinfo.col_expr.col_expr[column]) != 0 &&
611 strlen(cfile.cinfo.col_expr.col_expr_val[column]) != 0) {
612 /* leak a little but safer than ep_ here */
613 if (cfile.cinfo.col_fmt[column] == COL_CUSTOM) {
614 header_field_info *hfi = proto_registrar_get_byname(cfile.cinfo.col_custom_field[column]);
615 if (hfi->parent == -1) {
617 buf = se_strdup(cfile.cinfo.col_expr.col_expr[column]);
618 } else if (hfi->type == FT_STRING) {
619 /* Custom string, add quotes */
620 buf = se_strdup_printf("%s == \"%s\"", cfile.cinfo.col_expr.col_expr[column],
621 cfile.cinfo.col_expr.col_expr_val[column]);
625 buf = se_strdup_printf("%s == %s", cfile.cinfo.col_expr.col_expr[column],
626 cfile.cinfo.col_expr.col_expr_val[column]);
631 epan_dissect_cleanup(&edt);
638 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
640 match_selected_cb_do(data,
642 get_filter_from_packet_list_row_and_column(data));
645 /* This function allows users to right click in the details window and copy the text
646 * information to the operating systems clipboard.
648 * We first check to see if a string representation is setup in the tree and then
649 * read the string. If not available then we try to grab the value. If all else
650 * fails we display a message to the user to indicate the copy could not be completed.
653 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
655 GString *gtk_text_str = g_string_new("");
656 char labelstring[256];
657 char *stringpointer = labelstring;
661 case COPY_SELECTED_DESCRIPTION:
662 if (cfile.finfo_selected->rep &&
663 strlen (cfile.finfo_selected->rep->representation) > 0) {
664 g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
667 case COPY_SELECTED_FIELDNAME:
668 if (cfile.finfo_selected->hfinfo->abbrev != 0) {
669 g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
672 case COPY_SELECTED_VALUE:
673 if (cfile.edt !=0 ) {
674 g_string_append(gtk_text_str,
675 get_node_field_value(cfile.finfo_selected, cfile.edt));
682 if (gtk_text_str->len == 0) {
683 /* If no representation then... Try to read the value */
684 proto_item_fill_label(cfile.finfo_selected, stringpointer);
685 g_string_append(gtk_text_str, stringpointer);
688 if (gtk_text_str->len == 0) {
689 /* Could not get item so display error msg */
690 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
692 /* Copy string to clipboard */
693 copy_to_clipboard(gtk_text_str);
695 g_string_free(gtk_text_str, TRUE); /* Free the memory */
699 /* mark as reference time frame */
701 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
705 frame->flags.ref_time=1;
706 cfile.ref_time_count++;
708 frame->flags.ref_time=0;
709 cfile.ref_time_count--;
711 cf_reftime_packets(&cfile);
712 if (!frame->flags.ref_time && !frame->flags.passed_dfilter) {
713 new_packet_list_freeze();
714 cfile.displayed_count--;
715 new_packet_list_recreate_visible_rows();
716 new_packet_list_thaw();
718 new_packet_list_queue_draw();
722 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
726 timestamp_set_type(TS_RELATIVE);
727 recent.gui_time_format = TS_RELATIVE;
728 cf_timestamp_auto_precision(&cfile);
729 new_packet_list_queue_draw();
734 g_assert_not_reached();
737 if (cfile.current_frame) {
738 set_frame_reftime(!cfile.current_frame->flags.ref_time,
739 cfile.current_frame, cfile.current_row);
745 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
747 static GtkWidget *reftime_dialog = NULL;
751 if (cfile.current_frame) {
752 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
753 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
754 "%sSwitch to the appropriate Time Display Format?%s\n\n"
755 "Time References don't work well with the currently selected Time Display Format.\n\n"
756 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
757 simple_dialog_primary_start(), simple_dialog_primary_end());
758 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
760 set_frame_reftime(!cfile.current_frame->flags.ref_time,
761 cfile.current_frame, cfile.current_row);
765 case REFTIME_FIND_NEXT:
766 cf_find_packet_time_reference(&cfile, SD_FORWARD);
768 case REFTIME_FIND_PREV:
769 cf_find_packet_time_reference(&cfile, SD_BACKWARD);
775 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
777 cf_find_packet_marked(&cfile, SD_FORWARD);
781 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
783 cf_find_packet_marked(&cfile, SD_BACKWARD);
787 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
790 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
792 gboolean has_blurb = FALSE;
793 guint length = 0, byte_len;
794 GtkWidget *byte_view;
795 const guint8 *byte_data;
800 /* if nothing is selected */
801 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
804 * Which byte view is displaying the current protocol tree
807 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
808 if (byte_view == NULL)
811 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
812 if (byte_data == NULL)
815 cf_unselect_field(&cfile);
816 packet_hex_print(byte_view, byte_data,
817 cfile.current_frame, NULL, byte_len);
818 proto_help_menu_modify(sel, &cfile);
821 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
824 set_notebook_page(byte_nb_ptr_gbl, finfo->ds_tvb);
826 byte_view = get_notebook_bv_ptr(byte_nb_ptr_gbl);
827 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
828 g_assert(byte_data != NULL);
830 cfile.finfo_selected = finfo;
831 set_menus_for_selected_tree_row(&cfile);
834 if (finfo->hfinfo->blurb != NULL &&
835 finfo->hfinfo->blurb[0] != '\0') {
837 length = (guint) strlen(finfo->hfinfo->blurb);
839 length = (guint) strlen(finfo->hfinfo->name);
841 finfo_length = finfo->length + finfo->appendix_length;
843 if (finfo_length == 0) {
845 } else if (finfo_length == 1) {
846 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
848 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
850 statusbar_pop_field_msg(); /* get rid of current help msg */
852 statusbar_push_field_msg(" %s (%s)%s",
853 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
854 finfo->hfinfo->abbrev, len_str);
857 * Don't show anything if the field name is zero-length;
858 * the pseudo-field for "proto_tree_add_text()" is such
859 * a field, and we don't want "Text (text)" showing up
860 * on the status line if you've selected such a field.
862 * XXX - there are zero-length fields for which we *do*
863 * want to show the field name.
865 * XXX - perhaps the name and abbrev field should be null
866 * pointers rather than null strings for that pseudo-field,
867 * but we'd have to add checks for null pointers in some
868 * places if we did that.
870 * Or perhaps protocol tree items added with
871 * "proto_tree_add_text()" should have -1 as the field index,
872 * with no pseudo-field being used, but that might also
873 * require special checks for -1 to be added.
875 statusbar_push_field_msg("%s", "");
878 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
880 proto_help_menu_modify(sel, &cfile);
883 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
885 collapse_all_tree(cfile.edt->tree, tree_view_gbl);
888 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
890 expand_all_tree(cfile.edt->tree, tree_view_gbl);
893 void apply_as_custom_column_cb (GtkWidget *widget _U_, gpointer data _U_)
895 if (cfile.finfo_selected) {
896 column_prefs_add_custom(COL_CUSTOM, cfile.finfo_selected->hfinfo->name,
897 cfile.finfo_selected->hfinfo->abbrev,0);
898 /* Recreate the packet list according to new preferences */
899 new_packet_list_recreate ();
900 if (!prefs.gui_use_pref_save) {
903 cfile.cinfo.columns_changed = FALSE; /* Reset value */
907 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
910 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view_gbl), cfile.finfo_selected);
912 /* the mouse position is at an entry, expand that one */
913 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view_gbl), path, TRUE);
914 gtk_tree_path_free(path);
918 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
919 static const e_addr_resolve resolv_flags = {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE};
921 if (cfile.edt->tree) {
922 proto_tree_draw_resolve(cfile.edt->tree, tree_view_gbl, &resolv_flags);
926 /* Update main window items based on whether there's a capture in progress. */
928 main_set_for_capture_in_progress(gboolean capture_in_progress)
930 set_menus_for_capture_in_progress(capture_in_progress);
933 set_toolbar_for_capture_in_progress(capture_in_progress);
935 set_capture_if_dialog_for_capture_in_progress(capture_in_progress);
939 /* Update main window items based on whether we have a capture file. */
941 main_set_for_capture_file(gboolean have_capture_file_in)
943 have_capture_file = have_capture_file_in;
945 main_widgets_show_or_hide();
948 /* Update main window items based on whether we have captured packets. */
950 main_set_for_captured_packets(gboolean have_captured_packets)
952 set_menus_for_captured_packets(have_captured_packets);
953 set_toolbar_for_captured_packets(have_captured_packets);
956 /* Update main window items based on whether we have a packet history. */
958 main_set_for_packet_history(gboolean back_history, gboolean forward_history)
960 set_menus_for_packet_history(back_history, forward_history);
961 set_toolbar_for_packet_history(back_history, forward_history);
967 /* get the current geometry, before writing it to disk */
968 main_save_window_geometry(top_level);
970 /* write user's recent file to disk
971 * It is no problem to write this file, even if we do not quit */
972 write_profile_recent();
975 /* XXX - should we check whether the capture file is an
976 unsaved temporary file for a live capture and, if so,
977 pop up a "do you want to exit without saving the capture
978 file?" dialog, and then just return, leaving said dialog
979 box to forcibly quit if the user clicks "OK"?
981 If so, note that this should be done in a subroutine that
982 returns TRUE if we do so, and FALSE otherwise, and if it
983 returns TRUE we should return TRUE without nuking anything.
985 Note that, if we do that, we might also want to check if
986 an "Update list of packets in real time" capture is in
987 progress and, if so, ask whether they want to terminate
988 the capture and discard it, and return TRUE, before nuking
989 any child capture, if they say they don't want to do so. */
992 /* Nuke any child capture in progress. */
993 capture_kill_child(&global_capture_opts);
996 /* Are we in the middle of reading a capture? */
997 if (cfile.state == FILE_READ_IN_PROGRESS) {
998 /* Yes, so we can't just close the file and quit, as
999 that may yank the rug out from under the read in
1000 progress; instead, just set the state to
1001 "FILE_READ_ABORTED" and return - the code doing the read
1002 will check for that and, if it sees that, will clean
1004 cfile.state = FILE_READ_ABORTED;
1006 /* Say that the window should *not* be deleted;
1007 that'll be done by the code that cleans up. */
1010 /* Close any capture file we have open; on some OSes, you
1011 can't unlink a temporary capture file if you have it
1013 "cf_close()" will unlink it after closing it if
1014 it's a temporary file.
1016 We do this here, rather than after the main loop returns,
1017 as, after the main loop returns, the main window may have
1018 been destroyed (if this is called due to a "destroy"
1019 even on the main window rather than due to the user
1020 selecting a menu item), and there may be a crash
1021 or other problem when "cf_close()" tries to
1022 clean up stuff in the main window.
1024 XXX - is there a better place to put this?
1025 Or should we have a routine that *just* closes the
1026 capture file, and doesn't do anything with the UI,
1027 which we'd call here, and another routine that
1028 calls that routine and also cleans up the UI, which
1029 we'd call elsewhere? */
1032 /* Exit by leaving the main loop, so that any quit functions
1033 we registered get called. */
1036 /* Say that the window should be deleted. */
1042 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1044 /* If we're in the middle of stopping a capture, don't do anything;
1045 the user can try deleting the window after the capture stops. */
1046 if (capture_stopping)
1049 /* If there's unsaved data, let the user save it first.
1050 If they cancel out of it, don't quit. */
1051 if (do_file_close(&cfile, TRUE, " before quitting"))
1052 return main_do_quit();
1054 return TRUE; /* will this keep the window from being deleted? */
1059 main_pane_load_window_geometry(void)
1061 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1062 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1063 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
1064 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1070 main_load_window_geometry(GtkWidget *widget)
1072 window_geometry_t geom;
1074 geom.set_pos = prefs.gui_geometry_save_position;
1075 geom.x = recent.gui_geometry_main_x;
1076 geom.y = recent.gui_geometry_main_y;
1077 geom.set_size = prefs.gui_geometry_save_size;
1078 if (recent.gui_geometry_main_width > 0 &&
1079 recent.gui_geometry_main_height > 0) {
1080 geom.width = recent.gui_geometry_main_width;
1081 geom.height = recent.gui_geometry_main_height;
1082 geom.set_maximized = prefs.gui_geometry_save_maximized;
1084 /* We assume this means the width and height weren't set in
1085 the "recent" file (or that there is no "recent" file),
1086 and weren't set to a default value, so we don't set the
1087 size. (The "recent" file code rejects non-positive width
1088 and height values.) */
1089 geom.set_size = FALSE;
1091 geom.maximized = recent.gui_geometry_main_maximized;
1093 window_set_geometry(widget, &geom);
1095 main_pane_load_window_geometry();
1096 statusbar_load_window_geometry();
1101 main_save_window_geometry(GtkWidget *widget)
1103 window_geometry_t geom;
1105 window_get_geometry(widget, &geom);
1107 if (prefs.gui_geometry_save_position) {
1108 recent.gui_geometry_main_x = geom.x;
1109 recent.gui_geometry_main_y = geom.y;
1112 if (prefs.gui_geometry_save_size) {
1113 recent.gui_geometry_main_width = geom.width;
1114 recent.gui_geometry_main_height = geom.height;
1117 if(prefs.gui_geometry_save_maximized) {
1118 recent.gui_geometry_main_maximized = geom.maximized;
1121 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
1122 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
1123 statusbar_save_window_geometry();
1127 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1129 /* If there's unsaved data, let the user save it first. */
1130 if (do_file_close(&cfile, TRUE, " before quitting"))
1135 print_usage(gboolean print_ver) {
1145 fprintf(output, "Wireshark " VERSION "%s\n"
1146 "Interactively dump and analyze network traffic.\n"
1147 "See http://www.wireshark.org for more information.\n"
1150 wireshark_svnversion, get_copyright_info());
1154 fprintf(output, "\n");
1155 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1156 fprintf(output, "\n");
1159 fprintf(output, "Capture interface:\n");
1160 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1161 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1162 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1163 fprintf(output, " -p don't capture in promiscuous mode\n");
1164 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1165 fprintf(output, " -S update packet display when new packets are captured\n");
1166 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1167 #ifdef HAVE_PCAP_CREATE
1168 fprintf(output, " -I capture in monitor mode, if available\n");
1170 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
1171 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1173 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1174 fprintf(output, " -D print list of interfaces and exit\n");
1175 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1176 fprintf(output, "\n");
1177 fprintf(output, "Capture stop conditions:\n");
1178 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1179 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1180 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1181 fprintf(output, " files:NUM - stop after NUM files\n");
1182 /*fprintf(output, "\n");*/
1183 fprintf(output, "Capture output:\n");
1184 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1185 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1186 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1187 #endif /* HAVE_LIBPCAP */
1189 /*fprintf(output, "\n");*/
1190 fprintf(output, "Input file:\n");
1191 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1193 fprintf(output, "\n");
1194 fprintf(output, "Processing:\n");
1195 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1196 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1197 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1199 fprintf(output, "\n");
1200 fprintf(output, "User interface:\n");
1201 fprintf(output, " -C <config profile> start with specified configuration profile\n");
1202 fprintf(output, " -d <display filter> start with the given display filter\n");
1203 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1204 fprintf(output, " -J <jump filter> jump to the first packet matching the (display)\n");
1205 fprintf(output, " filter\n");
1206 fprintf(output, " -j search backwards for a matching packet after \"-J\"\n");
1207 fprintf(output, " -m <font> set the font name used for most text\n");
1208 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1209 fprintf(output, " -u s|hms output format of seconds (def: s: seconds)\n");
1210 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1211 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1213 fprintf(output, "\n");
1214 fprintf(output, "Output:\n");
1215 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1217 fprintf(output, "\n");
1218 fprintf(output, "Miscellaneous:\n");
1219 fprintf(output, " -h display this help and exit\n");
1220 fprintf(output, " -v display version info and exit\n");
1221 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1222 fprintf(output, " persdata:path - personal data files\n");
1223 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1224 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1226 fprintf(output, " --display=DISPLAY X display to use\n");
1241 printf(PACKAGE " " VERSION "%s\n"
1248 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1249 runtime_info_str->str);
1257 * Print to the standard error. On Windows, create a console for the
1258 * standard error to show up on, if necessary.
1259 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1260 * terminal isn't the standard error?
1263 vfprintf_stderr(const char *fmt, va_list ap)
1268 vfprintf(stderr, fmt, ap);
1272 fprintf_stderr(const char *fmt, ...)
1277 vfprintf_stderr(fmt, ap);
1282 * Report an error in command-line arguments.
1283 * Creates a console on Windows.
1286 cmdarg_err(const char *fmt, ...)
1290 fprintf_stderr("wireshark: ");
1292 vfprintf_stderr(fmt, ap);
1294 fprintf_stderr("\n");
1298 * Report additional information for an error in command-line arguments.
1299 * Creates a console on Windows.
1300 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1301 * terminal isn't the standard error?
1304 cmdarg_err_cont(const char *fmt, ...)
1309 vfprintf_stderr(fmt, ap);
1310 fprintf_stderr("\n");
1315 Once every 3 seconds we get a callback here which we use to update
1319 tap_update_cb(gpointer data _U_)
1321 draw_tap_listeners(FALSE);
1325 /* Restart the tap update display timer with new configured interval */
1326 void reset_tap_update_timer(void)
1328 g_source_remove(tap_update_timer_id);
1329 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, tap_update_cb, NULL);
1333 protect_thread_critical_region(void)
1335 /* Threading support for TAP:s removed
1336 * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
1337 * See the commit for removed code:
1338 * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
1342 unprotect_thread_critical_region(void)
1344 /* Threading support for TAP:s removed
1345 * http://www.wireshark.org/lists/wireshark-dev/200611/msg00199.html
1351 * Periodically process outstanding hostname lookups. If we have new items,
1352 * redraw the packet list and tree view.
1356 resolv_update_cb(gpointer data _U_)
1358 /* Anything new show up? */
1359 if (host_name_lookup_process(NULL)) {
1360 if (gtk_widget_get_window(pkt_scrollw))
1361 gdk_window_invalidate_rect(gtk_widget_get_window(pkt_scrollw), NULL, TRUE);
1362 if (gtk_widget_get_window(tv_scrollw))
1363 gdk_window_invalidate_rect(gtk_widget_get_window(tv_scrollw), NULL, TRUE);
1366 /* Always check. Even if we don't do async lookups we could still get
1367 passive updates, e.g. from DNS packets. */
1372 /* Set main_window_name and it's icon title to the capture filename */
1374 set_display_filename(capture_file *cf)
1376 gchar *display_name;
1380 display_name = cf_get_display_name(cf);
1381 window_name = g_strdup_printf("%s%s", cf->unsaved_changes ? "*" : "",
1383 g_free(display_name);
1384 main_set_window_name(window_name);
1385 g_free(window_name);
1387 main_set_window_name("The Wireshark Network Analyzer");
1391 /* Update various parts of the main window for a capture file "unsaved
1392 changes" change - update the title to reflect whether there are
1393 unsaved changes or not, and update the menus and toolbar to
1394 enable or disable the "Save" operation. */
1396 main_update_for_unsaved_changes(capture_file *cf)
1398 set_display_filename(cf);
1399 set_menus_for_capture_file(cf);
1400 set_toolbar_for_capture_file(cf);
1405 main_auto_scroll_live_changed(gboolean auto_scroll_live_in)
1407 /* Update menubar and toolbar */
1408 menu_auto_scroll_live_changed(auto_scroll_live_in);
1409 toolbar_auto_scroll_live_changed(auto_scroll_live_in);
1411 /* change auto scroll state */
1412 auto_scroll_live = auto_scroll_live_in;
1417 main_colorize_changed(gboolean packet_list_colorize)
1419 /* Update menubar and toolbar */
1420 menu_colorize_changed(packet_list_colorize);
1421 toolbar_colorize_changed(packet_list_colorize);
1423 /* change colorization */
1424 if(packet_list_colorize != recent.packet_list_colorize) {
1425 recent.packet_list_colorize = packet_list_colorize;
1426 color_filters_enable(packet_list_colorize);
1427 new_packet_list_colorize_packets();
1431 static GtkWidget *close_dlg = NULL;
1434 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1436 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1441 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1443 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1448 main_cf_cb_file_closing(capture_file *cf)
1450 /* if we have more than 10000 packets, show a splash screen while closing */
1451 /* XXX - don't know a better way to decide whether to show or not,
1452 * as most of the time is spend in various calls that destroy various
1453 * data structures, so it wouldn't be easy to use a progress bar,
1454 * rather than, say, a progress spinner, here! */
1455 if(cf->count > 10000) {
1456 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1457 "%sClosing file!%s\n\nPlease wait ...",
1458 simple_dialog_primary_start(),
1459 simple_dialog_primary_end());
1460 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1463 /* Destroy all windows that refer to the
1464 capture file we're closing. */
1465 destroy_packet_wins();
1467 /* Restore the standard title bar message. */
1468 main_set_window_name("The Wireshark Network Analyzer");
1470 /* Disable all menu items that make sense only if you have a capture. */
1471 set_menus_for_capture_file(NULL);
1472 set_toolbar_for_capture_file(NULL);
1473 main_set_for_captured_packets(FALSE);
1474 set_menus_for_selected_packet(cf);
1475 main_set_for_capture_in_progress(FALSE);
1476 set_capture_if_dialog_for_capture_in_progress(FALSE);
1477 set_menus_for_selected_tree_row(cf);
1479 /* Set up main window for no capture file. */
1480 main_set_for_capture_file(FALSE);
1482 main_window_update();
1486 main_cf_cb_file_closed(capture_file *cf _U_)
1488 if(close_dlg != NULL) {
1489 splash_destroy(close_dlg);
1496 main_cf_cb_file_read_started(capture_file *cf _U_)
1498 tap_param_dlg_update();
1500 /* Set up main window for a capture file. */
1501 main_set_for_capture_file(TRUE);
1505 main_cf_cb_file_read_finished(capture_file *cf)
1509 if (!cf->is_tempfile && cf->filename) {
1510 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1511 add_menu_recent_capture_file(cf->filename);
1513 /* Remember folder for next Open dialog and save it in recent */
1514 dir_path = get_dirname(g_strdup(cf->filename));
1515 set_last_open_dir(dir_path);
1519 /* Update the appropriate parts of the main window. */
1520 main_update_for_unsaved_changes(cf);
1522 /* Enable menu items that make sense if you have some captured packets. */
1523 main_set_for_captured_packets(TRUE);
1527 main_cf_cb_file_rescan_finished(capture_file *cf)
1531 if (!cf->is_tempfile && cf->filename) {
1532 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1533 add_menu_recent_capture_file(cf->filename);
1535 /* Remember folder for next Open dialog and save it in recent */
1536 dir_path = get_dirname(g_strdup(cf->filename));
1537 set_last_open_dir(dir_path);
1541 /* Update the appropriate parts of the main window. */
1542 main_update_for_unsaved_changes(cf);
1546 static GList *icon_list_create(
1547 const char **icon16_xpm,
1548 const char **icon32_xpm,
1549 const char **icon48_xpm,
1550 const char **icon64_xpm)
1552 GList *icon_list = NULL;
1553 GdkPixbuf * pixbuf16;
1554 GdkPixbuf * pixbuf32;
1555 GdkPixbuf * pixbuf48;
1556 GdkPixbuf * pixbuf64;
1559 if(icon16_xpm != NULL) {
1560 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1562 icon_list = g_list_append(icon_list, pixbuf16);
1565 if(icon32_xpm != NULL) {
1566 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1568 icon_list = g_list_append(icon_list, pixbuf32);
1571 if(icon48_xpm != NULL) {
1572 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1574 icon_list = g_list_append(icon_list, pixbuf48);
1577 if(icon64_xpm != NULL) {
1578 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1580 icon_list = g_list_append(icon_list, pixbuf64);
1587 main_capture_set_main_window_title(capture_options *capture_opts)
1589 GString *title = g_string_new("");
1591 g_string_append(title, "Capturing ");
1592 g_string_append_printf(title, "from %s ", cf_get_tempfile_source(capture_opts->cf));
1593 main_set_window_name(title->str);
1594 g_string_free(title, TRUE);
1598 main_capture_cb_capture_prepared(capture_options *capture_opts)
1600 static GList *icon_list = NULL;
1602 main_capture_set_main_window_title(capture_opts);
1604 if(icon_list == NULL) {
1605 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1607 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1609 /* Disable menu items that make no sense if you're currently running
1611 main_set_for_capture_in_progress(TRUE);
1612 set_capture_if_dialog_for_capture_in_progress(TRUE);
1614 /* Don't set up main window for a capture file. */
1615 main_set_for_capture_file(FALSE);
1619 main_capture_cb_capture_update_started(capture_options *capture_opts)
1621 /* We've done this in "prepared" above, but it will be cleared while
1622 switching to the next multiple file. */
1623 main_capture_set_main_window_title(capture_opts);
1625 main_set_for_capture_in_progress(TRUE);
1626 set_capture_if_dialog_for_capture_in_progress(TRUE);
1628 /* Enable menu items that make sense if you have some captured
1629 packets (yes, I know, we don't have any *yet*). */
1630 main_set_for_captured_packets(TRUE);
1632 /* Set up main window for a capture file. */
1633 main_set_for_capture_file(TRUE);
1637 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1639 capture_file *cf = capture_opts->cf;
1640 static GList *icon_list = NULL;
1642 /* The capture isn't stopping any more - it's stopped. */
1643 capture_stopping = FALSE;
1645 if (!cf->is_tempfile && cf->filename) {
1646 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1647 add_menu_recent_capture_file(cf->filename);
1650 /* Update the main window as appropriate */
1651 main_update_for_unsaved_changes(cf);
1653 /* Enable menu items that make sense if you're not currently running
1655 main_set_for_capture_in_progress(FALSE);
1656 set_capture_if_dialog_for_capture_in_progress(FALSE);
1658 /* Set up main window for a capture file. */
1659 main_set_for_capture_file(TRUE);
1661 if(icon_list == NULL) {
1662 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1664 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1666 if(global_capture_opts.quit_after_cap) {
1667 /* command line asked us to quit after the capture */
1668 /* don't pop up a dialog to ask for unsaved files etc. */
1674 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1676 /* Don't set up main window for a capture file. */
1677 main_set_for_capture_file(FALSE);
1681 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1684 capture_file *cf = capture_opts->cf;
1686 static GList *icon_list = NULL;
1688 /* The capture isn't stopping any more - it's stopped. */
1689 capture_stopping = FALSE;
1691 /*set_display_filename(cf);*/
1693 /* Enable menu items that make sense if you're not currently running
1695 main_set_for_capture_in_progress(FALSE);
1696 set_capture_if_dialog_for_capture_in_progress(FALSE);
1698 /* Restore the standard title bar message */
1699 /* (just in case we have trouble opening the capture file). */
1700 main_set_window_name("The Wireshark Network Analyzer");
1702 if(icon_list == NULL) {
1703 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1705 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1707 /* We don't have loaded the capture file, this will be done later.
1708 * For now we still have simply a blank screen. */
1710 if(global_capture_opts.quit_after_cap) {
1711 /* command line asked us to quit after the capture */
1712 /* don't pop up a dialog to ask for unsaved files etc. */
1718 main_capture_cb_capture_stopping(capture_options *capture_opts _U_)
1720 capture_stopping = TRUE;
1721 set_menus_for_capture_stopping();
1723 set_toolbar_for_capture_stopping();
1725 set_capture_if_dialog_for_capture_stopping();
1730 main_capture_cb_capture_failed(capture_options *capture_opts _U_)
1732 static GList *icon_list = NULL;
1734 /* Capture isn't stopping any more. */
1735 capture_stopping = FALSE;
1737 /* the capture failed before the first packet was captured
1738 reset title, menus and icon */
1740 main_set_window_name("The Wireshark Network Analyzer");
1742 main_set_for_capture_in_progress(FALSE);
1743 set_capture_if_dialog_for_capture_in_progress(FALSE);
1745 main_set_for_capture_file(FALSE);
1747 if(icon_list == NULL) {
1748 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1750 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1753 if(global_capture_opts.quit_after_cap) {
1754 /* command line asked us to quit after the capture */
1755 /* don't pop up a dialog to ask for unsaved files etc. */
1759 #endif /* HAVE_LIBPCAP */
1762 main_cf_cb_packet_selected(gpointer data)
1764 capture_file *cf = data;
1766 /* Display the GUI protocol tree and packet bytes.
1767 XXX - why do we dump core if we call "proto_tree_draw()"
1768 before calling "add_byte_views()"? */
1769 add_byte_views(cf->edt, tree_view_gbl, byte_nb_ptr_gbl);
1770 proto_tree_draw(cf->edt->tree, tree_view_gbl);
1772 /* Note: Both string and hex value searches in the packet data produce a non-zero
1773 search_pos if successful */
1774 if(cf->search_in_progress &&
1775 (cf->search_pos != 0 || (cf->string && cf->decode_data))) {
1776 highlight_field(cf->edt->tvb, cf->search_pos,
1777 (GtkTreeView *)tree_view_gbl, cf->edt->tree);
1780 /* A packet is selected. */
1781 set_menus_for_selected_packet(cf);
1785 main_cf_cb_packet_unselected(capture_file *cf)
1787 /* No packet is being displayed; clear the hex dump pane by getting
1788 rid of all the byte views. */
1789 while (gtk_notebook_get_nth_page(GTK_NOTEBOOK(byte_nb_ptr_gbl), 0) != NULL)
1790 gtk_notebook_remove_page(GTK_NOTEBOOK(byte_nb_ptr_gbl), 0);
1792 /* Add a placeholder byte view so that there's at least something
1793 displayed in the byte view notebook. */
1794 add_byte_tab(byte_nb_ptr_gbl, "", NULL, NULL, tree_view_gbl);
1796 /* And clear the protocol tree display as well. */
1797 proto_tree_draw(NULL, tree_view_gbl);
1799 /* No packet is selected. */
1800 set_menus_for_selected_packet(cf);
1804 main_cf_cb_field_unselected(capture_file *cf)
1806 set_menus_for_selected_tree_row(cf);
1810 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1813 case(cf_cb_file_closing):
1814 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1815 main_cf_cb_file_closing(data);
1817 case(cf_cb_file_closed):
1818 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1819 main_cf_cb_file_closed(data);
1821 case(cf_cb_file_read_started):
1822 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read started");
1823 main_cf_cb_file_read_started(data);
1825 case(cf_cb_file_read_finished):
1826 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1827 main_cf_cb_file_read_finished(data);
1829 case(cf_cb_file_reload_started):
1830 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload started");
1831 main_cf_cb_file_read_started(data);
1833 case(cf_cb_file_reload_finished):
1834 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Reload finished");
1835 main_cf_cb_file_read_finished(data);
1837 case(cf_cb_file_rescan_started):
1838 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Rescan started");
1840 case(cf_cb_file_rescan_finished):
1841 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Rescan finished");
1842 main_cf_cb_file_rescan_finished(data);
1844 case(cf_cb_file_fast_save_finished):
1845 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Fast save finished");
1846 main_cf_cb_file_rescan_finished(data);
1848 case(cf_cb_packet_selected):
1849 main_cf_cb_packet_selected(data);
1851 case(cf_cb_packet_unselected):
1852 main_cf_cb_packet_unselected(data);
1854 case(cf_cb_field_unselected):
1855 main_cf_cb_field_unselected(data);
1857 case(cf_cb_file_save_started):
1858 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save started");
1860 case(cf_cb_file_save_finished):
1861 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save finished");
1863 case(cf_cb_file_save_failed):
1864 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save failed");
1866 case(cf_cb_file_save_stopped):
1867 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Save stopped");
1869 case(cf_cb_file_export_specified_packets_started):
1870 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets started");
1872 case(cf_cb_file_export_specified_packets_finished):
1873 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets finished");
1875 case(cf_cb_file_export_specified_packets_failed):
1876 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets failed");
1878 case(cf_cb_file_export_specified_packets_stopped):
1879 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Export specified packets stopped");
1882 g_warning("main_cf_callback: event %u unknown", event);
1883 g_assert_not_reached();
1889 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1891 #ifdef HAVE_GTKOSXAPPLICATION
1892 GtkOSXApplication *theApp;
1895 case(capture_cb_capture_prepared):
1896 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1897 main_capture_cb_capture_prepared(capture_opts);
1899 case(capture_cb_capture_update_started):
1900 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1901 main_capture_cb_capture_update_started(capture_opts);
1902 #ifdef HAVE_GTKOSXAPPLICATION
1903 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1904 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsiconcap48_xpm));
1907 case(capture_cb_capture_update_continue):
1908 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1910 case(capture_cb_capture_update_finished):
1911 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1912 main_capture_cb_capture_update_finished(capture_opts);
1914 case(capture_cb_capture_fixed_started):
1915 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1916 main_capture_cb_capture_fixed_started(capture_opts);
1918 case(capture_cb_capture_fixed_continue):
1919 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1921 case(capture_cb_capture_fixed_finished):
1922 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1923 main_capture_cb_capture_fixed_finished(capture_opts);
1925 case(capture_cb_capture_stopping):
1926 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1927 /* Beware: this state won't be called, if the capture child
1928 * closes the capturing on it's own! */
1929 #ifdef HAVE_GTKOSXAPPLICATION
1930 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
1931 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
1933 main_capture_cb_capture_stopping(capture_opts);
1935 case(capture_cb_capture_failed):
1936 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture failed");
1937 main_capture_cb_capture_failed(capture_opts);
1940 g_warning("main_capture_callback: event %u unknown", event);
1941 g_assert_not_reached();
1947 get_gtk_compiled_info(GString *str)
1949 g_string_append(str, "with ");
1950 g_string_append_printf(str,
1951 #ifdef GTK_MAJOR_VERSION
1952 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1955 "GTK+ (version unknown)");
1957 g_string_append(str, ", ");
1959 g_string_append(str, "with Cairo ");
1960 g_string_append(str, CAIRO_VERSION_STRING);
1961 g_string_append(str, ", ");
1964 g_string_append(str, "with Pango ");
1965 g_string_append(str, PANGO_VERSION_STRING);
1966 g_string_append(str, ", ");
1972 get_gui_compiled_info(GString *str)
1974 epan_get_compiled_version_info(str);
1976 g_string_append(str, ", ");
1977 #ifdef HAVE_LIBPORTAUDIO
1978 #ifdef PORTAUDIO_API_1
1979 g_string_append(str, "with PortAudio <= V18");
1980 #else /* PORTAUDIO_API_1 */
1981 g_string_append(str, "with ");
1982 g_string_append(str, Pa_GetVersionText());
1983 #endif /* PORTAUDIO_API_1 */
1984 #else /* HAVE_LIBPORTAUDIO */
1985 g_string_append(str, "without PortAudio");
1986 #endif /* HAVE_LIBPORTAUDIO */
1988 g_string_append(str, ", ");
1990 get_compiled_airpcap_version(str);
1992 g_string_append(str, "without AirPcap");
1997 get_gui_runtime_info(GString *str)
1999 epan_get_runtime_version_info(str);
2002 g_string_append(str, ", ");
2003 get_runtime_airpcap_version(str);
2007 g_string_append(str, ", ");
2008 u3_runtime_info(str);
2013 read_configuration_files(char **gdp_path, char **dp_path)
2015 int gpf_open_errno, gpf_read_errno;
2016 int cf_open_errno, df_open_errno;
2017 int gdp_open_errno, gdp_read_errno;
2018 int dp_open_errno, dp_read_errno;
2019 char *gpf_path, *pf_path;
2020 char *cf_path, *df_path;
2021 int pf_open_errno, pf_read_errno;
2024 /* load the decode as entries of this profile */
2025 load_decode_as_entries();
2027 /* Read the preference files. */
2028 prefs_p = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
2029 &pf_open_errno, &pf_read_errno, &pf_path);
2031 if (gpf_path != NULL) {
2032 if (gpf_open_errno != 0) {
2033 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2034 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
2035 g_strerror(gpf_open_errno));
2037 if (gpf_read_errno != 0) {
2038 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2039 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
2040 g_strerror(gpf_read_errno));
2043 if (pf_path != NULL) {
2044 if (pf_open_errno != 0) {
2045 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2046 "Could not open your preferences file\n\"%s\": %s.", pf_path,
2047 g_strerror(pf_open_errno));
2049 if (pf_read_errno != 0) {
2050 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2051 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
2052 g_strerror(pf_read_errno));
2059 /* if the user wants a console to be always there, well, we should open one for him */
2060 if (prefs_p->gui_console_open == console_open_always) {
2065 /* Read the capture filter file. */
2066 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
2067 if (cf_path != NULL) {
2068 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2069 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
2070 g_strerror(cf_open_errno));
2074 /* Read the display filter file. */
2075 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
2076 if (df_path != NULL) {
2077 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2078 "Could not open your display filter file\n\"%s\": %s.", df_path,
2079 g_strerror(df_open_errno));
2083 /* Read the disabled protocols file. */
2084 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
2085 dp_path, &dp_open_errno, &dp_read_errno);
2086 if (*gdp_path != NULL) {
2087 if (gdp_open_errno != 0) {
2088 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2089 "Could not open global disabled protocols file\n\"%s\": %s.",
2090 *gdp_path, g_strerror(gdp_open_errno));
2092 if (gdp_read_errno != 0) {
2093 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2094 "I/O error reading global disabled protocols file\n\"%s\": %s.",
2095 *gdp_path, g_strerror(gdp_read_errno));
2100 if (*dp_path != NULL) {
2101 if (dp_open_errno != 0) {
2102 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2103 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
2104 g_strerror(dp_open_errno));
2106 if (dp_read_errno != 0) {
2107 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2108 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
2109 g_strerror(dp_read_errno));
2118 /* Check if there's something important to tell the user during startup.
2119 * We want to do this *after* showing the main window so that any windows
2120 * we pop up will be above the main window.
2124 check_and_warn_user_startup(gchar *cf_name)
2126 check_and_warn_user_startup(gchar *cf_name _U_)
2129 gchar *cur_user, *cur_group;
2130 gpointer priv_warning_dialog;
2132 /* Tell the user not to run as root. */
2133 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
2134 cur_user = get_cur_username();
2135 cur_group = get_cur_groupname();
2136 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2137 "Running as user \"%s\" and group \"%s\".\n"
2138 "This could be dangerous.\n\n"
2139 "If you're running Wireshark this way in order to perform live capture, "
2140 "you may want to be aware that there is a better way documented at\n"
2141 "http://wiki.wireshark.org/CaptureSetup/CapturePrivileges", cur_user, cur_group);
2144 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2145 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
2149 /* Warn the user if npf.sys isn't loaded. */
2150 if (!stdin_capture && !cf_name && !npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
2151 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2152 "The NPF driver isn't running. You may have trouble\n"
2153 "capturing or listing interfaces.");
2154 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2155 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
2162 /* And now our feature presentation... [ fade to music ] */
2164 main(int argc, char *argv[])
2166 char *init_progfile_dir_error;
2169 gboolean arg_error = FALSE;
2171 extern int info_update_freq; /* Found in about_dlg.c. */
2172 const gchar *filter;
2180 char *gdp_path, *dp_path;
2183 gboolean start_capture = FALSE;
2184 gboolean list_link_layer_types = FALSE;
2188 gboolean capture_option_specified = FALSE;
2195 gint pl_size = 280, tv_size = 95, bv_size = 75;
2196 gchar *rc_file, *cf_name = NULL, *rfilter = NULL, *dfilter = NULL, *jfilter = NULL;
2197 dfilter_t *rfcode = NULL;
2198 gboolean rfilter_parse_failed = FALSE;
2201 GtkWidget *splash_win = NULL;
2202 GLogLevelFlags log_flags;
2203 guint go_to_packet = 0;
2204 gboolean jump_backwards = FALSE;
2205 dfilter_t *jump_to_filter = NULL;
2208 #ifdef HAVE_GTKOSXAPPLICATION
2209 GtkOSXApplication *theApp;
2213 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2214 #define OPTSTRING_B "B:"
2216 #define OPTSTRING_B ""
2217 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2218 #else /* HAVE_LIBPCAP */
2219 #define OPTSTRING_B ""
2220 #endif /* HAVE_LIBPCAP */
2222 #ifdef HAVE_PCAP_CREATE
2223 #define OPTSTRING_I "I"
2225 #define OPTSTRING_I ""
2228 #define OPTSTRING "a:b:" OPTSTRING_B "c:C:d:Df:g:Hhi:" OPTSTRING_I "jJ:kK:lLm:nN:o:P:pr:R:Ss:t:u:vw:X:y:z:"
2230 static const char optstring[] = OPTSTRING;
2232 /* Set the C-language locale to the native environment. */
2233 setlocale(LC_ALL, "");
2235 arg_list_utf_16to8(argc, argv);
2239 * Get credential information for later use, and drop privileges
2240 * before doing anything else.
2241 * Let the user know if anything happened.
2243 init_process_policies();
2244 relinquish_special_privs_perm();
2247 * Attempt to get the pathname of the executable file.
2249 init_progfile_dir_error = init_progfile_dir(argv[0], main);
2251 /* initialize the funnel mini-api */
2252 initialize_funnel_ops();
2254 AirPDcapInitContext(&airpdcap_ctx);
2257 /* Load wpcap if possible. Do this before collecting the run-time version information */
2260 /* ... and also load the packet.dll from wpcap */
2261 wpcap_packet_load();
2264 /* Load the airpcap.dll. This must also be done before collecting
2265 * run-time version information. */
2266 airpcap_dll_ret_val = load_airpcap();
2268 switch (airpcap_dll_ret_val) {
2269 case AIRPCAP_DLL_OK:
2270 /* load the airpcap interfaces */
2271 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2273 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2274 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2275 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2278 airpcap_if_active = NULL;
2282 /* select the first ad default (THIS SHOULD BE CHANGED) */
2283 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2288 * XXX - Maybe we need to warn the user if one of the following happens???
2290 case AIRPCAP_DLL_OLD:
2291 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2294 case AIRPCAP_DLL_ERROR:
2295 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2298 case AIRPCAP_DLL_NOT_FOUND:
2299 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2303 #endif /* HAVE_AIRPCAP */
2305 /* Start windows sockets */
2306 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2309 profile_store_persconffiles (TRUE);
2311 /* Assemble the compile-time version information string */
2312 comp_info_str = g_string_new("Compiled ");
2314 get_compiled_version_info(comp_info_str, get_gtk_compiled_info, get_gui_compiled_info);
2316 /* Assemble the run-time version information string */
2317 runtime_info_str = g_string_new("Running ");
2318 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2320 /* Read the profile independent recent file. We have to do this here so we can */
2321 /* set the profile before it can be set from the command line parameterts */
2322 recent_read_static(&rf_path, &rf_open_errno);
2323 if (rf_path != NULL && rf_open_errno != 0) {
2324 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2325 "Could not open common recent file\n\"%s\": %s.",
2326 rf_path, g_strerror(rf_open_errno));
2329 /* "pre-scan" the command line parameters, if we have "console only"
2330 parameters. We do this so we don't start GTK+ if we're only showing
2331 command-line help or version information.
2333 XXX - this pre-scan is done before we start GTK+, so we haven't
2334 run gtk_init() on the arguments. That means that GTK+ arguments
2335 have not been removed from the argument list; those arguments
2336 begin with "--", and will be treated as an error by getopt().
2338 We thus ignore errors - *and* set "opterr" to 0 to suppress the
2341 optind_initial = optind;
2342 while ((opt = getopt(argc, argv, optstring)) != -1) {
2344 case 'C': /* Configuration Profile */
2345 if (profile_exists (optarg, FALSE)) {
2346 set_profile_name (optarg);
2348 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2352 case 'D': /* Print a list of capture devices and exit */
2354 if_list = capture_interface_list(&err, &err_str);
2355 if (if_list == NULL) {
2357 case CANT_GET_INTERFACE_LIST:
2358 case DONT_HAVE_PCAP:
2359 cmdarg_err("%s", err_str);
2363 case NO_INTERFACES_FOUND:
2364 cmdarg_err("There are no interfaces on which a capture can be done");
2369 capture_opts_print_interfaces(if_list);
2370 free_interface_list(if_list);
2373 capture_option_specified = TRUE;
2377 case 'h': /* Print help and exit */
2383 if (strcmp(optarg, "-") == 0)
2384 stdin_capture = TRUE;
2387 case 'P': /* Path settings - change these before the Preferences and alike are processed */
2388 status = filesystem_opt(opt, optarg);
2390 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2394 case 'v': /* Show version and exit */
2400 * Extension command line options have to be processed before
2401 * we call epan_init() as they are supposed to be used by dissectors
2402 * or taps very early in the registration process.
2406 case '?': /* Ignore errors - the "real" scan will catch them. */
2411 /* Init the "Open file" dialog directory */
2412 /* (do this after the path settings are processed) */
2414 /* Read the profile dependent (static part) of the recent file. */
2415 /* Only the static part of it will be read, as we don't have the gui now to fill the */
2416 /* recent lists which is done in the dynamic part. */
2417 /* We have to do this already here, so command line parameters can overwrite these values. */
2418 recent_read_profile_static(&rf_path, &rf_open_errno);
2419 if (rf_path != NULL && rf_open_errno != 0) {
2420 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2421 "Could not open recent file\n\"%s\": %s.",
2422 rf_path, g_strerror(rf_open_errno));
2425 if (recent.gui_fileopen_remembered_dir &&
2426 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
2427 set_last_open_dir(recent.gui_fileopen_remembered_dir);
2429 set_last_open_dir(get_persdatafile_dir());
2432 /* Set getopt index back to initial value, so it will start with the
2433 first command line parameter again. Also reset opterr to 1, so that
2434 error messages are printed by getopt().
2436 XXX - this seems to work on most platforms, but time will tell.
2437 The Single UNIX Specification says "The getopt() function need
2438 not be reentrant", so this isn't guaranteed to work. The Mac
2439 OS X 10.4[.x] getopt() man page says
2441 In order to use getopt() to evaluate multiple sets of arguments, or to
2442 evaluate a single set of arguments multiple times, the variable optreset
2443 must be set to 1 before the second and each additional set of calls to
2444 getopt(), and the variable optind must be reinitialized.
2448 The optreset variable was added to make it possible to call the getopt()
2449 function multiple times. This is an extension to the IEEE Std 1003.2
2450 (``POSIX.2'') specification.
2452 which I think comes from one of the other BSDs.
2454 XXX - if we want to control all the command-line option errors, so
2455 that we can display them where we choose (e.g., in a window), we'd
2456 want to leave opterr as 0, and produce our own messages using optopt.
2457 We'd have to check the value of optopt to see if it's a valid option
2458 letter, in which case *presumably* the error is "this option requires
2459 an argument but none was specified", or not a valid option letter,
2460 in which case *presumably* the error is "this option isn't valid".
2461 Some versions of getopt() let you supply a option string beginning
2462 with ':', which means that getopt() will return ':' rather than '?'
2463 for "this option requires an argument but none was specified", but
2465 optind = optind_initial;
2468 #if !GLIB_CHECK_VERSION(2,31,0)
2469 g_thread_init(NULL);
2472 /* Set the current locale according to the program environment.
2473 * We haven't localized anything, but some GTK widgets are localized
2474 * (the file selection dialogue, for example).
2475 * This also sets the C-language locale to the native environment. */
2476 setlocale (LC_ALL, "");
2478 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2479 gtk_init (&argc, &argv);
2481 cf_callback_add(main_cf_callback, NULL);
2483 capture_callback_add(main_capture_callback, NULL);
2485 cf_callback_add(statusbar_cf_callback, NULL);
2487 capture_callback_add(statusbar_capture_callback, NULL);
2490 /* Arrange that if we have no console window, and a GLib message logging
2491 routine is called to log a message, we pop up a console window.
2493 We do that by inserting our own handler for all messages logged
2494 to the default domain; that handler pops up a console if necessary,
2495 and then calls the default handler. */
2497 /* We might want to have component specific log levels later ... */
2501 G_LOG_LEVEL_CRITICAL|
2502 G_LOG_LEVEL_WARNING|
2503 G_LOG_LEVEL_MESSAGE|
2506 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2508 g_log_set_handler(NULL,
2510 console_log_handler, NULL /* user_data */);
2511 g_log_set_handler(LOG_DOMAIN_MAIN,
2513 console_log_handler, NULL /* user_data */);
2516 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2518 console_log_handler, NULL /* user_data */);
2519 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2521 console_log_handler, NULL /* user_data */);
2523 /* Set the initial values in the capture options. This might be overwritten
2524 by preference settings and then again by the command line parameters. */
2525 capture_opts_init(&global_capture_opts, &cfile);
2528 /* Initialize whatever we need to allocate colors for GTK+ */
2531 /* Non-blank filter means we're remote. Throttle splash screen and resolution updates. */
2532 filter = get_conn_cfilter();
2533 if ( *filter != '\0' ) {
2534 info_update_freq = 1000; /* Milliseconds */
2537 /* We won't come till here, if we had a "console only" command line parameter. */
2538 splash_win = splash_new("Loading Wireshark ...");
2539 if (init_progfile_dir_error != NULL) {
2540 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2541 "Can't get pathname of Wireshark: %s.\n"
2542 "It won't be possible to capture traffic.\n"
2543 "Report this to the Wireshark developers.",
2544 init_progfile_dir_error);
2545 g_free(init_progfile_dir_error);
2548 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2550 /* Register all dissectors; we must do this before checking for the
2551 "-G" flag, as the "-G" flag dumps information registered by the
2552 dissectors, and we must do it before we read the preferences, in
2553 case any dissectors register preferences. */
2554 epan_init(register_all_protocols,register_all_protocol_handoffs,
2555 splash_update, (gpointer) splash_win,
2556 failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2557 write_failure_alert_box);
2559 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2561 /* Register all tap listeners; we do this before we parse the arguments,
2562 as the "-z" argument can specify a registered tap. */
2564 /* we register the plugin taps before the other taps because
2565 stats_tree taps plugins will be registered as tap listeners
2566 by stats_tree_stat.c and need to registered before that */
2569 register_all_plugin_tap_listeners();
2572 register_all_tap_listeners();
2574 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2576 prefs_p = read_configuration_files (&gdp_path, &dp_path);
2577 /* Removed thread code:
2578 * http://anonsvn.wireshark.org/viewvc/viewvc.cgi?view=rev&revision=35027
2581 /* this is to keep tap extensions updating once every 3 seconds */
2582 tap_update_timer_id = g_timeout_add(prefs_p->tap_update_interval, tap_update_cb, NULL);
2584 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2586 cap_file_init(&cfile);
2588 /* Fill in capture options with values from the preferences */
2589 prefs_to_capture_opts();
2591 /*#ifdef HAVE_LIBPCAP
2592 fill_in_local_interfaces(&global_capture_opts);
2594 /* Now get our args */
2595 while ((opt = getopt(argc, argv, optstring)) != -1) {
2597 /*** capture option specific ***/
2598 case 'a': /* autostop criteria */
2599 case 'b': /* Ringbuffer option */
2600 case 'c': /* Capture xxx packets */
2601 case 'f': /* capture filter */
2602 case 'k': /* Start capture immediately */
2603 case 'H': /* Hide capture info dialog box */
2604 case 'p': /* Don't capture in promiscuous mode */
2605 case 'i': /* Use interface x */
2606 #ifdef HAVE_PCAP_CREATE
2607 case 'I': /* Capture in monitor mode, if available */
2609 case 's': /* Set the snapshot (capture) length */
2610 case 'S': /* "Sync" mode: used for following file ala tail -f */
2611 case 'w': /* Write to capture file xxx */
2612 case 'y': /* Set the pcap data link type */
2613 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
2614 case 'B': /* Buffer size */
2615 #endif /* _WIN32 or HAVE_PCAP_CREATE */
2617 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2623 capture_option_specified = TRUE;
2628 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2629 case 'K': /* Kerberos keytab file */
2630 read_keytab_file(optarg);
2634 /*** all non capture option specific ***/
2636 /* Configuration profile settings were already processed just ignore them this time*/
2641 case 'j': /* Search backwards for a matching packet from filter in option J */
2642 jump_backwards = TRUE;
2644 case 'g': /* Go to packet with the given packet number */
2645 go_to_packet = get_positive_int(optarg, "go to packet");
2647 case 'J': /* Jump to the first packet which matches the filter criteria */
2650 case 'l': /* Automatic scrolling in live capture mode */
2652 auto_scroll_live = TRUE;
2654 capture_option_specified = TRUE;
2658 case 'L': /* Print list of link-layer types and exit */
2660 list_link_layer_types = TRUE;
2662 capture_option_specified = TRUE;
2666 case 'm': /* Fixed-width font for the display */
2667 g_free(prefs_p->gui_font_name);
2668 prefs_p->gui_font_name = g_strdup(optarg);
2670 case 'n': /* No name resolution */
2671 gbl_resolv_flags.mac_name = FALSE;
2672 gbl_resolv_flags.network_name = FALSE;
2673 gbl_resolv_flags.transport_name = FALSE;
2674 gbl_resolv_flags.concurrent_dns = FALSE;
2676 case 'N': /* Select what types of addresses/port #s to resolve */
2677 badopt = string_to_name_resolve(optarg, &gbl_resolv_flags);
2678 if (badopt != '\0') {
2679 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2684 case 'o': /* Override preference from command line */
2685 switch (prefs_set_pref(optarg)) {
2688 case PREFS_SET_SYNTAX_ERR:
2689 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2692 case PREFS_SET_NO_SUCH_PREF:
2693 /* not a preference, might be a recent setting */
2694 switch (recent_set_arg(optarg)) {
2697 case PREFS_SET_SYNTAX_ERR:
2698 /* shouldn't happen, checked already above */
2699 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2702 case PREFS_SET_NO_SUCH_PREF:
2703 case PREFS_SET_OBSOLETE:
2704 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2709 g_assert_not_reached();
2712 case PREFS_SET_OBSOLETE:
2713 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2718 g_assert_not_reached();
2722 /* Path settings were already processed just ignore them this time*/
2724 case 'r': /* Read capture file xxx */
2725 /* We may set "last_open_dir" to "cf_name", and if we change
2726 "last_open_dir" later, we free the old value, so we have to
2727 set "cf_name" to something that's been allocated. */
2728 cf_name = g_strdup(optarg);
2730 case 'R': /* Read file filter */
2733 case 't': /* Time stamp type */
2734 if (strcmp(optarg, "r") == 0)
2735 timestamp_set_type(TS_RELATIVE);
2736 else if (strcmp(optarg, "a") == 0)
2737 timestamp_set_type(TS_ABSOLUTE);
2738 else if (strcmp(optarg, "ad") == 0)
2739 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2740 else if (strcmp(optarg, "d") == 0)
2741 timestamp_set_type(TS_DELTA);
2742 else if (strcmp(optarg, "dd") == 0)
2743 timestamp_set_type(TS_DELTA_DIS);
2744 else if (strcmp(optarg, "e") == 0)
2745 timestamp_set_type(TS_EPOCH);
2746 else if (strcmp(optarg, "u") == 0)
2747 timestamp_set_type(TS_UTC);
2748 else if (strcmp(optarg, "ud") == 0)
2749 timestamp_set_type(TS_UTC_WITH_DATE);
2751 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2752 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2753 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2757 case 'u': /* Seconds type */
2758 if (strcmp(optarg, "s") == 0)
2759 timestamp_set_seconds_type(TS_SECONDS_DEFAULT);
2760 else if (strcmp(optarg, "hms") == 0)
2761 timestamp_set_seconds_type(TS_SECONDS_HOUR_MIN_SEC);
2763 cmdarg_err("Invalid seconds type \"%s\"", optarg);
2764 cmdarg_err_cont("It must be \"s\" for seconds or \"hms\" for hours, minutes and seconds.");
2769 /* ext ops were already processed just ignore them this time*/
2772 /* We won't call the init function for the stat this soon
2773 as it would disallow MATE's fields (which are registered
2774 by the preferences set callback) from being used as
2775 part of a tap filter. Instead, we just add the argument
2776 to a list of stat arguments. */
2777 if (!process_stat_cmd_arg(optarg)) {
2778 cmdarg_err("Invalid -z argument.");
2779 cmdarg_err_cont(" -z argument must be one of :");
2780 list_stat_cmd_args();
2785 case '?': /* Bad flag - print usage message */
2794 if (cf_name != NULL) {
2796 * Input file name specified with "-r" *and* specified as a regular
2797 * command-line argument.
2799 cmdarg_err("File name specified both with -r and regular argument");
2803 * Input file name not specified with "-r", and a command-line argument
2804 * was specified; treat it as the input file name.
2806 * Yes, this is different from tshark, where non-flag command-line
2807 * arguments are a filter, but this works better on GUI desktops
2808 * where a command can be specified to be run to open a particular
2809 * file - yes, you could have "-r" as the last part of the command,
2810 * but that's a bit ugly.
2812 cf_name = g_strdup(argv[0]);
2820 * Extra command line arguments were specified; complain.
2822 cmdarg_err("Invalid argument: %s", argv[0]);
2827 #ifndef HAVE_LIBPCAP
2828 if (capture_option_specified) {
2829 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2837 fill_in_local_interfaces(&global_capture_opts);
2838 if (start_capture && list_link_layer_types) {
2839 /* Specifying *both* is bogus. */
2840 cmdarg_err("You can't specify both -L and a live capture.");
2844 if (list_link_layer_types) {
2845 /* We're supposed to list the link-layer types for an interface;
2846 did the user also specify a capture file to be read? */
2848 /* Yes - that's bogus. */
2849 cmdarg_err("You can't specify -L and a capture file to be read.");
2852 /* No - did they specify a ring buffer option? */
2853 if (global_capture_opts.multi_files_on) {
2854 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2858 /* We're supposed to do a live capture; did the user also specify
2859 a capture file to be read? */
2860 if (start_capture && cf_name) {
2861 /* Yes - that's bogus. */
2862 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2866 /* No - was the ring buffer option specified and, if so, does it make
2868 if (global_capture_opts.multi_files_on) {
2869 /* Ring buffer works only under certain conditions:
2870 a) ring buffer does not work with temporary files;
2871 b) real_time_mode and multi_files_on are mutually exclusive -
2872 real_time_mode takes precedence;
2873 c) it makes no sense to enable the ring buffer if the maximum
2874 file size is set to "infinite". */
2875 if (global_capture_opts.save_file == NULL) {
2876 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2877 global_capture_opts.multi_files_on = FALSE;
2879 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2880 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2881 /* XXX - this must be redesigned as the conditions changed */
2886 if (start_capture || list_link_layer_types) {
2887 /* Did the user specify an interface to use? */
2888 if (!capture_opts_trim_iface(&global_capture_opts,
2889 (prefs_p->capture_device) ? get_if_name(prefs_p->capture_device) : NULL)) {
2894 if (list_link_layer_types) {
2895 /* Get the list of link-layer types for the capture devices. */
2896 if_capabilities_t *caps;
2899 for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
2901 device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
2902 if (device.selected) {
2903 #if defined(HAVE_PCAP_CREATE)
2904 caps = capture_get_if_capabilities(device.name, device.monitor_mode_supported, &err_str);
2906 caps = capture_get_if_capabilities(device.name, FALSE, &err_str);
2909 cmdarg_err("%s", err_str);
2913 if (caps->data_link_types == NULL) {
2914 cmdarg_err("The capture device \"%s\" has no data link types.", device.name);
2917 #if defined(HAVE_PCAP_CREATE)
2918 capture_opts_print_if_capabilities(caps, device.name, device.monitor_mode_supported);
2920 capture_opts_print_if_capabilities(caps, device.name, FALSE);
2922 free_if_capabilities(caps);
2928 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2929 capture_opts_trim_ring_num_files(&global_capture_opts);
2930 #endif /* HAVE_LIBPCAP */
2932 /* Notify all registered modules that have had any of their preferences
2933 changed either from one of the preferences file or from the command
2934 line that their preferences have changed. */
2938 if ((global_capture_opts.num_selected == 0) &&
2939 (prefs.capture_device != NULL)) {
2942 for (i = 0; i < global_capture_opts.all_ifaces->len; i++) {
2943 device = g_array_index(global_capture_opts.all_ifaces, interface_t, i);
2944 if (!device.hidden && strcmp(device.display_name, prefs.capture_device) == 0) {
2945 device.selected = TRUE;
2946 global_capture_opts.num_selected++;
2947 global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
2948 g_array_insert_val(global_capture_opts.all_ifaces, i, device);
2955 /* disabled protocols as per configuration file */
2956 if (gdp_path == NULL && dp_path == NULL) {
2957 set_disabled_protos_list();
2960 build_column_format_array(&cfile.cinfo, prefs_p->num_cols, TRUE);
2962 /* read in rc file from global and personal configuration paths. */
2963 rc_file = get_datafile_path(RC_FILE);
2964 #if GTK_CHECK_VERSION(3,0,0)
2965 /* XXX resolve later */
2967 gtk_rc_parse(rc_file);
2969 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2970 gtk_rc_parse(rc_file);
2980 /* close the splash screen, as we are going to open the main window now */
2981 splash_destroy(splash_win);
2983 /************************************************************************/
2984 /* Everything is prepared now, preferences and command line was read in */
2986 /* Pop up the main window. */
2987 create_main_window(pl_size, tv_size, bv_size, prefs_p);
2989 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2990 recent_read_dynamic(&rf_path, &rf_open_errno);
2991 if (rf_path != NULL && rf_open_errno != 0) {
2992 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2993 "Could not open recent file\n\"%s\": %s.",
2994 rf_path, g_strerror(rf_open_errno));
2997 color_filters_enable(recent.packet_list_colorize);
2999 /* rearrange all the widgets as we now have all recent settings ready for this */
3000 main_widgets_rearrange();
3002 /* Fill in column titles. This must be done after the top level window
3005 XXX - is that still true, with fixed-width columns? */
3007 menu_recent_read_finished();
3009 main_auto_scroll_live_changed(auto_scroll_live);
3012 switch (user_font_apply()) {
3015 case FA_FONT_NOT_RESIZEABLE:
3016 /* "user_font_apply()" popped up an alert box. */
3017 /* turn off zooming - font can't be resized */
3018 case FA_FONT_NOT_AVAILABLE:
3019 /* XXX - did we successfully load the un-zoomed version earlier?
3020 If so, this *probably* means the font is available, but not at
3021 this particular zoom level, but perhaps some other failure
3022 occurred; I'm not sure you can determine which is the case,
3024 /* turn off zooming - zoom level is unavailable */
3026 /* in any other case than FA_SUCCESS, turn off zooming */
3027 recent.gui_zoom_level = 0;
3028 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
3031 dnd_init(top_level);
3033 color_filters_init();
3036 capture_filter_init();
3039 /* the window can be sized only, if it's not already shown, so do it now! */
3040 main_load_window_geometry(top_level);
3042 g_timeout_add(info_update_freq, resolv_update_cb, NULL);
3045 GtkWidget *filter_te;
3046 filter_te = gtk_bin_get_child(GTK_BIN(g_object_get_data(G_OBJECT(top_level), E_DFILTER_CM_KEY)));
3047 gtk_entry_set_text(GTK_ENTRY(filter_te), dfilter);
3049 /* Run the display filter so it goes in effect. */
3050 main_filter_packets(&cfile, dfilter, FALSE);
3053 /* If we were given the name of a capture file, read it in now;
3054 we defer it until now, so that, if we can't open it, and pop
3055 up an alert box, the alert box is more likely to come up on
3056 top of the main window - but before the preference-file-error
3057 alert box, so, if we get one of those, it's more likely to come
3060 show_main_window(TRUE);
3061 check_and_warn_user_startup(cf_name);
3062 if (rfilter != NULL) {
3063 if (!dfilter_compile(rfilter, &rfcode)) {
3064 bad_dfilter_alert_box(top_level, rfilter);
3065 rfilter_parse_failed = TRUE;
3068 if (!rfilter_parse_failed) {
3069 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
3070 /* "cf_open()" succeeded, so it closed the previous
3071 capture file, and thus destroyed any previous read filter
3072 attached to "cf". */
3074 cfile.rfcode = rfcode;
3075 /* Open stat windows; we do so after creating the main window,
3076 to avoid GTK warnings, and after successfully opening the
3077 capture file, so we know we have something to compute stats
3078 on, and after registering all dissectors, so that MATE will
3079 have registered its field array and we can have a tap filter
3080 with one of MATE's late-registered fields as part of the
3082 start_requested_stats();
3084 /* Read the capture file. */
3085 switch (cf_read(&cfile, FALSE)) {
3089 /* Just because we got an error, that doesn't mean we were unable
3090 to read any of the file; we handle what we could get from the
3092 /* if the user told us to jump to a specific packet, do it now */
3093 if(go_to_packet != 0) {
3094 /* Jump to the specified frame number, kept for backward
3096 cf_goto_frame(&cfile, go_to_packet);
3097 } else if (jfilter != NULL) {
3098 /* try to compile given filter */
3099 if (!dfilter_compile(jfilter, &jump_to_filter)) {
3100 bad_dfilter_alert_box(top_level, jfilter);
3102 /* Filter ok, jump to the first packet matching the filter
3103 conditions. Default search direction is forward, but if
3104 option d was given, search backwards */
3105 cf_find_packet_dfilter(&cfile, jump_to_filter, jump_backwards);
3110 case CF_READ_ABORTED:
3116 /* If the filename is not the absolute path, prepend the current dir. This happens
3117 when wireshark is invoked from a cmd shell (e.g.,'wireshark -r file.pcap'). */
3118 if (!g_path_is_absolute(cf_name)) {
3119 char *old_cf_name = cf_name;
3120 char *pwd = g_get_current_dir();
3121 cf_name = g_strdup_printf("%s%s%s", pwd, G_DIR_SEPARATOR_S, cf_name);
3122 g_free(old_cf_name);
3126 /* Save the name of the containing directory specified in the
3127 path name, if any; we can write over cf_name, which is a
3128 good thing, given that "get_dirname()" does write over its
3130 s = get_dirname(cf_name);
3131 set_last_open_dir(s);
3136 dfilter_free(rfcode);
3137 cfile.rfcode = NULL;
3138 show_main_window(FALSE);
3139 /* Don't call check_and_warn_user_startup(): we did it above */
3140 main_set_for_capture_in_progress(FALSE);
3141 set_capture_if_dialog_for_capture_in_progress(FALSE);
3146 if (start_capture) {
3147 if (global_capture_opts.save_file != NULL) {
3148 /* Save the directory name for future file dialogs. */
3149 /* (get_dirname overwrites filename) */
3150 s = get_dirname(g_strdup(global_capture_opts.save_file));
3151 set_last_open_dir(s);
3154 /* "-k" was specified; start a capture. */
3155 show_main_window(FALSE);
3156 check_and_warn_user_startup(cf_name);
3158 /* If no user interfaces were specified on the command line,
3159 copy the list of selected interfaces to the set of interfaces
3160 to use for this capture. */
3161 if (global_capture_opts.ifaces->len == 0)
3162 collect_ifaces(&global_capture_opts);
3163 if (capture_start(&global_capture_opts)) {
3164 /* The capture started. Open stat windows; we do so after creating
3165 the main window, to avoid GTK warnings, and after successfully
3166 opening the capture file, so we know we have something to compute
3167 stats on, and after registering all dissectors, so that MATE will
3168 have registered its field array and we can have a tap filter with
3169 one of MATE's late-registered fields as part of the filter. */
3170 start_requested_stats();
3173 show_main_window(FALSE);
3174 check_and_warn_user_startup(cf_name);
3175 main_set_for_capture_in_progress(FALSE);
3176 set_capture_if_dialog_for_capture_in_progress(FALSE);
3179 /* if the user didn't supply a capture filter, use the one to filter out remote connections like SSH */
3180 if (!start_capture && !global_capture_opts.default_options.cfilter) {
3181 global_capture_opts.default_options.cfilter = g_strdup(get_conn_cfilter());
3183 #else /* HAVE_LIBPCAP */
3184 show_main_window(FALSE);
3185 check_and_warn_user_startup(cf_name);
3186 main_set_for_capture_in_progress(FALSE);
3187 set_capture_if_dialog_for_capture_in_progress(FALSE);
3188 #endif /* HAVE_LIBPCAP */
3191 /* register our pid if we are being run from a U3 device */
3194 profile_store_persconffiles (FALSE);
3196 #ifdef HAVE_GTKOSXAPPLICATION
3197 theApp = g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
3198 gtk_osxapplication_set_dock_icon_pixbuf(theApp,gdk_pixbuf_new_from_xpm_data(wsicon64_xpm));
3199 gtk_osxapplication_ready(theApp);
3202 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
3205 gtk_iface_mon_start();
3208 /* we'll enter the GTK loop now and hand the control over to GTK ... */
3210 /* ... back from GTK, we're going down now! */
3213 gtk_iface_mon_stop();
3216 /* deregister our pid */
3217 u3_deregister_pid();
3221 AirPDcapDestroyContext(&airpdcap_ctx);
3224 /* hide the (unresponsive) main window, while asking the user to close the console window */
3225 gtk_widget_hide(top_level);
3227 #ifdef HAVE_GTKOSXAPPLICATION
3228 g_object_unref(theApp);
3231 /* Shutdown windows sockets */
3234 /* For some unknown reason, the "atexit()" call in "create_console()"
3235 doesn't arrange that "destroy_console()" be called when we exit,
3236 so we call it here if a console was created. */
3245 /* We build this as a GUI subsystem application on Win32, so
3246 "WinMain()", not "main()", gets called.
3248 Hack shamelessly stolen from the Win32 port of the GIMP. */
3250 #define _stdcall __attribute__((stdcall))
3254 WinMain (struct HINSTANCE__ *hInstance,
3255 struct HINSTANCE__ *hPrevInstance,
3259 INITCOMMONCONTROLSEX comm_ctrl;
3262 * Initialize our DLL search path. MUST be called before LoadLibrary
3265 ws_init_dll_search_path();
3267 /* Initialize our controls. Required for native Windows file dialogs. */
3268 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3269 comm_ctrl.dwSize = sizeof(comm_ctrl);
3270 /* Includes the animate, header, hot key, list view, progress bar,
3271 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3274 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3275 InitCommonControlsEx(&comm_ctrl);
3277 /* RichEd20.DLL is needed for filter entries. */
3278 ws_load_library("riched20.dll");
3280 has_console = FALSE;
3281 console_wait = FALSE;
3282 return main (__argc, __argv);
3285 /* The code to create and desstroy console windows should not be necessary,
3286 at least as I read the GLib source code, as it looks as if GLib is, on
3287 Win32, *supposed* to create a console window into which to display its
3290 That doesn't happen, however. I suspect there's something completely
3291 broken about that code in GLib-for-Win32, and that it may be related
3292 to the breakage that forces us to just call "printf()" on the message
3293 rather than passing the message on to "g_log_default_handler()"
3294 (which is the routine that does the aforementioned non-functional
3295 console window creation). */
3298 * If this application has no console window to which its standard output
3299 * would go, create one.
3302 create_console(void)
3304 if (stdin_capture) {
3305 /* We've been handed "-i -". Don't mess with stdio. */
3310 /* We have no console to which to print the version string, so
3311 create one and make it the standard input, output, and error. */
3314 * See if we have an existing console (i.e. we were run from a
3317 if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
3318 if (AllocConsole()) {
3319 console_wait = TRUE;
3320 SetConsoleTitle(_T("Wireshark Debug Console"));
3322 return; /* couldn't create console */
3326 ws_freopen("CONIN$", "r", stdin);
3327 ws_freopen("CONOUT$", "w", stdout);
3328 ws_freopen("CONOUT$", "w", stderr);
3329 fprintf(stdout, "\n");
3330 fprintf(stderr, "\n");
3332 /* Now register "destroy_console()" as a routine to be called just
3333 before the application exits, so that we can destroy the console
3334 after the user has typed a key (so that the console doesn't just
3335 disappear out from under them, giving the user no chance to see
3336 the message(s) we put in there). */
3337 atexit(destroy_console);
3339 /* Well, we have a console now. */
3345 destroy_console(void)
3348 printf("\n\nPress any key to exit\n");
3357 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3358 const char *message, gpointer user_data _U_)
3365 /* ignore log message, if log_level isn't interesting based
3366 upon the console log preferences.
3367 If the preferences haven't been loaded loaded yet, display the
3370 The default console_log_level preference value is such that only
3371 ERROR, CRITICAL and WARNING level messages are processed;
3372 MESSAGE, INFO and DEBUG level messages are ignored. */
3373 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3374 prefs.console_log_level != 0) {
3379 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3380 /* the user wants a console or the application will terminate immediately */
3384 /* For some unknown reason, the above doesn't appear to actually cause
3385 anything to be sent to the standard output, so we'll just splat the
3386 message out directly, just to make sure it gets out. */
3388 switch(log_level & G_LOG_LEVEL_MASK) {
3389 case G_LOG_LEVEL_ERROR:
3392 case G_LOG_LEVEL_CRITICAL:
3395 case G_LOG_LEVEL_WARNING:
3398 case G_LOG_LEVEL_MESSAGE:
3401 case G_LOG_LEVEL_INFO:
3404 case G_LOG_LEVEL_DEBUG:
3408 fprintf(stderr, "unknown log_level %u\n", log_level);
3410 g_assert_not_reached();
3413 /* create a "timestamp" */
3415 today = localtime(&curr);
3417 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3418 today->tm_hour, today->tm_min, today->tm_sec,
3419 log_domain != NULL ? log_domain : "",
3422 if(log_level & G_LOG_LEVEL_ERROR) {
3423 /* wait for a key press before the following error handler will terminate the program
3424 this way the user at least can read the error message */
3425 printf("\n\nPress any key to exit\n");
3429 /* XXX - on UN*X, should we just use g_log_default_handler()?
3430 We want the error messages to go to the standard output;
3431 on Mac OS X, that will cause them to show up in various
3432 per-user logs accessible through Console (details depend
3433 on whether you're running 10.0 through 10.4 or running
3434 10.5 and later), and, on other UN*X desktop environments,
3435 if they don't show up in some form of console log, that's
3436 a deficiency in that desktop environment. (Too bad
3437 Windows doesn't set the standard output and error for
3438 GUI apps to something that shows up in such a log.) */
3439 g_log_default_handler(log_domain, log_level, message, user_data);
3446 * Helper for main_widgets_rearrange()
3448 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3449 gtk_container_remove(GTK_CONTAINER(data), widget);
3452 static GtkWidget *main_widget_layout(gint layout_content)
3454 switch(layout_content) {
3455 case(layout_pane_content_none):
3457 case(layout_pane_content_plist):
3459 case(layout_pane_content_pdetails):
3461 case(layout_pane_content_pbytes):
3462 return byte_nb_ptr_gbl;
3464 g_assert_not_reached();
3471 * Rearrange the main window widgets
3473 void main_widgets_rearrange(void) {
3474 GtkWidget *first_pane_widget1, *first_pane_widget2;
3475 GtkWidget *second_pane_widget1, *second_pane_widget2;
3476 gboolean split_top_left = FALSE;
3478 /* be a bit faster */
3479 gtk_widget_hide(main_vbox);
3481 /* be sure we don't lose a widget while rearranging */
3482 g_object_ref(G_OBJECT(menubar));
3483 g_object_ref(G_OBJECT(main_tb));
3484 g_object_ref(G_OBJECT(filter_tb));
3485 g_object_ref(G_OBJECT(wireless_tb));
3486 g_object_ref(G_OBJECT(pkt_scrollw));
3487 g_object_ref(G_OBJECT(tv_scrollw));
3488 g_object_ref(G_OBJECT(byte_nb_ptr_gbl));
3489 g_object_ref(G_OBJECT(statusbar));
3490 g_object_ref(G_OBJECT(main_pane_v1));
3491 g_object_ref(G_OBJECT(main_pane_v2));
3492 g_object_ref(G_OBJECT(main_pane_h1));
3493 g_object_ref(G_OBJECT(main_pane_h2));
3494 g_object_ref(G_OBJECT(welcome_pane));
3496 /* empty all containers participating */
3497 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
3498 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
3499 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
3500 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
3501 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
3503 statusbar_widgets_emptying(statusbar);
3505 /* add the menubar always at the top */
3506 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3509 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3511 /* filter toolbar in toolbar area */
3512 if (!prefs.filter_toolbar_show_in_statusbar) {
3513 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3516 /* airpcap toolbar */
3517 gtk_box_pack_start(GTK_BOX(main_vbox), wireless_tb, FALSE, TRUE, 1);
3519 /* fill the main layout panes */
3520 switch(prefs.gui_layout_type) {
3521 case(layout_type_5):
3522 main_first_pane = main_pane_v1;
3523 main_second_pane = main_pane_v2;
3524 split_top_left = FALSE;
3526 case(layout_type_2):
3527 main_first_pane = main_pane_v1;
3528 main_second_pane = main_pane_h1;
3529 split_top_left = FALSE;
3531 case(layout_type_1):
3532 main_first_pane = main_pane_v1;
3533 main_second_pane = main_pane_h1;
3534 split_top_left = TRUE;
3536 case(layout_type_4):
3537 main_first_pane = main_pane_h1;
3538 main_second_pane = main_pane_v1;
3539 split_top_left = FALSE;
3541 case(layout_type_3):
3542 main_first_pane = main_pane_h1;
3543 main_second_pane = main_pane_v1;
3544 split_top_left = TRUE;
3546 case(layout_type_6):
3547 main_first_pane = main_pane_h1;
3548 main_second_pane = main_pane_h2;
3549 split_top_left = FALSE;
3552 main_first_pane = NULL;
3553 main_second_pane = NULL;
3554 g_assert_not_reached();
3556 if (split_top_left) {
3557 first_pane_widget1 = main_second_pane;
3558 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3559 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3560 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3562 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3563 first_pane_widget2 = main_second_pane;
3564 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3565 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3567 if (first_pane_widget1 != NULL)
3568 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3569 if (first_pane_widget2 != NULL)
3570 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3571 if (second_pane_widget1 != NULL)
3572 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3573 if (second_pane_widget2 != NULL)
3574 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3576 gtk_box_pack_start(GTK_BOX(main_vbox), main_first_pane, TRUE, TRUE, 0);
3579 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3582 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3584 /* filter toolbar in statusbar hbox */
3585 if (prefs.filter_toolbar_show_in_statusbar) {
3586 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3589 /* statusbar widgets */
3590 statusbar_widgets_pack(statusbar);
3592 /* hide widgets on users recent settings */
3593 main_widgets_show_or_hide();
3595 gtk_widget_show(main_vbox);
3599 is_widget_visible(GtkWidget *widget, gpointer data)
3601 gboolean *is_visible = data;
3604 if (gtk_widget_get_visible(widget))
3611 main_widgets_show_or_hide(void)
3613 gboolean main_second_pane_show;
3615 if (recent.main_toolbar_show) {
3616 gtk_widget_show(main_tb);
3618 gtk_widget_hide(main_tb);
3621 statusbar_widgets_show_or_hide(statusbar);
3623 if (recent.filter_toolbar_show) {
3624 gtk_widget_show(filter_tb);
3626 gtk_widget_hide(filter_tb);
3629 if (recent.wireless_toolbar_show) {
3630 gtk_widget_show(wireless_tb);
3632 gtk_widget_hide(wireless_tb);
3635 if (recent.packet_list_show && have_capture_file) {
3636 gtk_widget_show(pkt_scrollw);
3638 gtk_widget_hide(pkt_scrollw);
3641 if (recent.tree_view_show && have_capture_file) {
3642 gtk_widget_show(tv_scrollw);
3644 gtk_widget_hide(tv_scrollw);
3647 if (recent.byte_view_show && have_capture_file) {
3648 gtk_widget_show(byte_nb_ptr_gbl);
3650 gtk_widget_hide(byte_nb_ptr_gbl);
3653 if (have_capture_file) {
3654 gtk_widget_show(main_first_pane);
3656 gtk_widget_hide(main_first_pane);
3660 * Is anything in "main_second_pane" visible?
3661 * If so, show it, otherwise hide it.
3663 main_second_pane_show = FALSE;
3664 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3665 &main_second_pane_show);
3666 if (main_second_pane_show) {
3667 gtk_widget_show(main_second_pane);
3669 gtk_widget_hide(main_second_pane);
3672 if (!have_capture_file) {
3674 gtk_widget_show(welcome_pane);
3677 gtk_widget_hide(welcome_pane);
3682 /* called, when the window state changes (minimized, maximized, ...) */
3684 window_state_event_cb (GtkWidget *widget _U_,
3688 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3690 if( (event->type) == (GDK_WINDOW_STATE)) {
3691 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3692 /* we might have dialogs popped up while we where iconified,
3694 display_queued_messages();
3702 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3704 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3706 if (event->keyval == GDK_F8) {
3707 new_packet_list_next();
3709 } else if (event->keyval == GDK_F7) {
3710 new_packet_list_prev();
3712 } else if (event->state & NO_SHIFT_MOD_MASK) {
3713 return FALSE; /* Skip control, alt, and other modifiers */
3715 * A comment in gdkkeysyms.h says that it's autogenerated from
3716 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3717 * don't explicitly say so, isprint() should work as expected
3720 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3721 /* Forward the keypress on to the display filter entry */
3722 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3723 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3724 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3732 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs_p)
3734 GtkAccelGroup *accel;
3737 top_level = window_new(GTK_WINDOW_TOPLEVEL, "");
3738 main_set_window_name("The Wireshark Network Analyzer");
3740 gtk_widget_set_name(top_level, "main window");
3741 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3743 g_signal_connect(G_OBJECT(top_level), "window_state_event",
3744 G_CALLBACK(window_state_event_cb), NULL);
3745 g_signal_connect(G_OBJECT(top_level), "key-press-event",
3746 G_CALLBACK(top_level_key_pressed_cb), NULL );
3748 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3749 main_vbox = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 1, FALSE);
3751 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 0);
3752 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3753 gtk_widget_show(main_vbox);
3756 menubar = main_menu_new(&accel);
3758 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined (HAVE_GTKOSXAPPLICATION)
3759 /* Mac OS X native menus are created and displayed by main_menu_new() */
3760 if(!prefs_p->gui_macosx_style) {
3762 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3763 gtk_widget_show(menubar);
3764 #if defined(HAVE_IGE_MAC_INTEGRATION) || defined(HAVE_GTKOSXAPPLICATION)
3769 main_tb = toolbar_new();
3770 gtk_widget_show (main_tb);
3772 /* Filter toolbar */
3773 filter_tb = filter_toolbar_new();
3776 pkt_scrollw = new_packet_list_create();
3777 gtk_widget_set_size_request(pkt_scrollw, -1, pl_size);
3778 gtk_widget_show_all(pkt_scrollw);
3781 tv_scrollw = proto_tree_view_new(prefs_p, &tree_view_gbl);
3782 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3783 gtk_widget_show(tv_scrollw);
3785 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gbl)),
3786 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3787 g_signal_connect(tree_view_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3788 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3789 gtk_widget_show(tree_view_gbl);
3792 byte_nb_ptr_gbl = byte_view_new();
3793 gtk_widget_set_size_request(byte_nb_ptr_gbl, -1, bv_size);
3794 gtk_widget_show(byte_nb_ptr_gbl);
3796 g_signal_connect(byte_nb_ptr_gbl, "button_press_event", G_CALLBACK(popup_menu_handler),
3797 g_object_get_data(G_OBJECT(popup_menu_object), PM_BYTES_VIEW_KEY));
3799 /* Panes for the packet list, tree, and byte view */
3800 main_pane_v1 = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
3801 gtk_widget_show(main_pane_v1);
3802 main_pane_v2 = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
3803 gtk_widget_show(main_pane_v2);
3804 main_pane_h1 = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
3805 gtk_widget_show(main_pane_h1);
3806 main_pane_h2 = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
3807 gtk_widget_show(main_pane_h2);
3809 wireless_tb = airpcap_toolbar_new();
3811 wireless_tb = ws80211_toolbar_new();
3813 gtk_widget_show(wireless_tb);
3816 statusbar = statusbar_new();
3817 gtk_widget_show(statusbar);
3819 /* Pane for the welcome screen */
3820 welcome_pane = welcome_new();
3821 gtk_widget_show(welcome_pane);
3825 show_main_window(gboolean doing_work)
3827 main_set_for_capture_file(doing_work);
3829 /*** we have finished all init things, show the main window ***/
3830 gtk_widget_show(top_level);
3832 /* the window can be maximized only, if it's visible, so do it after show! */
3833 main_load_window_geometry(top_level);
3835 /* process all pending GUI events before continue */
3836 while (gtk_events_pending()) gtk_main_iteration();
3838 /* Pop up any queued-up alert boxes. */
3839 display_queued_messages();
3841 /* Move the main window to the front, in case it isn't already there */
3842 gdk_window_raise(gtk_widget_get_window(top_level));
3845 airpcap_toolbar_show(wireless_tb);
3846 #endif /* HAVE_AIRPCAP */
3849 /* Fill in capture options with values from the preferences */
3851 prefs_to_capture_opts(void)
3854 /* Set promiscuous mode from the preferences setting. */
3855 /* the same applies to other preferences settings as well. */
3856 global_capture_opts.default_options.promisc_mode = prefs.capture_prom_mode;
3857 global_capture_opts.use_pcapng = prefs.capture_pcap_ng;
3858 global_capture_opts.show_info = prefs.capture_show_info;
3859 global_capture_opts.real_time_mode = prefs.capture_real_time;
3860 auto_scroll_live = prefs.capture_auto_scroll;
3861 #endif /* HAVE_LIBPCAP */
3864 static void copy_global_profile (const gchar *profile_name)
3866 char *pf_dir_path, *pf_dir_path2, *pf_filename;
3868 if (create_persconffile_profile(profile_name, &pf_dir_path) == -1) {
3869 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3870 "Can't create directory\n\"%s\":\n%s.",
3871 pf_dir_path, g_strerror(errno));
3873 g_free(pf_dir_path);
3876 if (copy_persconffile_profile(profile_name, profile_name, TRUE, &pf_filename,
3877 &pf_dir_path, &pf_dir_path2) == -1) {
3878 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
3879 "Can't copy file \"%s\" in directory\n\"%s\" to\n\"%s\":\n%s.",
3880 pf_filename, pf_dir_path2, pf_dir_path, g_strerror(errno));
3882 g_free(pf_filename);
3883 g_free(pf_dir_path);
3884 g_free(pf_dir_path2);
3888 /* Change configuration profile */
3889 void change_configuration_profile (const gchar *profile_name)
3891 char *gdp_path, *dp_path;
3895 /* First check if profile exists */
3896 if (!profile_exists(profile_name, FALSE)) {
3897 if (profile_exists(profile_name, TRUE)) {
3898 /* Copy from global profile */
3899 copy_global_profile (profile_name);
3901 /* No personal and no global profile exists */
3906 /* Then check if changing to another profile */
3907 if (profile_name && strcmp (profile_name, get_profile_name()) == 0) {
3911 /* Get the current geometry, before writing it to disk */
3912 main_save_window_geometry(top_level);
3914 if (profile_exists(get_profile_name(), FALSE)) {
3915 /* Write recent file for profile we are leaving, if it still exists */
3916 write_profile_recent();
3919 /* Set profile name and update the status bar */
3920 set_profile_name (profile_name);
3921 profile_bar_update ();
3922 filter_expression_reinit(FILTER_EXPRESSION_REINIT_DESTROY);
3924 /* Reset current preferences and apply the new */
3928 (void) read_configuration_files (&gdp_path, &dp_path);
3930 recent_read_profile_static(&rf_path, &rf_open_errno);
3931 if (rf_path != NULL && rf_open_errno != 0) {
3932 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3933 "Could not open common recent file\n\"%s\": %s.",
3934 rf_path, g_strerror(rf_open_errno));
3936 if (recent.gui_fileopen_remembered_dir &&
3937 test_for_directory(recent.gui_fileopen_remembered_dir) == EISDIR) {
3938 set_last_open_dir(recent.gui_fileopen_remembered_dir);
3940 timestamp_set_type (recent.gui_time_format);
3941 timestamp_set_seconds_type (recent.gui_seconds_format);
3942 color_filters_enable(recent.packet_list_colorize);
3944 prefs_to_capture_opts();
3946 macros_post_update();
3948 /* Update window view and redraw the toolbar */
3949 main_titlebar_update();
3950 filter_expression_reinit(FILTER_EXPRESSION_REINIT_CREATE);
3951 toolbar_redraw_all();
3953 /* Enable all protocols and disable from the disabled list */
3955 if (gdp_path == NULL && dp_path == NULL) {
3956 set_disabled_protos_list();
3959 /* Reload color filters */
3960 color_filters_reload();
3962 /* Reload list of interfaces on welcome page */
3963 welcome_if_panel_reload();
3965 /* Recreate the packet list according to new preferences */
3966 new_packet_list_recreate ();
3967 cfile.cinfo.columns_changed = FALSE; /* Reset value */
3970 /* Update menus with new recent values */
3971 menu_recent_read_finished();
3973 /* Reload pane geometry, must be done after recreating the list */
3974 main_pane_load_window_geometry();
3977 /** redissect packets and update UI */
3978 void redissect_packets(void)
3980 cf_redissect_packets(&cfile);
3981 status_expert_update();