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/tap_dfilter_dlg.h"
155 #include "../image/wsicon16.xpm"
156 #include "../image/wsicon32.xpm"
157 #include "../image/wsicon48.xpm"
158 #include "../image/wsicon64.xpm"
159 #include "../image/wsiconcap16.xpm"
160 #include "../image/wsiconcap32.xpm"
161 #include "../image/wsiconcap48.xpm"
166 #include "airpcap_loader.h"
167 #include "airpcap_dlg.h"
168 #include "airpcap_gui_utils.h"
170 #include "./image/toolbar/wep_closed_24.xpm"
174 #include <epan/crypt/airpdcap_ws.h>
177 #ifdef HAVE_IGE_MAC_INTEGRATION
178 #include <ige-mac-menu.h>
182 * Files under personal and global preferences directories in which
183 * GTK settings for Wireshark are stored.
185 #define RC_FILE "gtkrc"
189 /* "exported" main widgets */
190 GtkWidget *top_level = NULL, *pkt_scrollw, *tree_view, *byte_nb_ptr;
192 /* placement widgets (can be a bit confusing, because of the many layout possibilities */
193 static GtkWidget *main_vbox, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
194 static GtkWidget *main_first_pane, *main_second_pane;
196 /* internally used widgets */
197 static GtkWidget *menubar, *main_tb, *filter_tb, *tv_scrollw, *statusbar, *welcome_pane;
200 GtkWidget *airpcap_tb;
201 int airpcap_dll_ret_val = -1;
204 GString *comp_info_str, *runtime_info_str;
205 gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
207 guint tap_update_timer_id;
210 static gboolean has_console; /* TRUE if app has console */
211 static void destroy_console(void);
212 static gboolean stdin_capture = FALSE; /* Don't grab stdin & stdout if TRUE */
214 static void console_log_handler(const char *log_domain,
215 GLogLevelFlags log_level, const char *message, gpointer user_data);
218 capture_options global_capture_opts;
222 static void create_main_window(gint, gint, gint, e_prefs*);
223 static void show_main_window(gboolean);
224 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
225 static void main_save_window_geometry(GtkWidget *widget);
228 /* Match selected byte pattern */
230 match_selected_cb_do(gpointer data, int action, gchar *text)
232 GtkWidget *filter_te;
233 char *cur_filter, *new_filter;
235 if ((!text) || (0 == strlen(text))) {
236 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
241 filter_te = g_object_get_data(G_OBJECT(data), E_DFILTER_TE_KEY);
244 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
246 switch (action&MATCH_SELECTED_MASK) {
248 case MATCH_SELECTED_REPLACE:
249 new_filter = g_strdup(text);
252 case MATCH_SELECTED_AND:
253 if ((!cur_filter) || (0 == strlen(cur_filter)))
254 new_filter = g_strdup(text);
256 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
259 case MATCH_SELECTED_OR:
260 if ((!cur_filter) || (0 == strlen(cur_filter)))
261 new_filter = g_strdup(text);
263 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
266 case MATCH_SELECTED_NOT:
267 new_filter = g_strconcat("!(", text, ")", NULL);
270 case MATCH_SELECTED_AND_NOT:
271 if ((!cur_filter) || (0 == strlen(cur_filter)))
272 new_filter = g_strconcat("!(", text, ")", NULL);
274 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
277 case MATCH_SELECTED_OR_NOT:
278 if ((!cur_filter) || (0 == strlen(cur_filter)))
279 new_filter = g_strconcat("!(", text, ")", NULL);
281 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
285 g_assert_not_reached();
290 /* Free up the copy we got of the old filter text. */
293 /* Don't change the current display filter if we only want to copy the filter */
294 if (action&MATCH_SELECTED_COPY_ONLY) {
295 GString *gtk_text_str = g_string_new("");
296 g_string_append_printf(gtk_text_str, "%s", new_filter);
297 copy_to_clipboard(gtk_text_str);
298 g_string_free(gtk_text_str, TRUE);
300 /* create a new one and set the display filter entry accordingly */
301 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
303 /* Run the display filter so it goes in effect. */
304 if (action&MATCH_SELECTED_APPLY_NOW)
305 main_filter_packets(&cfile, new_filter, FALSE);
308 /* Free up the new filter text. */
313 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
317 if (cfile.finfo_selected) {
318 filter = proto_construct_match_selected_string(cfile.finfo_selected,
320 match_selected_cb_do((data ? data : w), action, filter);
325 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
329 if (cfile.finfo_selected) {
330 filter = proto_construct_match_selected_string(cfile.finfo_selected,
332 if ((!filter) || (0 == strlen(filter))) {
333 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
334 "Could not acquire information to build a filter!\n"
335 "Try expanding or choosing another item.");
340 color_display_with_filter(filter);
343 color_filters_reset_tmp();
345 color_filters_set_tmp(filt_nr,filter, FALSE);
347 cf_colorize_packets(&cfile);
353 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
355 gchar *selected_proto_url;
356 gchar *proto_abbrev = data;
361 if (cfile.finfo_selected) {
362 /* open wiki page using the protocol abbreviation */
363 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
364 browser_open_url(selected_proto_url);
365 g_free(selected_proto_url);
368 case(ESD_BTN_CANCEL):
371 g_assert_not_reached();
377 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
380 const gchar *proto_abbrev;
384 if (cfile.finfo_selected) {
385 /* convert selected field to protocol abbreviation */
386 /* XXX - could this conversion be simplified? */
387 field_id = cfile.finfo_selected->hfinfo->id;
388 /* if the selected field isn't a protocol, get it's parent */
389 if(!proto_registrar_is_protocol(field_id)) {
390 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
393 proto_abbrev = proto_registrar_get_abbrev(field_id);
395 /* ask the user if the wiki page really should be opened */
396 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
397 "%sOpen Wireshark Wiki page of protocol \"%s\"?%s\n"
399 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
401 "The Wireshark Wiki is a collaborative approach to provide information\n"
402 "about Wireshark in several ways (not limited to protocol specifics).\n"
404 "This Wiki is new, so the page of the selected protocol\n"
405 "may not exist and/or may not contain valuable information.\n"
407 "As everyone can edit the Wiki and add new content (or extend existing),\n"
408 "you are encouraged to add information if you can.\n"
410 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
412 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate,\n"
413 "which will save you a lot of editing and will give a consistent look over the pages.",
414 simple_dialog_primary_start(), proto_abbrev, simple_dialog_primary_end(), proto_abbrev);
415 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer) proto_abbrev);
421 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
424 const gchar *proto_abbrev;
425 gchar *selected_proto_url;
428 if (cfile.finfo_selected) {
429 /* convert selected field to protocol abbreviation */
430 /* XXX - could this conversion be simplified? */
431 field_id = cfile.finfo_selected->hfinfo->id;
432 /* if the selected field isn't a protocol, get it's parent */
433 if(!proto_registrar_is_protocol(field_id)) {
434 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
437 proto_abbrev = proto_registrar_get_abbrev(field_id);
439 /* open reference page using the protocol abbreviation */
440 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s.html", proto_abbrev[0], proto_abbrev);
441 browser_open_url(selected_proto_url);
442 g_free(selected_proto_url);
447 get_text_from_packet_list(gpointer data)
449 gint row = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_ROW_KEY));
450 gint column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(data), E_MPACKET_LIST_COL_KEY));
451 frame_data *fdata = (frame_data *)packet_list_get_row_data(row);
453 if(strlen(fdata->col_expr.col_expr[column]) != 0 &&
454 strlen(fdata->col_expr.col_expr_val[column]) != 0)
455 return ep_strdup_printf("%s == %s",
456 fdata->col_expr.col_expr[column],
457 fdata->col_expr.col_expr_val[column]);
463 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
465 match_selected_cb_do(data,
467 get_text_from_packet_list(data));
470 /* This function allows users to right click in the details window and copy the text
471 * information to the operating systems clipboard.
473 * We first check to see if a string representation is setup in the tree and then
474 * read the string. If not available then we try to grab the value. If all else
475 * fails we display a message to the user to indicate the copy could not be completed.
478 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_)
480 GString *gtk_text_str = g_string_new("");
481 char labelstring[256];
482 char *stringpointer = labelstring;
484 if (cfile.finfo_selected->rep->representation != 0) {
485 g_string_append_printf(gtk_text_str, "%s", cfile.finfo_selected->rep->representation); /* Get the represented data */
487 if (gtk_text_str->len == 0) { /* If no representation then... */
488 proto_item_fill_label(cfile.finfo_selected, stringpointer); /* Try to read the value */
489 g_string_append_printf(gtk_text_str, "%s", stringpointer);
491 if (gtk_text_str->len == 0) { /* Could not get item so display error msg */
492 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
496 copy_to_clipboard(gtk_text_str); /* Copy string to clipboard */
498 g_string_free(gtk_text_str, TRUE); /* Free the memory */
502 /* mark as reference time frame */
504 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
508 frame->flags.ref_time=1;
510 frame->flags.ref_time=0;
512 cf_reftime_packets(&cfile);
516 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
520 timestamp_set_type(TS_RELATIVE);
521 recent.gui_time_format = TS_RELATIVE;
522 cf_change_time_formats(&cfile);
527 g_assert_not_reached();
530 if (cfile.current_frame) {
531 /* XXX hum, should better have a "cfile->current_row" here ... */
532 set_frame_reftime(!cfile.current_frame->flags.ref_time,
534 packet_list_find_row_from_data(cfile.current_frame));
540 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
542 static GtkWidget *reftime_dialog = NULL;
546 if (cfile.current_frame) {
547 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
548 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
549 "%sSwitch to the appropriate Time Display Format?%s\n\n"
550 "Time References don't work well with the currently selected Time Display Format.\n\n"
551 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?",
552 simple_dialog_primary_start(), simple_dialog_primary_end());
553 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
555 /* XXX hum, should better have a "cfile->current_row" here ... */
556 set_frame_reftime(!cfile.current_frame->flags.ref_time,
558 packet_list_find_row_from_data(cfile.current_frame));
562 case REFTIME_FIND_NEXT:
563 find_previous_next_frame_with_filter("frame.ref_time", FALSE);
565 case REFTIME_FIND_PREV:
566 find_previous_next_frame_with_filter("frame.ref_time", TRUE);
572 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
574 find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
578 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
580 find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
584 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
587 gchar *help_str = NULL;
588 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
590 gboolean has_blurb = FALSE;
591 guint length = 0, byte_len;
592 GtkWidget *byte_view;
593 const guint8 *byte_data;
598 /* if nothing is selected */
599 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
602 * Which byte view is displaying the current protocol tree
605 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
606 if (byte_view == NULL)
609 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
610 if (byte_data == NULL)
613 cf_unselect_field(&cfile);
614 packet_hex_print(byte_view, byte_data,
615 cfile.current_frame, NULL, byte_len);
618 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
621 set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
623 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
624 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
625 g_assert(byte_data != NULL);
627 cfile.finfo_selected = finfo;
628 set_menus_for_selected_tree_row(&cfile);
631 if (finfo->hfinfo->blurb != NULL &&
632 finfo->hfinfo->blurb[0] != '\0') {
634 length = strlen(finfo->hfinfo->blurb);
636 length = strlen(finfo->hfinfo->name);
638 finfo_length = finfo->length + finfo->appendix_length;
640 if (finfo_length == 0) {
642 } else if (finfo_length == 1) {
643 g_strlcpy (len_str, ", 1 byte", sizeof len_str);
645 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
647 statusbar_pop_field_msg(); /* get rid of current help msg */
649 help_str = g_strdup_printf(" %s (%s)%s",
650 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
651 finfo->hfinfo->abbrev, len_str);
652 statusbar_push_field_msg(help_str);
656 * Don't show anything if the field name is zero-length;
657 * the pseudo-field for "proto_tree_add_text()" is such
658 * a field, and we don't want "Text (text)" showing up
659 * on the status line if you've selected such a field.
661 * XXX - there are zero-length fields for which we *do*
662 * want to show the field name.
664 * XXX - perhaps the name and abbrev field should be null
665 * pointers rather than null strings for that pseudo-field,
666 * but we'd have to add checks for null pointers in some
667 * places if we did that.
669 * Or perhaps protocol tree items added with
670 * "proto_tree_add_text()" should have -1 as the field index,
671 * with no pseudo-field being used, but that might also
672 * require special checks for -1 to be added.
674 statusbar_push_field_msg("");
677 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
681 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
683 collapse_all_tree(cfile.edt->tree, tree_view);
686 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
688 expand_all_tree(cfile.edt->tree, tree_view);
691 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
694 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view), cfile.finfo_selected);
696 /* the mouse position is at an entry, expand that one */
697 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
698 gtk_tree_path_free(path);
702 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
703 if (cfile.edt->tree) {
704 guint32 tmp = g_resolv_flags;
705 g_resolv_flags = RESOLV_ALL;
706 proto_tree_draw(cfile.edt->tree, tree_view);
707 g_resolv_flags = tmp;
712 main_set_for_capture_file(gboolean have_capture_file_in)
714 have_capture_file = have_capture_file_in;
716 main_widgets_show_or_hide();
722 /* get the current geometry, before writing it to disk */
723 main_save_window_geometry(top_level);
725 /* write user's recent file to disk
726 * It is no problem to write this file, even if we do not quit */
727 write_profile_recent();
730 /* XXX - should we check whether the capture file is an
731 unsaved temporary file for a live capture and, if so,
732 pop up a "do you want to exit without saving the capture
733 file?" dialog, and then just return, leaving said dialog
734 box to forcibly quit if the user clicks "OK"?
736 If so, note that this should be done in a subroutine that
737 returns TRUE if we do so, and FALSE otherwise, and if it
738 returns TRUE we should return TRUE without nuking anything.
740 Note that, if we do that, we might also want to check if
741 an "Update list of packets in real time" capture is in
742 progress and, if so, ask whether they want to terminate
743 the capture and discard it, and return TRUE, before nuking
744 any child capture, if they say they don't want to do so. */
747 /* Nuke any child capture in progress. */
748 capture_kill_child(&global_capture_opts);
751 /* Are we in the middle of reading a capture? */
752 if (cfile.state == FILE_READ_IN_PROGRESS) {
753 /* Yes, so we can't just close the file and quit, as
754 that may yank the rug out from under the read in
755 progress; instead, just set the state to
756 "FILE_READ_ABORTED" and return - the code doing the read
757 will check for that and, if it sees that, will clean
759 cfile.state = FILE_READ_ABORTED;
761 /* Say that the window should *not* be deleted;
762 that'll be done by the code that cleans up. */
765 /* Close any capture file we have open; on some OSes, you
766 can't unlink a temporary capture file if you have it
768 "cf_close()" will unlink it after closing it if
769 it's a temporary file.
771 We do this here, rather than after the main loop returns,
772 as, after the main loop returns, the main window may have
773 been destroyed (if this is called due to a "destroy"
774 even on the main window rather than due to the user
775 selecting a menu item), and there may be a crash
776 or other problem when "cf_close()" tries to
777 clean up stuff in the main window.
779 XXX - is there a better place to put this?
780 Or should we have a routine that *just* closes the
781 capture file, and doesn't do anything with the UI,
782 which we'd call here, and another routine that
783 calls that routine and also cleans up the UI, which
784 we'd call elsewhere? */
787 /* Exit by leaving the main loop, so that any quit functions
788 we registered get called. */
791 /* Say that the window should be deleted. */
797 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
801 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
802 gtk_window_present(GTK_WINDOW(top_level));
803 /* user didn't saved his current file, ask him */
804 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
805 "%sSave capture file before program quit?%s\n\n"
806 "If you quit the program without saving, your capture data will be discarded.",
807 simple_dialog_primary_start(), simple_dialog_primary_end());
808 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
811 /* unchanged file, just exit */
812 /* "main_do_quit()" indicates whether the main window should be deleted. */
813 return main_do_quit();
819 main_pane_load_window_geometry(void)
821 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
822 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
823 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane) {
824 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
830 main_load_window_geometry(GtkWidget *widget)
832 window_geometry_t geom;
834 geom.set_pos = prefs.gui_geometry_save_position;
835 geom.x = recent.gui_geometry_main_x;
836 geom.y = recent.gui_geometry_main_y;
837 geom.set_size = prefs.gui_geometry_save_size;
838 if (recent.gui_geometry_main_width > 0 &&
839 recent.gui_geometry_main_height > 0) {
840 geom.width = recent.gui_geometry_main_width;
841 geom.height = recent.gui_geometry_main_height;
842 geom.set_maximized = prefs.gui_geometry_save_maximized;
844 /* We assume this means the width and height weren't set in
845 the "recent" file (or that there is no "recent" file),
846 and weren't set to a default value, so we don't set the
847 size. (The "recent" file code rejects non-positive width
848 and height values.) */
849 geom.set_size = FALSE;
851 geom.maximized = recent.gui_geometry_main_maximized;
853 window_set_geometry(widget, &geom);
855 main_pane_load_window_geometry();
856 statusbar_load_window_geometry();
861 main_save_window_geometry(GtkWidget *widget)
863 window_geometry_t geom;
865 window_get_geometry(widget, &geom);
867 if (prefs.gui_geometry_save_position) {
868 recent.gui_geometry_main_x = geom.x;
869 recent.gui_geometry_main_y = geom.y;
872 if (prefs.gui_geometry_save_size) {
873 recent.gui_geometry_main_width = geom.width;
874 recent.gui_geometry_main_height = geom.height;
877 if(prefs.gui_geometry_save_maximized) {
878 recent.gui_geometry_main_maximized = geom.maximized;
881 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
882 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
883 statusbar_save_window_geometry();
886 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
890 /* save file first */
891 file_save_as_cmd(after_save_exit, NULL);
893 case(ESD_BTN_DONT_SAVE):
896 case(ESD_BTN_CANCEL):
899 g_assert_not_reached();
904 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
908 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
909 /* user didn't saved his current file, ask him */
910 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
911 "%sSave capture file before program quit?%s\n\n"
912 "If you quit the program without saving, your capture data will be discarded.",
913 simple_dialog_primary_start(), simple_dialog_primary_end());
914 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
916 /* unchanged file, just exit */
922 print_usage(gboolean print_ver) {
932 fprintf(output, "Wireshark " VERSION "%s\n"
933 "Interactively dump and analyze network traffic.\n"
934 "See http://www.wireshark.org for more information.\n"
937 wireshark_svnversion, get_copyright_info());
941 fprintf(output, "\n");
942 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
943 fprintf(output, "\n");
946 fprintf(output, "Capture interface:\n");
947 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
948 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
949 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
950 fprintf(output, " -p don't capture in promiscuous mode\n");
951 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
952 fprintf(output, " -Q quit Wireshark after capturing\n");
953 fprintf(output, " -S update packet display when new packets are captured\n");
954 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
956 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
958 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
959 fprintf(output, " -D print list of interfaces and exit\n");
960 fprintf(output, " -L print list of link-layer types of iface and exit\n");
961 fprintf(output, "\n");
962 fprintf(output, "Capture stop conditions:\n");
963 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
964 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
965 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
966 fprintf(output, " files:NUM - stop after NUM files\n");
967 /*fprintf(output, "\n");*/
968 fprintf(output, "Capture output:\n");
969 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
970 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
971 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
972 #endif /* HAVE_LIBPCAP */
974 /*fprintf(output, "\n");*/
975 fprintf(output, "Input file:\n");
976 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
978 fprintf(output, "\n");
979 fprintf(output, "Processing:\n");
980 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
981 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
982 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
984 fprintf(output, "\n");
985 fprintf(output, "User interface:\n");
986 fprintf(output, " -C <config profile> start with specified configuration profile\n");
987 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
988 fprintf(output, " -m <font> set the font name used for most text\n");
989 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
990 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
991 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
993 fprintf(output, "\n");
994 fprintf(output, "Output:\n");
995 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
997 fprintf(output, "\n");
998 fprintf(output, "Miscellaneous:\n");
999 fprintf(output, " -h display this help and exit\n");
1000 fprintf(output, " -v display version info and exit\n");
1001 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1002 fprintf(output, " persdata:path - personal data files\n");
1003 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1004 fprintf(output, " -K <keytab> keytab file to use for kerberos decryption\n");
1006 fprintf(output, " --display=DISPLAY X display to use\n");
1021 printf(PACKAGE " " VERSION "%s\n"
1028 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1029 runtime_info_str->str);
1037 * Report an error in command-line arguments.
1038 * Creates a console on Windows.
1039 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1040 * terminal isn't the standard error?
1043 cmdarg_err(const char *fmt, ...)
1051 fprintf(stderr, "wireshark: ");
1052 vfprintf(stderr, fmt, ap);
1053 fprintf(stderr, "\n");
1058 * Report additional information for an error in command-line arguments.
1059 * Creates a console on Windows.
1060 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1061 * terminal isn't the standard error?
1064 cmdarg_err_cont(const char *fmt, ...)
1072 vfprintf(stderr, fmt, ap);
1073 fprintf(stderr, "\n");
1077 #if defined(_WIN32) || ! defined USE_THREADS
1079 Once every 3 seconds we get a callback here which we use to update
1080 the tap extensions. Since Gtk1 is single threaded we dont have to
1081 worry about any locking or critical regions.
1084 update_cb(gpointer data _U_)
1086 draw_tap_listeners(FALSE);
1090 /* Restart the tap update display timer with new configured interval */
1091 void reset_tap_update_timer(void)
1093 g_source_remove(tap_update_timer_id);
1094 tap_update_timer_id = g_timeout_add(prefs.tap_update_interval, update_cb, NULL);
1099 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1100 use threads all update_thread_mutex can be dropped and protect/unprotect
1101 would just be empty functions.
1103 This allows gtk2-rpcstat.c and friends to be copied unmodified to
1104 gtk1-wireshark and it will just work.
1106 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1108 update_thread(gpointer data _U_)
1112 g_get_current_time(&tv1);
1113 g_static_mutex_lock(&update_thread_mutex);
1114 gdk_threads_enter();
1115 draw_tap_listeners(FALSE);
1116 gdk_threads_leave();
1117 g_static_mutex_unlock(&update_thread_mutex);
1119 g_get_current_time(&tv2);
1121 /* Assuming it took less than configured time to update tap listeners... */
1122 if( (tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) >
1123 (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1124 /* Wait for remainder of configured time */
1125 g_usleep((tv1.tv_sec * 1000000 + tv1.tv_usec + prefs.tap_update_interval * 1000) -
1126 (tv2.tv_sec * 1000000 + tv2.tv_usec));
1133 protect_thread_critical_region(void)
1135 #if !defined(_WIN32) && defined USE_THREADS
1136 g_static_mutex_lock(&update_thread_mutex);
1140 unprotect_thread_critical_region(void)
1142 #if !defined(_WIN32) && defined USE_THREADS
1143 g_static_mutex_unlock(&update_thread_mutex);
1147 /* Set the file name in the name for the main window and in the name for the main window's icon. */
1149 set_display_filename(capture_file *cf)
1153 if (!cf->is_tempfile && cf->filename) {
1154 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1155 add_menu_recent_capture_file(cf->filename);
1159 win_name = g_strdup_printf("%s - Wireshark", cf_get_display_name(cf));
1160 set_main_window_name(win_name);
1164 GtkWidget *close_dlg = NULL;
1167 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1169 recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1174 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1176 recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1181 main_cf_cb_file_closing(capture_file *cf)
1184 /* if we have more than 10000 packets, show a splash screen while closing */
1185 /* XXX - don't know a better way to decide wether to show or not,
1186 * as most of the time is spend in a single eth_clist_clear function,
1187 * so we can't use a progress bar here! */
1188 if(cf->count > 10000) {
1189 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1190 "%sClosing file!%s\n\nPlease wait ...",
1191 simple_dialog_primary_start(),
1192 simple_dialog_primary_end());
1193 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1196 /* Destroy all windows, which refer to the
1197 capture file we're closing. */
1198 destroy_packet_wins();
1199 file_save_as_destroy();
1201 /* Restore the standard title bar message. */
1202 set_main_window_name("The Wireshark Network Analyzer");
1204 /* Disable all menu items that make sense only if you have a capture. */
1205 set_menus_for_capture_file(NULL);
1206 set_menus_for_captured_packets(FALSE);
1207 set_menus_for_selected_packet(cf);
1208 set_menus_for_capture_in_progress(FALSE);
1209 set_capture_if_dialog_for_capture_in_progress(FALSE);
1210 set_menus_for_selected_tree_row(cf);
1212 /* Set up main window for no capture file. */
1213 main_set_for_capture_file(FALSE);
1215 main_window_update();
1219 main_cf_cb_file_closed(capture_file *cf _U_)
1221 if(close_dlg != NULL) {
1222 splash_destroy(close_dlg);
1229 main_cf_cb_file_read_start(capture_file *cf _U_)
1231 tap_dfilter_dlg_update();
1233 /* Set up main window for a capture file. */
1234 main_set_for_capture_file(TRUE);
1238 main_cf_cb_file_read_finished(capture_file *cf)
1240 set_display_filename(cf);
1242 /* Enable menu items that make sense if you have a capture file you've
1243 finished reading. */
1244 set_menus_for_capture_file(cf);
1246 /* Enable menu items that make sense if you have some captured packets. */
1247 set_menus_for_captured_packets(TRUE);
1250 GList *icon_list_create(
1251 const char **icon16_xpm,
1252 const char **icon32_xpm,
1253 const char **icon48_xpm,
1254 const char **icon64_xpm)
1256 GList *icon_list = NULL;
1257 GdkPixbuf * pixbuf16;
1258 GdkPixbuf * pixbuf32;
1259 GdkPixbuf * pixbuf48;
1260 GdkPixbuf * pixbuf64;
1263 if(icon16_xpm != NULL) {
1264 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1266 icon_list = g_list_append(icon_list, pixbuf16);
1269 if(icon32_xpm != NULL) {
1270 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1272 icon_list = g_list_append(icon_list, pixbuf32);
1275 if(icon48_xpm != NULL) {
1276 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1278 icon_list = g_list_append(icon_list, pixbuf48);
1281 if(icon64_xpm != NULL) {
1282 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1284 icon_list = g_list_append(icon_list, pixbuf64);
1292 main_capture_cb_capture_prepared(capture_options *capture_opts)
1295 static GList *icon_list = NULL;
1298 if(capture_opts->iface) {
1299 title = g_strdup_printf("%s: Capturing - Wireshark",
1300 get_iface_description(capture_opts));
1302 title = g_strdup_printf("Capturing - Wireshark");
1304 set_main_window_name(title);
1307 if(icon_list == NULL) {
1308 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1310 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1312 /* Disable menu items that make no sense if you're currently running
1314 set_menus_for_capture_in_progress(TRUE);
1315 set_capture_if_dialog_for_capture_in_progress(TRUE);
1317 /* Don't set up main window for a capture file. */
1318 main_set_for_capture_file(FALSE);
1322 main_capture_cb_capture_update_started(capture_options *capture_opts)
1326 /* We've done this in "prepared" above, but it will be cleared while
1327 switching to the next multiple file. */
1328 if(capture_opts->iface) {
1329 title = g_strdup_printf("%s: Capturing - Wireshark",
1330 get_iface_description(capture_opts));
1332 title = g_strdup_printf("Capturing - Wireshark");
1334 set_main_window_name(title);
1337 set_menus_for_capture_in_progress(TRUE);
1338 set_capture_if_dialog_for_capture_in_progress(TRUE);
1340 /* Enable menu items that make sense if you have some captured
1341 packets (yes, I know, we don't have any *yet*). */
1342 set_menus_for_captured_packets(TRUE);
1344 /* Set up main window for a capture file. */
1345 main_set_for_capture_file(TRUE);
1349 main_capture_cb_capture_update_finished(capture_options *capture_opts)
1351 capture_file *cf = capture_opts->cf;
1352 static GList *icon_list = NULL;
1354 set_display_filename(cf);
1356 /* Enable menu items that make sense if you're not currently running
1358 set_menus_for_capture_in_progress(FALSE);
1359 set_capture_if_dialog_for_capture_in_progress(FALSE);
1361 /* Enable menu items that make sense if you have a capture file
1362 you've finished reading. */
1363 set_menus_for_capture_file(cf);
1365 /* Set up main window for a capture file. */
1366 main_set_for_capture_file(TRUE);
1368 if(icon_list == NULL) {
1369 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1371 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1373 if(global_capture_opts.quit_after_cap) {
1374 /* command line asked us to quit after the capture */
1375 /* don't pop up a dialog to ask for unsaved files etc. */
1381 main_capture_cb_capture_fixed_started(capture_options *capture_opts _U_)
1383 /* Don't set up main window for a capture file. */
1384 main_set_for_capture_file(FALSE);
1388 main_capture_cb_capture_fixed_finished(capture_options *capture_opts _U_)
1391 capture_file *cf = capture_opts->cf;
1393 static GList *icon_list = NULL;
1395 /*set_display_filename(cf);*/
1397 /* Enable menu items that make sense if you're not currently running
1399 set_menus_for_capture_in_progress(FALSE);
1400 set_capture_if_dialog_for_capture_in_progress(FALSE);
1402 /* Restore the standard title bar message */
1403 /* (just in case we have trouble opening the capture file). */
1404 set_main_window_name("The Wireshark Network Analyzer");
1406 if(icon_list == NULL) {
1407 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1409 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1411 /* We don't have loaded the capture file, this will be done later.
1412 * For now we still have simply a blank screen. */
1414 if(global_capture_opts.quit_after_cap) {
1415 /* command line asked us to quit after the capture */
1416 /* don't pop up a dialog to ask for unsaved files etc. */
1421 #endif /* HAVE_LIBPCAP */
1424 main_cf_cb_packet_selected(gpointer data)
1426 capture_file *cf = data;
1428 /* Display the GUI protocol tree and hex dump.
1429 XXX - why do we dump core if we call "proto_tree_draw()"
1430 before calling "add_byte_views()"? */
1431 add_main_byte_views(cf->edt);
1432 main_proto_tree_draw(cf->edt->tree);
1434 /* The user is searching for a string in the data or a hex value,
1435 * highlight the field that is found in the tree and hex displays. */
1436 if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1437 highlight_field(cf->edt->tvb, cfile.search_pos,
1438 (GtkTreeView *)tree_view, cf->edt->tree);
1439 cfile.search_pos = 0; /* Reset the position */
1442 /* A packet is selected. */
1443 set_menus_for_selected_packet(cf);
1447 main_cf_cb_packet_unselected(capture_file *cf)
1449 /* Clear out the display of that packet. */
1450 clear_tree_and_hex_views();
1452 /* No packet is selected. */
1453 set_menus_for_selected_packet(cf);
1457 main_cf_cb_field_unselected(capture_file *cf)
1459 set_menus_for_selected_tree_row(cf);
1463 main_cf_cb_file_safe_reload_finished(gpointer data _U_)
1465 set_menus_for_capture_file(&cfile);
1469 main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1472 case(cf_cb_file_closing):
1473 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1474 main_cf_cb_file_closing(data);
1476 case(cf_cb_file_closed):
1477 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1478 main_cf_cb_file_closed(data);
1480 case(cf_cb_file_read_start):
1481 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read start");
1482 main_cf_cb_file_read_start(data);
1484 case(cf_cb_file_read_finished):
1485 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1486 main_cf_cb_file_read_finished(data);
1488 case(cf_cb_packet_selected):
1489 main_cf_cb_packet_selected(data);
1491 case(cf_cb_packet_unselected):
1492 main_cf_cb_packet_unselected(data);
1494 case(cf_cb_field_unselected):
1495 main_cf_cb_field_unselected(data);
1497 case(cf_cb_file_safe_started):
1498 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe started");
1500 case(cf_cb_file_safe_finished):
1501 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe finished");
1503 case(cf_cb_file_safe_reload_finished):
1504 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: reload finished");
1505 main_cf_cb_file_safe_reload_finished(data);
1507 case(cf_cb_file_safe_failed):
1508 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe failed");
1511 g_warning("main_cf_callback: event %u unknown", event);
1512 g_assert_not_reached();
1518 main_capture_callback(gint event, capture_options *capture_opts, gpointer user_data _U_)
1521 case(capture_cb_capture_prepared):
1522 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1523 main_capture_cb_capture_prepared(capture_opts);
1525 case(capture_cb_capture_update_started):
1526 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1527 main_capture_cb_capture_update_started(capture_opts);
1529 case(capture_cb_capture_update_continue):
1530 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1532 case(capture_cb_capture_update_finished):
1533 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1534 main_capture_cb_capture_update_finished(capture_opts);
1536 case(capture_cb_capture_fixed_started):
1537 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1538 main_capture_cb_capture_fixed_started(capture_opts);
1540 case(capture_cb_capture_fixed_continue):
1541 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
1543 case(capture_cb_capture_fixed_finished):
1544 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
1545 main_capture_cb_capture_fixed_finished(capture_opts);
1547 case(capture_cb_capture_stopping):
1548 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
1549 /* Beware: this state won't be called, if the capture child
1550 * closes the capturing on it's own! */
1553 g_warning("main_capture_callback: event %u unknown", event);
1554 g_assert_not_reached();
1560 get_gui_compiled_info(GString *str)
1562 get_epan_compiled_version_info(str);
1564 g_string_append(str, ", ");
1565 #ifdef HAVE_LIBPORTAUDIO
1566 #ifdef PORTAUDIO_API_1
1567 g_string_append(str, "with PortAudio <= V18");
1568 #else /* PORTAUDIO_API_1 */
1569 g_string_append(str, "with ");
1570 g_string_append(str, Pa_GetVersionText());
1571 #endif /* PORTAUDIO_API_1 */
1572 #else /* HAVE_LIBPORTAUDIO */
1573 g_string_append(str, "without PortAudio");
1574 #endif /* HAVE_LIBPORTAUDIO */
1576 g_string_append(str, ", ");
1578 get_compiled_airpcap_version(str);
1580 g_string_append(str, "without AirPcap");
1585 get_gui_runtime_info(GString *str)
1588 g_string_append(str, ", ");
1589 get_runtime_airpcap_version(str);
1593 g_string_append(str, ", ");
1594 u3_runtime_info(str);
1600 read_configuration_files(char **gdp_path, char **dp_path)
1602 int gpf_open_errno, gpf_read_errno;
1603 int cf_open_errno, df_open_errno;
1604 int gdp_open_errno, gdp_read_errno;
1605 int dp_open_errno, dp_read_errno;
1606 char *gpf_path, *pf_path;
1607 char *cf_path, *df_path;
1608 int pf_open_errno, pf_read_errno;
1611 /* Read the preference files. */
1612 prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
1613 &pf_open_errno, &pf_read_errno, &pf_path);
1615 if (gpf_path != NULL) {
1616 if (gpf_open_errno != 0) {
1617 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1618 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1619 strerror(gpf_open_errno));
1621 if (gpf_read_errno != 0) {
1622 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1623 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
1624 strerror(gpf_read_errno));
1627 if (pf_path != NULL) {
1628 if (pf_open_errno != 0) {
1629 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1630 "Could not open your preferences file\n\"%s\": %s.", pf_path,
1631 strerror(pf_open_errno));
1633 if (pf_read_errno != 0) {
1634 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1635 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
1636 strerror(pf_read_errno));
1643 /* if the user wants a console to be always there, well, we should open one for him */
1644 if (prefs->gui_console_open == console_open_always) {
1649 /* Read the capture filter file. */
1650 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1651 if (cf_path != NULL) {
1652 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1653 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1654 strerror(cf_open_errno));
1658 /* Read the display filter file. */
1659 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1660 if (df_path != NULL) {
1661 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1662 "Could not open your display filter file\n\"%s\": %s.", df_path,
1663 strerror(df_open_errno));
1667 /* Read the disabled protocols file. */
1668 read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
1669 dp_path, &dp_open_errno, &dp_read_errno);
1670 if (*gdp_path != NULL) {
1671 if (gdp_open_errno != 0) {
1672 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1673 "Could not open global disabled protocols file\n\"%s\": %s.",
1674 *gdp_path, strerror(gdp_open_errno));
1676 if (gdp_read_errno != 0) {
1677 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1678 "I/O error reading global disabled protocols file\n\"%s\": %s.",
1679 *gdp_path, strerror(gdp_read_errno));
1684 if (*dp_path != NULL) {
1685 if (dp_open_errno != 0) {
1686 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1687 "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
1688 strerror(dp_open_errno));
1690 if (dp_read_errno != 0) {
1691 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
1692 "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
1693 strerror(dp_read_errno));
1702 /* And now our feature presentation... [ fade to music ] */
1704 main(int argc, char *argv[])
1706 char *init_progfile_dir_error;
1709 extern char *optarg;
1710 gboolean arg_error = FALSE;
1718 char *gdp_path, *dp_path;
1721 gboolean start_capture = FALSE;
1722 gboolean list_link_layer_types = FALSE;
1724 gboolean capture_option_specified = FALSE;
1726 gint pl_size = 280, tv_size = 95, bv_size = 75;
1727 gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
1728 dfilter_t *rfcode = NULL;
1729 gboolean rfilter_parse_failed = FALSE;
1732 GtkWidget *splash_win = NULL;
1733 gpointer priv_warning_dialog;
1734 GLogLevelFlags log_flags;
1735 guint go_to_packet = 0;
1738 gchar *cur_user, *cur_group;
1744 #define OPTSTRING_INIT "a:b:c:C:Df:g:Hhi:kK:lLm:nN:o:P:pQr:R:Ss:t:vw:X:y:z:"
1746 #if defined HAVE_LIBPCAP && defined _WIN32
1747 #define OPTSTRING_WIN32 "B:"
1749 #define OPTSTRING_WIN32 ""
1752 char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
1753 OPTSTRING_INIT OPTSTRING_WIN32;
1756 * Get credential information for later use, and drop privileges
1757 * before doing anything else.
1758 * Let the user know if anything happened.
1760 get_credential_info();
1761 relinquish_special_privs_perm();
1764 * Attempt to get the pathname of the executable file.
1766 init_progfile_dir_error = init_progfile_dir(argv[0]);
1768 /* initialize the funnel mini-api */
1769 initialize_funnel_ops();
1771 #ifdef HAVE_AIRPDCAP
1772 AirPDcapInitContext(&airpdcap_ctx);
1776 /* Load wpcap if possible. Do this before collecting the run-time version information */
1779 /* ... and also load the packet.dll from wpcap */
1780 wpcap_packet_load();
1783 /* Load the airpcap.dll. This must also be done before collecting
1784 * run-time version information. */
1785 airpcap_dll_ret_val = load_airpcap();
1787 switch (airpcap_dll_ret_val) {
1788 case AIRPCAP_DLL_OK:
1789 /* load the airpcap interfaces */
1790 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
1792 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
1793 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
1794 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
1797 airpcap_if_active = NULL;
1801 /* select the first ad default (THIS SHOULD BE CHANGED) */
1802 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
1807 * XXX - Maybe we need to warn the user if one of the following happens???
1809 case AIRPCAP_DLL_OLD:
1810 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
1813 case AIRPCAP_DLL_ERROR:
1814 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
1817 case AIRPCAP_DLL_NOT_FOUND:
1818 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
1822 #endif /* HAVE_AIRPCAP */
1824 /* Start windows sockets */
1825 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
1828 /* Assemble the compile-time version information string */
1829 comp_info_str = g_string_new("Compiled ");
1831 g_string_append(comp_info_str, "with ");
1832 g_string_append_printf(comp_info_str,
1833 #ifdef GTK_MAJOR_VERSION
1834 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1837 "GTK+ (version unknown)");
1839 g_string_append(comp_info_str, ", ");
1841 get_compiled_version_info(comp_info_str, get_gui_compiled_info);
1843 /* Assemble the run-time version information string */
1844 runtime_info_str = g_string_new("Running ");
1845 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
1848 /* "pre-scan" the command line parameters, if we have "console only"
1849 parameters. We do this so we don't start GTK+ if we're only showing
1850 command-line help or version information.
1852 XXX - this pre-scan is done before we start GTK+, so we haven't
1853 run gtk_init() on the arguments. That means that GTK+ arguments
1854 have not been removed from the argument list; those arguments
1855 begin with "--", and will be treated as an error by getopt().
1857 We thus ignore errors - *and* set "opterr" to 0 to suppress the
1860 optind_initial = optind;
1861 while ((opt = getopt(argc, argv, optstring)) != -1) {
1863 case 'C': /* Configuration Profile */
1864 if (profile_exists (optarg)) {
1865 set_profile_name (optarg);
1867 cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
1871 case 'h': /* Print help and exit */
1877 if (strcmp(optarg, "-") == 0)
1878 stdin_capture = TRUE;
1881 case 'P': /* Path settings - change these before the Preferences and alike are processed */
1882 status = filesystem_opt(opt, optarg);
1884 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
1888 case 'v': /* Show version and exit */
1894 * Extension command line options have to be processed before
1895 * we call epan_init() as they are supposed to be used by dissectors
1896 * or taps very early in the registration process.
1900 case '?': /* Ignore errors - the "real" scan will catch them. */
1905 /* Init the "Open file" dialog directory */
1906 /* (do this after the path settings are processed) */
1907 set_last_open_dir(get_persdatafile_dir());
1909 /* Set getopt index back to initial value, so it will start with the
1910 first command line parameter again. Also reset opterr to 1, so that
1911 error messages are printed by getopt().
1913 XXX - this seems to work on most platforms, but time will tell.
1914 The Single UNIX Specification says "The getopt() function need
1915 not be reentrant", so this isn't guaranteed to work. The Mac
1916 OS X 10.4[.x] getopt() man page says
1918 In order to use getopt() to evaluate multiple sets of arguments, or to
1919 evaluate a single set of arguments multiple times, the variable optreset
1920 must be set to 1 before the second and each additional set of calls to
1921 getopt(), and the variable optind must be reinitialized.
1925 The optreset variable was added to make it possible to call the getopt()
1926 function multiple times. This is an extension to the IEEE Std 1003.2
1927 (``POSIX.2'') specification.
1929 which I think comes from one of the other BSDs.
1931 XXX - if we want to control all the command-line option errors, so
1932 that we can display them where we choose (e.g., in a window), we'd
1933 want to leave opterr as 0, and produce our own messages using optopt.
1934 We'd have to check the value of optopt to see if it's a valid option
1935 letter, in which case *presumably* the error is "this option requires
1936 an argument but none was specified", or not a valid option letter,
1937 in which case *presumably* the error is "this option isn't valid".
1938 Some versions of getopt() let you supply a option string beginning
1939 with ':', which means that getopt() will return ':' rather than '?'
1940 for "this option requires an argument but none was specified", but
1942 optind = optind_initial;
1945 /* Set the current locale according to the program environment.
1946 * We haven't localized anything, but some GTK widgets are localized
1947 * (the file selection dialogue, for example).
1948 * This also sets the C-language locale to the native environment. */
1951 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
1952 gtk_init (&argc, &argv);
1954 cf_callback_add(main_cf_callback, NULL);
1956 capture_callback_add(main_capture_callback, NULL);
1958 cf_callback_add(statusbar_cf_callback, NULL);
1960 capture_callback_add(statusbar_capture_callback, NULL);
1963 /* Arrange that if we have no console window, and a GLib message logging
1964 routine is called to log a message, we pop up a console window.
1966 We do that by inserting our own handler for all messages logged
1967 to the default domain; that handler pops up a console if necessary,
1968 and then calls the default handler. */
1970 /* We might want to have component specific log levels later ... */
1974 G_LOG_LEVEL_CRITICAL|
1975 G_LOG_LEVEL_WARNING|
1976 G_LOG_LEVEL_MESSAGE|
1979 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
1981 g_log_set_handler(NULL,
1983 console_log_handler, NULL /* user_data */);
1984 g_log_set_handler(LOG_DOMAIN_MAIN,
1986 console_log_handler, NULL /* user_data */);
1989 g_log_set_handler(LOG_DOMAIN_CAPTURE,
1991 console_log_handler, NULL /* user_data */);
1992 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
1994 console_log_handler, NULL /* user_data */);
1996 /* Set the initial values in the capture options. This might be overwritten
1997 by preference settings and then again by the command line parameters. */
1998 capture_opts_init(&global_capture_opts, &cfile);
2000 global_capture_opts.snaplen = MIN_PACKET_SIZE;
2001 global_capture_opts.has_ring_num_files = TRUE;
2004 /* Initialize whatever we need to allocate colors for GTK+ */
2007 /* We won't come till here, if we had a "console only" command line parameter. */
2008 splash_win = splash_new("Loading Wireshark ...");
2009 if (init_progfile_dir_error != NULL) {
2010 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2011 "Can't get pathname of Wireshark: %s.\n"
2012 "It won't be possible to capture traffic.\n"
2013 "Report this to the Wireshark developers.",
2014 init_progfile_dir_error);
2015 g_free(init_progfile_dir_error);
2018 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2020 /* Register all dissectors; we must do this before checking for the
2021 "-G" flag, as the "-G" flag dumps information registered by the
2022 dissectors, and we must do it before we read the preferences, in
2023 case any dissectors register preferences. */
2024 epan_init(register_all_protocols,register_all_protocol_handoffs,
2025 splash_update, (gpointer) splash_win,
2026 failure_alert_box,open_failure_alert_box,read_failure_alert_box);
2028 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2030 /* Register all tap listeners; we do this before we parse the arguments,
2031 as the "-z" argument can specify a registered tap. */
2033 /* we register the plugin taps before the other taps because
2034 stats_tree taps plugins will be registered as tap listeners
2035 by stats_tree_stat.c and need to registered before that */
2038 register_all_plugin_tap_listeners();
2041 register_all_tap_listeners();
2043 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2045 /* Now register the preferences for any non-dissector modules.
2046 We must do that before we read the preferences as well. */
2047 prefs_register_modules();
2049 prefs = read_configuration_files (&gdp_path, &dp_path);
2051 /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2052 #if !defined(_WIN32) && defined(G_THREADS_ENABLED) && defined USE_THREADS
2055 g_thread_init(NULL);
2057 ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2058 g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2060 #else /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2061 /* this is to keep tap extensions updating once every 3 seconds */
2062 tap_update_timer_id = g_timeout_add(prefs->tap_update_interval, update_cb, NULL);
2063 #endif /* !_WIN32 && G_THREADS_ENABLED && USE_THREADS */
2066 g_timeout_add(750, host_name_lookup_process, NULL);
2069 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2072 /* Read the (static part) of the recent file. Only the static part of it will be read, */
2073 /* as we don't have the gui now to fill the recent lists which is done in the dynamic part. */
2074 /* We have to do this already here, so command line parameters can overwrite these values. */
2075 recent_read_static(&rf_path, &rf_open_errno);
2076 if (rf_path != NULL && rf_open_errno != 0) {
2077 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2078 "Could not open common recent file\n\"%s\": %s.",
2079 rf_path, strerror(rf_open_errno));
2081 recent_read_profile_static(&rf_path, &rf_open_errno);
2082 if (rf_path != NULL && rf_open_errno != 0) {
2083 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2084 "Could not open recent file\n\"%s\": %s.",
2085 rf_path, strerror(rf_open_errno));
2088 init_cap_file(&cfile);
2090 /* Fill in capture options with values from the preferences */
2091 prefs_to_capture_opts();
2093 /* Now get our args */
2094 while ((opt = getopt(argc, argv, optstring)) != -1) {
2096 /*** capture option specific ***/
2097 case 'a': /* autostop criteria */
2098 case 'b': /* Ringbuffer option */
2099 case 'c': /* Capture xxx packets */
2100 case 'f': /* capture filter */
2101 case 'k': /* Start capture immediately */
2102 case 'H': /* Hide capture info dialog box */
2103 case 'i': /* Use interface xxx */
2104 case 'p': /* Don't capture in promiscuous mode */
2105 case 'Q': /* Quit after capture (just capture to file) */
2106 case 's': /* Set the snapshot (capture) length */
2107 case 'S': /* "Sync" mode: used for following file ala tail -f */
2108 case 'w': /* Write to capture file xxx */
2109 case 'y': /* Set the pcap data link type */
2111 case 'B': /* Buffer size */
2114 status = capture_opts_add_opt(&global_capture_opts, opt, optarg,
2120 capture_option_specified = TRUE;
2125 #if defined(HAVE_HEIMDAL_KERBEROS) || defined(HAVE_MIT_KERBEROS)
2126 case 'K': /* Kerberos keytab file */
2127 read_keytab_file(optarg);
2131 /*** all non capture option specific ***/
2133 /* Configuration profile settings were already processed just ignore them this time*/
2135 case 'D': /* Print a list of capture devices and exit */
2137 capture_opts_list_interfaces(FALSE);
2140 capture_option_specified = TRUE;
2144 case 'g': /* Go to packet */
2145 go_to_packet = get_positive_int(optarg, "go to packet");
2147 case 'l': /* Automatic scrolling in live capture mode */
2149 auto_scroll_live = TRUE;
2151 capture_option_specified = TRUE;
2155 case 'L': /* Print list of link-layer types and exit */
2157 list_link_layer_types = TRUE;
2159 capture_option_specified = TRUE;
2163 case 'm': /* Fixed-width font for the display */
2164 if (prefs->gui_font_name != NULL)
2165 g_free(prefs->gui_font_name);
2166 prefs->gui_font_name = g_strdup(optarg);
2168 case 'n': /* No name resolution */
2169 g_resolv_flags = RESOLV_NONE;
2171 case 'N': /* Select what types of addresses/port #s to resolve */
2172 if (g_resolv_flags == RESOLV_ALL)
2173 g_resolv_flags = RESOLV_NONE;
2174 badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2175 if (badopt != '\0') {
2176 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2181 case 'o': /* Override preference from command line */
2182 switch (prefs_set_pref(optarg)) {
2185 case PREFS_SET_SYNTAX_ERR:
2186 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2189 case PREFS_SET_NO_SUCH_PREF:
2190 /* not a preference, might be a recent setting */
2191 switch (recent_set_arg(optarg)) {
2194 case PREFS_SET_SYNTAX_ERR:
2195 /* shouldn't happen, checked already above */
2196 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2199 case PREFS_SET_NO_SUCH_PREF:
2200 case PREFS_SET_OBSOLETE:
2201 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2206 g_assert_not_reached();
2209 case PREFS_SET_OBSOLETE:
2210 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2215 g_assert_not_reached();
2219 /* Path settings were already processed just ignore them this time*/
2221 case 'r': /* Read capture file xxx */
2222 /* We may set "last_open_dir" to "cf_name", and if we change
2223 "last_open_dir" later, we free the old value, so we have to
2224 set "cf_name" to something that's been allocated. */
2225 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2226 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2227 cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2229 cf_name = g_strdup(optarg);
2232 case 'R': /* Read file filter */
2235 case 't': /* Time stamp type */
2236 if (strcmp(optarg, "r") == 0)
2237 timestamp_set_type(TS_RELATIVE);
2238 else if (strcmp(optarg, "a") == 0)
2239 timestamp_set_type(TS_ABSOLUTE);
2240 else if (strcmp(optarg, "ad") == 0)
2241 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2242 else if (strcmp(optarg, "d") == 0)
2243 timestamp_set_type(TS_DELTA);
2244 else if (strcmp(optarg, "dd") == 0)
2245 timestamp_set_type(TS_DELTA_DIS);
2246 else if (strcmp(optarg, "e") == 0)
2247 timestamp_set_type(TS_EPOCH);
2249 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2250 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2251 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2256 /* ext ops were already processed just ignore them this time*/
2259 /* We won't call the init function for the stat this soon
2260 as it would disallow MATE's fields (which are registered
2261 by the preferences set callback) from being used as
2262 part of a tap filter. Instead, we just add the argument
2263 to a list of stat arguments. */
2264 if (!process_stat_cmd_arg(optarg)) {
2265 cmdarg_err("Invalid -z argument.");
2266 cmdarg_err_cont(" -z argument must be one of :");
2267 list_stat_cmd_args();
2272 case '?': /* Bad flag - print usage message */
2280 if (cf_name != NULL) {
2282 * Input file name specified with "-r" *and* specified as a regular
2283 * command-line argument.
2285 cmdarg_err("File name specified both with -r and regular argument");
2289 * Input file name not specified with "-r", and a command-line argument
2290 * was specified; treat it as the input file name.
2292 * Yes, this is different from tshark, where non-flag command-line
2293 * arguments are a filter, but this works better on GUI desktops
2294 * where a command can be specified to be run to open a particular
2295 * file - yes, you could have "-r" as the last part of the command,
2296 * but that's a bit ugly.
2298 #if defined _WIN32 && GLIB_CHECK_VERSION(2,6,0)
2299 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2300 cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2302 cf_name = g_strdup(argv[0]);
2313 * Extra command line arguments were specified; complain.
2315 cmdarg_err("Invalid argument: %s", argv[0]);
2320 #ifndef HAVE_LIBPCAP
2321 if (capture_option_specified) {
2322 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2330 if (start_capture && list_link_layer_types) {
2331 /* Specifying *both* is bogus. */
2332 cmdarg_err("You can't specify both -L and a live capture.");
2336 if (list_link_layer_types) {
2337 /* We're supposed to list the link-layer types for an interface;
2338 did the user also specify a capture file to be read? */
2340 /* Yes - that's bogus. */
2341 cmdarg_err("You can't specify -L and a capture file to be read.");
2344 /* No - did they specify a ring buffer option? */
2345 if (global_capture_opts.multi_files_on) {
2346 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2350 /* We're supposed to do a live capture; did the user also specify
2351 a capture file to be read? */
2352 if (start_capture && cf_name) {
2353 /* Yes - that's bogus. */
2354 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2358 /* No - was the ring buffer option specified and, if so, does it make
2360 if (global_capture_opts.multi_files_on) {
2361 /* Ring buffer works only under certain conditions:
2362 a) ring buffer does not work with temporary files;
2363 b) real_time_mode and multi_files_on are mutually exclusive -
2364 real_time_mode takes precedence;
2365 c) it makes no sense to enable the ring buffer if the maximum
2366 file size is set to "infinite". */
2367 if (global_capture_opts.save_file == NULL) {
2368 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2369 global_capture_opts.multi_files_on = FALSE;
2371 /* if (global_capture_opts.real_time_mode) {
2372 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2373 global_capture_opts.multi_files_on = FALSE;
2375 if (!global_capture_opts.has_autostop_filesize && !global_capture_opts.has_file_duration) {
2376 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2377 /* XXX - this must be redesigned as the conditions changed */
2378 /* global_capture_opts.multi_files_on = FALSE;*/
2383 if (start_capture || list_link_layer_types) {
2384 /* Did the user specify an interface to use? */
2385 if (!capture_opts_trim_iface(&global_capture_opts,
2386 (prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
2391 if (list_link_layer_types) {
2392 status = capture_opts_list_link_layer_types(&global_capture_opts, FALSE);
2396 capture_opts_trim_snaplen(&global_capture_opts, MIN_PACKET_SIZE);
2397 capture_opts_trim_ring_num_files(&global_capture_opts);
2398 #endif /* HAVE_LIBPCAP */
2400 /* Notify all registered modules that have had any of their preferences
2401 changed either from one of the preferences file or from the command
2402 line that their preferences have changed. */
2405 /* disabled protocols as per configuration file */
2406 if (gdp_path == NULL && dp_path == NULL) {
2407 set_disabled_protos_list();
2410 build_column_format_array(&cfile.cinfo, TRUE);
2412 /* read in rc file from global and personal configuration paths. */
2413 rc_file = get_datafile_path(RC_FILE);
2414 gtk_rc_parse(rc_file);
2416 rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
2417 gtk_rc_parse(rc_file);
2424 /* close the splash screen, as we are going to open the main window now */
2425 splash_destroy(splash_win);
2427 /************************************************************************/
2428 /* Everything is prepared now, preferences and command line was read in */
2430 /* Pop up the main window. */
2431 create_main_window(pl_size, tv_size, bv_size, prefs);
2433 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2434 recent_read_dynamic(&rf_path, &rf_open_errno);
2435 if (rf_path != NULL && rf_open_errno != 0) {
2436 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2437 "Could not open recent file\n\"%s\": %s.",
2438 rf_path, strerror(rf_open_errno));
2441 color_filters_enable(recent.packet_list_colorize);
2443 /* rearrange all the widgets as we now have all recent settings ready for this */
2444 main_widgets_rearrange();
2446 /* Fill in column titles. This must be done after the top level window
2449 XXX - is that still true, with fixed-width columns? */
2450 packet_list_set_column_titles();
2452 menu_recent_read_finished();
2454 menu_auto_scroll_live_changed(auto_scroll_live);
2457 switch (user_font_apply()) {
2460 case FA_FONT_NOT_RESIZEABLE:
2461 /* "user_font_apply()" popped up an alert box. */
2462 /* turn off zooming - font can't be resized */
2463 case FA_FONT_NOT_AVAILABLE:
2464 /* XXX - did we successfully load the un-zoomed version earlier?
2465 If so, this *probably* means the font is available, but not at
2466 this particular zoom level, but perhaps some other failure
2467 occurred; I'm not sure you can determine which is the case,
2469 /* turn off zooming - zoom level is unavailable */
2471 /* in any other case than FA_SUCCESS, turn off zooming */
2472 recent.gui_zoom_level = 0;
2473 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2476 dnd_init(top_level);
2478 color_filters_init();
2481 /* the window can be sized only, if it's not already shown, so do it now! */
2482 main_load_window_geometry(top_level);
2484 /* Tell the user not to run as root. */
2485 if (running_with_special_privs() && recent.privs_warn_if_elevated) {
2486 cur_user = get_cur_username();
2487 cur_group = get_cur_groupname();
2488 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2489 "Running as user \"%s\" and group \"%s\".\n"
2490 "This could be dangerous.", cur_user, cur_group);
2493 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2494 simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
2498 /* Warn the user if npf.sys isn't loaded. */
2499 if (!npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
2500 priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2501 "The NPF driver isn't running. You may have trouble\n"
2502 "capturing or listing interfaces.");
2503 simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
2504 simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
2508 /* If we were given the name of a capture file, read it in now;
2509 we defer it until now, so that, if we can't open it, and pop
2510 up an alert box, the alert box is more likely to come up on
2511 top of the main window - but before the preference-file-error
2512 alert box, so, if we get one of those, it's more likely to come
2515 show_main_window(TRUE);
2516 if (rfilter != NULL) {
2517 if (!dfilter_compile(rfilter, &rfcode)) {
2518 bad_dfilter_alert_box(rfilter);
2519 rfilter_parse_failed = TRUE;
2522 if (!rfilter_parse_failed) {
2523 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2524 /* "cf_open()" succeeded, so it closed the previous
2525 capture file, and thus destroyed any previous read filter
2526 attached to "cf". */
2528 cfile.rfcode = rfcode;
2529 /* Open stat windows; we do so after creating the main window,
2530 to avoid GTK warnings, and after successfully opening the
2531 capture file, so we know we have something to compute stats
2532 on, and after registering all dissectors, so that MATE will
2533 have registered its field array and we can have a tap filter
2534 with one of MATE's late-registered fields as part of the
2536 start_requested_stats();
2538 /* Read the capture file. */
2539 switch (cf_read(&cfile)) {
2543 /* Just because we got an error, that doesn't mean we were unable
2544 to read any of the file; we handle what we could get from the
2546 /* if the user told us to jump to a specific packet, do it now */
2547 if(go_to_packet != 0) {
2548 cf_goto_frame(&cfile, go_to_packet);
2552 case CF_READ_ABORTED:
2557 /* Save the name of the containing directory specified in the
2558 path name, if any; we can write over cf_name, which is a
2559 good thing, given that "get_dirname()" does write over its
2561 s = get_dirname(cf_name);
2562 set_last_open_dir(s);
2567 dfilter_free(rfcode);
2568 cfile.rfcode = NULL;
2569 show_main_window(FALSE);
2570 set_menus_for_capture_in_progress(FALSE);
2571 set_capture_if_dialog_for_capture_in_progress(FALSE);
2576 if (start_capture) {
2577 if (global_capture_opts.save_file != NULL) {
2578 /* Save the directory name for future file dialogs. */
2579 /* (get_dirname overwrites filename) */
2580 s = get_dirname(g_strdup(global_capture_opts.save_file));
2581 set_last_open_dir(s);
2584 /* "-k" was specified; start a capture. */
2585 show_main_window(TRUE);
2586 if (capture_start(&global_capture_opts)) {
2587 /* The capture started. Open stat windows; we do so after creating
2588 the main window, to avoid GTK warnings, and after successfully
2589 opening the capture file, so we know we have something to compute
2590 stats on, and after registering all dissectors, so that MATE will
2591 have registered its field array and we can have a tap filter with
2592 one of MATE's late-registered fields as part of the filter. */
2593 start_requested_stats();
2597 show_main_window(FALSE);
2598 set_menus_for_capture_in_progress(FALSE);
2599 set_capture_if_dialog_for_capture_in_progress(FALSE);
2602 /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2603 if (!start_capture && strlen(global_capture_opts.cfilter) == 0) {
2604 g_free(global_capture_opts.cfilter);
2605 global_capture_opts.cfilter = g_strdup(get_conn_cfilter());
2607 #else /* HAVE_LIBPCAP */
2608 show_main_window(FALSE);
2609 set_menus_for_capture_in_progress(FALSE);
2610 set_capture_if_dialog_for_capture_in_progress(FALSE);
2611 #endif /* HAVE_LIBPCAP */
2614 /* register our pid if we are being run from a U3 device */
2617 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
2619 /* we'll enter the GTK loop now and hand the control over to GTK ... */
2621 /* ... back from GTK, we're going down now! */
2623 /* deregister our pid */
2624 u3_deregister_pid();
2628 #ifdef HAVE_AIRPDCAP
2629 AirPDcapDestroyContext(&airpdcap_ctx);
2633 /* hide the (unresponsive) main window, while asking the user to close the console window */
2634 gtk_widget_hide(top_level);
2636 /* Shutdown windows sockets */
2639 /* For some unknown reason, the "atexit()" call in "create_console()"
2640 doesn't arrange that "destroy_console()" be called when we exit,
2641 so we call it here if a console was created. */
2647 /* This isn't reached, but we need it to keep GCC from complaining
2648 that "main()" returns without returning a value - it knows that
2649 "exit()" never returns, but it doesn't know that "gtk_exit()"
2650 doesn't, as GTK+ doesn't declare it with the attribute
2652 return 0; /* not reached */
2657 /* We build this as a GUI subsystem application on Win32, so
2658 "WinMain()", not "main()", gets called.
2660 Hack shamelessly stolen from the Win32 port of the GIMP. */
2662 #define _stdcall __attribute__((stdcall))
2666 WinMain (struct HINSTANCE__ *hInstance,
2667 struct HINSTANCE__ *hPrevInstance,
2671 INITCOMMONCONTROLSEX comm_ctrl;
2673 /* Initialize our controls. Required for native Windows file dialogs. */
2674 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
2675 comm_ctrl.dwSize = sizeof(comm_ctrl);
2676 /* Includes the animate, header, hot key, list view, progress bar,
2677 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
2680 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
2681 InitCommonControlsEx(&comm_ctrl);
2683 /* RichEd20.DLL is needed for filter entries. */
2684 LoadLibrary(_T("riched20.dll"));
2686 has_console = FALSE;
2687 return main (__argc, __argv);
2691 * If this application has no console window to which its standard output
2692 * would go, create one.
2695 create_console(void)
2697 if (stdin_capture) {
2698 /* We've been handed "-i -". Don't mess with stdio. */
2703 /* We have no console to which to print the version string, so
2704 create one and make it the standard input, output, and error. */
2705 if (!AllocConsole())
2706 return; /* couldn't create console */
2708 ws_freopen("CONIN$", "r", stdin);
2709 ws_freopen("CONOUT$", "w", stdout);
2710 ws_freopen("CONOUT$", "w", stderr);
2712 /* Well, we have a console now. */
2715 /* Now register "destroy_console()" as a routine to be called just
2716 before the application exits, so that we can destroy the console
2717 after the user has typed a key (so that the console doesn't just
2718 disappear out from under them, giving the user no chance to see
2719 the message(s) we put in there). */
2720 atexit(destroy_console);
2722 SetConsoleTitle(_T("Wireshark Debug Console"));
2727 destroy_console(void)
2730 printf("\n\nPress any key to exit\n");
2738 /* This routine should not be necessary, at least as I read the GLib
2739 source code, as it looks as if GLib is, on Win32, *supposed* to
2740 create a console window into which to display its output.
2742 That doesn't happen, however. I suspect there's something completely
2743 broken about that code in GLib-for-Win32, and that it may be related
2744 to the breakage that forces us to just call "printf()" on the message
2745 rather than passing the message on to "g_log_default_handler()"
2746 (which is the routine that does the aforementioned non-functional
2747 console window creation). */
2749 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
2750 const char *message, gpointer user_data _U_)
2757 /* ignore log message, if log_level isn't interesting.
2758 If preferences aren't loaded yet, display message anyway */
2759 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
2760 prefs.console_log_level != 0) {
2764 /* create a "timestamp" */
2766 today = localtime(&curr);
2769 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
2770 /* the user wants a console or the application will terminate immediately */
2774 /* For some unknown reason, the above doesn't appear to actually cause
2775 anything to be sent to the standard output, so we'll just splat the
2776 message out directly, just to make sure it gets out. */
2778 switch(log_level & G_LOG_LEVEL_MASK) {
2779 case G_LOG_LEVEL_ERROR:
2782 case G_LOG_LEVEL_CRITICAL:
2785 case G_LOG_LEVEL_WARNING:
2788 case G_LOG_LEVEL_MESSAGE:
2791 case G_LOG_LEVEL_INFO:
2794 case G_LOG_LEVEL_DEBUG:
2798 fprintf(stderr, "unknown log_level %u\n", log_level);
2800 g_assert_not_reached();
2803 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
2804 today->tm_hour, today->tm_min, today->tm_sec,
2805 log_domain != NULL ? log_domain : "",
2808 if(log_level & G_LOG_LEVEL_ERROR) {
2809 /* wait for a key press before the following error handler will terminate the program
2810 this way the user at least can read the error message */
2811 printf("\n\nPress any key to exit\n");
2815 g_log_default_handler(log_domain, log_level, message, user_data);
2822 * Helper for main_widgets_rearrange()
2824 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
2825 gtk_container_remove(GTK_CONTAINER(data), widget);
2828 static GtkWidget *main_widget_layout(gint layout_content)
2830 switch(layout_content) {
2831 case(layout_pane_content_none):
2833 case(layout_pane_content_plist):
2835 case(layout_pane_content_pdetails):
2837 case(layout_pane_content_pbytes):
2840 g_assert_not_reached();
2847 * Rearrange the main window widgets
2849 void main_widgets_rearrange(void) {
2850 GtkWidget *first_pane_widget1, *first_pane_widget2;
2851 GtkWidget *second_pane_widget1, *second_pane_widget2;
2852 gboolean split_top_left;
2854 /* be a bit faster */
2855 gtk_widget_hide(main_vbox);
2857 /* be sure we don't lose a widget while rearranging */
2858 gtk_widget_ref(menubar);
2859 gtk_widget_ref(main_tb);
2860 gtk_widget_ref(filter_tb);
2862 gtk_widget_ref(airpcap_tb);
2864 gtk_widget_ref(pkt_scrollw);
2865 gtk_widget_ref(tv_scrollw);
2866 gtk_widget_ref(byte_nb_ptr);
2867 gtk_widget_ref(statusbar);
2868 gtk_widget_ref(main_pane_v1);
2869 gtk_widget_ref(main_pane_v2);
2870 gtk_widget_ref(main_pane_h1);
2871 gtk_widget_ref(main_pane_h2);
2872 gtk_widget_ref(welcome_pane);
2874 /* empty all containers participating */
2875 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
2876 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
2877 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
2878 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
2879 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
2881 statusbar_widgets_emptying(statusbar);
2883 /* add the menubar always at the top */
2884 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
2887 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
2889 /* filter toolbar in toolbar area */
2890 if (!prefs.filter_toolbar_show_in_statusbar) {
2891 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
2895 /* airpcap toolbar */
2896 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
2899 /* fill the main layout panes */
2900 switch(prefs.gui_layout_type) {
2901 case(layout_type_5):
2902 main_first_pane = main_pane_v1;
2903 main_second_pane = main_pane_v2;
2904 split_top_left = FALSE;
2906 case(layout_type_2):
2907 main_first_pane = main_pane_v1;
2908 main_second_pane = main_pane_h1;
2909 split_top_left = FALSE;
2911 case(layout_type_1):
2912 main_first_pane = main_pane_v1;
2913 main_second_pane = main_pane_h1;
2914 split_top_left = TRUE;
2916 case(layout_type_4):
2917 main_first_pane = main_pane_h1;
2918 main_second_pane = main_pane_v1;
2919 split_top_left = FALSE;
2921 case(layout_type_3):
2922 main_first_pane = main_pane_h1;
2923 main_second_pane = main_pane_v1;
2924 split_top_left = TRUE;
2926 case(layout_type_6):
2927 main_first_pane = main_pane_h1;
2928 main_second_pane = main_pane_h2;
2929 split_top_left = FALSE;
2932 main_first_pane = NULL;
2933 main_second_pane = NULL;
2934 split_top_left = FALSE;
2935 g_assert_not_reached();
2937 if (split_top_left) {
2938 first_pane_widget1 = main_second_pane;
2939 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
2940 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
2941 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
2943 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
2944 first_pane_widget2 = main_second_pane;
2945 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
2946 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
2948 if (first_pane_widget1 != NULL)
2949 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
2950 if (first_pane_widget2 != NULL)
2951 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
2952 if (second_pane_widget1 != NULL)
2953 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
2954 if (second_pane_widget2 != NULL)
2955 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
2957 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
2960 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
2963 gtk_box_pack_start(GTK_BOX(main_vbox), statusbar, FALSE, TRUE, 0);
2965 /* filter toolbar in statusbar hbox */
2966 if (prefs.filter_toolbar_show_in_statusbar) {
2967 gtk_box_pack_start(GTK_BOX(statusbar), filter_tb, FALSE, TRUE, 1);
2971 /* airpcap toolbar */
2972 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
2975 /* statusbar widgets */
2976 statusbar_widgets_pack(statusbar);
2978 /* hide widgets on users recent settings */
2979 main_widgets_show_or_hide();
2981 gtk_widget_show(main_vbox);
2985 is_widget_visible(GtkWidget *widget, gpointer data)
2987 gboolean *is_visible = data;
2990 if (GTK_WIDGET_VISIBLE(widget))
2997 main_widgets_show_or_hide(void)
2999 gboolean main_second_pane_show;
3001 if (recent.main_toolbar_show) {
3002 gtk_widget_show(main_tb);
3004 gtk_widget_hide(main_tb);
3007 statusbar_widgets_show_or_hide(statusbar);
3009 if (recent.filter_toolbar_show) {
3010 gtk_widget_show(filter_tb);
3012 gtk_widget_hide(filter_tb);
3016 if (recent.airpcap_toolbar_show) {
3017 gtk_widget_show(airpcap_tb);
3019 gtk_widget_hide(airpcap_tb);
3023 if (recent.packet_list_show && have_capture_file) {
3024 gtk_widget_show(pkt_scrollw);
3026 gtk_widget_hide(pkt_scrollw);
3029 if (recent.tree_view_show && have_capture_file) {
3030 gtk_widget_show(tv_scrollw);
3032 gtk_widget_hide(tv_scrollw);
3035 if (recent.byte_view_show && have_capture_file) {
3036 gtk_widget_show(byte_nb_ptr);
3038 gtk_widget_hide(byte_nb_ptr);
3041 if (have_capture_file) {
3042 gtk_widget_show(main_first_pane);
3044 gtk_widget_hide(main_first_pane);
3048 * Is anything in "main_second_pane" visible?
3049 * If so, show it, otherwise hide it.
3051 main_second_pane_show = FALSE;
3052 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
3053 &main_second_pane_show);
3054 if (main_second_pane_show) {
3055 gtk_widget_show(main_second_pane);
3057 gtk_widget_hide(main_second_pane);
3060 if (!have_capture_file) {
3062 gtk_widget_show(welcome_pane);
3065 gtk_widget_hide(welcome_pane);
3068 /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
3069 packet_list_freeze ();
3070 packet_list_thaw ();
3074 /* called, when the window state changes (minimized, maximized, ...) */
3076 window_state_event_cb (GtkWidget *widget _U_,
3080 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
3082 if( (event->type) == (GDK_WINDOW_STATE)) {
3083 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
3084 /* we might have dialogs popped up while we where iconified,
3086 display_queued_messages();
3094 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_MOD2_MASK|GDK_LOCK_MASK))
3096 top_level_key_pressed_cb(GtkCTree *ctree _U_, GdkEventKey *event, gpointer user_data _U_)
3098 if (event->keyval == GDK_F8) {
3101 } else if (event->keyval == GDK_F7) {
3104 } else if (event->state & NO_SHIFT_MOD_MASK) {
3105 return FALSE; /* Skip control, alt, and other modifiers */
3107 * A comment in gdkkeysyms.h says that it's autogenerated from
3108 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
3109 * don't explicitly say so, isprint() should work as expected
3112 } else if (isascii(event->keyval) && isprint(event->keyval)) {
3113 /* Forward the keypress on to the display filter entry */
3114 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
3115 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
3116 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
3124 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
3126 GtkTooltips *tooltips;
3127 GtkAccelGroup *accel;
3130 /* use user-defined title if preference is set */
3131 title = create_user_window_title("The Wireshark Network Analyzer");
3134 top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
3137 tooltips = gtk_tooltips_new();
3139 gtk_widget_set_name(top_level, "main window");
3140 g_signal_connect(top_level, "delete_event", G_CALLBACK(main_window_delete_event_cb),
3142 g_signal_connect(GTK_OBJECT(top_level), "window_state_event",
3143 G_CALLBACK(window_state_event_cb), NULL);
3144 g_signal_connect(GTK_OBJECT(top_level), "key-press-event",
3145 G_CALLBACK(top_level_key_pressed_cb), NULL );
3147 gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
3149 /* Vertical container for menu bar, toolbar(s), paned windows and progress/info box */
3150 main_vbox = gtk_vbox_new(FALSE, 1);
3151 gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1);
3152 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
3153 gtk_widget_show(main_vbox);
3156 menubar = main_menu_new(&accel);
3157 #ifdef HAVE_IGE_MAC_INTEGRATION
3158 if(prefs->gui_macosx_style) {
3159 ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(menubar));
3160 ige_mac_menu_set_global_key_handler_enabled(TRUE);
3163 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
3164 gtk_widget_show(menubar);
3165 #ifdef HAVE_IGE_MAC_INTEGRATION
3170 main_tb = toolbar_new();
3171 gtk_widget_show (main_tb);
3173 /* Filter toolbar */
3174 filter_tb = filter_toolbar_new();
3177 pkt_scrollw = packet_list_new(prefs);
3178 gtk_widget_set_size_request(packet_list, -1, pl_size);
3179 gtk_widget_show(pkt_scrollw);
3182 tv_scrollw = main_tree_view_new(prefs, &tree_view);
3183 gtk_widget_set_size_request(tv_scrollw, -1, tv_size);
3184 gtk_widget_show(tv_scrollw);
3186 g_signal_connect(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
3187 "changed", G_CALLBACK(tree_view_selection_changed_cb), NULL);
3188 g_signal_connect(tree_view, "button_press_event", G_CALLBACK(popup_menu_handler),
3189 g_object_get_data(G_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
3190 gtk_widget_show(tree_view);
3193 byte_nb_ptr = byte_view_new();
3194 gtk_widget_set_size_request(byte_nb_ptr, -1, bv_size);
3195 gtk_widget_show(byte_nb_ptr);
3197 g_signal_connect(byte_nb_ptr, "button_press_event", G_CALLBACK(popup_menu_handler),
3198 g_object_get_data(G_OBJECT(popup_menu_object), PM_HEXDUMP_KEY));
3201 /* Panes for the packet list, tree, and byte view */
3202 main_pane_v1 = gtk_vpaned_new();
3203 gtk_widget_show(main_pane_v1);
3204 main_pane_v2 = gtk_vpaned_new();
3205 gtk_widget_show(main_pane_v2);
3206 main_pane_h1 = gtk_hpaned_new();
3207 gtk_widget_show(main_pane_h1);
3208 main_pane_h2 = gtk_hpaned_new();
3209 gtk_widget_show(main_pane_h2);
3211 airpcap_tb = airpcap_toolbar_new();
3212 gtk_widget_show(airpcap_tb);
3215 statusbar = statusbar_new();
3216 gtk_widget_show(statusbar);
3218 /* Pane for the welcome screen */
3219 welcome_pane = welcome_new();
3220 gtk_widget_show(welcome_pane);
3224 show_main_window(gboolean doing_work)
3226 main_set_for_capture_file(doing_work);
3228 /*** we have finished all init things, show the main window ***/
3229 gtk_widget_show(top_level);
3231 /* the window can be maximized only, if it's visible, so do it after show! */
3232 main_load_window_geometry(top_level);
3234 /* process all pending GUI events before continue */
3235 while (gtk_events_pending()) gtk_main_iteration();
3237 /* Pop up any queued-up alert boxes. */
3238 display_queued_messages();
3240 /* Move the main window to the front, in case it isn't already there */
3241 gdk_window_raise(top_level->window);
3244 airpcap_toolbar_show(airpcap_tb);
3245 #endif /* HAVE_AIRPCAP */
3248 /* Fill in capture options with values from the preferences */
3250 prefs_to_capture_opts(void)
3253 /* Set promiscuous mode from the preferences setting. */
3254 /* the same applies to other preferences settings as well. */
3255 global_capture_opts.promisc_mode = prefs.capture_prom_mode;
3256 global_capture_opts.show_info = prefs.capture_show_info;
3257 global_capture_opts.real_time_mode = prefs.capture_real_time;
3258 auto_scroll_live = prefs.capture_auto_scroll;
3259 #endif /* HAVE_LIBPCAP */
3261 /* Set the name resolution code's flags from the preferences. */
3262 g_resolv_flags = prefs.name_resolve;
3266 /* Change configuration profile */
3267 void change_configuration_profile (const gchar *profile_name)
3269 char *gdp_path, *dp_path;
3273 /* First check if profile exists */
3274 if (!profile_exists(profile_name)) {
3278 /* Get the current geometry, before writing it to disk */
3279 main_save_window_geometry(top_level);
3281 /* Write recent file for profile we are leaving */
3282 write_profile_recent();
3284 /* Set profile name and update the status bar */
3285 set_profile_name (profile_name);
3286 profile_bar_update ();
3288 /* Reset current preferences and apply the new */
3290 (void) read_configuration_files (&gdp_path, &dp_path);
3292 recent_read_profile_static(&rf_path, &rf_open_errno);
3293 if (rf_path != NULL && rf_open_errno != 0) {
3294 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3295 "Could not open common recent file\n\"%s\": %s.",
3296 rf_path, strerror(rf_open_errno));
3298 timestamp_set_type (recent.gui_time_format);
3299 color_filters_enable(recent.packet_list_colorize);
3300 menu_recent_read_finished();
3301 main_pane_load_window_geometry();
3302 recent.gui_time_format = timestamp_get_type ();
3304 prefs_to_capture_opts();
3307 /* Update window view and redraw the toolbar */
3308 update_main_window_name();
3309 toolbar_redraw_all();
3311 /* Enable all protocols and disable from the disabled list */
3313 if (gdp_path == NULL && dp_path == NULL) {
3314 set_disabled_protos_list();
3317 /* Reload color filters */
3318 color_filters_reload();
3320 /* Reload list of interfaces on welcome page */
3321 welcome_if_panel_reload();
3323 /* Recreate the packet list according to new preferences */
3324 packet_list_recreate ();
3325 status_expert_update();
3326 cfile.cinfo.columns_changed = FALSE; /* Reset value */