5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * Richard Sharpe, 13-Feb-1999, added support for initializing structures
10 * needed by dissect routines
11 * Jeff Foster, 2001/03/12, added support tabbed hex display windowss
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #include <gdk/gdkkeysyms.h>
43 #ifdef NEED_STRERROR_H
51 #ifdef _WIN32 /* Needed for console I/O */
56 #ifdef HAVE_LIBPORTAUDIO
57 #include <portaudio.h>
58 #endif /* HAVE_LIBPORTAUDIO */
60 #include <epan/epan.h>
61 #include <epan/filesystem.h>
62 #include <wsutil/privileges.h>
63 #include <epan/epan_dissect.h>
64 #include <epan/timestamp.h>
65 #include <epan/packet.h>
66 #include <epan/plugins.h>
67 #include <epan/dfilter/dfilter.h>
68 #include <epan/strutil.h>
69 #include <epan/addr_resolv.h>
70 #include <epan/emem.h>
71 #include <epan/ex-opt.h>
72 #include <epan/funnel.h>
73 #include <epan/expert.h>
74 #include <epan/frequency-utils.h>
75 #include <epan/prefs.h>
76 #include <epan/prefs-int.h>
78 #include <epan/stat_cmd_args.h>
80 #include <epan/emem.h>
81 #include <epan/column.h>
83 /* general (not GTK specific) */
85 #include "../summary.h"
86 #include "../filters.h"
87 #include "../disabled_protos.h"
89 #include "../color_filters.h"
91 #include "../simple_dialog.h"
92 #include "../register.h"
93 #include "../ringbuffer.h"
94 #include "../ui_util.h"
96 #include "../clopts_common.h"
97 #include "../cmdarg_err.h"
98 #include "../version_info.h"
100 #include "../alert_box.h"
101 #include "../capture_ui_utils.h"
103 #include <wsutil/file_util.h>
107 #include "../capture-pcap-util.h"
108 #include "../capture.h"
109 #include "../capture_sync.h"
113 #include "../capture-wpcap.h"
114 #include "../capture_wpcap_packet.h"
115 #include <tchar.h> /* Needed for Unicode */
116 #include <commctrl.h>
120 #include "gtk/file_dlg.h"
121 #include "gtk/gtkglobals.h"
122 #include "gtk/color_utils.h"
123 #include "gtk/gui_utils.h"
124 #include "gtk/color_dlg.h"
125 #include "gtk/filter_dlg.h"
126 #include "gtk/uat_gui.h"
128 #include "gtk/main.h"
129 #include "gtk/main_airpcap_toolbar.h"
130 #include "gtk/main_filter_toolbar.h"
131 #include "gtk/main_menu.h"
132 #include "gtk/main_packet_list.h"
133 #include "gtk/main_statusbar.h"
134 #include "gtk/main_statusbar_private.h"
135 #include "gtk/main_toolbar.h"
136 #include "gtk/main_welcome.h"
137 #include "gtk/drag_and_drop.h"
138 #include "gtk/capture_file_dlg.h"
139 #include "gtk/main_proto_draw.h"
140 #include "gtk/keys.h"
141 #include "gtk/packet_win.h"
142 #include "gtk/stock_icons.h"
143 #include "gtk/find_dlg.h"
144 #include "gtk/recent.h"
145 #include "gtk/follow_tcp.h"
146 #include "gtk/font_utils.h"
147 #include "gtk/about_dlg.h"
148 #include "gtk/help_dlg.h"
149 #include "gtk/decode_as_dlg.h"
150 #include "gtk/webbrowser.h"
151 #include "gtk/capture_dlg.h"
152 #include "gtk/capture_if_dlg.h"
153 #include "gtk/tap_dfilter_dlg.h"
156 #include "../image/wsicon16.xpm"
157 #include "../image/wsicon32.xpm"
158 #include "../image/wsicon48.xpm"
159 #include "../image/wsicon64.xpm"
160 #include "../image/wsiconcap16.xpm"
161 #include "../image/wsiconcap32.xpm"
162 #include "../image/wsiconcap48.xpm"
167 #include "airpcap_loader.h"
168 #include "airpcap_dlg.h"
169 #include "airpcap_gui_utils.h"
171 #include "./image/toolbar/wep_closed_24.xpm"
175 #include <epan/crypt/airpdcap_ws.h>
179 * Files under personal and global preferences directories in which
180 * GTK settings for Wireshark are stored.
182 #define RC_FILE "gtkrc"
186 /* "exported" main widgets */
187 GtkWidget *top_level = NULL, *pkt_scrollw, *tree_view, *byte_nb_ptr;
189 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
190 static GtkWidget *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
191 static GtkWidget *main_first_pane, *main_second_pane;
193 /* internally used widgets */
194 static GtkWidget *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
197 GtkWidget *airpcap_tb;
198 int airpcap_dll_ret_val = -1;
201 GString *comp_info_str, *runtime_info_str;
202 gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
204 guint tap_update_timer_id;
207 static gboolean has_console; /* TRUE if app has console */
208 static void destroy_console(void);
209 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
211 static void console_log_handler(const char *log_domain,
212 GLogLevelFlags log_level, const char *message, gpointer user_data);
215 capture_options global_capture_opts;
219 static void create_main_window(gint, gint, gint, e_prefs*);
220 static void show_main_window(gboolean);
221 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
222 static void main_save_window_geometry(GtkWidget *widget);
225 /* Match selected byte pattern */
227 match_selected_cb_do(gpointer data, int action, gchar *text)
229 GtkWidget *filter_te;
230 char *cur_filter, *new_filter;
232 if ((!text) || (0 == strlen(text))) {
233 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
238 filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
241 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
243 switch (action&MATCH_SELECTED_MASK) {
245 case MATCH_SELECTED_REPLACE:
246 new_filter = g_strdup(text);
249 case MATCH_SELECTED_AND:
250 if ((!cur_filter) || (0 == strlen(cur_filter)))
251 new_filter = g_strdup(text);
253 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
256 case MATCH_SELECTED_OR:
257 if ((!cur_filter) || (0 == strlen(cur_filter)))
258 new_filter = g_strdup(text);
260 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
263 case MATCH_SELECTED_NOT:
264 new_filter = g_strconcat("!(", text, ")", NULL);
267 case MATCH_SELECTED_AND_NOT:
268 if ((!cur_filter) || (0 == strlen(cur_filter)))
269 new_filter = g_strconcat("!(", text, ")", NULL);
271 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
274 case MATCH_SELECTED_OR_NOT:
275 if ((!cur_filter) || (0 == strlen(cur_filter)))
276 new_filter = g_strconcat("!(", text, ")", NULL);
278 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
282 g_assert_not_reached();
287 /* Free up the copy we got of the old filter text. */
290 /* Don't change the current display filter if we only want to copy the filter */
291 if (action&MATCH_SELECTED_COPY_ONLY) {
292 GString *gtk_text_str = g_string_new("");
293 g_string_append(gtk_text_str, new_filter);
294 copy_to_clipboard(gtk_text_str);
295 g_string_free(gtk_text_str, TRUE);
297 /* create a new one and set the display filter entry accordingly */
298 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
300 /* Run the display filter so it goes in effect. */
301 if (action&MATCH_SELECTED_APPLY_NOW)
302 main_filter_packets(&cfile, new_filter, FALSE);
305 /* Free up the new filter text. */
310 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
314 if (cfile.finfo_selected) {
315 filter = proto_construct_match_selected_string(cfile.finfo_selected,
317 match_selected_cb_do((data ? data : w), action, filter);
322 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
326 if (cfile.finfo_selected) {
327 filter = proto_construct_match_selected_string(cfile.finfo_selected,
329 if ((!filter) || (0 == strlen(filter))) {
330 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
331 "Could not acquire information to build a filter!\n"
332 "Try expanding or choosing another item.");
337 color_display_with_filter(filter);
340 color_filters_reset_tmp();
342 color_filters_set_tmp(filt_nr,filter, FALSE);
344 cf_colorize_packets(&cfile);
350 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
352 gchar *selected_proto_url;
353 gchar *proto_abbrev = data;
358 if (cfile.finfo_selected) {
359 /* open wiki page using the protocol abbreviation */
360 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
361 browser_open_url(selected_proto_url);
362 g_free(selected_proto_url);
365 case(ESD_BTN_CANCEL):
368 g_assert_not_reached();
374 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
377 const gchar *proto_abbrev;
381 if (cfile.finfo_selected) {
382 /* convert selected field to protocol abbreviation */
383 /* XXX - could this conversion be simplified? */
384 field_id = cfile.finfo_selected->hfinfo->id;
385 /* if the selected field isn't a protocol, get it's parent */
386 if(!proto_registrar_is_protocol(field_id)) {
387 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
390 proto_abbrev = proto_registrar_get_abbrev(field_id);
392 if (!proto_is_private(field_id)) {
393 /* ask the user if the wiki page really should be opened */
394 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
395 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
397 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
399 "The Wireshark Wiki is a collaborative approach to provide information "
400 "about Wireshark in several ways (not limited to protocol specifics).\n"
402 "This Wiki is new, so the page of the selected protocol "
403 "may not exist and/or may not contain valuable information.\n"
405 "As everyone can edit the Wiki and add new content (or extend existing), "
406 "you are encouraged to add information if you can.\n"
408 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
410 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate, "
411 "which will save you a lot of editing and will give a consistent look over the pages.",
412 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
413 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer)proto_abbrev);
415 /* appologize to the user that the wiki page cannot be opened */
416 dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
417 "%sCan't open Wireshark Wiki page of protocol \"%s\"%s\n"
419 "This would open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
421 "Since this is a private protocol, such information is not available in "
422 "a public wiki. Therefore this wiki entry is blocked.\n"
424 "Sorry for the inconvenience.\n",
425 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
430 static void selected_ptree_ref_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
432 gchar *selected_proto_url;
433 gchar *proto_abbrev = data;
437 if (cfile.finfo_selected) {
438 /* open reference page using the protocol abbreviation */
439 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
440 browser_open_url(selected_proto_url);
441 g_free(selected_proto_url);
444 case(ESD_BTN_CANCEL):
447 g_assert_not_reached();
452 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
455 const gchar *proto_abbrev;
459 if (cfile.finfo_selected) {
460 /* convert selected field to protocol abbreviation */
461 /* XXX - could this conversion be simplified? */
462 field_id = cfile.finfo_selected->hfinfo->id;
463 /* if the selected field isn't a protocol, get it's parent */
464 if(!proto_registrar_is_protocol(field_id)) {
465 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
468 proto_abbrev = proto_registrar_get_abbrev(field_id);
470 if (!proto_is_private(field_id)) {
471 /* ask the user if the wiki page really should be opened */
472 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
473 "%sOpen Wireshark filter reference page of protocol \"%s\"?%s\n"
475 "This will open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
477 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
478 simple_dialog_set_cb(dialog, selected_ptree_ref_answered_cb, (gpointer)proto_abbrev);
480 /* appologize to the user that the wiki page cannot be opened */
481 dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
482 "%sCan't open Wireshark filter reference page of protocol \"%s\"%s\n"
484 "This would open the \"%s\" related Wireshark filter reference page in your Web browser.\n"
486 "Since this is a private protocol, such information is not available on "
487 "a public website. Therefore this filter entry is blocked.\n"
489 "Sorry for the inconvenience.\n",
490 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
496 get_text_from_packet_list(gpointer data)
498 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
499 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
500 frame_data *fdata = (frame_data *)packet_list_get_row_data(row);
502 if(strlen(fdata->col_expr.col_expr[column]) != 0 &&
503 strlen(fdata->col_expr.col_expr_val[column]) != 0)
504 return ep_strdup_printf("%s == %s",
505 fdata->col_expr.col_expr[column],
506 fdata->col_expr.col_expr_val[column]);
512 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
514 match_selected_cb_do(data,
516 get_text_from_packet_list(data));
519 /* This function allows users to right click in the details window and copy the text
520 * information to the operating systems clipboard.
522 * We first check to see if a string representation is setup in the tree and then
523 * read the string. If not available then we try to grab the value. If all else
524 * fails we display a message to the user to indicate the copy could not be completed.
527 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_, COPY_SELECTED_E action)
529 GString *gtk_text_str = g_string_new("");
530 char labelstring[256];
531 char *stringpointer = labelstring;
535 case COPY_SELECTED_DESCRIPTION:
536 if (cfile.finfo_selected->rep->representation != 0) {
537 g_string_append(gtk_text_str, cfile.finfo_selected->rep->representation);
540 case COPY_SELECTED_FIELDNAME:
541 if (cfile.finfo_selected->hfinfo->abbrev != 0) {
542 g_string_append(gtk_text_str, cfile.finfo_selected->hfinfo->abbrev);
545 case COPY_SELECTED_VALUE:
546 if (cfile.edt !=0 ) {
547 g_string_append(gtk_text_str,
548 get_node_field_value(cfile.finfo_selected, cfile.edt));
555 if (gtk_text_str->len == 0) {
556 /* If no representation then... Try to read the value */
557 proto_item_fill_label(cfile.finfo_selected, stringpointer);
558 g_string_append(gtk_text_str, stringpointer);
561 if (gtk_text_str->len == 0) {
562 /* Could not get item so display error msg */
563 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
565 /* Copy string to clipboard */
566 copy_to_clipboard(gtk_text_str);
568 g_string_free(gtk_text_str, TRUE); /* Free the memory */
572 /* mark as reference time frame */
574 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
578 frame->flags.ref_time=1;
580 frame->flags.ref_time=0;
582 cf_reftime_packets(&cfile);
586 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
590 timestamp_set_type(TS_RELATIVE);
591 recent.gui_time_format = TS_RELATIVE;
592 cf_change_time_formats(&cfile);
597 g_assert_not_reached();
600 if (cfile.current_frame) {
601 set_frame_reftime(!cfile.current_frame->flags.ref_time,
602 cfile.current_frame, cfile.current_row);
608 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
610 static GtkWidget *reftime_dialog = NULL;
614 if (cfile.current_frame) {
615 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
616 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
617 "%sSwitch to the appropriate Time Display Format?%s\n\n"
618 "Time References don't work well with the currently selected Time Display Format.\n\n"
619 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
620 simple_dialog_primary_start(), simple_dialog_primary_end());
621 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
623 set_frame_reftime(!cfile.current_frame->flags.ref_time,
624 cfile.current_frame, cfile.current_row);
628 case REFTIME_FIND_NEXT:
629 find_previous_next_frame_with_filter("frame.ref_time", FALSE);
631 case REFTIME_FIND_PREV:
632 find_previous_next_frame_with_filter("frame.ref_time", TRUE);
638 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
640 find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
644 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
646 find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
650 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
653 gchar *help_str = NULL;
654 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
656 gboolean has_blurb = FALSE;
657 guint length = 0, byte_len;
658 GtkWidget *byte_view;
659 const guint8 *byte_data;
664 /* if nothing is selected */
665 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
668 * Which byte view is displaying the current protocol tree
671 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
672 if (byte_view == NULL)
675 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
676 if (byte_data == NULL)
679 cf_unselect_field(&cfile);
680 packet_hex_print(byte_view, byte_data,
681 cfile.current_frame, NULL, byte_len);
684 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
687 set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
689 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
690 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
691 g_assert(byte_data != NULL);
693 cfile.finfo_selected = finfo;
694 set_menus_for_selected_tree_row(&cfile);
697 if (finfo->hfinfo->blurb != NULL &&
698 finfo->hfinfo->blurb[0] != '\0') {
700 length = strlen(finfo->hfinfo->blurb);
702 length = strlen(finfo->hfinfo->name);
704 finfo_length = finfo->length + finfo->appendix_length;
706 if (finfo_length == 0) {
708 } else if (finfo_length == 1) {
709 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
711 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
713 statusbar_pop_field_msg(); /* get rid of current help msg */
715 help_str = g_strdup_printf(" %s (%s)%s",
716 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
717 finfo->hfinfo->abbrev, len_str);
718 statusbar_push_field_msg(help_str);
722 * Don't show anything if the field name is zero-length;
723 * the pseudo-field for "proto_tree_add_text()" is such
724 * a field, and we don't want "Text (text)" showing up
725 * on the status line if you've selected such a field.
727 * XXX - there are zero-length fields for which we *do*
728 * want to show the field name.
730 * XXX - perhaps the name and abbrev field should be null
731 * pointers rather than null strings for that pseudo-field,
732 * but we'd have to add checks for null pointers in some
733 * places if we did that.
735 * Or perhaps protocol tree items added with
736 * "proto_tree_add_text()" should have -1 as the field index,
737 * with no pseudo-field being used, but that might also
738 * require special checks for -1 to be added.
740 statusbar_push_field_msg("");
743 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
747 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
749 collapse_all_tree(cfile.edt->tree, tree_view);
752 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
754 expand_all_tree(cfile.edt->tree, tree_view);
757 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
760 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view), cfile.finfo_selected);
762 /* the mouse position is at an entry, expand that one */
763 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
764 gtk_tree_path_free(path);
768 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
769 if (cfile.edt->tree) {
770 guint32 tmp = g_resolv_flags;
771 g_resolv_flags = RESOLV_ALL;
772 proto_tree_draw(cfile.edt->tree, tree_view);
773 g_resolv_flags = tmp;
778 main_set_for_capture_file(gboolean have_capture_file_in)
780 have_capture_file = have_capture_file_in;
782 main_widgets_show_or_hide();
788 /* get the current geometry, before writing it to disk */
789 main_save_window_geometry(top_level);
791 /* write user's recent file to disk
792 * It is no problem to write this file, even if we do not quit */
793 write_profile_recent();
796 /* XXX - should we check whether the capture file is an
797 unsaved temporary file for a live capture and, if so,
798 pop up a "do you want to exit without saving the capture
799 file?" dialog, and then just return, leaving said dialog
800 box to forcibly quit if the user clicks "OK"?
802 If so, note that this should be done in a subroutine that
803 returns TRUE if we do so, and FALSE otherwise, and if it
804 returns TRUE we should return TRUE without nuking anything.
806 Note that, if we do that, we might also want to check if
807 an "Update list of packets in real time" capture is in
808 progress and, if so, ask whether they want to terminate
809 the capture and discard it, and return TRUE, before nuking
810 any child capture, if they say they don't want to do so. */
813 /* Nuke any child capture in progress. */
814 capture_kill_child(&global_capture_opts);
817 /* Are we in the middle of reading a capture? */
818 if (cfile.state == FILE_READ_IN_PROGRESS) {
819 /* Yes, so we can't just close the file and quit, as
820 that may yank the rug out from under the read in
821 progress; instead, just set the state to
822 "FILE_READ_ABORTED" and return - the code doing the read
823 will check for that and, if it sees that, will clean
825 cfile.state = FILE_READ_ABORTED;
827 /* Say that the window should *not* be deleted;
828 that'll be done by the code that cleans up. */
831 /* Close any capture file we have open; on some OSes, you
832 can't unlink a temporary capture file if you have it
834 "cf_close()" will unlink it after closing it if
835 it's a temporary file.
837 We do this here, rather than after the main loop returns,
838 as, after the main loop returns, the main window may have
839 been destroyed (if this is called due to a "destroy"
840 even on the main window rather than due to the user
841 selecting a menu item), and there may be a crash
842 or other problem when "cf_close()" tries to
843 clean up stuff in the main window.
845 XXX - is there a better place to put this?
846 Or should we have a routine that *just* closes the
847 capture file, and doesn't do anything with the UI,
848 which we'd call here, and another routine that
849 calls that routine and also cleans up the UI, which
850 we'd call elsewhere? */
853 /* Exit by leaving the main loop, so that any quit functions
854 we registered get called. */
857 /* Say that the window should be deleted. */
863 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
867 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
868 gtk_window_present(GTK_WINDOW(top_level));
869 /* user didn't saved his current file, ask him */
870 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
871 "%sSave capture file before program quit?%s\n\n"
872 "If you quit the program without saving, your capture data will be discarded.",
873 simple_dialog_primary_start(), simple_dialog_primary_end());
874 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
877 /* unchanged file, just exit */
878 /* "main_do_quit()" indicates whether the main window should be deleted. */
879 return main_do_quit();
885 main_pane_load_window_geometry(void)
887 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
888 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
889 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
890 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
896 main_load_window_geometry(GtkWidget *widget)
898 window_geometry_t geom;
900 geom.set_pos = prefs.gui_geometry_save_position;
901 geom.x = recent.gui_geometry_main_x;
902 geom.y = recent.gui_geometry_main_y;
903 geom.set_size = prefs.gui_geometry_save_size;
904 if (recent.gui_geometry_main_width > 0 &&
905 recent.gui_geometry_main_height > 0) {
906 geom.width = recent.gui_geometry_main_width;
907 geom.height = recent.gui_geometry_main_height;
908 geom.set_maximized = prefs.gui_geometry_save_maximized;
910 /* We assume this means the width and height weren't set in
911 the "recent" file (or that there is no "recent" file),
912 and weren't set to a default value, so we don't set the
913 size. (The "recent" file code rejects non-positive width
914 and height values.) */
915 geom.set_size = FALSE;
917 geom.maximized = recent.gui_geometry_main_maximized;
919 window_set_geometry(widget, &geom);
921 main_pane_load_window_geometry();
922 statusbar_load_window_geometry();
927 main_save_window_geometry(GtkWidget *widget)
929 window_geometry_t geom;
931 window_get_geometry(widget, &geom);
933 if (prefs.gui_geometry_save_position) {
934 recent.gui_geometry_main_x = geom.x;
935 recent.gui_geometry_main_y = geom.y;
938 if (prefs.gui_geometry_save_size) {
939 recent.gui_geometry_main_width = geom.width;
940 recent.gui_geometry_main_height = geom.height;
943 if(prefs.gui_geometry_save_maximized) {
944 recent.gui_geometry_main_maximized = geom.maximized;
947 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
948 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
949 statusbar_save_window_geometry();
952 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
956 /* save file first */
957 file_save_as_cmd(after_save_exit, NULL);
959 case(ESD_BTN_DONT_SAVE):
962 case(ESD_BTN_CANCEL):
965 g_assert_not_reached();
970 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
974 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
975 /* user didn't saved his current file, ask him */
976 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
977 "%sSave capture file before program quit?%s\n\n"
978 "If you quit the program without saving, your capture data will be discarded.",
979 simple_dialog_primary_start(), simple_dialog_primary_end());
980 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
982 /* unchanged file, just exit */
988 print_usage(gboolean print_ver) {
998 fprintf(output, "Wireshark " VERSION "%s\n"
999 "Interactively dump and analyze network traffic.\n"
1000 "See http://www.wireshark.org for more information.\n"
1003 wireshark_svnversion, get_copyright_info());
1007 fprintf(output, "\n");
1008 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1009 fprintf(output, "\n");
1012 fprintf(output, "Capture interface:\n");
1013 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1014 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1015 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1016 fprintf(output, " -p don't capture in promiscuous mode\n");
1017 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1018 fprintf(output, " -Q quit Wireshark after capturing\n");
1019 fprintf(output, " -S update packet display when new packets are captured\n");
1020 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1022 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1024 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1025 fprintf(output, " -D print list of interfaces and exit\n");
1026 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1027 fprintf(output, "\n");
1028 fprintf(output, "Capture stop conditions:\n");
1029 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1030 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1031 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1032 fprintf(output, " files:NUM - stop after NUM files\n");
1033 /*fprintf(output, "\n");*/
1034 fprintf(output, "Capture output:\n");
1035 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1036 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1037 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1038 #endif /* HAVE_LIBPCAP */
1040 /*fprintf(output, "\n");*/
1041 fprintf(output, "Input file:\n");
1042 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1044 fprintf(output, "\n");
1045 fprintf(output, "Processing:\n");
1046 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1047 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1048 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1050 fprintf(output, "\n");
1051 fprintf(output, "User interface:\n");
1052 fprintf(output, " -C <config profile> start with specified configuration profile\n");
1053 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1054 fprintf(output, " -m <font> set the font name used for most text\n");
1055 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1056 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1057 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1059 fprintf(output, "\n");
1060 fprintf(output, "Output:\n");
1061 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1063 fprintf(output, "\n");
1064 fprintf(output, "Miscellaneous:\n");
1065 fprintf(output, " -h display this help and exit\n");
1066 fprintf(output, " -v display version info and exit\n");
1067 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1068 fprintf(output, " persdata:path - personal data files\n");
1069 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1070 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1072 fprintf(output, " --display=DISPLAY X display to use\n");
1087 printf(PACKAGE " " VERSION "%s\n"
1094 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1095 runtime_info_str->str);
1103 * Report an error in command-line arguments.
1104 * Creates a console on Windows.
1105 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1106 * terminal isn't the standard error?
1109 cmdarg_err(const char *fmt, ...)
1117 fprintf(stderr, "wireshark: ");
1118 vfprintf(stderr, fmt, ap);
1119 fprintf(stderr, "\n");
1124 * Report additional information for an error in command-line arguments.
1125 * Creates a console on Windows.
1126 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1127 * terminal isn't the standard error?
1130 cmdarg_err_cont(const char *fmt, ...)
1138 vfprintf(stderr, fmt, ap);
1139 fprintf(stderr, "\n");
1143 #if defined(_WIN32) || ! defined USE_THREADS
1145 Once every 3 seconds we get a callback here which we use to update
1146 the tap extensions. Since Gtk1 is single threaded we dont have to
1147 worry about any locking or critical regions.
1150 update_cb(gpointer data _U_)
1152 draw_tap_listeners(FALSE);
1156 /* Restart the tap update display timer with new configured interval */
1157 void reset_tap_update_timer(void)
1159 g_source_remove(tap_update_timer_id);
1160 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, update_cb, NULL);
1165 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1166 use threads all update_thread_mutex can be dropped and protect/unprotect
1167 would just be empty functions.
1169 This allows gtk2-rpcstat.c and friends to be copied unmodified to
1170 gtk1-wireshark and it will just work.
1172 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1174 update_thread(gpointer data _U_)
1178 g_get_current_time(&tv1);
1179 g_static_mutex_lock(&update_thread_mutex);
1180 gdk_threads_enter();
1181 draw_tap_listeners(FALSE);
1182 gdk_threads_leave();
1183 g_static_mutex_unlock(&update_thread_mutex);
1185 g_get_current_time(&tv2);
1187 /* Assuming it took less than configured time to update tap listeners... */
1188 if( (tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) >
1189 (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1190 /* Wait for remainder of configured time */
1191 g_usleep((tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) -
1192 (tv2.tv_sec * 1000000 + tv2.tv_usec));
1199 protect_thread_critical_region(void)
1201 #if !defined(_WIN32) && defined USE_THREADS
1202 g_static_mutex_lock(&update_thread_mutex);
1206 unprotect_thread_critical_region(void)
1208 #if !defined(_WIN32) && defined USE_THREADS
1209 g_static_mutex_unlock(&update_thread_mutex);
1213 /* Set the file name in the name for the main window and in the name for the main window's icon. */
1215 set_display_filename(capture_file *cf)
1219 if (!cf->is_tempfile && cf->filename) {
1220 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1221 add_menu_recent_capture_file(cf->filename);
1225 win_name = g_strdup_printf("%s - Wireshark", cf_get_display_name(cf));
1226 set_main_window_name(win_name);
1230 GtkWidget *close_dlg = NULL;
1233 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1235 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1240 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1242 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1247 main_cf_cb_file_closing(capture_file *cf)
1250 /* if we have more than 10000 packets, show a splash screen while closing */
1251 /* XXX - don't know a better way to decide whether to show or not,
1252 * as most of the time is spend in a single eth_clist_clear function,
1253 * so we can't use a progress bar here! */
1254 if(cf->count > 10000) {
1255 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1256 "%sClosing file!%s\n\nPlease wait ...",
1257 simple_dialog_primary_start(),
1258 simple_dialog_primary_end());
1259 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1262 /* Destroy all windows, which refer to the
1263 capture file we're closing. */
1264 destroy_packet_wins();
1265 file_save_as_destroy();
1267 /* Restore the standard title bar message. */
1268 set_main_window_name("The Wireshark Network Analyzer");
1270 /* Disable all menu items that make sense only if you have a capture. */
1271 set_menus_for_capture_file(NULL);
1272 set_menus_for_captured_packets(FALSE);
1273 set_menus_for_selected_packet(cf);
1274 set_menus_for_capture_in_progress(FALSE);
1275 set_capture_if_dialog_for_capture_in_progress(FALSE);
1276 set_menus_for_selected_tree_row(cf);
1278 /* Set up main window for no capture file. */
1279 main_set_for_capture_file(FALSE);
1281 main_window_update();
1285 main_cf_cb_file_closed(capture_file *cf _U_)
1287 if(close_dlg != NULL) {
1288 splash_destroy(close_dlg);
1295 main_cf_cb_file_read_start(capture_file *cf _U_)
1297 tap_dfilter_dlg_update();
1299 /* Set up main window for a capture file. */
1300 main_set_for_capture_file(TRUE);
1304 main_cf_cb_file_read_finished(capture_file *cf)
1306 set_display_filename(cf);
1308 /* Enable menu items that make sense if you have a capture file you've
1309 finished reading. */
1310 set_menus_for_capture_file(cf);
1312 /* Enable menu items that make sense if you have some captured packets. */
1313 set_menus_for_captured_packets(TRUE);
1316 GList *icon_list_create(
1317 const char **icon16_xpm,
1318 const char **icon32_xpm,
1319 const char **icon48_xpm,
1320 const char **icon64_xpm)
1322 GList *icon_list = NULL;
1323 GdkPixbuf * pixbuf16;
1324 GdkPixbuf * pixbuf32;
1325 GdkPixbuf * pixbuf48;
1326 GdkPixbuf * pixbuf64;
1329 if(icon16_xpm != NULL) {
1330 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1332 icon_list = g_list_append(icon_list, pixbuf16);
1335 if(icon32_xpm != NULL) {
1336 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1338 icon_list = g_list_append(icon_list, pixbuf32);
1341 if(icon48_xpm != NULL) {
1342 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1344 icon_list = g_list_append(icon_list, pixbuf48);
1347 if(icon64_xpm != NULL) {
1348 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1350 icon_list = g_list_append(icon_list, pixbuf64);
1358 main_capture_cb_capture_prepared(capture_options *capture_opts)
1361 static GList *icon_list = NULL;
1364 if(capture_opts->iface) {
1365 title = g_strdup_printf("%s: Capturing - Wireshark",
1366 get_iface_description(capture_opts));
1368 title = g_strdup_printf("Capturing - Wireshark");
1370 set_main_window_name(title);
1373 if(icon_list == NULL) {
1374 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1376 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1378 /* Disable menu items that make no sense if you're currently running
1380 set_menus_for_capture_in_progress(TRUE);
1381 set_capture_if_dialog_for_capture_in_progress(TRUE);
1383 /* Don't set up main window for a capture file. */
1384 main_set_for_capture_file(FALSE);
1388 main_capture_cb_capture_update_started(capture_options *capture_opts)
1392 /* We've done this in "prepared" above, but it will be cleared while
1393 switching to the next multiple file. */
1394 if(capture_opts->iface) {
1395 title = g_strdup_printf("%s: Capturing - Wireshark",
1396 get_iface_description(capture_opts));
1398 title = g_strdup_printf("Capturing - Wireshark");
1400 set_main_window_name(title);
1403 set_menus_for_capture_in_progress(TRUE);
1404 set_capture_if_dialog_for_capture_in_progress(TRUE);
1406 /* Enable menu items that make sense if you have some captured
1407 packets (yes, I know, we don't have any *yet*). */
1408 set_menus_for_captured_packets(TRUE);
1410 /* Set up main window for a capture file. */
1411 main_set_for_capture_file(TRUE);
1415 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1417 capture_file *cf = capture_opts->cf;
1418 static GList *icon_list = NULL;
1420 set_display_filename(cf);
1422 /* Enable menu items that make sense if you're not currently running
1424 set_menus_for_capture_in_progress(FALSE);
1425 set_capture_if_dialog_for_capture_in_progress(FALSE);
1427 /* Enable menu items that make sense if you have a capture file
1428 you've finished reading. */
1429 set_menus_for_capture_file(cf);
1431 /* Set up main window for a capture file. */
1432 main_set_for_capture_file(TRUE);
1434 if(icon_list == NULL) {
1435 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1437 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1439 if(global_capture_opts.quit_after_cap) {
1440 /* command line asked us to quit after the capture */
1441 /* don't pop up a dialog to ask for unsaved files etc. */
1447 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1449 /* Don't set up main window for a capture file. */
1450 main_set_for_capture_file(FALSE);
1454 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1457 capture_file *cf = capture_opts->cf;
1459 static GList *icon_list = NULL;
1461 /*set_display_filename(cf);*/
1463 /* Enable menu items that make sense if you're not currently running
1465 set_menus_for_capture_in_progress(FALSE);
1466 set_capture_if_dialog_for_capture_in_progress(FALSE);
1468 /* Restore the standard title bar message */
1469 /* (just in case we have trouble opening the capture file). */
1470 set_main_window_name("The Wireshark Network Analyzer");
1472 if(icon_list == NULL) {
1473 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1475 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1477 /* We don't have loaded the capture file, this will be done later.
1478 * For now we still have simply a blank screen. */
1480 if(global_capture_opts.quit_after_cap) {
1481 /* command line asked us to quit after the capture */
1482 /* don't pop up a dialog to ask for unsaved files etc. */
1487 #endif /* HAVE_LIBPCAP */
1490 main_cf_cb_packet_selected(gpointer data)
1492 capture_file *cf = data;
1494 /* Display the GUI protocol tree and hex dump.
1495 XXX - why do we dump core if we call "proto_tree_draw()"
1496 before calling "add_byte_views()"? */
1497 add_main_byte_views(cf->edt);
1498 main_proto_tree_draw(cf->edt->tree);
1500 /* The user is searching for a string in the data or a hex value,
1501 * highlight the field that is found in the tree and hex displays. */
1502 if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1503 highlight_field(cf->edt->tvb, cfile.search_pos,
1504 (GtkTreeView *)tree_view, cf->edt->tree);
1505 cfile.search_pos = 0; /* Reset the position */
1508 /* A packet is selected. */
1509 set_menus_for_selected_packet(cf);
1513 main_cf_cb_packet_unselected(capture_file *cf)
1515 /* Clear out the display of that packet. */
1516 clear_tree_and_hex_views();
1518 /* No packet is selected. */
1519 set_menus_for_selected_packet(cf);
1523 main_cf_cb_field_unselected(capture_file *cf)
1525 set_menus_for_selected_tree_row(cf);
1529 main_cf_cb_file_safe_reload_finished(gpointer data _U_)
1531 set_menus_for_capture_file(&cfile);
1535 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1538 case(cf_cb_file_closing):
1539 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1540 main_cf_cb_file_closing(data);
1542 case(cf_cb_file_closed):
1543 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1544 main_cf_cb_file_closed(data);
1546 case(cf_cb_file_read_start):
1547 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read start");
1548 main_cf_cb_file_read_start(data);
1550 case(cf_cb_file_read_finished):
1551 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1552 main_cf_cb_file_read_finished(data);
1554 case(cf_cb_packet_selected):
1555 main_cf_cb_packet_selected(data);
1557 case(cf_cb_packet_unselected):
1558 main_cf_cb_packet_unselected(data);
1560 case(cf_cb_field_unselected):
1561 main_cf_cb_field_unselected(data);
1563 case(cf_cb_file_safe_started):
1564 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe started");
1566 case(cf_cb_file_safe_finished):
1567 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe finished");
1569 case(cf_cb_file_safe_reload_finished):
1570 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: reload finished");
1571 main_cf_cb_file_safe_reload_finished(data);
1573 case(cf_cb_file_safe_failed):
1574 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe failed");
1577 g_warning("main_cf_callback: event %u unknown", event);
1578 g_assert_not_reached();
1584 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1587 case(capture_cb_capture_prepared):
1588 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1589 main_capture_cb_capture_prepared(capture_opts);
1591 case(capture_cb_capture_update_started):
1592 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1593 main_capture_cb_capture_update_started(capture_opts);
1595 case(capture_cb_capture_update_continue):
1596 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1598 case(capture_cb_capture_update_finished):
1599 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1600 main_capture_cb_capture_update_finished(capture_opts);
1602 case(capture_cb_capture_fixed_started):
1603 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1604 main_capture_cb_capture_fixed_started(capture_opts);
1606 case(capture_cb_capture_fixed_continue):
1607 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1609 case(capture_cb_capture_fixed_finished):
1610 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1611 main_capture_cb_capture_fixed_finished(capture_opts);
1613 case(capture_cb_capture_stopping):
1614 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1615 /* Beware: this state won't be called, if the capture child
1616 * closes the capturing on it's own! */
1619 g_warning("main_capture_callback: event %u unknown", event);
1620 g_assert_not_reached();
1626 get_gui_compiled_info(GString *str)
1628 get_epan_compiled_version_info(str);
1630 g_string_append(str, ", ");
1631 #ifdef HAVE_LIBPORTAUDIO
1632 #ifdef PORTAUDIO_API_1
1633 g_string_append(str, "with PortAudio <= V18");
1634 #else /* PORTAUDIO_API_1 */
1635 g_string_append(str, "with ");
1636 g_string_append(str, Pa_GetVersionText());
1637 #endif /* PORTAUDIO_API_1 */
1638 #else /* HAVE_LIBPORTAUDIO */
1639 g_string_append(str, "without PortAudio");
1640 #endif /* HAVE_LIBPORTAUDIO */
1642 g_string_append(str, ", ");
1644 get_compiled_airpcap_version(str);
1646 g_string_append(str, "without AirPcap");
1651 get_gui_runtime_info(GString *str)
1654 g_string_append(str, ", ");
1655 get_runtime_airpcap_version(str);
1659 g_string_append(str, ", ");
1660 u3_runtime_info(str);
1666 read_configuration_files(char **gdp_path, char **dp_path)
1668 int gpf_open_errno, gpf_read_errno;
1669 int cf_open_errno, df_open_errno;
1670 int gdp_open_errno, gdp_read_errno;
1671 int dp_open_errno, dp_read_errno;
1672 char *gpf_path, *pf_path;
1673 char *cf_path, *df_path;
1674 int pf_open_errno, pf_read_errno;
1677 /* Read the preference files. */
1678 prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1679 &pf_open_errno, &pf_read_errno, &pf_path);
1681 if (gpf_path != NULL) {
1682 if (gpf_open_errno != 0) {
1683 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1684 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1685 strerror(gpf_open_errno));
1687 if (gpf_read_errno != 0) {
1688 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1689 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1690 strerror(gpf_read_errno));
1693 if (pf_path != NULL) {
1694 if (pf_open_errno != 0) {
1695 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1696 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1697 strerror(pf_open_errno));
1699 if (pf_read_errno != 0) {
1700 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1701 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1702 strerror(pf_read_errno));
1709 /* if the user wants a console to be always there, well, we should open one for him */
1710 if (prefs->gui_console_open == console_open_always) {
1715 /* Read the capture filter file. */
1716 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1717 if (cf_path != NULL) {
1718 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1719 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1720 strerror(cf_open_errno));
1724 /* Read the display filter file. */
1725 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1726 if (df_path != NULL) {
1727 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1728 "Could not open your display filter file\n\"%s\": %s.", df_path,
1729 strerror(df_open_errno));
1733 /* Read the disabled protocols file. */
1734 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1735 dp_path, &dp_open_errno, &dp_read_errno);
1736 if (*gdp_path != NULL) {
1737 if (gdp_open_errno != 0) {
1738 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1739 "Could not open global disabled protocols file\n\"%s\": %s.",
1740 *gdp_path, strerror(gdp_open_errno));
1742 if (gdp_read_errno != 0) {
1743 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1744 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1745 *gdp_path, strerror(gdp_read_errno));
1750 if (*dp_path != NULL) {
1751 if (dp_open_errno != 0) {
1752 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1753 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1754 strerror(dp_open_errno));
1756 if (dp_read_errno != 0) {
1757 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1758 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1759 strerror(dp_read_errno));
1768 /* And now our feature presentation... [ fade to music ] */
1770 main(int argc, char *argv[])
1772 char *init_progfile_dir_error;
1775 extern char *optarg;
1776 gboolean arg_error = FALSE;
1784 char *gdp_path, *dp_path;
1787 gboolean start_capture = FALSE;
1788 gboolean list_link_layer_types = FALSE;
1790 gboolean capture_option_specified = FALSE;
1792 gint pl_size = 280, tv_size = 95, bv_size = 75;
1793 gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
1794 dfilter_t *rfcode = NULL;
1795 gboolean rfilter_parse_failed = FALSE;
1798 GtkWidget *splash_win = NULL;
1799 gpointer priv_warning_dialog;
1800 GLogLevelFlags log_flags;
1801 guint go_to_packet = 0;
1804 gchar *cur_user, *cur_group;
1810 #define OPTSTRING_INIT "a:b:c:C:Df:g:Hhi:kK:lLm:nN:o:P:pQr:R:Ss:t:vw:X:y:z:"
1812 #if defined HAVE_LIBPCAP && defined _WIN32
1813 #define OPTSTRING_WIN32 "B:"
1815 #define OPTSTRING_WIN32 ""
1818 char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
1819 OPTSTRING_INIT OPTSTRING_WIN32;
1822 * Get credential information for later use, and drop privileges
1823 * before doing anything else.
1824 * Let the user know if anything happened.
1826 get_credential_info();
1827 relinquish_special_privs_perm();
1830 * Attempt to get the pathname of the executable file.
1832 init_progfile_dir_error = init_progfile_dir(argv[0], main);
1834 /* initialize the funnel mini-api */
1835 initialize_funnel_ops();
1837 #ifdef HAVE_AIRPDCAP
1838 AirPDcapInitContext(&airpdcap_ctx);
1842 /* Load wpcap if possible. Do this before collecting the run-time version information */
1845 /* ... and also load the packet.dll from wpcap */
1846 wpcap_packet_load();
1849 /* Load the airpcap.dll. This must also be done before collecting
1850 * run-time version information. */
1851 airpcap_dll_ret_val = load_airpcap();
1853 switch (airpcap_dll_ret_val) {
1854 case AIRPCAP_DLL_OK:
1855 /* load the airpcap interfaces */
1856 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
1858 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
1859 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
1860 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
1863 airpcap_if_active = NULL;
1867 /* select the first ad default (THIS SHOULD BE CHANGED) */
1868 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
1873 * XXX - Maybe we need to warn the user if one of the following happens???
1875 case AIRPCAP_DLL_OLD:
1876 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
1879 case AIRPCAP_DLL_ERROR:
1880 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
1883 case AIRPCAP_DLL_NOT_FOUND:
1884 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
1888 #endif /* HAVE_AIRPCAP */
1890 /* Start windows sockets */
1891 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
1894 /* Assemble the compile-time version information string */
1895 comp_info_str = g_string_new("Compiled ");
1897 g_string_append(comp_info_str, "with ");
1898 g_string_append_printf(comp_info_str,
1899 #ifdef GTK_MAJOR_VERSION
1900 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1903 "GTK+ (version unknown)");
1905 g_string_append(comp_info_str, ", ");
1907 get_compiled_version_info(comp_info_str, get_gui_compiled_info);
1909 /* Assemble the run-time version information string */
1910 runtime_info_str = g_string_new("Running ");
1911 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
1913 /* Read the profile independent recent file. We have to do this here so we can */
1914 /* set the profile before it can be set from the command line parameterts */
1915 recent_read_static(&rf_path, &rf_open_errno);
1916 if (rf_path != NULL && rf_open_errno != 0) {
1917 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1918 "Could not open common recent file\n\"%s\": %s.",
1919 rf_path, strerror(rf_open_errno));
1922 /* "pre-scan" the command line parameters, if we have "console only"
1923 parameters. We do this so we don't start GTK+ if we're only showing
1924 command-line help or version information.
1926 XXX - this pre-scan is done before we start GTK+, so we haven't
1927 run gtk_init() on the arguments. That means that GTK+ arguments
1928 have not been removed from the argument list; those arguments
1929 begin with "--", and will be treated as an error by getopt().
1931 We thus ignore errors - *and* set "opterr" to 0 to suppress the
1934 optind_initial = optind;
1935 while ((opt = getopt(argc, argv, optstring)) != -1) {
1937 case 'C': /* Configuration Profile */
1938 if (profile_exists (optarg)) {
1939 set_profile_name (optarg);
1941 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
1945 case 'h': /* Print help and exit */
1951 if (strcmp(optarg, "-") == 0)
1952 stdin_capture = TRUE;
1955 case 'P': /* Path settings - change these before the Preferences and alike are processed */
1956 status = filesystem_opt(opt, optarg);
1958 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
1962 case 'v': /* Show version and exit */
1968 * Extension command line options have to be processed before
1969 * we call epan_init() as they are supposed to be used by dissectors
1970 * or taps very early in the registration process.
1974 case '?': /* Ignore errors - the "real" scan will catch them. */
1979 /* Init the "Open file" dialog directory */
1980 /* (do this after the path settings are processed) */
1981 set_last_open_dir(get_persdatafile_dir());
1983 /* Set getopt index back to initial value, so it will start with the
1984 first command line parameter again. Also reset opterr to 1, so that
1985 error messages are printed by getopt().
1987 XXX - this seems to work on most platforms, but time will tell.
1988 The Single UNIX Specification says "The getopt() function need
1989 not be reentrant", so this isn't guaranteed to work. The Mac
1990 OS X 10.4[.x] getopt() man page says
1992 In order to use getopt() to evaluate multiple sets of arguments, or to
1993 evaluate a single set of arguments multiple times, the variable optreset
1994 must be set to 1 before the second and each additional set of calls to
1995 getopt(), and the variable optind must be reinitialized.
1999 The optreset variable was added to make it possible to call the getopt()
2000 function multiple times. This is an extension to the IEEE Std 1003.2
2001 (``POSIX.2'') specification.
2003 which I think comes from one of the other BSDs.
2005 XXX - if we want to control all the command-line option errors, so
2006 that we can display them where we choose (e.g., in a window), we'd
2007 want to leave opterr as 0, and produce our own messages using optopt.
2008 We'd have to check the value of optopt to see if it's a valid option
2009 letter, in which case *presumably* the error is "this option requires
2010 an argument but none was specified", or not a valid option letter,
2011 in which case *presumably* the error is "this option isn't valid".
2012 Some versions of getopt() let you supply a option string beginning
2013 with ':', which means that getopt() will return ':' rather than '?'
2014 for "this option requires an argument but none was specified", but
2016 optind = optind_initial;
2019 /* Set the current locale according to the program environment.
2020 * We haven't localized anything, but some GTK widgets are localized
2021 * (the file selection dialogue, for example).
2022 * This also sets the C-language locale to the native environment. */
2025 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2026 gtk_init (&argc, &argv);
2028 cf_callback_add(main_cf_callback, NULL);
2030 capture_callback_add(main_capture_callback, NULL);
2032 cf_callback_add(statusbar_cf_callback, NULL);
2034 capture_callback_add(statusbar_capture_callback, NULL);
2037 /* Arrange that if we have no console window, and a GLib message logging
2038 routine is called to log a message, we pop up a console window.
2040 We do that by inserting our own handler for all messages logged
2041 to the default domain; that handler pops up a console if necessary,
2042 and then calls the default handler. */
2044 /* We might want to have component specific log levels later ... */
2048 G_LOG_LEVEL_CRITICAL|
2049 G_LOG_LEVEL_WARNING|
2050 G_LOG_LEVEL_MESSAGE|
2053 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2055 g_log_set_handler(NULL,
2057 console_log_handler, NULL /* user_data */);
2058 g_log_set_handler(LOG_DOMAIN_MAIN,
2060 console_log_handler, NULL /* user_data */);
2063 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2065 console_log_handler, NULL /* user_data */);
2066 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2068 console_log_handler, NULL /* user_data */);
2070 /* Set the initial values in the capture options. This might be overwritten
2071 by preference settings and then again by the command line parameters. */
2072 capture_opts_init(&global_capture_opts, &cfile);
2074 global_capture_opts.snaplen = MIN_PACKET_SIZE;
2075 global_capture_opts.has_ring_num_files = TRUE;
2078 /* Initialize whatever we need to allocate colors for GTK+ */
2081 /* We won't come till here, if we had a "console only" command line parameter. */
2082 splash_win = splash_new("Loading Wireshark ...");
2083 if (init_progfile_dir_error != NULL) {
2084 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2085 "Can't get pathname of Wireshark: %s.\n"
2086 "It won't be possible to capture traffic.\n"
2087 "Report this to the Wireshark developers.",
2088 init_progfile_dir_error);
2089 g_free(init_progfile_dir_error);
2092 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2094 /* Register all dissectors; we must do this before checking for the
2095 "-G" flag, as the "-G" flag dumps information registered by the
2096 dissectors, and we must do it before we read the preferences, in
2097 case any dissectors register preferences. */
2098 epan_init(register_all_protocols,register_all_protocol_handoffs,
2099 splash_update, (gpointer) splash_win,
2100 failure_alert_box,open_failure_alert_box,read_failure_alert_box,
2101 write_failure_alert_box);
2103 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2105 /* Register all tap listeners; we do this before we parse the arguments,
2106 as the "-z" argument can specify a registered tap. */
2108 /* we register the plugin taps before the other taps because
2109 stats_tree taps plugins will be registered as tap listeners
2110 by stats_tree_stat.c and need to registered before that */
2113 register_all_plugin_tap_listeners();
2116 register_all_tap_listeners();
2118 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2120 /* Now register the preferences for any non-dissector modules.
2121 We must do that before we read the preferences as well. */
2122 prefs_register_modules();
2124 prefs = read_configuration_files (&gdp_path, &dp_path);
2126 /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2127 #if !defined(_WIN32) && defined(G_THREADS_ENABLED) && defined USE_THREADS
2130 g_thread_init(NULL);
2132 ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2133 g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2135 #else /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2136 /* this is to keep tap extensions updating once every 3 seconds */
2137 tap_update_timer_id = g_timeout_add(prefs->tap_update_interval, update_cb, NULL);
2138 #endif /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2141 g_timeout_add(750, host_name_lookup_process, NULL);
2144 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2147 /* Read the profile dependent (static part) of the recent file. */
2148 /* Only the static part of it will be read, as we don't have the gui now to fill the */
2149 /* recent lists which is done in the dynamic part. */
2150 /* We have to do this already here, so command line parameters can overwrite these values. */
2151 recent_read_profile_static(&rf_path, &rf_open_errno);
2152 if (rf_path != NULL && rf_open_errno != 0) {
2153 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2154 "Could not open recent file\n\"%s\": %s.",
2155 rf_path, strerror(rf_open_errno));
2158 init_cap_file(&cfile);
2160 /* Fill in capture options with values from the preferences */
2161 prefs_to_capture_opts();
2163 /* Now get our args */
2164 while ((opt = getopt(argc, argv, optstring)) != -1) {
2166 /*** capture option specific ***/
2167 case 'a': /* autostop criteria */
2168 case 'b': /* Ringbuffer option */
2169 case 'c': /* Capture xxx packets */
2170 case 'f': /* capture filter */
2171 case 'k': /* Start capture immediately */
2172 case 'H': /* Hide capture info dialog box */
2173 case 'i': /* Use interface xxx */
2174 case 'p': /* Don't capture in promiscuous mode */
2175 case 'Q': /* Quit after capture (just capture to file) */
2176 case 's': /* Set the snapshot (capture) length */
2177 case 'S': /* "Sync" mode: used for following file ala tail -f */
2178 case 'w': /* Write to capture file xxx */
2179 case 'y': /* Set the pcap data link type */
2181 case 'B': /* Buffer size */
2184 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2190 capture_option_specified = TRUE;
2195 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2196 case 'K': /* Kerberos keytab file */
2197 read_keytab_file(optarg);
2201 /*** all non capture option specific ***/
2203 /* Configuration profile settings were already processed just ignore them this time*/
2205 case 'D': /* Print a list of capture devices and exit */
2207 capture_opts_list_interfaces(FALSE);
2210 capture_option_specified = TRUE;
2214 case 'g': /* Go to packet */
2215 go_to_packet = get_positive_int(optarg, "go to packet");
2217 case 'l': /* Automatic scrolling in live capture mode */
2219 auto_scroll_live = TRUE;
2221 capture_option_specified = TRUE;
2225 case 'L': /* Print list of link-layer types and exit */
2227 list_link_layer_types = TRUE;
2229 capture_option_specified = TRUE;
2233 case 'm': /* Fixed-width font for the display */
2234 g_free(prefs->gui_font_name);
2235 prefs->gui_font_name = g_strdup(optarg);
2237 case 'n': /* No name resolution */
2238 g_resolv_flags = RESOLV_NONE;
2240 case 'N': /* Select what types of addresses/port #s to resolve */
2241 if (g_resolv_flags == RESOLV_ALL)
2242 g_resolv_flags = RESOLV_NONE;
2243 badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2244 if (badopt != '\0') {
2245 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2250 case 'o': /* Override preference from command line */
2251 switch (prefs_set_pref(optarg)) {
2254 case PREFS_SET_SYNTAX_ERR:
2255 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2258 case PREFS_SET_NO_SUCH_PREF:
2259 /* not a preference, might be a recent setting */
2260 switch (recent_set_arg(optarg)) {
2263 case PREFS_SET_SYNTAX_ERR:
2264 /* shouldn't happen, checked already above */
2265 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2268 case PREFS_SET_NO_SUCH_PREF:
2269 case PREFS_SET_OBSOLETE:
2270 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2275 g_assert_not_reached();
2278 case PREFS_SET_OBSOLETE:
2279 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2284 g_assert_not_reached();
2288 /* Path settings were already processed just ignore them this time*/
2290 case 'r': /* Read capture file xxx */
2291 /* We may set "last_open_dir" to "cf_name", and if we change
2292 "last_open_dir" later, we free the old value, so we have to
2293 set "cf_name" to something that's been allocated. */
2294 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2295 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2296 cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2298 cf_name = g_strdup(optarg);
2301 case 'R': /* Read file filter */
2304 case 't': /* Time stamp type */
2305 if (strcmp(optarg, "r") == 0)
2306 timestamp_set_type(TS_RELATIVE);
2307 else if (strcmp(optarg, "a") == 0)
2308 timestamp_set_type(TS_ABSOLUTE);
2309 else if (strcmp(optarg, "ad") == 0)
2310 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2311 else if (strcmp(optarg, "d") == 0)
2312 timestamp_set_type(TS_DELTA);
2313 else if (strcmp(optarg, "dd") == 0)
2314 timestamp_set_type(TS_DELTA_DIS);
2315 else if (strcmp(optarg, "e") == 0)
2316 timestamp_set_type(TS_EPOCH);
2318 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2319 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2320 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2325 /* ext ops were already processed just ignore them this time*/
2328 /* We won't call the init function for the stat this soon
2329 as it would disallow MATE's fields (which are registered
2330 by the preferences set callback) from being used as
2331 part of a tap filter. Instead, we just add the argument
2332 to a list of stat arguments. */
2333 if (!process_stat_cmd_arg(optarg)) {
2334 cmdarg_err("Invalid -z argument.");
2335 cmdarg_err_cont(" -z argument must be one of :");
2336 list_stat_cmd_args();
2341 case '?': /* Bad flag - print usage message */
2349 if (cf_name != NULL) {
2351 * Input file name specified with "-r" *and* specified as a regular
2352 * command-line argument.
2354 cmdarg_err("File name specified both with -r and regular argument");
2358 * Input file name not specified with "-r", and a command-line argument
2359 * was specified; treat it as the input file name.
2361 * Yes, this is different from tshark, where non-flag command-line
2362 * arguments are a filter, but this works better on GUI desktops
2363 * where a command can be specified to be run to open a particular
2364 * file - yes, you could have "-r" as the last part of the command,
2365 * but that's a bit ugly.
2367 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2368 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2369 cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2371 cf_name = g_strdup(argv[0]);
2382 * Extra command line arguments were specified; complain.
2384 cmdarg_err("Invalid argument: %s", argv[0]);
2389 #ifndef HAVE_LIBPCAP
2390 if (capture_option_specified) {
2391 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2399 if (start_capture && list_link_layer_types) {
2400 /* Specifying *both* is bogus. */
2401 cmdarg_err("You can't specify both -L and a live capture.");
2405 if (list_link_layer_types) {
2406 /* We're supposed to list the link-layer types for an interface;
2407 did the user also specify a capture file to be read? */
2409 /* Yes - that's bogus. */
2410 cmdarg_err("You can't specify -L and a capture file to be read.");
2413 /* No - did they specify a ring buffer option? */
2414 if (global_capture_opts.multi_files_on) {
2415 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2419 /* We're supposed to do a live capture; did the user also specify
2420 a capture file to be read? */
2421 if (start_capture && cf_name) {
2422 /* Yes - that's bogus. */
2423 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2427 /* No - was the ring buffer option specified and, if so, does it make
2429 if (global_capture_opts.multi_files_on) {
2430 /* Ring buffer works only under certain conditions:
2431 a) ring buffer does not work with temporary files;
2432 b) real_time_mode and multi_files_on are mutually exclusive -
2433 real_time_mode takes precedence;
2434 c) it makes no sense to enable the ring buffer if the maximum
2435 file size is set to "infinite". */
2436 if (global_capture_opts.save_file == NULL) {
2437 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2438 global_capture_opts.multi_files_on = FALSE;
2440 /* if (global_capture_opts.real_time_mode) {
2441 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2442 global_capture_opts.multi_files_on = FALSE;
2444 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2445 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2446 /* XXX - this must be redesigned as the conditions changed */
2447 /* global_capture_opts.multi_files_on = FALSE;*/
2452 if (start_capture || list_link_layer_types) {
2453 /* Did the user specify an interface to use? */
2454 if (!capture_opts_trim_iface(&global_capture_opts,
2455 (prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
2460 if (list_link_layer_types) {
2461 status = capture_opts_list_link_layer_types(&global_capture_opts, FALSE);
2465 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2466 capture_opts_trim_ring_num_files(&global_capture_opts);
2467 #endif /* HAVE_LIBPCAP */
2469 /* Notify all registered modules that have had any of their preferences
2470 changed either from one of the preferences file or from the command
2471 line that their preferences have changed. */
2474 /* disabled protocols as per configuration file */
2475 if (gdp_path == NULL && dp_path == NULL) {
2476 set_disabled_protos_list();
2479 build_column_format_array(&cfile.cinfo, TRUE);
2481 /* read in rc file from global and personal configuration paths. */
2482 rc_file = get_datafile_path(RC_FILE);
2483 gtk_rc_parse(rc_file);
2485 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2486 gtk_rc_parse(rc_file);
2493 /* close the splash screen, as we are going to open the main window now */
2494 splash_destroy(splash_win);
2496 /************************************************************************/
2497 /* Everything is prepared now, preferences and command line was read in */
2499 /* Pop up the main window. */
2500 create_main_window(pl_size, tv_size, bv_size, prefs);
2502 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2503 recent_read_dynamic(&rf_path, &rf_open_errno);
2504 if (rf_path != NULL && rf_open_errno != 0) {
2505 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2506 "Could not open recent file\n\"%s\": %s.",
2507 rf_path, strerror(rf_open_errno));
2510 color_filters_enable(recent.packet_list_colorize);
2512 /* rearrange all the widgets as we now have all recent settings ready for this */
2513 main_widgets_rearrange();
2515 /* Fill in column titles. This must be done after the top level window
2518 XXX - is that still true, with fixed-width columns? */
2519 packet_list_set_column_titles();
2521 menu_recent_read_finished();
2523 menu_auto_scroll_live_changed(auto_scroll_live);
2526 switch (user_font_apply()) {
2529 case FA_FONT_NOT_RESIZEABLE:
2530 /* "user_font_apply()" popped up an alert box. */
2531 /* turn off zooming - font can't be resized */
2532 case FA_FONT_NOT_AVAILABLE:
2533 /* XXX - did we successfully load the un-zoomed version earlier?
2534 If so, this *probably* means the font is available, but not at
2535 this particular zoom level, but perhaps some other failure
2536 occurred; I'm not sure you can determine which is the case,
2538 /* turn off zooming - zoom level is unavailable */
2540 /* in any other case than FA_SUCCESS, turn off zooming */
2541 recent.gui_zoom_level = 0;
2542 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2545 dnd_init(top_level);
2547 color_filters_init();
2550 /* the window can be sized only, if it's not already shown, so do it now! */
2551 main_load_window_geometry(top_level);
2553 /* Tell the user not to run as root. */
2554 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
2555 cur_user = get_cur_username();
2556 cur_group = get_cur_groupname();
2557 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2558 "Running as user \"%s\" and group \"%s\".\n"
2559 "This could be dangerous.", cur_user, cur_group);
2562 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2563 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
2567 /* Warn the user if npf.sys isn't loaded. */
2568 if (!npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
2569 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2570 "The NPF driver isn't running. You may have trouble\n"
2571 "capturing or listing interfaces.");
2572 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2573 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
2577 /* If we were given the name of a capture file, read it in now;
2578 we defer it until now, so that, if we can't open it, and pop
2579 up an alert box, the alert box is more likely to come up on
2580 top of the main window - but before the preference-file-error
2581 alert box, so, if we get one of those, it's more likely to come
2584 show_main_window(TRUE);
2585 if (rfilter != NULL) {
2586 if (!dfilter_compile(rfilter, &rfcode)) {
2587 bad_dfilter_alert_box(rfilter);
2588 rfilter_parse_failed = TRUE;
2591 if (!rfilter_parse_failed) {
2592 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2593 /* "cf_open()" succeeded, so it closed the previous
2594 capture file, and thus destroyed any previous read filter
2595 attached to "cf". */
2597 cfile.rfcode = rfcode;
2598 /* Open stat windows; we do so after creating the main window,
2599 to avoid GTK warnings, and after successfully opening the
2600 capture file, so we know we have something to compute stats
2601 on, and after registering all dissectors, so that MATE will
2602 have registered its field array and we can have a tap filter
2603 with one of MATE's late-registered fields as part of the
2605 start_requested_stats();
2607 /* Read the capture file. */
2608 switch (cf_read(&cfile)) {
2612 /* Just because we got an error, that doesn't mean we were unable
2613 to read any of the file; we handle what we could get from the
2615 /* if the user told us to jump to a specific packet, do it now */
2616 if(go_to_packet != 0) {
2617 cf_goto_frame(&cfile, go_to_packet);
2621 case CF_READ_ABORTED:
2626 /* Save the name of the containing directory specified in the
2627 path name, if any; we can write over cf_name, which is a
2628 good thing, given that "get_dirname()" does write over its
2630 s = get_dirname(cf_name);
2631 set_last_open_dir(s);
2636 dfilter_free(rfcode);
2637 cfile.rfcode = NULL;
2638 show_main_window(FALSE);
2639 set_menus_for_capture_in_progress(FALSE);
2640 set_capture_if_dialog_for_capture_in_progress(FALSE);
2645 if (start_capture) {
2646 if (global_capture_opts.save_file != NULL) {
2647 /* Save the directory name for future file dialogs. */
2648 /* (get_dirname overwrites filename) */
2649 s = get_dirname(g_strdup(global_capture_opts.save_file));
2650 set_last_open_dir(s);
2653 /* "-k" was specified; start a capture. */
2654 show_main_window(TRUE);
2655 if (capture_start(&global_capture_opts)) {
2656 /* The capture started. Open stat windows; we do so after creating
2657 the main window, to avoid GTK warnings, and after successfully
2658 opening the capture file, so we know we have something to compute
2659 stats on, and after registering all dissectors, so that MATE will
2660 have registered its field array and we can have a tap filter with
2661 one of MATE's late-registered fields as part of the filter. */
2662 start_requested_stats();
2666 show_main_window(FALSE);
2667 set_menus_for_capture_in_progress(FALSE);
2668 set_capture_if_dialog_for_capture_in_progress(FALSE);
2671 /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2672 if (!start_capture && strlen(global_capture_opts.cfilter) == 0) {
2673 g_free(global_capture_opts.cfilter);
2674 global_capture_opts.cfilter = g_strdup(get_conn_cfilter());
2676 #else /* HAVE_LIBPCAP */
2677 show_main_window(FALSE);
2678 set_menus_for_capture_in_progress(FALSE);
2679 set_capture_if_dialog_for_capture_in_progress(FALSE);
2680 #endif /* HAVE_LIBPCAP */
2683 /* register our pid if we are being run from a U3 device */
2686 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
2688 /* we'll enter the GTK loop now and hand the control over to GTK ... */
2690 /* ... back from GTK, we're going down now! */
2692 /* deregister our pid */
2693 u3_deregister_pid();
2697 #ifdef HAVE_AIRPDCAP
2698 AirPDcapDestroyContext(&airpdcap_ctx);
2702 /* hide the (unresponsive) main window, while asking the user to close the console window */
2703 gtk_widget_hide(top_level);
2705 /* Shutdown windows sockets */
2708 /* For some unknown reason, the "atexit()" call in "create_console()"
2709 doesn't arrange that "destroy_console()" be called when we exit,
2710 so we call it here if a console was created. */
2716 /* This isn't reached, but we need it to keep GCC from complaining
2717 that "main()" returns without returning a value - it knows that
2718 "exit()" never returns, but it doesn't know that "gtk_exit()"
2719 doesn't, as GTK+ doesn't declare it with the attribute
2721 return 0; /* not reached */
2726 /* We build this as a GUI subsystem application on Win32, so
2727 "WinMain()", not "main()", gets called.
2729 Hack shamelessly stolen from the Win32 port of the GIMP. */
2731 #define _stdcall __attribute__((stdcall))
2735 WinMain (struct HINSTANCE__ *hInstance,
2736 struct HINSTANCE__ *hPrevInstance,
2740 INITCOMMONCONTROLSEX comm_ctrl;
2742 /* Initialize our controls. Required for native Windows file dialogs. */
2743 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
2744 comm_ctrl.dwSize = sizeof(comm_ctrl);
2745 /* Includes the animate, header, hot key, list view, progress bar,
2746 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
2749 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
2750 InitCommonControlsEx(&comm_ctrl);
2752 /* RichEd20.DLL is needed for filter entries. */
2753 LoadLibrary(_T("riched20.dll"));
2755 has_console = FALSE;
2756 return main (__argc, __argv);
2760 * If this application has no console window to which its standard output
2761 * would go, create one.
2764 create_console(void)
2766 if (stdin_capture) {
2767 /* We've been handed "-i -". Don't mess with stdio. */
2772 /* We have no console to which to print the version string, so
2773 create one and make it the standard input, output, and error. */
2774 if (!AllocConsole())
2775 return; /* couldn't create console */
2777 ws_freopen("CONIN$", "r", stdin);
2778 ws_freopen("CONOUT$", "w", stdout);
2779 ws_freopen("CONOUT$", "w", stderr);
2781 /* Well, we have a console now. */
2784 /* Now register "destroy_console()" as a routine to be called just
2785 before the application exits, so that we can destroy the console
2786 after the user has typed a key (so that the console doesn't just
2787 disappear out from under them, giving the user no chance to see
2788 the message(s) we put in there). */
2789 atexit(destroy_console);
2791 SetConsoleTitle(_T("Wireshark Debug Console"));
2796 destroy_console(void)
2799 printf("\n\nPress any key to exit\n");
2807 /* This routine should not be necessary, at least as I read the GLib
2808 source code, as it looks as if GLib is, on Win32, *supposed* to
2809 create a console window into which to display its output.
2811 That doesn't happen, however. I suspect there's something completely
2812 broken about that code in GLib-for-Win32, and that it may be related
2813 to the breakage that forces us to just call "printf()" on the message
2814 rather than passing the message on to "g_log_default_handler()"
2815 (which is the routine that does the aforementioned non-functional
2816 console window creation). */
2818 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
2819 const char *message, gpointer user_data _U_)
2826 /* ignore log message, if log_level isn't interesting.
2827 If preferences aren't loaded yet, display message anyway */
2828 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
2829 prefs.console_log_level != 0) {
2833 /* create a "timestamp" */
2835 today = localtime(&curr);
2838 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
2839 /* the user wants a console or the application will terminate immediately */
2843 /* For some unknown reason, the above doesn't appear to actually cause
2844 anything to be sent to the standard output, so we'll just splat the
2845 message out directly, just to make sure it gets out. */
2847 switch(log_level & G_LOG_LEVEL_MASK) {
2848 case G_LOG_LEVEL_ERROR:
2851 case G_LOG_LEVEL_CRITICAL:
2854 case G_LOG_LEVEL_WARNING:
2857 case G_LOG_LEVEL_MESSAGE:
2860 case G_LOG_LEVEL_INFO:
2863 case G_LOG_LEVEL_DEBUG:
2867 fprintf(stderr, "unknown log_level %u\n", log_level);
2869 g_assert_not_reached();
2872 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
2873 today->tm_hour, today->tm_min, today->tm_sec,
2874 log_domain != NULL ? log_domain : "",
2877 if(log_level & G_LOG_LEVEL_ERROR) {
2878 /* wait for a key press before the following error handler will terminate the program
2879 this way the user at least can read the error message */
2880 printf("\n\nPress any key to exit\n");
2884 g_log_default_handler(log_domain, log_level, message, user_data);
2891 * Helper for main_widgets_rearrange()
2893 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
2894 gtk_container_remove(GTK_CONTAINER(data), widget);
2897 static GtkWidget *main_widget_layout(gint layout_content)
2899 switch(layout_content) {
2900 case(layout_pane_content_none):
2902 case(layout_pane_content_plist):
2904 case(layout_pane_content_pdetails):
2906 case(layout_pane_content_pbytes):
2909 g_assert_not_reached();
2916 * Rearrange the main window widgets
2918 void main_widgets_rearrange(void) {
2919 GtkWidget *first_pane_widget1, *first_pane_widget2;
2920 GtkWidget *second_pane_widget1, *second_pane_widget2;
2921 gboolean split_top_left;
2923 /* be a bit faster */
2924 gtk_widget_hide(main_vbox);
2926 /* be sure we don't lose a widget while rearranging */
2927 g_object_ref(G_OBJECT(menubar));
2928 g_object_ref(G_OBJECT(main_tb));
2929 g_object_ref(G_OBJECT(filter_tb));
2931 g_object_ref(G_OBJECT(airpcap_tb));
2933 g_object_ref(G_OBJECT(pkt_scrollw));
2934 g_object_ref(G_OBJECT(tv_scrollw));
2935 g_object_ref(G_OBJECT(byte_nb_ptr));
2936 g_object_ref(G_OBJECT(statusbar));
2937 g_object_ref(G_OBJECT(main_pane_v1));
2938 g_object_ref(G_OBJECT(main_pane_v2));
2939 g_object_ref(G_OBJECT(main_pane_h1));
2940 g_object_ref(G_OBJECT(main_pane_h2));
2941 g_object_ref(G_OBJECT(welcome_pane));
2943 /* empty all containers participating */
2944 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
2945 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
2946 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
2947 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
2948 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
2950 statusbar_widgets_emptying(statusbar);
2952 /* add the menubar always at the top */
2953 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
2956 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
2958 /* filter toolbar in toolbar area */
2959 if (!prefs.filter_toolbar_show_in_statusbar) {
2960 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
2964 /* airpcap toolbar */
2965 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
2968 /* fill the main layout panes */
2969 switch(prefs.gui_layout_type) {
2970 case(layout_type_5):
2971 main_first_pane = main_pane_v1;
2972 main_second_pane = main_pane_v2;
2973 split_top_left = FALSE;
2975 case(layout_type_2):
2976 main_first_pane = main_pane_v1;
2977 main_second_pane = main_pane_h1;
2978 split_top_left = FALSE;
2980 case(layout_type_1):
2981 main_first_pane = main_pane_v1;
2982 main_second_pane = main_pane_h1;
2983 split_top_left = TRUE;
2985 case(layout_type_4):
2986 main_first_pane = main_pane_h1;
2987 main_second_pane = main_pane_v1;
2988 split_top_left = FALSE;
2990 case(layout_type_3):
2991 main_first_pane = main_pane_h1;
2992 main_second_pane = main_pane_v1;
2993 split_top_left = TRUE;
2995 case(layout_type_6):
2996 main_first_pane = main_pane_h1;
2997 main_second_pane = main_pane_h2;
2998 split_top_left = FALSE;
3001 main_first_pane = NULL;
3002 main_second_pane = NULL;
3003 split_top_left = FALSE;
3004 g_assert_not_reached();
3006 if (split_top_left) {
3007 first_pane_widget1 = main_second_pane;
3008 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3009 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3010 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3012 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3013 first_pane_widget2 = main_second_pane;
3014 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3015 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3017 if (first_pane_widget1 != NULL)
3018 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3019 if (first_pane_widget2 != NULL)
3020 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3021 if (second_pane_widget1 != NULL)
3022 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3023 if (second_pane_widget2 != NULL)
3024 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3026 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3029 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3032 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
3034 /* filter toolbar in statusbar hbox */
3035 if (prefs.filter_toolbar_show_in_statusbar) {
3036 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
3040 /* airpcap toolbar */
3041 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3044 /* statusbar widgets */
3045 statusbar_widgets_pack(statusbar);
3047 /* hide widgets on users recent settings */
3048 main_widgets_show_or_hide();
3050 gtk_widget_show(main_vbox);
3054 is_widget_visible(GtkWidget *widget, gpointer data)
3056 gboolean *is_visible = data;
3059 if (GTK_WIDGET_VISIBLE(widget))
3066 main_widgets_show_or_hide(void)
3068 gboolean main_second_pane_show;
3070 if (recent.main_toolbar_show) {
3071 gtk_widget_show(main_tb);
3073 gtk_widget_hide(main_tb);
3076 statusbar_widgets_show_or_hide(statusbar);
3078 if (recent.filter_toolbar_show) {
3079 gtk_widget_show(filter_tb);
3081 gtk_widget_hide(filter_tb);
3085 if (recent.airpcap_toolbar_show) {
3086 gtk_widget_show(airpcap_tb);
3088 gtk_widget_hide(airpcap_tb);
3092 if (recent.packet_list_show && have_capture_file) {
3093 gtk_widget_show(pkt_scrollw);
3095 gtk_widget_hide(pkt_scrollw);
3098 if (recent.tree_view_show && have_capture_file) {
3099 gtk_widget_show(tv_scrollw);
3101 gtk_widget_hide(tv_scrollw);
3104 if (recent.byte_view_show && have_capture_file) {
3105 gtk_widget_show(byte_nb_ptr);
3107 gtk_widget_hide(byte_nb_ptr);
3110 if (have_capture_file) {
3111 gtk_widget_show(main_first_pane);
3113 gtk_widget_hide(main_first_pane);
3117 * Is anything in "main_second_pane" visible?
3118 * If so, show it, otherwise hide it.
3120 main_second_pane_show = FALSE;
3121 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3122 &main_second_pane_show);
3123 if (main_second_pane_show) {
3124 gtk_widget_show(main_second_pane);
3126 gtk_widget_hide(main_second_pane);
3129 if (!have_capture_file) {
3131 gtk_widget_show(welcome_pane);
3134 gtk_widget_hide(welcome_pane);
3137 /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3138 packet_list_freeze ();
3139 packet_list_thaw ();
3143 /* called, when the window state changes (minimized, maximized, ...) */
3145 window_state_event_cb (GtkWidget *widget _U_,
3149 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3151 if( (event->type) == (GDK_WINDOW_STATE)) {
3152 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3153 /* we might have dialogs popped up while we where iconified,
3155 display_queued_messages();
3163 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3165 top_level_key_pressed_cb(GtkWidget *w _U_, GdkEventKey *event, gpointer user_data _U_)
3167 if (event->keyval == GDK_F8) {
3170 } else if (event->keyval == GDK_F7) {
3173 } else if (event->state & NO_SHIFT_MOD_MASK) {
3174 return FALSE; /* Skip control, alt, and other modifiers */
3176 * A comment in gdkkeysyms.h says that it's autogenerated from
3177 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3178 * don't explicitly say so, isprint() should work as expected
3181 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3182 /* Forward the keypress on to the display filter entry */
3183 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3184 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3185 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3193 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
3195 GtkTooltips *tooltips;
3196 GtkAccelGroup *accel;
3199 /* use user-defined title if preference is set */
3200 title = create_user_window_title("The Wireshark Network Analyzer");
3203 top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
3206 tooltips = gtk_tooltips_new();
3208 gtk_widget_set_name(top_level, "main window");
3209 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3211 g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3212 G_CALLBACK(window_state_event_cb), NULL);
3213 g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3214 G_CALLBACK(top_level_key_pressed_cb), NULL );
3216 gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
3218 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3219 main_vbox = gtk_vbox_new(FALSE, 1);
3220 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
3221 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3222 gtk_widget_show(main_vbox);
3225 menubar = main_menu_new(&accel);
3227 #ifdef HAVE_IGE_MAC_INTEGRATION
3228 /* MacOS X native menus are created and displayed by main_menu_new() */
3229 if(!prefs->gui_macosx_style) {
3231 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3232 gtk_widget_show(menubar);
3233 #ifdef HAVE_IGE_MAC_INTEGRATION
3238 main_tb = toolbar_new();
3239 gtk_widget_show (main_tb);
3241 /* Filter toolbar */
3242 filter_tb = filter_toolbar_new();
3245 pkt_scrollw = packet_list_new(prefs);
3246 gtk_widget_set_size_request(packet_list, -1, pl_size);
3247 gtk_widget_show(pkt_scrollw);
3250 tv_scrollw = main_tree_view_new(prefs, &tree_view);
3251 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3252 gtk_widget_show(tv_scrollw);
3254 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
3255 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3256 g_signal_connect(tree_view, "button_press_event", G_CALLBACK(popup_menu_handler),
3257 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3258 gtk_widget_show(tree_view);
3261 byte_nb_ptr = byte_view_new();
3262 gtk_widget_set_size_request(byte_nb_ptr, -1, bv_size);
3263 gtk_widget_show(byte_nb_ptr);
3265 g_signal_connect(byte_nb_ptr, "button_press_event", G_CALLBACK(popup_menu_handler),
3266 g_object_get_data(G_OBJECT(popup_menu_object), PM_HEXDUMP_KEY));
3269 /* Panes for the packet list, tree, and byte view */
3270 main_pane_v1 = gtk_vpaned_new();
3271 gtk_widget_show(main_pane_v1);
3272 main_pane_v2 = gtk_vpaned_new();
3273 gtk_widget_show(main_pane_v2);
3274 main_pane_h1 = gtk_hpaned_new();
3275 gtk_widget_show(main_pane_h1);
3276 main_pane_h2 = gtk_hpaned_new();
3277 gtk_widget_show(main_pane_h2);
3279 airpcap_tb = airpcap_toolbar_new();
3280 gtk_widget_show(airpcap_tb);
3283 statusbar = statusbar_new();
3284 gtk_widget_show(statusbar);
3286 /* Pane for the welcome screen */
3287 welcome_pane = welcome_new();
3288 gtk_widget_show(welcome_pane);
3292 show_main_window(gboolean doing_work)
3294 main_set_for_capture_file(doing_work);
3296 /*** we have finished all init things, show the main window ***/
3297 gtk_widget_show(top_level);
3299 /* the window can be maximized only, if it's visible, so do it after show! */
3300 main_load_window_geometry(top_level);
3302 /* process all pending GUI events before continue */
3303 while (gtk_events_pending()) gtk_main_iteration();
3305 /* Pop up any queued-up alert boxes. */
3306 display_queued_messages();
3308 /* Move the main window to the front, in case it isn't already there */
3309 gdk_window_raise(top_level->window);
3312 airpcap_toolbar_show(airpcap_tb);
3313 #endif /* HAVE_AIRPCAP */
3316 /* Fill in capture options with values from the preferences */
3318 prefs_to_capture_opts(void)
3321 /* Set promiscuous mode from the preferences setting. */
3322 /* the same applies to other preferences settings as well. */
3323 global_capture_opts.promisc_mode = prefs.capture_prom_mode;
3324 global_capture_opts.show_info = prefs.capture_show_info;
3325 global_capture_opts.real_time_mode = prefs.capture_real_time;
3326 auto_scroll_live = prefs.capture_auto_scroll;
3327 #endif /* HAVE_LIBPCAP */
3329 /* Set the name resolution code's flags from the preferences. */
3330 g_resolv_flags = prefs.name_resolve;
3334 /* Change configuration profile */
3335 void change_configuration_profile (const gchar *profile_name)
3337 char *gdp_path, *dp_path;
3341 /* First check if profile exists */
3342 if (!profile_exists(profile_name)) {
3346 /* Get the current geometry, before writing it to disk */
3347 main_save_window_geometry(top_level);
3349 if (profile_exists(get_profile_name())) {
3350 /* Write recent file for profile we are leaving, if it still exists */
3351 write_profile_recent();
3354 /* Set profile name and update the status bar */
3355 set_profile_name (profile_name);
3356 profile_bar_update ();
3358 /* Reset current preferences and apply the new */
3360 (void) read_configuration_files (&gdp_path, &dp_path);
3362 recent_read_profile_static(&rf_path, &rf_open_errno);
3363 if (rf_path != NULL && rf_open_errno != 0) {
3364 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3365 "Could not open common recent file\n\"%s\": %s.",
3366 rf_path, strerror(rf_open_errno));
3368 timestamp_set_type (recent.gui_time_format);
3369 color_filters_enable(recent.packet_list_colorize);
3370 menu_recent_read_finished();
3371 main_pane_load_window_geometry();
3372 recent.gui_time_format = timestamp_get_type ();
3374 prefs_to_capture_opts();
3377 /* Update window view and redraw the toolbar */
3378 update_main_window_name();
3379 toolbar_redraw_all();
3381 /* Enable all protocols and disable from the disabled list */
3383 if (gdp_path == NULL && dp_path == NULL) {
3384 set_disabled_protos_list();
3387 /* Reload color filters */
3388 color_filters_reload();
3390 /* Reload list of interfaces on welcome page */
3391 welcome_if_panel_reload();
3393 /* Recreate the packet list according to new preferences */
3394 packet_list_recreate ();
3395 status_expert_update();
3396 cfile.cinfo.columns_changed = FALSE; /* Reset value */