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 <epan/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>
75 /* general (not GTK specific) */
79 #include "disabled_protos.h"
80 #include <epan/prefs.h>
81 #include "filter_dlg.h"
82 #include "layout_prefs.h"
84 #include "color_filters.h"
86 #include "simple_dialog.h"
88 #include <epan/prefs-int.h>
89 #include "ringbuffer.h"
90 #include "../ui_util.h"
92 #include <epan/stat_cmd_args.h>
94 #include "clopts_common.h"
95 #include "cmdarg_err.h"
96 #include "version_info.h"
103 #include "capture-pcap-util.h"
105 #include "capture_sync.h"
109 #include "capture-wpcap.h"
110 #include "capture_wpcap_packet.h"
111 #include <tchar.h> /* Needed for Unicode */
112 #if GTK_MAJOR_VERSION >= 2
113 #include <commctrl.h>
114 #endif /* GTK_MAJOR_VERSION >= 2 */
117 #if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
118 #include "ethclist.h"
122 #include "statusbar.h"
123 #include "alert_box.h"
125 #include "dlg_utils.h"
127 #include "file_dlg.h"
128 #include "gtkglobals.h"
130 #include "gui_utils.h"
131 #include "compat_macros.h"
135 #include "../main_window.h"
137 #include "capture_file_dlg.h"
138 #include <epan/column.h>
139 #include "proto_draw.h"
141 #include "packet_win.h"
143 #include "find_dlg.h"
144 #include "packet_list.h"
146 #include "follow_dlg.h"
147 #include "font_utils.h"
148 #include "about_dlg.h"
149 #include "help_dlg.h"
150 #include "decode_as_dlg.h"
151 #include "webbrowser.h"
152 #include "capture_dlg.h"
153 #include "capture_ui_utils.h"
155 #include "../epan/emem.h"
156 #include "file_util.h"
157 #if GTK_MAJOR_VERSION >= 2
158 #include "../image/wsicon16.xpm"
159 #include "../image/wsicon32.xpm"
160 #include "../image/wsicon48.xpm"
161 #include "../image/wsicon64.xpm"
162 #include "../image/wsiconcap16.xpm"
163 #include "../image/wsiconcap32.xpm"
164 #include "../image/wsiconcap48.xpm"
166 #ifdef SHOW_WELCOME_PAGE
167 #include "../image/wssplash.xpm"
172 #include "airpcap_loader.h"
173 #include "airpcap_dlg.h"
174 #include "airpcap_gui_utils.h"
176 #include "./gtk/toolbar.h"
178 #include "./image/toolbar/wep_closed_24.xpm"
182 /* Davide Schiera (2006-11-22): including AirPDcap project */
183 #include <epan/crypt/airpdcap_ws.h>
184 /* Davide Schiera (2006-11-22) ---------------------------------------------- */
188 * Files under personal and global preferences directories in which
189 * GTK settings for Wireshark are stored.
191 #define RC_FILE "gtkrc"
194 #define DEF_READY_MESSAGE " Ready to load or capture"
196 #define DEF_READY_MESSAGE " Ready to load file"
200 GtkWidget *main_display_filter_widget=NULL;
201 GtkWidget *top_level = NULL, *tree_view, *byte_nb_ptr, *tv_scrollw;
202 GtkWidget *pkt_scrollw;
203 static GtkWidget *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
204 static GtkWidget *main_first_pane, *main_second_pane;
205 static GtkWidget *status_pane;
206 static GtkWidget *menubar, *main_vbox, *main_tb, *stat_hbox, *filter_tb;
209 GtkWidget *airpcap_tb;
210 static GtkWidget *driver_warning_dialog;
211 static int airpcap_dll_ret_val = -1;
214 static GtkWidget *info_bar;
215 static GtkWidget *packets_bar = NULL;
216 static GtkWidget *welcome_pane;
217 static guint main_ctx, file_ctx, help_ctx;
218 static guint packets_ctx;
219 static gchar *packets_str = NULL;
220 GString *comp_info_str, *runtime_info_str;
221 gboolean have_capture_file = FALSE; /* XXX - is there an aquivalent in cfile? */
224 static gboolean has_console; /* TRUE if app has console */
225 static void destroy_console(void);
227 static void console_log_handler(const char *log_domain,
228 GLogLevelFlags log_level, const char *message, gpointer user_data);
231 static gboolean list_link_layer_types;
232 capture_options global_capture_opts;
233 capture_options *capture_opts = &global_capture_opts;
236 gboolean block_toolbar_signals = FALSE;
238 static void create_main_window(gint, gint, gint, e_prefs*);
239 static void show_main_window(gboolean);
240 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
241 static void main_save_window_geometry(GtkWidget *widget);
243 #define E_DFILTER_CM_KEY "display_filter_combo"
244 #define E_DFILTER_FL_KEY "display_filter_list"
246 /* Match selected byte pattern */
248 match_selected_cb_do(gpointer data, int action, gchar *text)
250 GtkWidget *filter_te;
251 char *cur_filter, *new_filter;
253 if ((!text) || (0 == strlen(text))) {
254 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
259 filter_te = OBJECT_GET_DATA(data, E_DFILTER_TE_KEY);
262 cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
264 switch (action&MATCH_SELECTED_MASK) {
266 case MATCH_SELECTED_REPLACE:
267 new_filter = g_strdup(text);
270 case MATCH_SELECTED_AND:
271 if ((!cur_filter) || (0 == strlen(cur_filter)))
272 new_filter = g_strdup(text);
274 new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
277 case MATCH_SELECTED_OR:
278 if ((!cur_filter) || (0 == strlen(cur_filter)))
279 new_filter = g_strdup(text);
281 new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
284 case MATCH_SELECTED_NOT:
285 new_filter = g_strconcat("!(", text, ")", NULL);
288 case MATCH_SELECTED_AND_NOT:
289 if ((!cur_filter) || (0 == strlen(cur_filter)))
290 new_filter = g_strconcat("!(", text, ")", NULL);
292 new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
295 case MATCH_SELECTED_OR_NOT:
296 if ((!cur_filter) || (0 == strlen(cur_filter)))
297 new_filter = g_strconcat("!(", text, ")", NULL);
299 new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
303 g_assert_not_reached();
308 /* Free up the copy we got of the old filter text. */
311 /* Don't change the current display filter if we only want to copy the filter */
312 if (action&MATCH_SELECTED_COPY_ONLY) {
313 GString *gtk_text_str = g_string_new("");
314 g_string_sprintfa(gtk_text_str, "%s", new_filter);
315 copy_to_clipboard(gtk_text_str);
316 g_string_free(gtk_text_str, TRUE);
318 /* create a new one and set the display filter entry accordingly */
319 gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
321 /* Run the display filter so it goes in effect. */
322 if (action&MATCH_SELECTED_APPLY_NOW)
323 main_filter_packets(&cfile, new_filter, FALSE);
326 /* Free up the new filter text. */
331 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
335 if (cfile.finfo_selected) {
336 filter = proto_construct_match_selected_string(cfile.finfo_selected,
338 match_selected_cb_do((data ? data : w), action, filter);
343 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
345 gchar *selected_proto_url;
346 gchar *proto_abbrev = data;
351 if (cfile.finfo_selected) {
352 /* open wiki page using the protocol abbreviation */
353 selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
354 browser_open_url(selected_proto_url);
355 g_free(selected_proto_url);
358 case(ESD_BTN_CANCEL):
361 g_assert_not_reached();
367 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
370 const gchar *proto_abbrev;
374 if (cfile.finfo_selected) {
375 /* convert selected field to protocol abbreviation */
376 /* XXX - could this conversion be simplified? */
377 field_id = cfile.finfo_selected->hfinfo->id;
378 /* if the selected field isn't a protocol, get it's parent */
379 if(!proto_registrar_is_protocol(field_id)) {
380 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
383 proto_abbrev = proto_registrar_get_abbrev(field_id);
385 /* ask the user if the wiki page really should be opened */
386 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
387 PRIMARY_TEXT_START "Open Wireshark Wiki page of protocol \"%s\"?" PRIMARY_TEXT_END "\n"
389 "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
391 "The Wireshark Wiki is a collaborative approach to provide information\n"
392 "about Wireshark in several ways (not limited to protocol specifics).\n"
394 "This Wiki is new, so the page of the selected protocol\n"
395 "may not exist and/or may not contain valuable information.\n"
397 "As everyone can edit the Wiki and add new content (or extend existing),\n"
398 "you are encouraged to add information if you can.\n"
400 "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
402 "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate,\n"
403 "which will save you a lot of editing and will give a consistent look over the pages.",
404 proto_abbrev, proto_abbrev);
405 simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer) proto_abbrev);
411 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
414 const gchar *proto_abbrev;
415 gchar *selected_proto_url;
418 if (cfile.finfo_selected) {
419 /* convert selected field to protocol abbreviation */
420 /* XXX - could this conversion be simplified? */
421 field_id = cfile.finfo_selected->hfinfo->id;
422 /* if the selected field isn't a protocol, get it's parent */
423 if(!proto_registrar_is_protocol(field_id)) {
424 field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
427 proto_abbrev = proto_registrar_get_abbrev(field_id);
429 /* open reference page using the protocol abbreviation */
430 selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s.html", proto_abbrev[0], proto_abbrev);
431 browser_open_url(selected_proto_url);
432 g_free(selected_proto_url);
437 get_text_from_packet_list(gpointer data)
439 gint row = GPOINTER_TO_INT(OBJECT_GET_DATA(data, E_MPACKET_LIST_ROW_KEY));
440 gint column = GPOINTER_TO_INT(OBJECT_GET_DATA(data, E_MPACKET_LIST_COL_KEY));
441 frame_data *fdata = (frame_data *)packet_list_get_row_data(row);
449 if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
450 cfile.pd, fdata->cap_len, &err, &err_info)) {
451 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
452 cf_read_error_message(err, err_info), cfile.filename);
456 edt = epan_dissect_new(FALSE, FALSE);
457 epan_dissect_run(edt, &cfile.pseudo_header, cfile.pd, fdata,
459 epan_dissect_fill_in_columns(edt);
461 if (strlen(cfile.cinfo.col_expr[column]) != 0 &&
462 strlen(cfile.cinfo.col_expr_val[column]) != 0) {
463 len = strlen(cfile.cinfo.col_expr[column]) +
464 strlen(cfile.cinfo.col_expr_val[column]) + 5;
465 buf = ep_alloc0(len);
466 g_snprintf(buf, len, "%s == %s", cfile.cinfo.col_expr[column],
467 cfile.cinfo.col_expr_val[column]);
470 epan_dissect_free(edt);
477 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
479 match_selected_cb_do(data,
481 get_text_from_packet_list(data));
484 /* This function allows users to right click in the details window and copy the text
485 * information to the operating systems clipboard.
487 * We first check to see if a string representation is setup in the tree and then
488 * read the string. If not available then we try to grab the value. If all else
489 * fails we display a message to the user to indicate the copy could not be completed.
492 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_)
494 GString *gtk_text_str = g_string_new("");
495 char labelstring[256];
496 char *stringpointer = labelstring;
498 if (cfile.finfo_selected->rep->representation != 0) {
499 g_string_sprintfa(gtk_text_str, "%s", cfile.finfo_selected->rep->representation); /* Get the represented data */
501 if (gtk_text_str->len == 0) { /* If no representation then... */
502 proto_item_fill_label(cfile.finfo_selected, stringpointer); /* Try to read the value */
503 g_string_sprintfa(gtk_text_str, "%s", stringpointer);
505 if (gtk_text_str->len == 0) { /* Could not get item so display error msg */
506 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
510 copy_to_clipboard(gtk_text_str); /* Copy string to clipboard */
512 g_string_free(gtk_text_str, TRUE); /* Free the memory */
516 /* XXX: use a preference for this setting! */
517 static guint dfilter_combo_max_recent = 10;
519 /* add a display filter to the combo box */
520 /* Note: a new filter string will replace an old identical one */
522 dfilter_combo_add(GtkWidget *filter_cm, char *s) {
524 GList *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
527 /* GtkCombos don't let us get at their list contents easily, so we maintain
528 our own filter list, and feed it to gtk_combo_set_popdown_strings when
529 a new filter is added. */
530 li = g_list_first(dfilter_list);
532 /* If the filter is already in the list, remove the old one and
533 * append the new one at the latest position (at g_list_append() below) */
534 if (li->data && strcmp(s, li->data) == 0) {
535 dfilter_list = g_list_remove(dfilter_list, li->data);
541 dfilter_list = g_list_append(dfilter_list, s);
542 OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, dfilter_list);
543 gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), dfilter_list);
544 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(filter_cm)->entry), g_list_last(dfilter_list)->data);
550 /* write all non empty display filters (until maximum count)
551 * of the combo box GList to the user's recent file */
553 dfilter_recent_combo_write_all(FILE *rf) {
554 GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
555 GList *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
560 /* write all non empty display filter strings to the recent file (until max count) */
561 li = g_list_first(dfilter_list);
562 while ( li && (max_count++ <= dfilter_combo_max_recent) ) {
563 if (strlen(li->data)) {
564 fprintf (rf, RECENT_KEY_DISPLAY_FILTER ": %s\n", (char *)li->data);
570 /* empty the combobox entry field */
572 dfilter_combo_add_empty(void) {
573 GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
575 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(filter_cm)->entry), "");
579 /* add a display filter coming from the user's recent file to the dfilter combo box */
581 dfilter_combo_add_recent(gchar *s) {
582 GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
586 if (!dfilter_combo_add(filter_cm, dup)) {
595 /* call cf_filter_packets() and add this filter string to the recent filter list */
597 main_filter_packets(capture_file *cf, const gchar *dftext, gboolean force)
599 GtkCombo *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
600 GList *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
602 gboolean add_filter = TRUE;
603 gboolean free_filter = TRUE;
605 cf_status_t cf_status;
607 s = g_strdup(dftext);
609 cf_status = cf_filter_packets(cf, s, force);
611 return (cf_status == CF_OK);
613 /* GtkCombos don't let us get at their list contents easily, so we maintain
614 our own filter list, and feed it to gtk_combo_set_popdown_strings when
615 a new filter is added. */
616 if (cf_status == CF_OK) {
617 li = g_list_first(dfilter_list);
619 if (li->data && strcmp(s, li->data) == 0)
625 /* trim list size first */
626 while (g_list_length(dfilter_list) >= dfilter_combo_max_recent) {
627 dfilter_list = g_list_remove(dfilter_list, g_list_first(dfilter_list)->data);
631 dfilter_list = g_list_append(dfilter_list, s);
632 OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, dfilter_list);
633 gtk_combo_set_popdown_strings(filter_cm, dfilter_list);
634 gtk_entry_set_text(GTK_ENTRY(filter_cm->entry), g_list_last(dfilter_list)->data);
640 return (cf_status == CF_OK);
644 /* Run the current display filter on the current packet set, and
647 filter_activate_cb(GtkWidget *w _U_, gpointer data)
651 s = gtk_entry_get_text(GTK_ENTRY(data));
653 main_filter_packets(&cfile, s, FALSE);
656 /* redisplay with no display filter */
658 filter_reset_cb(GtkWidget *w, gpointer data _U_)
660 GtkWidget *filter_te = NULL;
662 if ((filter_te = OBJECT_GET_DATA(w, E_DFILTER_TE_KEY))) {
663 gtk_entry_set_text(GTK_ENTRY(filter_te), "");
665 main_filter_packets(&cfile, NULL, FALSE);
668 /* mark as reference time frame */
670 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
674 frame->flags.ref_time=1;
676 frame->flags.ref_time=0;
678 cf_reftime_packets(&cfile);
682 GtkWidget *reftime_dialog = NULL;
684 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
688 timestamp_set_type(TS_RELATIVE);
689 recent.gui_time_format = TS_RELATIVE;
690 cf_change_time_formats(&cfile);
695 g_assert_not_reached();
698 if (cfile.current_frame) {
699 /* XXX hum, should better have a "cfile->current_row" here ... */
700 set_frame_reftime(!cfile.current_frame->flags.ref_time,
702 packet_list_find_row_from_data(cfile.current_frame));
708 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
713 if (cfile.current_frame) {
714 if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
715 reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
716 PRIMARY_TEXT_START "Switch to the appropriate Time Display Format?" PRIMARY_TEXT_END "\n\n"
717 "Time References don't work well with the currently selected Time Display Format.\n\n"
718 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?");
719 simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
721 /* XXX hum, should better have a "cfile->current_row" here ... */
722 set_frame_reftime(!cfile.current_frame->flags.ref_time,
724 packet_list_find_row_from_data(cfile.current_frame));
728 case REFTIME_FIND_NEXT:
729 find_previous_next_frame_with_filter("frame.ref_time", FALSE);
731 case REFTIME_FIND_PREV:
732 find_previous_next_frame_with_filter("frame.ref_time", TRUE);
738 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
740 find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
744 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
746 find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
749 #if GTK_MAJOR_VERSION < 2
751 tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column _U_,
752 gpointer user_data _U_)
755 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
759 gchar *help_str = NULL;
760 gchar len_str[2+10+1+5+1]; /* ", {N} bytes\0",
762 gboolean has_blurb = FALSE;
763 guint length = 0, byte_len;
764 GtkWidget *byte_view;
765 const guint8 *byte_data;
766 #if GTK_MAJOR_VERSION >= 2
771 #if GTK_MAJOR_VERSION >= 2
772 /* if nothing is selected */
773 if (!gtk_tree_selection_get_selected(sel, &model, &iter))
776 * Which byte view is displaying the current protocol tree
779 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
780 if (byte_view == NULL)
783 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
784 if (byte_data == NULL)
787 cf_unselect_field(&cfile);
788 packet_hex_print(byte_view, byte_data,
789 cfile.current_frame, NULL, byte_len);
792 gtk_tree_model_get(model, &iter, 1, &finfo, -1);
795 finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
799 set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
801 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
802 byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
803 g_assert(byte_data != NULL);
805 cfile.finfo_selected = finfo;
806 set_menus_for_selected_tree_row(&cfile);
809 if (finfo->hfinfo->blurb != NULL &&
810 finfo->hfinfo->blurb[0] != '\0') {
812 length = strlen(finfo->hfinfo->blurb);
814 length = strlen(finfo->hfinfo->name);
816 if (finfo->length == 0) {
818 } else if (finfo->length == 1) {
819 strcpy (len_str, ", 1 byte");
821 g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo->length);
823 statusbar_pop_field_msg(); /* get rid of current help msg */
825 help_str = g_strdup_printf("%s (%s)%s",
826 (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
827 finfo->hfinfo->abbrev, len_str);
828 statusbar_push_field_msg(help_str);
832 * Don't show anything if the field name is zero-length;
833 * the pseudo-field for "proto_tree_add_text()" is such
834 * a field, and we don't want "Text (text)" showing up
835 * on the status line if you've selected such a field.
837 * XXX - there are zero-length fields for which we *do*
838 * want to show the field name.
840 * XXX - perhaps the name and abbrev field should be null
841 * pointers rather than null strings for that pseudo-field,
842 * but we'd have to add checks for null pointers in some
843 * places if we did that.
845 * Or perhaps protocol tree items added with
846 * "proto_tree_add_text()" should have -1 as the field index,
847 * with no pseudo-field being used, but that might also
848 * require special checks for -1 to be added.
850 statusbar_push_field_msg("");
854 packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
858 #if GTK_MAJOR_VERSION < 2
860 tree_view_unselect_row_cb(GtkCTree *ctree _U_, GList *node _U_, gint column _U_,
861 gpointer user_data _U_)
863 GtkWidget *byte_view;
868 * Which byte view is displaying the current protocol tree
871 byte_view = get_notebook_bv_ptr(byte_nb_ptr);
872 if (byte_view == NULL)
875 data = get_byte_view_data_and_length(byte_view, &len);
879 cf_unselect_field(&cfile);
880 packet_hex_print(byte_view, data, cfile.current_frame, NULL, len);
884 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
886 collapse_all_tree(cfile.edt->tree, tree_view);
889 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
891 expand_all_tree(cfile.edt->tree, tree_view);
894 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
895 #if GTK_MAJOR_VERSION < 2
901 #if GTK_MAJOR_VERSION < 2
902 node = gtk_ctree_find_by_row_data(GTK_CTREE(tree_view), NULL, cfile.finfo_selected);
904 /* the mouse position is at an entry, expand that one */
905 gtk_ctree_expand_recursive(GTK_CTREE(tree_view), node);
908 path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view), cfile.finfo_selected);
910 /* the mouse position is at an entry, expand that one */
911 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
912 gtk_tree_path_free(path);
917 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
918 if (cfile.edt->tree) {
919 guint32 tmp = g_resolv_flags;
920 g_resolv_flags = RESOLV_ALL;
921 proto_tree_draw(cfile.edt->tree, tree_view);
922 g_resolv_flags = tmp;
927 * Push a message referring to file access onto the statusbar.
930 statusbar_push_file_msg(const gchar *msg)
932 /*g_warning("statusbar_push: %s", msg);*/
933 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, msg);
937 * Pop a message referring to file access off the statusbar.
940 statusbar_pop_file_msg(void)
942 /*g_warning("statusbar_pop");*/
943 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
947 * XXX - do we need multiple statusbar contexts?
951 * Push a message referring to the currently-selected field onto the statusbar.
954 statusbar_push_field_msg(const gchar *msg)
956 gtk_statusbar_push(GTK_STATUSBAR(info_bar), help_ctx, msg);
960 * Pop a message referring to the currently-selected field off the statusbar.
963 statusbar_pop_field_msg(void)
965 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
969 * update the packets statusbar to the current values
971 void packets_bar_update(void)
975 /* remove old status */
978 gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
981 /* do we have any packets? */
983 if(cfile.drops_known) {
984 packets_str = g_strdup_printf(" P: %u D: %u M: %u Drops: %u",
985 cfile.count, cfile.displayed_count, cfile.marked_count, cfile.drops);
987 packets_str = g_strdup_printf(" P: %u D: %u M: %u",
988 cfile.count, cfile.displayed_count, cfile.marked_count);
991 packets_str = g_strdup(" No Packets");
993 gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, packets_str);
998 main_set_for_capture_file(gboolean have_capture_file_in)
1000 have_capture_file = have_capture_file_in;
1002 main_widgets_show_or_hide();
1008 /* get the current geometry, before writing it to disk */
1009 main_save_window_geometry(top_level);
1011 /* write user's recent file to disk
1012 * It is no problem to write this file, even if we do not quit */
1015 /* XXX - should we check whether the capture file is an
1016 unsaved temporary file for a live capture and, if so,
1017 pop up a "do you want to exit without saving the capture
1018 file?" dialog, and then just return, leaving said dialog
1019 box to forcibly quit if the user clicks "OK"?
1021 If so, note that this should be done in a subroutine that
1022 returns TRUE if we do so, and FALSE otherwise, and if it
1023 returns TRUE we should return TRUE without nuking anything.
1025 Note that, if we do that, we might also want to check if
1026 an "Update list of packets in real time" capture is in
1027 progress and, if so, ask whether they want to terminate
1028 the capture and discard it, and return TRUE, before nuking
1029 any child capture, if they say they don't want to do so. */
1032 /* Nuke any child capture in progress. */
1033 capture_kill_child(capture_opts);
1036 /* Are we in the middle of reading a capture? */
1037 if (cfile.state == FILE_READ_IN_PROGRESS) {
1038 /* Yes, so we can't just close the file and quit, as
1039 that may yank the rug out from under the read in
1040 progress; instead, just set the state to
1041 "FILE_READ_ABORTED" and return - the code doing the read
1042 will check for that and, if it sees that, will clean
1044 cfile.state = FILE_READ_ABORTED;
1046 /* Say that the window should *not* be deleted;
1047 that'll be done by the code that cleans up. */
1050 /* Close any capture file we have open; on some OSes, you
1051 can't unlink a temporary capture file if you have it
1053 "cf_close()" will unlink it after closing it if
1054 it's a temporary file.
1056 We do this here, rather than after the main loop returns,
1057 as, after the main loop returns, the main window may have
1058 been destroyed (if this is called due to a "destroy"
1059 even on the main window rather than due to the user
1060 selecting a menu item), and there may be a crash
1061 or other problem when "cf_close()" tries to
1062 clean up stuff in the main window.
1064 XXX - is there a better place to put this?
1065 Or should we have a routine that *just* closes the
1066 capture file, and doesn't do anything with the UI,
1067 which we'd call here, and another routine that
1068 calls that routine and also cleans up the UI, which
1069 we'd call elsewhere? */
1072 /* Exit by leaving the main loop, so that any quit functions
1073 we registered get called. */
1076 /* Say that the window should be deleted. */
1082 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1086 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1087 #if GTK_MAJOR_VERSION >= 2
1088 gtk_window_present(GTK_WINDOW(top_level));
1090 /* user didn't saved his current file, ask him */
1091 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1092 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
1093 "If you quit the program without saving, your capture data will be discarded.");
1094 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1097 /* unchanged file, just exit */
1098 /* "main_do_quit()" indicates whether the main window should be deleted. */
1099 return main_do_quit();
1106 main_load_window_geometry(GtkWidget *widget)
1108 window_geometry_t geom;
1110 geom.set_pos = prefs.gui_geometry_save_position;
1111 geom.x = recent.gui_geometry_main_x;
1112 geom.y = recent.gui_geometry_main_y;
1113 geom.set_size = prefs.gui_geometry_save_size;
1114 if (recent.gui_geometry_main_width > 0 &&
1115 recent.gui_geometry_main_height > 0) {
1116 geom.width = recent.gui_geometry_main_width;
1117 geom.height = recent.gui_geometry_main_height;
1118 geom.set_maximized = prefs.gui_geometry_save_maximized;
1120 /* We assume this means the width and height weren't set in
1121 the "recent" file (or that there is no "recent" file),
1122 and weren't set to a default value, so we don't set the
1123 size. (The "recent" file code rejects non-positive width
1124 and height values.) */
1125 geom.set_size = FALSE;
1127 geom.maximized = recent.gui_geometry_main_maximized;
1129 window_set_geometry(widget, &geom);
1131 if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1132 gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1133 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane)
1134 gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1135 if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_status_pane)
1136 gtk_paned_set_position(GTK_PANED(status_pane), recent.gui_geometry_status_pane);
1141 main_save_window_geometry(GtkWidget *widget)
1143 window_geometry_t geom;
1145 window_get_geometry(widget, &geom);
1147 if (prefs.gui_geometry_save_position) {
1148 recent.gui_geometry_main_x = geom.x;
1149 recent.gui_geometry_main_y = geom.y;
1152 if (prefs.gui_geometry_save_size) {
1153 recent.gui_geometry_main_width = geom.width,
1154 recent.gui_geometry_main_height = geom.height;
1157 #if GTK_MAJOR_VERSION >= 2
1158 if(prefs.gui_geometry_save_maximized) {
1159 recent.gui_geometry_main_maximized = geom.maximized;
1162 recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
1163 recent.gui_geometry_main_lower_pane = gtk_paned_get_position(GTK_PANED(main_second_pane));
1164 recent.gui_geometry_status_pane = gtk_paned_get_position(GTK_PANED(status_pane));
1168 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1172 /* save file first */
1173 file_save_as_cmd(after_save_exit, NULL);
1175 case(ESD_BTN_DONT_SAVE):
1178 case(ESD_BTN_CANCEL):
1181 g_assert_not_reached();
1186 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1190 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1191 /* user didn't saved his current file, ask him */
1192 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1193 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
1194 "If you quit the program without saving, your capture data will be discarded.");
1195 simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1197 /* unchanged file, just exit */
1203 print_usage(gboolean print_ver) {
1213 fprintf(output, "Wireshark " VERSION "%s\n"
1214 "Interactively dump and analyze network traffic.\n"
1215 "See http://www.wireshark.org for more information.\n"
1218 wireshark_svnversion, get_copyright_info());
1222 fprintf(output, "\n");
1223 fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1224 fprintf(output, "\n");
1227 fprintf(output, "Capture interface:\n");
1228 fprintf(output, " -i <interface> name or idx of interface (def: first non-loopback)\n");
1229 fprintf(output, " -f <capture filter> packet filter in libpcap filter syntax\n");
1230 fprintf(output, " -s <snaplen> packet snapshot length (def: 65535)\n");
1231 fprintf(output, " -p don't capture in promiscuous mode\n");
1232 fprintf(output, " -k start capturing immediately (def: do nothing)\n");
1233 fprintf(output, " -Q quit Wireshark after capturing\n");
1234 fprintf(output, " -S update packet display when new packets are captured\n");
1235 fprintf(output, " -l turn on automatic scrolling while -S is in use\n");
1237 fprintf(output, " -B <buffer size> size of kernel buffer (def: 1MB)\n");
1239 fprintf(output, " -y <link type> link layer type (def: first appropriate)\n");
1240 fprintf(output, " -D print list of interfaces and exit\n");
1241 fprintf(output, " -L print list of link-layer types of iface and exit\n");
1242 fprintf(output, "\n");
1243 fprintf(output, "Capture stop conditions:\n");
1244 fprintf(output, " -c <packet count> stop after n packets (def: infinite)\n");
1245 fprintf(output, " -a <autostop cond.> ... duration:NUM - stop after NUM seconds\n");
1246 fprintf(output, " filesize:NUM - stop this file after NUM KB\n");
1247 fprintf(output, " files:NUM - stop after NUM files\n");
1248 /*fprintf(output, "\n");*/
1249 fprintf(output, "Capture output:\n");
1250 fprintf(output, " -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1251 fprintf(output, " filesize:NUM - switch to next file after NUM KB\n");
1252 fprintf(output, " files:NUM - ringbuffer: replace after NUM files\n");
1253 #endif /* HAVE_LIBPCAP */
1255 /*fprintf(output, "\n");*/
1256 fprintf(output, "Input file:\n");
1257 fprintf(output, " -r <infile> set the filename to read from (no pipes or stdin!)\n");
1259 fprintf(output, "\n");
1260 fprintf(output, "Processing:\n");
1261 fprintf(output, " -R <read filter> packet filter in Wireshark display filter syntax\n");
1262 fprintf(output, " -n disable all name resolutions (def: all enabled)\n");
1263 fprintf(output, " -N <name resolve flags> enable specific name resolution(s): \"mntC\"\n");
1265 fprintf(output, "\n");
1266 fprintf(output, "User interface:\n");
1267 fprintf(output, " -g <packet number> go to specified packet number after \"-r\"\n");
1268 fprintf(output, " -m <font> set the font name used for most text\n");
1269 fprintf(output, " -t ad|a|r|d|dd|e output format of time stamps (def: r: rel. to first)\n");
1270 fprintf(output, " -X <key>:<value> eXtension options, see man page for details\n");
1271 fprintf(output, " -z <statistics> show various statistics, see man page for details\n");
1273 fprintf(output, "\n");
1274 fprintf(output, "Output:\n");
1275 fprintf(output, " -w <outfile|-> set the output filename (or '-' for stdout)\n");
1277 fprintf(output, "\n");
1278 fprintf(output, "Miscellaneous:\n");
1279 fprintf(output, " -h display this help and exit\n");
1280 fprintf(output, " -v display version info and exit\n");
1281 fprintf(output, " -P <key>:<path> persconf:path - personal configuration files\n");
1282 fprintf(output, " persdata:path - personal data files\n");
1283 fprintf(output, " -o <name>:<value> ... override preference or recent setting\n");
1285 fprintf(output, " --display=DISPLAY X display to use\n");
1300 printf(PACKAGE " " VERSION "%s\n"
1307 wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1308 runtime_info_str->str);
1316 * Report an error in command-line arguments.
1317 * Creates a console on Windows.
1318 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1319 * terminal isn't the standard error?
1322 cmdarg_err(const char *fmt, ...)
1330 fprintf(stderr, "wireshark: ");
1331 vfprintf(stderr, fmt, ap);
1332 fprintf(stderr, "\n");
1337 * Report additional information for an error in command-line arguments.
1338 * Creates a console on Windows.
1339 * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1340 * terminal isn't the standard error?
1343 cmdarg_err_cont(const char *fmt, ...)
1351 vfprintf(stderr, fmt, ap);
1352 fprintf(stderr, "\n");
1356 #if defined(_WIN32) || GTK_MAJOR_VERSION < 2 || ! defined USE_THREADS
1358 Once every 3 seconds we get a callback here which we use to update
1359 the tap extensions. Since Gtk1 is single threaded we dont have to
1360 worry about any locking or critical regions.
1363 update_cb(gpointer data _U_)
1365 draw_tap_listeners(FALSE);
1370 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1371 use threads all updte_thread_mutex can be dropped and protect/unprotect
1372 would just be empty functions.
1374 This allows gtk2-rpcstat.c and friends to be copied unmodified to
1375 gtk1-wireshark and it will just work.
1377 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1379 update_thread(gpointer data _U_)
1383 g_get_current_time(&tv1);
1384 g_static_mutex_lock(&update_thread_mutex);
1385 gdk_threads_enter();
1386 draw_tap_listeners(FALSE);
1387 gdk_threads_leave();
1388 g_static_mutex_unlock(&update_thread_mutex);
1390 g_get_current_time(&tv2);
1391 if( ((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) >
1392 (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1393 g_usleep(((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) -
1394 (tv2.tv_sec * 1000000 + tv2.tv_usec));
1401 protect_thread_critical_region(void)
1403 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
1404 g_static_mutex_lock(&update_thread_mutex);
1408 unprotect_thread_critical_region(void)
1410 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
1411 g_static_mutex_unlock(&update_thread_mutex);
1415 /* Set the file name in the status line, in the name for the main window,
1416 and in the name for the main window's icon. */
1418 set_display_filename(capture_file *cf)
1420 const gchar *name_ptr;
1425 name_ptr = cf_get_display_name(cf);
1427 if (!cf->is_tempfile && cf->filename) {
1428 /* Add this filename to the list of recent files in the "Recent Files" submenu */
1429 add_menu_recent_capture_file(cf->filename);
1432 /* convert file size */
1433 if (cf->f_datalen/1024/1024 > 10) {
1434 size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d MB", cf->f_datalen/1024/1024);
1435 } else if (cf->f_datalen/1024 > 10) {
1436 size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d KB", cf->f_datalen/1024);
1438 size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d Bytes", cf->f_datalen);
1443 /* XXX - don't show the highest expert level unless the TCP checksum offloading is "solved" */
1444 status_msg = g_strdup_printf(" File: \"%s\" %s %02lu:%02lu:%02lu [Expert: %s]",
1445 (cf->filename) ? cf->filename : "", size_str,
1446 (long)cf->elapsed_time.secs/3600,
1447 (long)cf->elapsed_time.secs%3600/60,
1448 (long)cf->elapsed_time.secs%60,
1449 val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1451 status_msg = g_strdup_printf(" File: \"%s\" %s %02lu:%02lu:%02lu",
1452 (cf->filename) ? cf->filename : "", size_str,
1453 (long)cf->elapsed_time.secs/3600,
1454 (long)cf->elapsed_time.secs%3600/60,
1455 (long)cf->elapsed_time.secs%60);
1457 statusbar_push_file_msg(status_msg);
1461 win_name = g_strdup_printf("%s - Wireshark", name_ptr);
1462 set_main_window_name(win_name);
1466 GtkWidget *close_dlg = NULL;
1469 main_cf_cb_file_closing(capture_file *cf)
1472 /* if we have more than 10000 packets, show a splash screen while closing */
1473 /* XXX - don't know a better way to decide wether to show or not,
1474 * as most of the time is spend in a single eth_clist_clear function,
1475 * so we can't use a progress bar here! */
1476 if(cf->count > 10000) {
1477 close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1478 "%sClosing file!%s\n\nPlease wait ...",
1479 simple_dialog_primary_start(),
1480 simple_dialog_primary_end());
1481 #if GTK_MAJOR_VERSION >= 2
1482 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1484 gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER);
1488 /* Destroy all windows, which refer to the
1489 capture file we're closing. */
1490 destroy_packet_wins();
1491 file_save_as_destroy();
1493 /* Clear any file-related status bar messages.
1494 XXX - should be "clear *ALL* file-related status bar messages;
1495 will there ever be more than one on the stack? */
1496 statusbar_pop_file_msg();
1498 /* Restore the standard title bar message. */
1499 set_main_window_name("The Wireshark Network Analyzer");
1501 /* Disable all menu items that make sense only if you have a capture. */
1502 set_menus_for_capture_file(NULL);
1503 set_menus_for_captured_packets(FALSE);
1504 set_menus_for_selected_packet(cf);
1505 set_menus_for_capture_in_progress(FALSE);
1506 set_menus_for_selected_tree_row(cf);
1508 /* Set up main window for no capture file. */
1509 main_set_for_capture_file(FALSE);
1511 main_window_update();
1515 main_cf_cb_file_closed(capture_file *cf _U_)
1517 if(close_dlg != NULL) {
1518 splash_destroy(close_dlg);
1522 /* go back to "No packets" */
1523 packets_bar_update();
1527 main_cf_cb_file_read_start(capture_file *cf)
1529 const gchar *name_ptr;
1532 name_ptr = get_basename(cf->filename);
1534 load_msg = g_strdup_printf(" Loading: %s", name_ptr);
1535 statusbar_push_file_msg(load_msg);
1538 /* Set up main window for a capture file. */
1539 main_set_for_capture_file(TRUE);
1543 main_cf_cb_file_read_finished(capture_file *cf)
1545 statusbar_pop_file_msg();
1546 set_display_filename(cf);
1548 /* Enable menu items that make sense if you have a capture file you've
1549 finished reading. */
1550 set_menus_for_capture_file(cf);
1552 /* Enable menu items that make sense if you have some captured packets. */
1553 set_menus_for_captured_packets(TRUE);
1556 #if GTK_MAJOR_VERSION >= 2
1557 GList *icon_list_create(
1558 const char **icon16_xpm,
1559 const char **icon32_xpm,
1560 const char **icon48_xpm,
1561 const char **icon64_xpm)
1563 GList *icon_list = NULL;
1564 GdkPixbuf * pixbuf16;
1565 GdkPixbuf * pixbuf32;
1566 GdkPixbuf * pixbuf48;
1567 GdkPixbuf * pixbuf64;
1570 if(icon16_xpm != NULL) {
1571 pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1573 icon_list = g_list_append(icon_list, pixbuf16);
1576 if(icon32_xpm != NULL) {
1577 pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1579 icon_list = g_list_append(icon_list, pixbuf32);
1582 if(icon48_xpm != NULL) {
1583 pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1585 icon_list = g_list_append(icon_list, pixbuf48);
1588 if(icon64_xpm != NULL) {
1589 pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1591 icon_list = g_list_append(icon_list, pixbuf64);
1600 main_cf_cb_live_capture_prepared(capture_options *capture_opts)
1603 #if GTK_MAJOR_VERSION >= 2
1604 static GList *icon_list = NULL;
1608 if(capture_opts->iface) {
1609 title = g_strdup_printf("%s: Capturing - Wireshark",
1610 get_interface_descriptive_name(capture_opts->iface));
1612 title = g_strdup_printf("Capturing - Wireshark");
1614 set_main_window_name(title);
1617 #if GTK_MAJOR_VERSION >= 2
1618 if(icon_list == NULL) {
1619 icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1621 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1624 /* Disable menu items that make no sense if you're currently running
1626 set_menus_for_capture_in_progress(TRUE);
1628 /* update statusbar */
1629 statusbar_push_file_msg("Waiting for capture input data ...");
1631 /* Don't set up main window for a capture file. */
1632 main_set_for_capture_file(FALSE);
1636 main_cf_cb_live_capture_update_started(capture_options *capture_opts)
1641 /* We've done this in "prepared" above, but it will be cleared while
1642 switching to the next multiple file. */
1643 if(capture_opts->iface) {
1644 title = g_strdup_printf("%s: Capturing - Wireshark",
1645 get_interface_descriptive_name(capture_opts->iface));
1647 title = g_strdup_printf("Capturing - Wireshark");
1649 set_main_window_name(title);
1652 set_menus_for_capture_in_progress(TRUE);
1654 /* Enable menu items that make sense if you have some captured
1655 packets (yes, I know, we don't have any *yet*). */
1656 set_menus_for_captured_packets(TRUE);
1658 statusbar_pop_file_msg();
1660 if(capture_opts->iface) {
1661 capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
1662 get_interface_descriptive_name(capture_opts->iface),
1663 (capture_opts->save_file) ? capture_opts->save_file : "");
1665 capture_msg = g_strdup_printf(" <live capture in progress> to file: %s",
1666 (capture_opts->save_file) ? capture_opts->save_file : "");
1669 statusbar_push_file_msg(capture_msg);
1671 g_free(capture_msg);
1673 /* Set up main window for a capture file. */
1674 main_set_for_capture_file(TRUE);
1678 main_cf_cb_live_capture_update_continue(capture_file *cf)
1683 statusbar_pop_file_msg();
1686 /* XXX - don't show the highest expert level unless the TCP checksum offloading is "solved" */
1687 if (cf->f_datalen/1024/1024 > 10) {
1688 capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld MB [Expert: %s]",
1689 get_interface_descriptive_name(capture_opts->iface),
1690 capture_opts->save_file,
1691 cf->f_datalen/1024/1024,
1692 val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1693 } else if (cf->f_datalen/1024 > 10) {
1694 capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld KB [Expert: %s]",
1695 get_interface_descriptive_name(capture_opts->iface),
1696 capture_opts->save_file,
1698 val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1700 capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %lld Bytes [Expert: %s]",
1701 get_interface_descriptive_name(capture_opts->iface),
1702 capture_opts->save_file,
1704 val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1707 if (cf->f_datalen/1024/1024 > 10) {
1708 capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d MB",
1709 get_interface_descriptive_name(capture_opts->iface),
1710 capture_opts->save_file,
1711 cf->f_datalen/1024/1024);
1712 } else if (cf->f_datalen/1024 > 10) {
1713 capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d KB",
1714 get_interface_descriptive_name(capture_opts->iface),
1715 capture_opts->save_file,
1716 cf->f_datalen/1024);
1718 capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d Bytes",
1719 get_interface_descriptive_name(capture_opts->iface),
1720 capture_opts->save_file,
1724 statusbar_push_file_msg(capture_msg);
1727 GtkWidget * stop_dlg = NULL;
1730 main_cf_cb_live_capture_update_finished(capture_file *cf)
1732 #if GTK_MAJOR_VERSION >= 2
1733 static GList *icon_list = NULL;
1736 if(stop_dlg != NULL) {
1737 simple_dialog_close(stop_dlg);
1741 /* Pop the "<live capture in progress>" message off the status bar. */
1742 statusbar_pop_file_msg();
1744 set_display_filename(cf);
1746 /* Enable menu items that make sense if you're not currently running
1748 set_menus_for_capture_in_progress(FALSE);
1750 /* Enable menu items that make sense if you have a capture file
1751 you've finished reading. */
1752 set_menus_for_capture_file(cf);
1754 /* Set up main window for a capture file. */
1755 main_set_for_capture_file(TRUE);
1757 #if GTK_MAJOR_VERSION >= 2
1758 if(icon_list == NULL) {
1759 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1761 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1764 if(capture_opts->quit_after_cap) {
1765 /* command line asked us to quit after the capture */
1766 /* don't pop up a dialog to ask for unsaved files etc. */
1772 main_cf_cb_live_capture_fixed_started(capture_options *capture_opts)
1777 /* Enable menu items that make sense if you have some captured
1778 packets (yes, I know, we don't have any *yet*). */
1779 /*set_menus_for_captured_packets(TRUE);*/
1781 statusbar_pop_file_msg();
1783 capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
1784 get_interface_descriptive_name(capture_opts->iface),
1785 (capture_opts->save_file) ? capture_opts->save_file : "");
1787 statusbar_push_file_msg(capture_msg);
1788 gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, " P: 0");
1790 g_free(capture_msg);
1792 /* Don't set up main window for a capture file. */
1793 main_set_for_capture_file(FALSE);
1797 main_cf_cb_live_capture_fixed_continue(capture_file *cf)
1802 gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
1804 capture_msg = g_strdup_printf(" P: %u",
1805 cf_get_packet_count(cf));
1807 gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, capture_msg);
1809 g_free(capture_msg);
1813 main_cf_cb_live_capture_fixed_finished(capture_file *cf _U_)
1815 #if GTK_MAJOR_VERSION >= 2
1816 static GList *icon_list = NULL;
1819 if(stop_dlg != NULL) {
1820 simple_dialog_close(stop_dlg);
1824 /* Pop the "<live capture in progress>" message off the status bar. */
1825 statusbar_pop_file_msg();
1827 /* Pop the "<capturing>" message off the status bar */
1828 gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
1830 /*set_display_filename(cf);*/
1832 /* Enable menu items that make sense if you're not currently running
1834 set_menus_for_capture_in_progress(FALSE);
1836 /* Restore the standard title bar message */
1837 /* (just in case we have trouble opening the capture file). */
1838 set_main_window_name("The Wireshark Network Analyzer");
1840 #if GTK_MAJOR_VERSION >= 2
1841 if(icon_list == NULL) {
1842 icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1844 gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1847 /* We don't have loaded the capture file, this will be done later.
1848 * For now we still have simply a blank screen. */
1850 if(capture_opts->quit_after_cap) {
1851 /* command line asked us to quit after the capture */
1852 /* don't pop up a dialog to ask for unsaved files etc. */
1858 main_cf_cb_live_capture_stopping(capture_file *cf _U_)
1860 /* Beware: this state won't be called, if the capture child
1861 * closes the capturing on it's own! */
1863 /* XXX - the time to stop the capture has been reduced (this was only a
1864 * problem on Win32 because of the capture piping), so showing a splash
1865 * isn't really necessary any longer. Unfortunately, the GTKClist packet
1866 * list seems to have problems updating after the dialog is closed, so
1867 * this was disabled here. */
1868 stop_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE, "%sCapture stop!%s\n\nPlease wait ...",
1869 simple_dialog_primary_start(), simple_dialog_primary_end());
1870 #if GTK_MAJOR_VERSION >= 2
1871 gtk_window_set_position(GTK_WINDOW(stop_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1873 gtk_window_set_position(GTK_WINDOW(stop_dlg), GTK_WIN_POS_CENTER);
1881 main_cf_cb_packet_selected(gpointer data)
1883 capture_file *cf = data;
1885 /* Display the GUI protocol tree and hex dump.
1886 XXX - why do we dump core if we call "proto_tree_draw()"
1887 before calling "add_byte_views()"? */
1888 add_main_byte_views(cf->edt);
1889 main_proto_tree_draw(cf->edt->tree);
1891 /* The user is searching for a string in the data or a hex value,
1892 * highlight the field that is found in the tree and hex displays. */
1893 #if GTK_MAJOR_VERSION < 2
1894 if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1895 highlight_field(cf->edt->tvb, cfile.search_pos,
1896 (GtkCTree *)tree_view, cf->edt->tree);
1898 if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
1899 highlight_field(cf->edt->tvb, cfile.search_pos,
1900 (GtkTreeView *)tree_view, cf->edt->tree);
1902 cfile.search_pos = 0; /* Reset the position */
1905 /* A packet is selected. */
1906 set_menus_for_selected_packet(cf);
1910 main_cf_cb_packet_unselected(capture_file *cf)
1912 /* Clear out the display of that packet. */
1913 clear_tree_and_hex_views();
1915 /* No packet is selected. */
1916 set_menus_for_selected_packet(cf);
1920 main_cf_cb_field_unselected(capture_file *cf)
1922 statusbar_pop_field_msg();
1923 set_menus_for_selected_tree_row(cf);
1927 main_cf_cb_file_safe_started(gchar * filename)
1929 const gchar *name_ptr;
1932 name_ptr = get_basename(filename);
1934 save_msg = g_strdup_printf(" Saving: %s...", name_ptr);
1936 statusbar_push_file_msg(save_msg);
1941 main_cf_cb_file_safe_finished(gpointer data _U_)
1943 /* Pop the "Saving:" message off the status bar. */
1944 statusbar_pop_file_msg();
1948 main_cf_cb_file_safe_failed(gpointer data _U_)
1950 /* Pop the "Saving:" message off the status bar. */
1951 statusbar_pop_file_msg();
1955 main_cf_cb_file_safe_reload_finished(gpointer data _U_)
1957 set_menus_for_capture_file(&cfile);
1960 static void main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
1963 case(cf_cb_file_closing):
1964 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
1965 main_cf_cb_file_closing(data);
1967 case(cf_cb_file_closed):
1968 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
1969 main_cf_cb_file_closed(data);
1971 case(cf_cb_file_read_start):
1972 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read start");
1973 main_cf_cb_file_read_start(data);
1975 case(cf_cb_file_read_finished):
1976 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
1977 main_cf_cb_file_read_finished(data);
1980 case(cf_cb_live_capture_prepared):
1981 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
1982 main_cf_cb_live_capture_prepared(data);
1984 case(cf_cb_live_capture_update_started):
1985 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
1986 main_cf_cb_live_capture_update_started(data);
1988 case(cf_cb_live_capture_update_continue):
1989 /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
1990 main_cf_cb_live_capture_update_continue(data);
1992 case(cf_cb_live_capture_update_finished):
1993 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
1994 main_cf_cb_live_capture_update_finished(data);
1996 case(cf_cb_live_capture_fixed_started):
1997 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
1998 main_cf_cb_live_capture_fixed_started(data);
2000 case(cf_cb_live_capture_fixed_continue):
2001 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");
2002 main_cf_cb_live_capture_fixed_continue(data);
2004 case(cf_cb_live_capture_fixed_finished):
2005 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
2006 main_cf_cb_live_capture_fixed_finished(data);
2008 case(cf_cb_live_capture_stopping):
2009 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
2010 main_cf_cb_live_capture_stopping(data);
2013 case(cf_cb_packet_selected):
2014 main_cf_cb_packet_selected(data);
2016 case(cf_cb_packet_unselected):
2017 main_cf_cb_packet_unselected(data);
2019 case(cf_cb_field_unselected):
2020 main_cf_cb_field_unselected(data);
2022 case(cf_cb_file_safe_started):
2023 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe started");
2024 main_cf_cb_file_safe_started(data);
2026 case(cf_cb_file_safe_finished):
2027 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe finished");
2028 main_cf_cb_file_safe_finished(data);
2030 case(cf_cb_file_safe_reload_finished):
2031 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: reload finished");
2032 main_cf_cb_file_safe_reload_finished(data);
2034 case(cf_cb_file_safe_failed):
2035 g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe failed");
2036 main_cf_cb_file_safe_failed(data);
2039 g_warning("main_cf_callback: event %u unknown", event);
2040 g_assert_not_reached();
2045 get_gui_compiled_info(GString *str)
2047 get_epan_compiled_version_info(str);
2049 g_string_append(str, ", ");
2050 #ifdef HAVE_LIBPORTAUDIO
2051 #ifdef PORTAUDIO_API_1
2052 g_string_append(str, "with PortAudio <= V18");
2053 #else /* PORTAUDIO_API_1 */
2054 g_string_append(str, "with PortAudio ");
2055 g_string_append(str, Pa_GetVersionText());
2056 #endif /* PORTAUDIO_API_1 */
2057 #else /* HAVE_LIBPORTAUDIO */
2058 g_string_append(str, "without PortAudio");
2059 #endif /* HAVE_LIBPORTAUDIO */
2061 g_string_append(str, ", ");
2063 get_compiled_airpcap_version(str);
2065 g_string_append(str, "without AirPcap");
2070 get_gui_runtime_info(GString *str
2071 #ifndef HAVE_AIRPCAP
2077 g_string_append(str, ", ");
2078 get_runtime_airpcap_version(str);
2082 g_string_append(str, ", ");
2083 u3_runtime_info(str);
2088 /* And now our feature presentation... [ fade to music ] */
2090 main(int argc, char *argv[])
2092 char *init_progfile_dir_error;
2095 extern char *optarg;
2096 gboolean arg_error = FALSE;
2104 char *gpf_path, *pf_path;
2105 char *cf_path, *df_path;
2106 char *gdp_path, *dp_path;
2107 int gpf_open_errno, gpf_read_errno;
2108 int pf_open_errno, pf_read_errno;
2109 int cf_open_errno, df_open_errno;
2110 int gdp_open_errno, gdp_read_errno;
2111 int dp_open_errno, dp_read_errno;
2114 gboolean start_capture = FALSE;
2116 gboolean capture_option_specified = FALSE;
2118 gint pl_size = 280, tv_size = 95, bv_size = 75;
2119 gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
2120 dfilter_t *rfcode = NULL;
2121 gboolean rfilter_parse_failed = FALSE;
2124 GtkWidget *splash_win = NULL;
2125 GLogLevelFlags log_flags;
2126 guint go_to_packet = 0;
2132 /*gchar *cant_get_if_list_errstr;*/
2135 #define OPTSTRING_INIT "a:b:c:Df:g:Hhi:klLm:nN:o:P:pQr:R:Ss:t:vw:X:y:z:"
2137 #if defined HAVE_LIBPCAP && defined _WIN32
2138 #define OPTSTRING_WIN32 "B:"
2140 #define OPTSTRING_WIN32 ""
2143 char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
2144 OPTSTRING_INIT OPTSTRING_WIN32;
2146 #ifdef HAVE_AIRPDCAP
2147 /* Davide Schiera (2006-11-18): init AirPDcap context */
2148 AirPDcapInitContext(&airpdcap_ctx);
2149 /* Davide Schiera (2006-11-18) ------------------------------------------- */
2153 * Get credential information for later use.
2155 get_credential_info();
2158 * Attempt to get the pathname of the executable file.
2160 init_progfile_dir_error = init_progfile_dir(argv[0]);
2162 /* initialize the funnel mini-api */
2163 initialize_funnel_ops();
2166 /* Load wpcap if possible. Do this before collecting the run-time version information */
2169 /* ... and also load the packet.dll from wpcap */
2170 wpcap_packet_load();
2173 /* Load the airpcap.dll. This must also be done before collecting
2174 * run-time version information. */
2175 airpcap_dll_ret_val = load_airpcap();
2177 switch (airpcap_dll_ret_val) {
2178 case AIRPCAP_DLL_OK:
2179 /* load the airpcap interfaces */
2180 airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2182 if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2183 if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2184 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2187 airpcap_if_active = NULL;
2191 /* select the first ad default (THIS SHOULD BE CHANGED) */
2192 airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2197 * XXX - Maybe we need to warn the user if one of the following happens???
2199 case AIRPCAP_DLL_OLD:
2200 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2203 case AIRPCAP_DLL_ERROR:
2204 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2207 case AIRPCAP_DLL_NOT_FOUND:
2208 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2212 #endif /* HAVE_AIRPCAP */
2214 /* Start windows sockets */
2215 WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2218 /* Assemble the compile-time version information string */
2219 comp_info_str = g_string_new("Compiled ");
2221 g_string_append(comp_info_str, "with ");
2222 g_string_sprintfa(comp_info_str,
2223 #ifdef GTK_MAJOR_VERSION
2224 "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
2227 "GTK+ (version unknown)");
2229 g_string_append(comp_info_str, ", ");
2231 get_compiled_version_info(comp_info_str, get_gui_compiled_info);
2233 /* Assemble the run-time version information string */
2234 runtime_info_str = g_string_new("Running ");
2235 get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2238 /* "pre-scan" the command line parameters, if we have "console only"
2239 parameters. We do this so we don't start GTK+ if we're only showing
2240 command-line help or version information.
2242 XXX - this pre-scan is doen before we start GTK+, so we haven't
2243 run gtk_init() on the arguments. That means that GTK+ arguments
2244 have not been removed from the argument list; those arguments
2245 begin with "--", and will be treated as an error by getopt().
2247 We thus ignore errors - *and* set "opterr" to 0 to suppress the
2250 optind_initial = optind;
2251 while ((opt = getopt(argc, argv, optstring)) != -1) {
2253 case 'h': /* Print help and exit */
2257 case 'P': /* Path settings - change these before the Preferences and alike are processed */
2258 status = filesystem_opt(opt, optarg);
2260 cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2264 case 'v': /* Show version and exit */
2270 * Extension command line options have to be processed before
2271 * we call epan_init() as they are supposed to be used by dissectors
2272 * or taps very early in the registration process.
2276 case '?': /* Ignore errors - the "real" scan will catch them. */
2281 /* Init the "Open file" dialog directory */
2282 /* (do this after the path settings are processed) */
2283 set_last_open_dir(get_persdatafile_dir());
2285 /* Set getopt index back to initial value, so it will start with the
2286 first command line parameter again. Also reset opterr to 1, so that
2287 error messages are printed by getopt().
2289 XXX - this seems to work on most platforms, but time will tell.
2290 The Single UNIX Specification says "The getopt() function need
2291 not be reentrant", so this isn't guaranteed to work. The Mac
2292 OS X 10.4[.x] getopt() man page says
2294 In order to use getopt() to evaluate multiple sets of arguments, or to
2295 evaluate a single set of arguments multiple times, the variable optreset
2296 must be set to 1 before the second and each additional set of calls to
2297 getopt(), and the variable optind must be reinitialized.
2301 The optreset variable was added to make it possible to call the getopt()
2302 function multiple times. This is an extension to the IEEE Std 1003.2
2303 (``POSIX.2'') specification.
2305 which I think comes from one of the other BSDs.
2307 XXX - if we want to control all the command-line option errors, so
2308 that we can display them where we choose (e.g., in a window), we'd
2309 want to leave opterr as 0, and produce our own messages using optopt.
2310 We'd have to check the value of optopt to see if it's a valid option
2311 letter, in which case *presumably* the error is "this option requires
2312 an argument but none was specified", or not a valid option letter,
2313 in which case *presumably* the error is "this option isn't valid".
2314 Some versions of getopt() let you supply a option string beginning
2315 with ':', which means that getopt() will return ':' rather than '?'
2316 for "this option requires an argument but none was specified", but
2318 optind = optind_initial;
2321 /* Set the current locale according to the program environment.
2322 * We haven't localized anything, but some GTK widgets are localized
2323 * (the file selection dialogue, for example).
2324 * This also sets the C-language locale to the native environment. */
2327 /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2328 gtk_init (&argc, &argv);
2330 cf_callback_add(main_cf_callback, NULL);
2332 #if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
2333 /* initialize our GTK eth_clist_type */
2334 init_eth_clist_type();
2337 /* Arrange that if we have no console window, and a GLib message logging
2338 routine is called to log a message, we pop up a console window.
2340 We do that by inserting our own handler for all messages logged
2341 to the default domain; that handler pops up a console if necessary,
2342 and then calls the default handler. */
2344 /* We might want to have component specific log levels later ... */
2348 G_LOG_LEVEL_CRITICAL|
2349 G_LOG_LEVEL_WARNING|
2350 G_LOG_LEVEL_MESSAGE|
2353 G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2355 g_log_set_handler(NULL,
2357 console_log_handler, NULL /* user_data */);
2358 g_log_set_handler(LOG_DOMAIN_MAIN,
2360 console_log_handler, NULL /* user_data */);
2363 g_log_set_handler(LOG_DOMAIN_CAPTURE,
2365 console_log_handler, NULL /* user_data */);
2366 g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2368 console_log_handler, NULL /* user_data */);
2370 /* Set the initial values in the capture_opts. This might be overwritten
2371 by preference settings and then again by the command line parameters. */
2372 capture_opts_init(capture_opts, &cfile);
2374 capture_opts->snaplen = MIN_PACKET_SIZE;
2375 capture_opts->has_ring_num_files = TRUE;
2378 /* We won't come till here, if we had a "console only" command line parameter. */
2379 splash_win = splash_new("Loading Wireshark ...");
2380 if (init_progfile_dir_error != NULL) {
2381 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2382 "Can't get pathname of Wireshark: %s.\n"
2383 "It won't be possible to capture traffic.\n"
2384 "Report this to the Wireshark developers.",
2385 init_progfile_dir_error);
2386 g_free(init_progfile_dir_error);
2389 splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2391 /* Register all dissectors; we must do this before checking for the
2392 "-G" flag, as the "-G" flag dumps information registered by the
2393 dissectors, and we must do it before we read the preferences, in
2394 case any dissectors register preferences. */
2395 epan_init(register_all_protocols,register_all_protocol_handoffs,
2396 splash_update, (gpointer) splash_win,
2397 failure_alert_box,open_failure_alert_box,read_failure_alert_box);
2399 splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2401 /* Register all tap listeners; we do this before we parse the arguments,
2402 as the "-z" argument can specify a registered tap. */
2404 /* we register the plugin taps before the other taps because
2405 stats_tree taps plugins will be registered as tap listeners
2406 by stats_tree_stat.c and need to registered before that */
2409 register_all_plugin_tap_listeners();
2412 register_all_tap_listeners();
2414 splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2416 /* Now register the preferences for any non-dissector modules.
2417 We must do that before we read the preferences as well. */
2418 prefs_register_modules();
2420 /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2421 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined(G_THREADS_ENABLED) && defined USE_THREADS
2424 g_thread_init(NULL);
2426 ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2427 g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2429 #else /* _WIN32 || GTK1.2 || !G_THREADS_ENABLED || !USE_THREADS */
2430 /* this is to keep tap extensions updating once every 3 seconds */
2431 gtk_timeout_add(3000, (GtkFunction)update_cb,(gpointer)NULL);
2432 #endif /* !_WIN32 && GTK2 && G_THREADS_ENABLED */
2435 gtk_timeout_add(750, (GtkFunction) host_name_lookup_process, NULL);
2438 splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2440 /* Read the preference files. */
2441 prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
2442 &pf_open_errno, &pf_read_errno, &pf_path);
2444 if (gpf_path != NULL) {
2445 if (gpf_open_errno != 0) {
2446 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2447 "Could not open global preferences file\n\"%s\": %s.", gpf_path,
2448 strerror(gpf_open_errno));
2450 if (gpf_read_errno != 0) {
2451 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2452 "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
2453 strerror(gpf_read_errno));
2456 if (pf_path != NULL) {
2457 if (pf_open_errno != 0) {
2458 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2459 "Could not open your preferences file\n\"%s\": %s.", pf_path,
2460 strerror(pf_open_errno));
2462 if (pf_read_errno != 0) {
2463 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2464 "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
2465 strerror(pf_read_errno));
2472 /* if the user wants a console to be always there, well, we should open one for him */
2473 if (prefs->gui_console_open == console_open_always) {
2478 /* Fill in capture options with values from the preferences */
2479 prefs_to_capture_opts();
2481 /* Read the capture filter file. */
2482 read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
2483 if (cf_path != NULL) {
2484 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2485 "Could not open your capture filter file\n\"%s\": %s.", cf_path,
2486 strerror(cf_open_errno));
2490 /* Read the display filter file. */
2491 read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
2492 if (df_path != NULL) {
2493 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2494 "Could not open your display filter file\n\"%s\": %s.", df_path,
2495 strerror(df_open_errno));
2499 /* Read the disabled protocols file. */
2500 read_disabled_protos_list(&gdp_path, &gdp_open_errno, &gdp_read_errno,
2501 &dp_path, &dp_open_errno, &dp_read_errno);
2502 if (gdp_path != NULL) {
2503 if (gdp_open_errno != 0) {
2504 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2505 "Could not open global disabled protocols file\n\"%s\": %s.",
2506 gdp_path, strerror(gdp_open_errno));
2508 if (gdp_read_errno != 0) {
2509 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2510 "I/O error reading global disabled protocols file\n\"%s\": %s.",
2511 gdp_path, strerror(gdp_read_errno));
2515 if (dp_path != NULL) {
2516 if (dp_open_errno != 0) {
2517 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2518 "Could not open your disabled protocols file\n\"%s\": %s.", dp_path,
2519 strerror(dp_open_errno));
2521 if (dp_read_errno != 0) {
2522 simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2523 "I/O error reading your disabled protocols file\n\"%s\": %s.", dp_path,
2524 strerror(dp_read_errno));
2529 /* Read the (static part) of the recent file. Only the static part of it will be read, */
2530 /* as we don't have the gui now to fill the recent lists which is done in the dynamic part. */
2531 /* We have to do this already here, so command line parameters can overwrite these values. */
2532 recent_read_static(&rf_path, &rf_open_errno);
2534 init_cap_file(&cfile);
2536 /* Now get our args */
2537 while ((opt = getopt(argc, argv, optstring)) != -1) {
2539 /*** capture option specific ***/
2540 case 'a': /* autostop criteria */
2541 case 'b': /* Ringbuffer option */
2542 case 'c': /* Capture xxx packets */
2543 case 'f': /* capture filter */
2544 case 'k': /* Start capture immediately */
2545 case 'H': /* Hide capture info dialog box */
2546 case 'i': /* Use interface xxx */
2547 case 'p': /* Don't capture in promiscuous mode */
2548 case 'Q': /* Quit after capture (just capture to file) */
2549 case 's': /* Set the snapshot (capture) length */
2550 case 'S': /* "Sync" mode: used for following file ala tail -f */
2551 case 'w': /* Write to capture file xxx */
2552 case 'y': /* Set the pcap data link type */
2554 case 'B': /* Buffer size */
2557 status = capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
2562 capture_option_specified = TRUE;
2567 /*** all non capture option specific ***/
2568 case 'D': /* Print a list of capture devices and exit */
2570 capture_opts_list_interfaces(FALSE);
2573 capture_option_specified = TRUE;
2577 case 'g': /* Go to packet */
2578 go_to_packet = get_positive_int(optarg, "go to packet");
2580 case 'l': /* Automatic scrolling in live capture mode */
2582 auto_scroll_live = TRUE;
2584 capture_option_specified = TRUE;
2588 case 'L': /* Print list of link-layer types and exit */
2590 list_link_layer_types = TRUE;
2592 capture_option_specified = TRUE;
2596 case 'm': /* Fixed-width font for the display */
2597 if (prefs->PREFS_GUI_FONT_NAME != NULL)
2598 g_free(prefs->PREFS_GUI_FONT_NAME);
2599 prefs->PREFS_GUI_FONT_NAME = g_strdup(optarg);
2601 case 'n': /* No name resolution */
2602 g_resolv_flags = RESOLV_NONE;
2604 case 'N': /* Select what types of addresses/port #s to resolve */
2605 if (g_resolv_flags == RESOLV_ALL)
2606 g_resolv_flags = RESOLV_NONE;
2607 badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2608 if (badopt != '\0') {
2609 cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2614 case 'o': /* Override preference from command line */
2615 switch (prefs_set_pref(optarg)) {
2618 case PREFS_SET_SYNTAX_ERR:
2619 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2622 case PREFS_SET_NO_SUCH_PREF:
2623 /* not a preference, might be a recent setting */
2624 switch (recent_set_arg(optarg)) {
2627 case PREFS_SET_SYNTAX_ERR:
2628 /* shouldn't happen, checked already above */
2629 cmdarg_err("Invalid -o flag \"%s\"", optarg);
2632 case PREFS_SET_NO_SUCH_PREF:
2633 case PREFS_SET_OBSOLETE:
2634 cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2639 g_assert_not_reached();
2642 case PREFS_SET_OBSOLETE:
2643 cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2648 g_assert_not_reached();
2652 /* Path settings were already processed just ignore them this time*/
2654 case 'r': /* Read capture file xxx */
2655 /* We may set "last_open_dir" to "cf_name", and if we change
2656 "last_open_dir" later, we free the old value, so we have to
2657 set "cf_name" to something that's been allocated. */
2658 #if defined _WIN32 && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
2659 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2660 cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2662 cf_name = g_strdup(optarg);
2665 case 'R': /* Read file filter */
2668 case 't': /* Time stamp type */
2669 if (strcmp(optarg, "r") == 0)
2670 timestamp_set_type(TS_RELATIVE);
2671 else if (strcmp(optarg, "a") == 0)
2672 timestamp_set_type(TS_ABSOLUTE);
2673 else if (strcmp(optarg, "ad") == 0)
2674 timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2675 else if (strcmp(optarg, "d") == 0)
2676 timestamp_set_type(TS_DELTA);
2677 else if (strcmp(optarg, "dd") == 0)
2678 timestamp_set_type(TS_DELTA_DIS);
2679 else if (strcmp(optarg, "e") == 0)
2680 timestamp_set_type(TS_EPOCH);
2682 cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2683 cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2684 cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2689 /* ext ops were already processed just ignore them this time*/
2692 /* We won't call the init function for the stat this soon
2693 as it would disallow MATE's fields (which are registered
2694 by the preferences set callback) from being used as
2695 part of a tap filter. Instead, we just add the argument
2696 to a list of stat arguments. */
2697 if (!process_stat_cmd_arg(optarg)) {
2698 cmdarg_err("Invalid -z argument.");
2699 cmdarg_err_cont(" -z argument must be one of :");
2700 list_stat_cmd_args();
2705 case '?': /* Bad flag - print usage message */
2713 if (cf_name != NULL) {
2715 * Input file name specified with "-r" *and* specified as a regular
2716 * command-line argument.
2718 cmdarg_err("File name specified both with -r and regular argument");
2722 * Input file name not specified with "-r", and a command-line argument
2723 * was specified; treat it as the input file name.
2725 * Yes, this is different from tshark, where non-flag command-line
2726 * arguments are a filter, but this works better on GUI desktops
2727 * where a command can be specified to be run to open a particular
2728 * file - yes, you could have "-r" as the last part of the command,
2729 * but that's a bit ugly.
2731 #if defined _WIN32 && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
2732 /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2733 cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2735 cf_name = g_strdup(argv[0]);
2746 * Extra command line arguments were specified; complain.
2748 cmdarg_err("Invalid argument: %s", argv[0]);
2753 #ifndef HAVE_LIBPCAP
2754 if (capture_option_specified) {
2755 cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2763 if (start_capture && list_link_layer_types) {
2764 /* Specifying *both* is bogus. */
2765 cmdarg_err("You can't specify both -L and a live capture.");
2769 if (list_link_layer_types) {
2770 /* We're supposed to list the link-layer types for an interface;
2771 did the user also specify a capture file to be read? */
2773 /* Yes - that's bogus. */
2774 cmdarg_err("You can't specify -L and a capture file to be read.");
2777 /* No - did they specify a ring buffer option? */
2778 if (capture_opts->multi_files_on) {
2779 cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2783 /* We're supposed to do a live capture; did the user also specify
2784 a capture file to be read? */
2785 if (start_capture && cf_name) {
2786 /* Yes - that's bogus. */
2787 cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2791 /* No - was the ring buffer option specified and, if so, does it make
2793 if (capture_opts->multi_files_on) {
2794 /* Ring buffer works only under certain conditions:
2795 a) ring buffer does not work with temporary files;
2796 b) real_time_mode and multi_files_on are mutually exclusive -
2797 real_time_mode takes precedence;
2798 c) it makes no sense to enable the ring buffer if the maximum
2799 file size is set to "infinite". */
2800 if (capture_opts->save_file == NULL) {
2801 cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2802 capture_opts->multi_files_on = FALSE;
2804 /* if (capture_opts->real_time_mode) {
2805 cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2806 capture_opts->multi_files_on = FALSE;
2808 if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
2809 cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2810 /* XXX - this must be redesigned as the conditions changed */
2811 /* capture_opts->multi_files_on = FALSE;*/
2816 if (start_capture || list_link_layer_types) {
2817 /* Did the user specify an interface to use? */
2818 if (!capture_opts_trim_iface(capture_opts,
2819 (prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
2824 if (list_link_layer_types) {
2825 status = capture_opts_list_link_layer_types(capture_opts, FALSE);
2829 capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
2830 capture_opts_trim_ring_num_files(capture_opts);
2831 #endif /* HAVE_LIBPCAP */
2833 /* Notify all registered modules that have had any of their preferences
2834 changed either from one of the preferences file or from the command
2835 line that their preferences have changed. */
2838 /* disabled protocols as per configuration file */
2839 if (gdp_path == NULL && dp_path == NULL) {
2840 set_disabled_protos_list();
2843 build_column_format_array(&cfile, TRUE);
2845 /* read in rc file from global and personal configuration paths. */
2846 rc_file = get_datafile_path(RC_FILE);
2847 gtk_rc_parse(rc_file);
2848 rc_file = get_persconffile_path(RC_FILE, FALSE);
2849 gtk_rc_parse(rc_file);
2853 /* close the splash screen, as we are going to open the main window now */
2854 splash_destroy(splash_win);
2856 /************************************************************************/
2857 /* Everything is prepared now, preferences and command line was read in */
2859 /* Pop up the main window. */
2860 create_main_window(pl_size, tv_size, bv_size, prefs);
2862 /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
2863 recent_read_dynamic(&rf_path, &rf_open_errno);
2864 color_filters_enable(recent.packet_list_colorize);
2866 /* rearrange all the widgets as we now have all recent settings ready for this */
2867 main_widgets_rearrange();
2869 /* Fill in column titles. This must be done after the top level window
2872 XXX - is that still true, with fixed-width columns? */
2873 packet_list_set_column_titles();
2875 menu_recent_read_finished();
2877 switch (user_font_apply()) {
2880 case FA_FONT_NOT_RESIZEABLE:
2881 /* "user_font_apply()" popped up an alert box. */
2882 /* turn off zooming - font can't be resized */
2883 case FA_FONT_NOT_AVAILABLE:
2884 /* XXX - did we successfully load the un-zoomed version earlier?
2885 If so, this *probably* means the font is available, but not at
2886 this particular zoom level, but perhaps some other failure
2887 occurred; I'm not sure you can determine which is the case,
2889 /* turn off zooming - zoom level is unavailable */
2891 /* in any other case than FA_SUCCESS, turn off zooming */
2892 recent.gui_zoom_level = 0;
2893 /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
2896 dnd_init(top_level);
2899 color_filters_init();
2902 /* the window can be sized only, if it's not already shown, so do it now! */
2903 main_load_window_geometry(top_level);
2905 /* If we were given the name of a capture file, read it in now;
2906 we defer it until now, so that, if we can't open it, and pop
2907 up an alert box, the alert box is more likely to come up on
2908 top of the main window - but before the preference-file-error
2909 alert box, so, if we get one of those, it's more likely to come
2912 show_main_window(TRUE);
2913 if (rfilter != NULL) {
2914 if (!dfilter_compile(rfilter, &rfcode)) {
2915 bad_dfilter_alert_box(rfilter);
2916 rfilter_parse_failed = TRUE;
2919 if (!rfilter_parse_failed) {
2920 if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
2921 /* "cf_open()" succeeded, so it closed the previous
2922 capture file, and thus destroyed any previous read filter
2923 attached to "cf". */
2925 cfile.rfcode = rfcode;
2926 /* Open stat windows; we do so after creating the main window,
2927 to avoid GTK warnings, and after successfully opening the
2928 capture file, so we know we have something to compute stats
2929 on, and after registering all dissectors, so that MATE will
2930 have registered its field array and we can have a tap filter
2931 with one of MATE's late-registered fields as part of the
2933 start_requested_stats();
2935 /* Read the capture file. */
2936 switch (cf_read(&cfile)) {
2940 /* Just because we got an error, that doesn't mean we were unable
2941 to read any of the file; we handle what we could get from the
2943 /* if the user told us to jump to a specific packet, do it now */
2944 if(go_to_packet != 0) {
2945 cf_goto_frame(&cfile, go_to_packet);
2949 case CF_READ_ABORTED:
2954 /* Save the name of the containing directory specified in the
2955 path name, if any; we can write over cf_name, which is a
2956 good thing, given that "get_dirname()" does write over its
2958 s = get_dirname(cf_name);
2959 set_last_open_dir(s);
2964 dfilter_free(rfcode);
2965 cfile.rfcode = NULL;
2966 show_main_window(FALSE);
2967 set_menus_for_capture_in_progress(FALSE);
2972 if (start_capture) {
2973 if (capture_opts->save_file != NULL) {
2974 /* Save the directory name for future file dialogs. */
2975 /* (get_dirname overwrites filename) */
2976 s = get_dirname(g_strdup(capture_opts->save_file));
2977 set_last_open_dir(s);
2980 /* "-k" was specified; start a capture. */
2981 show_main_window(TRUE);
2982 if (capture_start(capture_opts)) {
2983 /* The capture started. Open stat windows; we do so after creating
2984 the main window, to avoid GTK warnings, and after successfully
2985 opening the capture file, so we know we have something to compute
2986 stats on, and after registering all dissectors, so that MATE will
2987 have registered its field array and we can have a tap filter with
2988 one of MATE's late-registered fields as part of the filter. */
2989 start_requested_stats();
2993 show_main_window(FALSE);
2994 set_menus_for_capture_in_progress(FALSE);
2997 /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
2998 if (!start_capture && strlen(capture_opts->cfilter) == 0) {
2999 g_free(capture_opts->cfilter);
3000 capture_opts->cfilter = g_strdup(get_conn_cfilter());
3002 #else /* HAVE_LIBPCAP */
3003 show_main_window(FALSE);
3004 set_menus_for_capture_in_progress(FALSE);
3005 #endif /* HAVE_LIBPCAP */
3008 /* register our pid if we are being run from a U3 device */
3011 /* we'll enter the GTK loop now and hand the control over to GTK ... */
3013 /* ... back from GTK, we're going down now! */
3015 /* deregister our pid */
3016 u3_deregister_pid();
3021 #ifdef HAVE_AIRPDCAP
3022 /* Davide Schiera (2006-11-18): destroy AirPDcap context */
3023 AirPDcapDestroyContext(&airpdcap_ctx);
3024 /* Davide Schiera (2006-11-18) ------------------------------------------- */
3028 /* hide the (unresponsive) main window, while asking the user to close the console window */
3029 gtk_widget_hide(top_level);
3031 /* Shutdown windows sockets */
3034 /* For some unknown reason, the "atexit()" call in "create_console()"
3035 doesn't arrange that "destroy_console()" be called when we exit,
3036 so we call it here if a console was created. */
3042 /* This isn't reached, but we need it to keep GCC from complaining
3043 that "main()" returns without returning a value - it knows that
3044 "exit()" never returns, but it doesn't know that "gtk_exit()"
3045 doesn't, as GTK+ doesn't declare it with the attribute
3047 return 0; /* not reached */
3052 /* We build this as a GUI subsystem application on Win32, so
3053 "WinMain()", not "main()", gets called.
3055 Hack shamelessly stolen from the Win32 port of the GIMP. */
3057 #define _stdcall __attribute__((stdcall))
3061 WinMain (struct HINSTANCE__ *hInstance,
3062 struct HINSTANCE__ *hPrevInstance,
3066 #if GTK_MAJOR_VERSION >= 2
3067 INITCOMMONCONTROLSEX comm_ctrl;
3069 /* Initialize our controls. Required for native Windows file dialogs. */
3070 memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3071 comm_ctrl.dwSize = sizeof(comm_ctrl);
3072 /* Includes the animate, header, hot key, list view, progress bar,
3073 * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3076 comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3077 InitCommonControlsEx(&comm_ctrl);
3079 /* RichEd20.DLL is needed for filter entries. */
3080 LoadLibrary(_T("riched20.dll"));
3081 #endif /* GTK_MAJOR_VERSION >= 2 */
3083 has_console = FALSE;
3084 return main (__argc, __argv);
3088 * If this application has no console window to which its standard output
3089 * would go, create one.
3092 create_console(void)
3095 /* We have no console to which to print the version string, so
3096 create one and make it the standard input, output, and error. */
3097 if (!AllocConsole())
3098 return; /* couldn't create console */
3099 eth_freopen("CONIN$", "r", stdin);
3100 eth_freopen("CONOUT$", "w", stdout);
3101 eth_freopen("CONOUT$", "w", stderr);
3103 /* Well, we have a console now. */
3106 /* Now register "destroy_console()" as a routine to be called just
3107 before the application exits, so that we can destroy the console
3108 after the user has typed a key (so that the console doesn't just
3109 disappear out from under them, giving the user no chance to see
3110 the message(s) we put in there). */
3111 atexit(destroy_console);
3113 SetConsoleTitle(_T("Wireshark Debug Console"));
3118 destroy_console(void)
3121 printf("\n\nPress any key to exit\n");
3129 /* This routine should not be necessary, at least as I read the GLib
3130 source code, as it looks as if GLib is, on Win32, *supposed* to
3131 create a console window into which to display its output.
3133 That doesn't happen, however. I suspect there's something completely
3134 broken about that code in GLib-for-Win32, and that it may be related
3135 to the breakage that forces us to just call "printf()" on the message
3136 rather than passing the message on to "g_log_default_handler()"
3137 (which is the routine that does the aforementioned non-functional
3138 console window creation). */
3140 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3141 const char *message, gpointer user_data _U_)
3148 /* ignore log message, if log_level isn't interesting.
3149 If preferences aren't loaded yet, display message anyway */
3150 if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3151 prefs.console_log_level != 0) {
3155 /* create a "timestamp" */
3157 today = localtime(&curr);
3160 if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3161 /* the user wants a console or the application will terminate immediately */
3165 /* For some unknown reason, the above doesn't appear to actually cause
3166 anything to be sent to the standard output, so we'll just splat the
3167 message out directly, just to make sure it gets out. */
3169 switch(log_level & G_LOG_LEVEL_MASK) {
3170 case G_LOG_LEVEL_ERROR:
3173 case G_LOG_LEVEL_CRITICAL:
3176 case G_LOG_LEVEL_WARNING:
3179 case G_LOG_LEVEL_MESSAGE:
3182 case G_LOG_LEVEL_INFO:
3185 case G_LOG_LEVEL_DEBUG:
3189 fprintf(stderr, "unknown log_level %u\n", log_level);
3191 g_assert_not_reached();
3194 fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3195 today->tm_hour, today->tm_min, today->tm_sec,
3196 log_domain != NULL ? log_domain : "",
3199 if(log_level & G_LOG_LEVEL_ERROR) {
3200 /* wait for a key press before the following error handler will terminate the program
3201 this way the user at least can read the error message */
3202 printf("\n\nPress any key to exit\n");
3206 g_log_default_handler(log_domain, log_level, message, user_data);
3212 static GtkWidget *info_bar_new(void)
3214 /* tip: tooltips don't work on statusbars! */
3215 info_bar = gtk_statusbar_new();
3216 main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
3217 file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
3218 help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
3219 #if GTK_MAJOR_VERSION >= 2
3220 gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), FALSE);
3222 gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
3227 static GtkWidget *packets_bar_new(void)
3229 /* tip: tooltips don't work on statusbars! */
3230 packets_bar = gtk_statusbar_new();
3231 packets_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(packets_bar), "packets");
3232 packets_bar_update();
3239 * Helper for main_widgets_rearrange()
3241 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3242 gtk_container_remove(GTK_CONTAINER(data), widget);
3245 static GtkWidget *main_widget_layout(gint layout_content)
3247 switch(layout_content) {
3248 case(layout_pane_content_none):
3251 case(layout_pane_content_plist):
3254 case(layout_pane_content_pdetails):
3257 case(layout_pane_content_pbytes):
3261 g_assert_not_reached();
3268 * Rearrange the main window widgets
3270 void main_widgets_rearrange(void) {
3271 GtkWidget *first_pane_widget1, *first_pane_widget2;
3272 GtkWidget *second_pane_widget1, *second_pane_widget2;
3273 gboolean split_top_left;
3275 /* be a bit faster */
3276 gtk_widget_hide(main_vbox);
3278 /* be sure, we don't loose a widget while rearranging */
3279 gtk_widget_ref(menubar);
3280 gtk_widget_ref(main_tb);
3281 gtk_widget_ref(filter_tb);
3284 gtk_widget_ref(airpcap_tb);
3287 gtk_widget_ref(pkt_scrollw);
3288 gtk_widget_ref(tv_scrollw);
3289 gtk_widget_ref(byte_nb_ptr);
3290 gtk_widget_ref(stat_hbox);
3291 gtk_widget_ref(info_bar);
3292 gtk_widget_ref(packets_bar);
3293 gtk_widget_ref(status_pane);
3294 gtk_widget_ref(main_pane_v1);
3295 gtk_widget_ref(main_pane_v2);
3296 gtk_widget_ref(main_pane_h1);
3297 gtk_widget_ref(main_pane_h2);
3298 gtk_widget_ref(welcome_pane);
3300 /* empty all containers participating */
3301 gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
3302 gtk_container_foreach(GTK_CONTAINER(stat_hbox), foreach_remove_a_child, stat_hbox);
3303 gtk_container_foreach(GTK_CONTAINER(status_pane), foreach_remove_a_child, status_pane);
3304 gtk_container_foreach(GTK_CONTAINER(main_pane_v1), foreach_remove_a_child, main_pane_v1);
3305 gtk_container_foreach(GTK_CONTAINER(main_pane_v2), foreach_remove_a_child, main_pane_v2);
3306 gtk_container_foreach(GTK_CONTAINER(main_pane_h1), foreach_remove_a_child, main_pane_h1);
3307 gtk_container_foreach(GTK_CONTAINER(main_pane_h2), foreach_remove_a_child, main_pane_h2);
3309 /* add the menubar always at the top */
3310 gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3313 gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3315 /* filter toolbar in toolbar area */
3316 if (!prefs.filter_toolbar_show_in_statusbar) {
3317 gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3321 /* airpcap toolbar */
3322 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3325 /* fill the main layout panes */
3326 switch(prefs.gui_layout_type) {
3327 case(layout_type_5):
3328 main_first_pane = main_pane_v1;
3329 main_second_pane = main_pane_v2;
3330 split_top_left = FALSE;
3332 case(layout_type_2):
3333 main_first_pane = main_pane_v1;
3334 main_second_pane = main_pane_h1;
3335 split_top_left = FALSE;
3337 case(layout_type_1):
3338 main_first_pane = main_pane_v1;
3339 main_second_pane = main_pane_h1;
3340 split_top_left = TRUE;
3342 case(layout_type_4):
3343 main_first_pane = main_pane_h1;
3344 main_second_pane = main_pane_v1;
3345 split_top_left = FALSE;
3347 case(layout_type_3):
3348 main_first_pane = main_pane_h1;
3349 main_second_pane = main_pane_v1;
3350 split_top_left = TRUE;
3352 case(layout_type_6):
3353 main_first_pane = main_pane_h1;
3354 main_second_pane = main_pane_h2;
3355 split_top_left = FALSE;
3358 main_first_pane = NULL;
3359 main_second_pane = NULL;
3360 split_top_left = FALSE;
3361 g_assert_not_reached();
3363 if (split_top_left) {
3364 first_pane_widget1 = main_second_pane;
3365 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3366 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3367 first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3369 first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3370 first_pane_widget2 = main_second_pane;
3371 second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3372 second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3374 if (first_pane_widget1 != NULL)
3375 gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3376 if (first_pane_widget2 != NULL)
3377 gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3378 if (second_pane_widget1 != NULL)
3379 gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3380 if (second_pane_widget2 != NULL)
3381 gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3383 gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3386 gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3388 /* statusbar hbox */
3389 gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
3391 /* filter toolbar in statusbar hbox */
3392 if (prefs.filter_toolbar_show_in_statusbar) {
3393 gtk_box_pack_start(GTK_BOX(stat_hbox), filter_tb, FALSE, TRUE, 1);
3397 /* airpcap toolbar */
3398 gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3402 gtk_box_pack_start(GTK_BOX(stat_hbox), status_pane, TRUE, TRUE, 0);
3403 gtk_paned_pack1(GTK_PANED(status_pane), info_bar, FALSE, FALSE);
3404 gtk_paned_pack2(GTK_PANED(status_pane), packets_bar, FALSE, FALSE);
3406 /* hide widgets on users recent settings */
3407 main_widgets_show_or_hide();
3409 gtk_widget_show(main_vbox);
3413 is_widget_visible(GtkWidget *widget, gpointer data)
3415 gboolean *is_visible = data;
3418 if (GTK_WIDGET_VISIBLE(widget))
3423 /*#define SHOW_WELCOME_PAGE*/
3424 #ifdef SHOW_WELCOME_PAGE
3425 /* XXX - There seems to be some disagreement about if and how this feature should be implemented.
3426 As I currently don't have the time to continue this, it's temporarily disabled. - ULFL */
3428 welcome_item(const gchar *stock_item, const gchar * label, const gchar * message, const gchar * tooltip,
3429 GtkSignalFunc callback, void *callback_data)
3431 GtkWidget *w, *item_hb;
3432 #if GTK_MAJOR_VERSION >= 2
3433 gchar *formatted_message;
3434 GtkTooltips *tooltips;
3436 tooltips = gtk_tooltips_new();
3439 item_hb = gtk_hbox_new(FALSE, 1);
3441 w = BUTTON_NEW_FROM_STOCK(stock_item);
3442 WIDGET_SET_SIZE(w, 80, 40);
3443 #if GTK_MAJOR_VERSION >= 2
3444 gtk_button_set_label(GTK_BUTTON(w), label);
3445 gtk_tooltips_set_tip(tooltips, w, tooltip, NULL);
3447 gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 0);
3448 SIGNAL_CONNECT(w, "clicked", callback, callback_data);
3450 w = gtk_label_new(message);
3451 gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
3452 #if GTK_MAJOR_VERSION >= 2
3453 formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\">%s</span>", message);
3454 gtk_label_set_markup(GTK_LABEL(w), formatted_message);
3455 g_free(formatted_message);
3458 gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 10);
3465 welcome_header_new(void)
3476 /* background color of the header bar */
3479 bg.green = 210 * 255;
3480 bg.blue = 229 * 255;
3482 item_vb = gtk_vbox_new(FALSE, 0);
3486 eb = gtk_event_box_new();
3487 gtk_container_add(GTK_CONTAINER(eb), item_vb);
3488 #if GTK_MAJOR_VERSION >= 2
3489 gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &bg);
3492 item_hb = gtk_hbox_new(FALSE, 0);
3493 gtk_box_pack_start(GTK_BOX(item_vb), item_hb, FALSE, FALSE, 10);
3495 icon = xpm_to_widget_from_parent(top_level, wssplash_xpm);
3496 /*icon = xpm_to_widget_from_parent(top_level, wsicon64_xpm);*/
3497 gtk_box_pack_start(GTK_BOX(item_hb), icon, FALSE, FALSE, 10);
3499 #if GTK_MAJOR_VERSION < 2
3500 message = "The World's Most Popular Network Protocol Analyzer";
3502 message = "<span weight=\"bold\" size=\"x-large\">" "The World's Most Popular Network Protocol Analyzer" "</span>";
3504 w = gtk_label_new(message);
3505 #if GTK_MAJOR_VERSION >= 2
3506 gtk_label_set_markup(GTK_LABEL(w), message);
3508 gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
3509 gtk_box_pack_start(GTK_BOX(item_hb), w, TRUE, TRUE, 5);
3511 gtk_widget_show_all(eb);
3517 welcome_topic_header_new(const char *header)
3522 #if GTK_MAJOR_VERSION >= 2
3523 gchar *formatted_message;
3527 w = gtk_label_new(header);
3528 #if GTK_MAJOR_VERSION >= 2
3529 formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\">%s</span>", header);
3530 gtk_label_set_markup(GTK_LABEL(w), formatted_message);
3531 g_free(formatted_message);
3534 /* topic header background color */
3537 bg.green = 151 * 255;
3538 bg.blue = 192 * 255;
3542 eb = gtk_event_box_new();
3543 gtk_container_add(GTK_CONTAINER(eb), w);
3544 #if GTK_MAJOR_VERSION >= 2
3545 gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &bg);
3553 welcome_topic_new(const char *header, GtkWidget **to_fill)
3555 GtkWidget *topic_vb;
3556 GtkWidget *layout_vb;
3557 GtkWidget *topic_eb;
3558 GtkWidget *topic_header;
3561 topic_vb = gtk_vbox_new(FALSE, 0);
3563 /* topic content background color */
3566 bg.green = 226 * 255;
3567 bg.blue = 228 * 255;
3569 topic_header = welcome_topic_header_new(header);
3570 gtk_box_pack_start(GTK_BOX(topic_vb), topic_header, FALSE, FALSE, 0);
3572 layout_vb = gtk_vbox_new(FALSE, 5);
3573 gtk_container_border_width(GTK_CONTAINER(layout_vb), 10);
3574 gtk_box_pack_start(GTK_BOX(topic_vb), layout_vb, FALSE, FALSE, 0);
3576 /* colorize vbox (we need an event box for this!) */
3578 topic_eb = gtk_event_box_new();
3579 gtk_container_add(GTK_CONTAINER(topic_eb), topic_vb);
3580 #if GTK_MAJOR_VERSION >= 2
3581 gtk_widget_modify_bg(topic_eb, GTK_STATE_NORMAL, &bg);
3583 *to_fill = layout_vb;
3589 #if GTK_MAJOR_VERSION >= 2
3591 welcome_link_enter_cb(GtkWidget *widget _U_, GdkEventCrossing *event _U_, gpointer user_data)
3594 GtkWidget *w = user_data;
3596 message = g_strdup_printf("<span foreground='blue' underline='single'>%s</span>", OBJECT_GET_DATA(w,"TEXT"));
3597 #if GTK_MAJOR_VERSION >= 2
3598 gtk_label_set_markup(GTK_LABEL(w), message);
3606 welcome_link_leave_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer user_data)
3609 GtkWidget *w = user_data;
3611 message = g_strdup_printf("<span foreground='blue'>%s</span>", OBJECT_GET_DATA(w,"TEXT"));
3612 #if GTK_MAJOR_VERSION >= 2
3613 gtk_label_set_markup(GTK_LABEL(w), message);
3623 welcome_link_press_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_) {
3625 g_warning("TBD: link pressed");
3631 welcome_link_new(const gchar *text, GtkWidget **label /*, void *callback, void *private_data */)
3637 #if GTK_MAJOR_VERSION < 2
3638 message = g_strdup(text);
3640 message = g_strdup_printf("<span foreground='blue'>%s</span>", text);
3642 w = gtk_label_new(message);
3644 #if GTK_MAJOR_VERSION >= 2
3645 gtk_label_set_markup(GTK_LABEL(w), message);
3650 eb = gtk_event_box_new();
3651 gtk_container_add(GTK_CONTAINER(eb), w);
3653 #if GTK_MAJOR_VERSION >= 2
3654 SIGNAL_CONNECT(eb, "enter-notify-event", welcome_link_enter_cb, w);
3655 SIGNAL_CONNECT(eb, "leave-notify-event", welcome_link_leave_cb, w);
3657 SIGNAL_CONNECT(eb, "button-press-event", welcome_link_press_cb, w);
3660 OBJECT_SET_DATA(w, "TEXT", g_strdup(text));
3666 welcome_filename_link_new(const char *filename, GtkWidget **label)
3670 const unsigned int max = 60;
3673 str = g_string_new(filename);
3675 if(str->len > max) {
3676 g_string_erase(str, 0, str->len-max /*cut*/);
3677 g_string_prepend(str, "... ");
3680 w = welcome_link_new(str->str, label);
3682 g_string_free(str, TRUE);
3689 welcome_if_new(const char *if_name, GdkColor *topic_bg, gboolean active)
3691 GtkWidget *interface_hb;
3694 GtkTooltips *tooltips;
3698 tooltips = gtk_tooltips_new();
3700 interface_hb = gtk_hbox_new(FALSE, 5);
3702 w = welcome_link_new("START", &label);
3703 gtk_tooltips_set_tip(tooltips, w, "Immediately start a capture on this interface", NULL);
3704 #if GTK_MAJOR_VERSION >= 2
3705 gtk_widget_modify_bg(w, GTK_STATE_NORMAL, topic_bg);
3707 gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
3708 gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
3710 w = welcome_link_new("OPTIONS", &label);
3711 gtk_tooltips_set_tip(tooltips, w, "Show the capture options of this interface", NULL);
3712 #if GTK_MAJOR_VERSION >= 2
3713 gtk_widget_modify_bg(w, GTK_STATE_NORMAL, topic_bg);
3715 gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
3716 gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
3718 w = welcome_link_new("DETAILS", &label);
3719 gtk_tooltips_set_tip(tooltips, w, "Show detailed information about this interface", NULL);
3720 #if GTK_MAJOR_VERSION >= 2
3721 gtk_widget_modify_bg(w, GTK_STATE_NORMAL, topic_bg);
3723 gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
3724 gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
3726 message = g_string_new(if_name);
3728 /* truncate string if it's too long */
3729 if(message->len > 38) {
3730 g_string_truncate(message, 35);
3731 g_string_append (message, " ...");
3733 #if GTK_MAJOR_VERSION >= 2
3734 /* if this is the "active" interface, display it bold */
3736 g_string_prepend(message, "<span weight=\"bold\">");
3737 g_string_append (message, "</span>");
3740 w = gtk_label_new(message->str);
3741 #if GTK_MAJOR_VERSION >= 2
3742 gtk_label_set_markup(GTK_LABEL(w), message->str);
3744 g_string_free(message, TRUE);
3746 gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
3747 gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
3749 return interface_hb;
3752 /* XXX - the layout has to be improved */
3756 GtkWidget *welcome_scrollw;
3757 GtkWidget *welcome_vb;
3758 GtkWidget *welcome_hb;
3759 GtkWidget *column_vb;
3764 GtkWidget *topic_vb;
3765 GtkWidget *topic_to_fill;
3766 GtkWidget *interface_hb;
3770 /* topic content background color */
3772 topic_bg.red = 221 * 255;
3773 topic_bg.green = 226 * 255;
3774 topic_bg.blue = 228 * 255;
3776 welcome_scrollw = scrolled_window_new(NULL, NULL);
3778 welcome_vb = gtk_vbox_new(FALSE, 0);
3781 header = welcome_header_new();
3782 gtk_box_pack_start(GTK_BOX(welcome_vb), header, FALSE, FALSE, 0);
3785 welcome_hb = gtk_hbox_new(FALSE, 10);
3786 gtk_container_border_width(GTK_CONTAINER(welcome_hb), 10);
3787 gtk_box_pack_start(GTK_BOX(welcome_vb), welcome_hb, TRUE, TRUE, 0);
3789 /* column capture */
3790 column_vb = gtk_vbox_new(FALSE, 10);
3791 gtk_box_pack_start(GTK_BOX(welcome_hb), column_vb, TRUE, TRUE, 0);
3794 topic_vb = welcome_topic_new("Capture", &topic_to_fill);
3795 gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
3798 item_hb = welcome_item(WIRESHARK_STOCK_CAPTURE_INTERFACES,
3800 "Interface Life List",
3801 "Show a life list of the available capture interfaces",
3802 GTK_SIGNAL_FUNC(capture_if_cb), NULL);
3803 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
3806 w = gtk_label_new("Available Interfaces:");
3807 gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
3808 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
3810 interface_hb = welcome_if_new("Generic dialup adapter", &topic_bg, FALSE);
3811 gtk_box_pack_start(GTK_BOX(topic_to_fill), interface_hb, FALSE, FALSE, 0);
3813 /* Marvell interface (currently "active") */
3814 interface_hb = welcome_if_new("Marvell Gigabit Ethernet Controller", &topic_bg, TRUE);
3815 gtk_box_pack_start(GTK_BOX(topic_to_fill), interface_hb, FALSE, FALSE, 0);
3817 /* Wireless interface */
3818 interface_hb = welcome_if_new("Intel(R) PRO/Wireless 3945ABG Network Connection", &topic_bg, FALSE);
3819 gtk_box_pack_start(GTK_BOX(topic_to_fill), interface_hb, FALSE, FALSE, 0);
3822 /* capture help topic */
3823 topic_vb = welcome_topic_new("Capture Help", &topic_to_fill);
3824 gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
3827 item_hb = welcome_item(WIRESHARK_STOCK_CAPTURE_START,
3829 "How To: Setup a Capture",
3830 "How To: Setup a Capture (online from the Wiki)",
3831 GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
3832 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
3834 item_hb = welcome_item(WIRESHARK_STOCK_CAPTURE_START,
3836 "Capture Filter Examples",
3837 "Capture Filter Examples (online from the Wiki)",
3838 GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
3839 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
3842 /* fill bottom space */
3843 w = gtk_label_new("");
3844 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
3848 topic_vb = welcome_topic_new("Files", &topic_to_fill);
3849 gtk_box_pack_start(GTK_BOX(welcome_hb), topic_vb, TRUE, TRUE, 0);
3851 item_hb = welcome_item(GTK_STOCK_OPEN,
3853 "Open a Capture File",
3854 "Open a previously captured file",
3855 GTK_SIGNAL_FUNC(file_open_cmd_cb), NULL);
3856 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
3858 item_hb = welcome_item(GTK_STOCK_OPEN,
3860 "Download Examples",
3861 "Download Example Capture Files (from the Wiki)",
3862 GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
3863 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
3865 w = gtk_label_new("Recent Files:");
3866 gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
3867 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
3869 w = welcome_link_new("C:\\Testfiles\\hello.pcap", &label);
3870 #if GTK_MAJOR_VERSION >= 2
3871 gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &topic_bg);
3873 gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
3874 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 0);
3876 w = welcome_filename_link_new("C:\\Testfiles\\hello2.pcap", &label);
3877 #if GTK_MAJOR_VERSION >= 2
3878 gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &topic_bg);
3880 gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
3881 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 0);
3883 w = welcome_filename_link_new(
3884 "C:\\Testfiles\\to avoid screen garbage\\Unfortunately this is a very long filename which had to be truncated.pcap",
3886 #if GTK_MAJOR_VERSION >= 2
3887 gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &topic_bg);
3889 gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
3890 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 0);
3892 w = gtk_label_new("");
3893 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
3897 column_vb = gtk_vbox_new(FALSE, 10);
3898 gtk_box_pack_start(GTK_BOX(welcome_hb), column_vb, TRUE, TRUE, 0);
3901 topic_vb = welcome_topic_new("Online", &topic_to_fill);
3902 gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
3904 #if (GLIB_MAJOR_VERSION >= 2)
3905 item_hb = welcome_item(WIRESHARK_STOCK_WEB_SUPPORT,
3907 "Show the User's Guide",
3908 "Show the User's Guide (local version, if available)",
3909 GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
3910 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
3912 item_hb = welcome_item(GTK_STOCK_HOME,
3914 "Projects Home Page",
3915 "Visit www.wireshark.org, the project's home page",
3916 GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_HOME));
3917 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
3921 topic_vb = welcome_topic_new("Updates", &topic_to_fill);
3922 gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
3924 w = gtk_label_new("No updates available!");
3925 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
3929 gtk_widget_show_all(welcome_vb);
3931 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(welcome_scrollw),
3933 gtk_widget_show_all(welcome_scrollw);
3935 return welcome_scrollw;
3941 /* this is just a dummy to fill up window space, simply showing nothing */
3942 return scrolled_window_new(NULL, NULL);
3949 * XXX - this doesn't appear to work with the paned widgets in
3950 * GTK+ 1.2[.x]; if you hide one of the panes, the splitter remains
3951 * and the other pane doesn't grow to take up the rest of the pane.
3952 * It does appear to work with GTK+ 2.x.
3955 main_widgets_show_or_hide(void)
3957 gboolean main_second_pane_show;
3959 if (recent.main_toolbar_show) {
3960 gtk_widget_show(main_tb);
3962 gtk_widget_hide(main_tb);
3966 * Show the status hbox if either:
3968 * 1) we're showing the filter toolbar and we want it in the status
3973 * 2) we're showing the status bar.
3975 if ((recent.filter_toolbar_show && prefs.filter_toolbar_show_in_statusbar) ||
3976 recent.statusbar_show) {
3977 gtk_widget_show(stat_hbox);
3979 gtk_widget_hide(stat_hbox);
3982 if (recent.statusbar_show) {
3983 gtk_widget_show(status_pane);
3985 gtk_widget_hide(status_pane);
3988 if (recent.filter_toolbar_show) {
3989 gtk_widget_show(filter_tb);
3991 gtk_widget_hide(filter_tb);
3995 if (recent.airpcap_toolbar_show) {
3996 gtk_widget_show(airpcap_tb);
3998 gtk_widget_hide(airpcap_tb);
4002 if (recent.packet_list_show && have_capture_file) {
4003 gtk_widget_show(pkt_scrollw);
4005 gtk_widget_hide(pkt_scrollw);
4008 if (recent.tree_view_show && have_capture_file) {
4009 gtk_widget_show(tv_scrollw);
4011 gtk_widget_hide(tv_scrollw);
4014 if (recent.byte_view_show && have_capture_file) {
4015 gtk_widget_show(byte_nb_ptr);
4017 gtk_widget_hide(byte_nb_ptr);
4020 if (have_capture_file) {
4021 gtk_widget_show(main_first_pane);
4023 gtk_widget_hide(main_first_pane);
4027 * Is anything in "main_second_pane" visible?
4028 * If so, show it, otherwise hide it.
4030 main_second_pane_show = FALSE;
4031 gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
4032 &main_second_pane_show);
4033 if (main_second_pane_show) {
4034 gtk_widget_show(main_second_pane);
4036 gtk_widget_hide(main_second_pane);
4039 if (!have_capture_file) {
4041 gtk_widget_show(welcome_pane);
4044 gtk_widget_hide(welcome_pane);
4047 /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
4048 packet_list_freeze ();
4049 packet_list_thaw ();
4053 #if GTK_MAJOR_VERSION >= 2
4054 /* called, when the window state changes (minimized, maximized, ...) */
4056 window_state_event_cb (GtkWidget *widget _U_,
4060 GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
4062 if( (event->type) == (GDK_WINDOW_STATE)) {
4063 if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
4064 /* we might have dialogs popped up while we where iconified,
4066 display_queued_messages();
4075 * Changed callback for the channel combobox
4078 airpcap_toolbar_channel_changed_cb(GtkWidget *w _U_, gpointer data)
4083 if ((data != NULL) && (w != NULL) && change_airpcap_settings) {
4084 s = gtk_entry_get_text(GTK_ENTRY(w));
4085 if ((g_strcasecmp("",s))) {
4086 ch_freq = airpcap_get_frequency_from_str(s);
4087 if (airpcap_if_active != NULL) {
4088 airpcap_if_active->channelInfo.Frequency = ch_freq;
4089 airpcap_update_channel_offset_cb(airpcap_if_active, ch_freq, GTK_WIDGET(data));
4096 * Changed callback for the channel offset combobox
4099 on_channel_offset_cb_changed(GtkWidget *w _U_, gpointer data)
4104 if ((data != NULL) && (w != NULL) && change_airpcap_settings)
4106 s = gtk_entry_get_text(GTK_ENTRY(w));
4107 if ((g_strcasecmp("",s)))
4109 if (airpcap_if_active != NULL)
4111 sscanf(s,"%d",&offset);
4112 airpcap_if_active->channelInfo.ExtChannel = offset;
4113 if (change_airpcap_settings != NULL)
4115 airpcap_update_frequency_and_offset(airpcap_if_active);
4123 * Callback for the wrong crc combo
4126 airpcap_toolbar_wrong_crc_combo_cb(GtkWidget *entry, gpointer user_data)
4128 gchar ebuf[AIRPCAP_ERRBUF_SIZE];
4131 if( !block_toolbar_signals && (airpcap_if_active != NULL)) {
4132 ad = airpcap_if_open(airpcap_if_active->name, ebuf);
4135 airpcap_if_active->CrcValidationOn = airpcap_get_validation_type(gtk_entry_get_text(GTK_ENTRY(entry)));
4136 airpcap_if_set_fcs_validation(ad,airpcap_if_active->CrcValidationOn);
4137 /* Save configuration */
4138 airpcap_if_store_cur_config_as_adapter_default(ad);
4139 airpcap_if_close(ad);
4145 airpcap_toolbar_encryption_cb(GtkWidget *entry, gpointer user_data)
4147 /* We need to directly access the .ddl functions here... */
4148 gchar ebuf[AIRPCAP_ERRBUF_SIZE];
4153 airpcap_if_info_t* curr_if = NULL;
4155 /* Apply changes to the current adapter */
4156 if( (airpcap_if_active != NULL)) {
4157 ad = airpcap_if_open(airpcap_if_active->name, ebuf);
4160 if(airpcap_if_active->DecryptionOn == AIRPCAP_DECRYPTION_ON) {
4161 airpcap_if_active->DecryptionOn = AIRPCAP_DECRYPTION_OFF;
4162 airpcap_if_set_decryption_state(ad,airpcap_if_active->DecryptionOn);
4163 /* Save configuration */
4164 if(!airpcap_if_store_cur_config_as_adapter_default(ad)) {
4165 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Cannot save configuration!!!\nRemember that in order to store the configuration in the registry you have to:\n\n- Close all the airpcap-based applications.\n- Be sure to have administrative privileges.");
4167 airpcap_if_close(ad);
4169 airpcap_if_active->DecryptionOn = AIRPCAP_DECRYPTION_ON;
4170 airpcap_if_set_decryption_state(ad,airpcap_if_active->DecryptionOn);
4171 /* Save configuration */
4172 if(!airpcap_if_store_cur_config_as_adapter_default(ad)) {
4173 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Cannot save configuration!!!\nRemember that in order to store the configuration in the registry you have to:\n\n- Close all the airpcap-based applications.\n- Be sure to have administrative privileges.");
4175 airpcap_if_close(ad);
4179 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No active AirPcap Adapter selected!");
4183 if (!(airpcap_if_list == NULL)){
4184 n = g_list_length(airpcap_if_list);
4186 /* The same kind of settings should be propagated to all the adapters */
4187 /* Apply this change to all the adapters !!! */
4188 for(i = 0; i < n; i++) {
4189 curr_if = (airpcap_if_info_t*)g_list_nth_data(airpcap_if_list,i);
4191 if( (curr_if != NULL) && (curr_if != airpcap_if_selected) ) {
4192 ad = airpcap_if_open(curr_if->name, ebuf);
4194 curr_if->DecryptionOn = airpcap_if_selected->DecryptionOn;
4195 airpcap_if_set_decryption_state(ad,curr_if->DecryptionOn);
4196 /* Save configuration for the curr_if */
4197 if(!airpcap_if_store_cur_config_as_adapter_default(ad)) {
4198 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Cannot save configuration!!!\nRemember that in order to store the configuration in the registry you have to:\n\n- Close all the airpcap-based applications.\n- Be sure to have administrative privileges.");
4200 airpcap_if_close(ad);
4205 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "AirPcap Adapter Error!");
4211 * Callback for the Advanced Wireless Settings button
4214 toolbar_display_airpcap_advanced_cb(GtkWidget *w, gpointer data)
4218 from_widget = (gint*)g_malloc(sizeof(gint));
4219 *from_widget = AIRPCAP_ADVANCED_FROM_TOOLBAR;
4220 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_ADVANCED_FROM_KEY,from_widget);
4222 display_airpcap_advanced_cb(w,data);
4226 * Callback for the Decryption Key Management button
4229 toolbar_display_airpcap_key_management_cb(GtkWidget *w, gpointer data)
4233 from_widget = (gint*)g_malloc(sizeof(gint));
4234 *from_widget = AIRPCAP_ADVANCED_FROM_TOOLBAR;
4235 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_ADVANCED_FROM_KEY,from_widget);
4237 display_airpcap_key_management_cb(w,data);
4239 #endif /* HAVE_AIRPCAP */
4241 #if GTK_MAJOR_VERSION >= 2
4242 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_LOCK_MASK))
4244 top_level_key_pressed_cb(GtkCTree *ctree _U_, GdkEventKey *event, gpointer user_data _U_)
4246 if (event->keyval == GDK_F8) {
4249 } else if (event->keyval == GDK_F7) {
4252 } else if (event->state & NO_SHIFT_MOD_MASK) {
4253 return FALSE; /* Skip control, alt, and other modifiers */
4255 * A comment in gdkkeysyms.h says that it's autogenerated from
4256 * freedesktop.org/x.org's keysymdef.h. Although the GDK docs
4257 * don't explicitly say so, isprint() should work as expected
4260 } else if (isascii(event->keyval) && isprint(event->keyval)) {
4261 /* Forward the keypress on to the display filter entry */
4262 if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
4263 gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
4264 gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
4273 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
4276 *filter_bt, *filter_cm, *filter_te,
4277 *filter_add_expr_bt,
4280 GList *dfilter_list = NULL;
4281 GtkTooltips *tooltips;
4283 GtkAccelGroup *accel;
4287 GtkWidget *key_management_bt = NULL,
4288 #if GTK_MAJOR_VERSION >= 2 /* For some reason this button's action crashes under GTK 1. */
4289 *advanced_bt = NULL,
4293 *channel_offset_lb = NULL,
4294 *channel_offset_cb = NULL,
4295 *wrong_crc_lb = NULL,
4296 *wrong_crc_cm = NULL;
4298 GtkWidget *enable_decryption_lb;
4299 GtkWidget *enable_decryption_cb;
4300 GList *enable_decryption_cb_items = NULL;
4301 GtkWidget *enable_decryption_en;
4303 GList *channel_list = NULL;
4304 GList *linktype_list = NULL;
4305 GList *link_list = NULL;
4306 GtkTooltips *airpcap_tooltips;
4307 /* gchar *if_label_text; */
4308 gint *from_widget = NULL;
4311 /* Display filter construct dialog has an Apply button, and "OK" not
4312 only sets our text widget, it activates it (i.e., it causes us to
4313 filter the capture). */
4314 static construct_args_t args = {
4315 "Wireshark: Display Filter",
4321 /* use user-defined title if preference is set */
4322 title = create_user_window_title("The Wireshark Network Analyzer");
4325 top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
4328 tooltips = gtk_tooltips_new();
4331 airpcap_tooltips = gtk_tooltips_new();
4335 #if GTK_MAJOR_VERSION < 2
4336 /* has to be done, after top_level window is created */
4337 app_font_gtk1_init(top_level);
4341 gtk_widget_set_name(top_level, "main window");
4342 SIGNAL_CONNECT(top_level, "delete_event", main_window_delete_event_cb,
4344 #if GTK_MAJOR_VERSION >= 2
4345 SIGNAL_CONNECT(GTK_OBJECT(top_level), "window_state_event",
4346 G_CALLBACK (window_state_event_cb), NULL);
4347 SIGNAL_CONNECT(GTK_OBJECT(top_level), "key-press-event",
4348 G_CALLBACK (top_level_key_pressed_cb), NULL );
4351 gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
4353 /* Container for menu bar, toolbar(s), paned windows and progress/info box */
4354 main_vbox = gtk_vbox_new(FALSE, 1);
4355 gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
4356 gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
4357 gtk_widget_show(main_vbox);
4360 menubar = main_menu_new(&accel);
4361 gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
4362 gtk_widget_show(menubar);
4365 main_tb = toolbar_new();
4366 gtk_widget_show (main_tb);
4369 pkt_scrollw = packet_list_new(prefs);
4370 WIDGET_SET_SIZE(packet_list, -1, pl_size);
4371 gtk_widget_show(pkt_scrollw);
4374 tv_scrollw = main_tree_view_new(prefs, &tree_view);
4375 WIDGET_SET_SIZE(tv_scrollw, -1, tv_size);
4376 gtk_widget_show(tv_scrollw);
4378 #if GTK_MAJOR_VERSION < 2
4379 SIGNAL_CONNECT(tree_view, "tree-select-row", tree_view_select_row_cb, NULL);
4380 SIGNAL_CONNECT(tree_view, "tree-unselect-row", tree_view_unselect_row_cb,
4383 SIGNAL_CONNECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
4384 "changed", tree_view_selection_changed_cb, NULL);
4386 SIGNAL_CONNECT(tree_view, "button_press_event", popup_menu_handler,
4387 OBJECT_GET_DATA(popup_menu_object, PM_TREE_VIEW_KEY));
4388 gtk_widget_show(tree_view);
4391 byte_nb_ptr = byte_view_new();
4392 WIDGET_SET_SIZE(byte_nb_ptr, -1, bv_size);
4393 gtk_widget_show(byte_nb_ptr);
4395 SIGNAL_CONNECT(byte_nb_ptr, "button_press_event", popup_menu_handler,
4396 OBJECT_GET_DATA(popup_menu_object, PM_HEXDUMP_KEY));
4399 /* Panes for the packet list, tree, and byte view */
4400 main_pane_v1 = gtk_vpaned_new();
4401 gtk_widget_show(main_pane_v1);
4402 main_pane_v2 = gtk_vpaned_new();
4403 gtk_widget_show(main_pane_v2);
4404 main_pane_h1 = gtk_hpaned_new();
4405 gtk_widget_show(main_pane_h1);
4406 main_pane_h2 = gtk_hpaned_new();
4407 gtk_widget_show(main_pane_h2);
4410 /* airpcap toolbar */
4411 #if GTK_MAJOR_VERSION < 2
4412 airpcap_tb = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
4415 airpcap_tb = gtk_toolbar_new();
4416 gtk_toolbar_set_orientation(GTK_TOOLBAR(airpcap_tb),
4417 GTK_ORIENTATION_HORIZONTAL);
4418 #endif /* GTK_MAJOR_VERSION */
4419 gtk_widget_show(airpcap_tb);
4421 /* Interface Label */
4422 /*if(airpcap_if_active != NULL) {
4423 if_label_text = g_strdup_printf("%s %s\t","Current Wireless Interface: #",airpcap_get_if_string_number(airpcap_if_active));
4424 interface_lb = gtk_label_new(if_label_text);
4425 g_free(if_label_text);
4427 interface_lb = gtk_label_new("No Wireless Interface Found ");
4430 /* Add the label to the toolbar */
4431 /*gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), interface_lb,
4432 "Current Wireless Interface", "Private");
4433 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_INTERFACE_KEY,interface_lb);
4434 gtk_widget_show(interface_lb);
4435 gtk_toolbar_insert_space(GTK_TOOLBAR(airpcap_tb),1);*/
4438 /* Create the "802.11 Channel:" label */
4439 channel_lb = gtk_label_new("802.11 Channel: ");
4440 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_CHANNEL_LABEL_KEY,channel_lb);
4441 gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), channel_lb,
4442 "Current 802.11 Channel", "Private");
4443 gtk_widget_show(channel_lb);
4445 WIDGET_SET_SIZE(channel_lb, 85, 28);
4447 /* Create the channel combo box */
4448 channel_cm = gtk_combo_new();
4449 gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(channel_cm)->entry),FALSE);
4450 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_CHANNEL_KEY,channel_cm);
4452 if (airpcap_if_active != NULL && airpcap_if_active->pSupportedChannels != NULL && airpcap_if_active->numSupportedChannels > 0){
4454 for (; i<airpcap_if_active->numSupportedChannels; i++){
4455 channel_list = g_list_append(channel_list, airpcap_get_channelstr_from_freq(airpcap_if_active->pSupportedChannels[i].Frequency));
4457 gtk_combo_set_popdown_strings( GTK_COMBO(channel_cm), channel_list) ;
4460 gtk_tooltips_set_tip(airpcap_tooltips, GTK_WIDGET(GTK_COMBO(channel_cm)->entry),
4461 "Change the 802.11 RF channel", NULL);
4463 WIDGET_SET_SIZE(channel_cm, 120, 28);
4465 if(airpcap_if_active != NULL)
4466 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(channel_cm)->entry), airpcap_get_channelstr_from_freq(airpcap_if_active->channelInfo.Frequency));
4468 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(channel_cm)->entry),"");
4470 gtk_widget_show(channel_cm);
4472 gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), channel_cm,
4473 "802.11 Channel", "Private");
4475 /* gtk_toolbar_append_space(GTK_TOOLBAR(airpcap_tb)); */
4477 /* Create the "Channel Offset:" label */
4478 channel_offset_lb = gtk_label_new("Channel Offset: ");
4479 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_CHANNEL_OFFSET_LABEL_KEY,channel_offset_lb);
4480 gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), channel_offset_lb,
4481 "Current 802.11 Channel Offset", "Private");
4482 gtk_widget_show(channel_offset_lb);
4484 WIDGET_SET_SIZE(channel_offset_lb, 80, 28);
4486 /* Start: Channel offset combo box */
4487 channel_offset_cb = gtk_combo_new();
4488 gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(channel_offset_cb)->entry),FALSE);
4489 OBJECT_SET_DATA(airpcap_tb, AIRPCAP_TOOLBAR_CHANNEL_OFFSET_KEY, channel_offset_cb);
4491 if(airpcap_if_active != NULL){
4492 airpcap_update_channel_offset_cb(airpcap_if_active, airpcap_if_active->channelInfo.Frequency, channel_offset_cb);
4493 airpcap_update_channel_offset_combo_entry(channel_offset_cb, airpcap_if_active->channelInfo.ExtChannel);
4495 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(channel_offset_cb)->entry),"");
4498 gtk_tooltips_set_tip(airpcap_tooltips, GTK_WIDGET(GTK_COMBO(channel_offset_cb)->entry),
4499 "Change channel offset", NULL);
4501 WIDGET_SET_SIZE(channel_offset_cb, 50, 28);
4503 gtk_widget_show(channel_offset_cb);
4505 gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), channel_offset_cb,
4506 "802.11 Channel Offset", "Private");
4508 gtk_toolbar_append_space(GTK_TOOLBAR(airpcap_tb));
4510 /* callback for channel combo box */
4511 SIGNAL_CONNECT(GTK_COMBO(channel_cm)->entry,"changed", airpcap_toolbar_channel_changed_cb, channel_offset_cb);
4512 /* callback for channel offset combo box */
4513 SIGNAL_CONNECT(GTK_COMBO(channel_offset_cb)->entry,"changed", on_channel_offset_cb_changed, channel_offset_cb);
4514 /* End: Channel offset combo box */
4516 /* Wrong CRC Label */
4517 wrong_crc_lb = gtk_label_new(" FCS Filter: ");
4518 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_FCS_FILTER_LABEL_KEY,wrong_crc_lb);
4519 gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), wrong_crc_lb,
4521 gtk_widget_show(wrong_crc_lb);
4523 /* Wrong CRC combo */
4524 wrong_crc_cm = gtk_combo_new();
4525 gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(wrong_crc_cm)->entry),FALSE);
4526 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_FCS_FILTER_KEY,wrong_crc_cm);
4527 gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), wrong_crc_cm,
4530 WIDGET_SET_SIZE(wrong_crc_cm, 100, -1);
4532 linktype_list = g_list_append(linktype_list, AIRPCAP_VALIDATION_TYPE_NAME_ALL);
4533 linktype_list = g_list_append(linktype_list, AIRPCAP_VALIDATION_TYPE_NAME_CORRECT);
4534 linktype_list = g_list_append(linktype_list, AIRPCAP_VALIDATION_TYPE_NAME_CORRUPT);
4536 gtk_combo_set_popdown_strings( GTK_COMBO(wrong_crc_cm), linktype_list) ;
4537 gtk_tooltips_set_tip(airpcap_tooltips, GTK_WIDGET(GTK_COMBO(wrong_crc_cm)->entry),
4538 "Select the 802.11 FCS filter that the wireless adapter will apply.",
4541 if(airpcap_if_active != NULL)
4542 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(wrong_crc_cm)->entry), airpcap_get_validation_name(airpcap_if_active->CrcValidationOn));
4544 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(wrong_crc_cm)->entry),"");
4546 SIGNAL_CONNECT(GTK_COMBO(wrong_crc_cm)->entry,"changed",airpcap_toolbar_wrong_crc_combo_cb,airpcap_tb);
4547 gtk_widget_show(wrong_crc_cm);
4549 gtk_toolbar_append_space(GTK_TOOLBAR(airpcap_tb));
4551 /* Decryption mode combo box */
4552 enable_decryption_lb = gtk_label_new ("Decryption Mode: ");
4553 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_DECRYPTION_LABEL_KEY,enable_decryption_lb);
4554 gtk_widget_set_name (enable_decryption_lb, "enable_decryption_lb");
4555 gtk_widget_show (enable_decryption_lb);
4556 gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), enable_decryption_lb,
4559 enable_decryption_cb = gtk_combo_new ();
4560 gtk_widget_set_name (enable_decryption_cb, "enable_decryption_cb");
4561 gtk_widget_show (enable_decryption_cb);
4562 WIDGET_SET_SIZE (enable_decryption_cb, 83, -1);
4563 update_decryption_mode_list(enable_decryption_cb);
4565 enable_decryption_en = GTK_COMBO (enable_decryption_cb)->entry;
4566 gtk_widget_set_name (enable_decryption_en, "enable_decryption_en");
4567 gtk_widget_show (enable_decryption_en);
4568 gtk_editable_set_editable (GTK_EDITABLE (enable_decryption_en), FALSE);
4569 GTK_WIDGET_UNSET_FLAGS (enable_decryption_en, GTK_CAN_FOCUS);
4571 gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), enable_decryption_cb,
4572 "Choose a Decryption Mode", "Private");
4574 /* Set current decryption mode!!!! */
4575 update_decryption_mode_cm(enable_decryption_cb);
4576 SIGNAL_CONNECT (enable_decryption_en, "changed",on_enable_decryption_en_changed, airpcap_tb);
4577 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_DECRYPTION_KEY,enable_decryption_cb);
4579 gtk_toolbar_append_space(GTK_TOOLBAR(airpcap_tb));
4581 #if GTK_MAJOR_VERSION >= 2 /* For some reason this button's action crashes under GTK 1. */
4582 /* Advanced button */
4583 advanced_bt = gtk_button_new_with_label("Wireless Settings...");
4584 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_ADVANCED_KEY,advanced_bt);
4586 SIGNAL_CONNECT(advanced_bt, "clicked", toolbar_display_airpcap_advanced_cb, airpcap_tb);
4587 gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), advanced_bt,
4588 "Set Advanced Wireless Settings", "Private");
4591 gtk_widget_show(advanced_bt);
4592 #endif /* GTK_MAJOR_VERSION */
4594 /* Key Management button */
4595 key_management_bt = gtk_button_new_with_label("Decryption Keys...");
4596 OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_KEY_MANAGEMENT_KEY,key_management_bt);
4598 SIGNAL_CONNECT(key_management_bt, "clicked", toolbar_display_airpcap_key_management_cb, airpcap_tb);
4599 gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), key_management_bt,
4600 "Manage Decryption Keys", "Private");
4601 gtk_widget_show(key_management_bt);
4603 /* If no airpcap interface is present, gray everything */
4604 if(airpcap_if_active == NULL) {
4605 if(airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0) {
4606 /*No airpcap device found */
4607 airpcap_enable_toolbar_widgets(airpcap_tb,FALSE);
4608 /* recent.airpcap_toolbar_show = TRUE; */
4610 /* default adapter is not airpcap... or is airpcap but is not found*/
4611 airpcap_set_toolbar_stop_capture(airpcap_if_active);
4612 airpcap_enable_toolbar_widgets(airpcap_tb,FALSE);
4613 /* recent.airpcap_toolbar_show = TRUE; */
4616 airpcap_set_toolbar_stop_capture(airpcap_if_active);
4617 /* recent.airpcap_toolbar_show = TRUE; */
4621 /* filter toolbar */
4622 #if GTK_MAJOR_VERSION < 2
4623 filter_tb = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
4626 filter_tb = gtk_toolbar_new();
4627 gtk_toolbar_set_orientation(GTK_TOOLBAR(filter_tb),
4628 GTK_ORIENTATION_HORIZONTAL);
4629 #endif /* GTK_MAJOR_VERSION */
4630 gtk_widget_show(filter_tb);
4632 /* Create the "Filter:" button */
4633 filter_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
4634 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
4635 gtk_widget_show(filter_bt);
4636 OBJECT_SET_DATA(top_level, E_FILT_BT_PTR_KEY, filter_bt);
4638 gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_bt,
4639 "Open the \"Display Filter\" dialog, to edit/apply filters", "Private");
4641 /* Create the filter combobox */
4642 filter_cm = gtk_combo_new();
4643 dfilter_list = NULL;
4644 gtk_combo_disable_activate(GTK_COMBO(filter_cm));
4645 gtk_combo_set_case_sensitive(GTK_COMBO(filter_cm), TRUE);
4646 OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, dfilter_list);
4647 filter_te = GTK_COMBO(filter_cm)->entry;
4648 main_display_filter_widget=filter_te;
4649 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
4650 OBJECT_SET_DATA(filter_te, E_DFILTER_CM_KEY, filter_cm);
4651 OBJECT_SET_DATA(top_level, E_DFILTER_CM_KEY, filter_cm);
4652 SIGNAL_CONNECT(filter_te, "activate", filter_activate_cb, filter_te);
4653 SIGNAL_CONNECT(filter_te, "changed", filter_te_syntax_check_cb, NULL);
4654 WIDGET_SET_SIZE(filter_cm, 400, -1);
4655 gtk_widget_show(filter_cm);
4656 gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_cm,
4658 /* setting a tooltip for a combobox will do nothing, so add it to the corresponding text entry */
4659 gtk_tooltips_set_tip(tooltips, filter_te,
4660 "Enter a display filter, or choose one of your recently used filters. "
4661 "The background color of this field is changed by a continuous syntax check (green is valid, red is invalid).",
4664 /* Create the "Add Expression..." button, to pop up a dialog
4665 for constructing filter comparison expressions. */
4666 filter_add_expr_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_ADD_EXPRESSION);
4667 OBJECT_SET_DATA(filter_tb, E_FILT_FILTER_TE_KEY, filter_te);
4668 SIGNAL_CONNECT(filter_add_expr_bt, "clicked", filter_add_expr_bt_cb, filter_tb);
4669 gtk_widget_show(filter_add_expr_bt);
4670 gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_add_expr_bt,
4671 "Add an expression to this filter string", "Private");
4673 /* Create the "Clear" button */
4674 filter_reset = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLEAR);
4675 OBJECT_SET_DATA(filter_reset, E_DFILTER_TE_KEY, filter_te);
4676 SIGNAL_CONNECT(filter_reset, "clicked", filter_reset_cb, NULL);
4677 gtk_widget_show(filter_reset);
4678 gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_reset,
4679 "Clear this filter string and update the display", "Private");
4681 /* Create the "Apply" button */
4682 filter_apply = BUTTON_NEW_FROM_STOCK(GTK_STOCK_APPLY);
4683 OBJECT_SET_DATA(filter_apply, E_DFILTER_CM_KEY, filter_cm);
4684 SIGNAL_CONNECT(filter_apply, "clicked", filter_activate_cb, filter_te);
4685 gtk_widget_show(filter_apply);
4686 gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_apply,
4687 "Apply this filter string to the display", "Private");
4689 /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
4690 * of any widget that ends up calling a callback which needs
4691 * that text entry pointer */
4692 set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
4693 set_menu_object_data("/Edit/Copy/As Filter", E_DFILTER_TE_KEY,
4695 set_menu_object_data("/Analyze/Display Filters...", E_FILT_TE_PTR_KEY,
4697 set_menu_object_data("/Analyze/Follow TCP Stream", E_DFILTER_TE_KEY,
4699 set_menu_object_data("/Analyze/Follow SSL Stream", E_DFILTER_TE_KEY,
4701 set_menu_object_data("/Analyze/Apply as Filter/Selected", E_DFILTER_TE_KEY,
4703 set_menu_object_data("/Analyze/Apply as Filter/Not Selected", E_DFILTER_TE_KEY,
4705 set_menu_object_data("/Analyze/Apply as Filter/... and Selected", E_DFILTER_TE_KEY,
4707 set_menu_object_data("/Analyze/Apply as Filter/... or Selected", E_DFILTER_TE_KEY,
4709 set_menu_object_data("/Analyze/Apply as Filter/... and not Selected", E_DFILTER_TE_KEY,
4711 set_menu_object_data("/Analyze/Apply as Filter/... or not Selected", E_DFILTER_TE_KEY,
4713 set_menu_object_data("/Analyze/Prepare a Filter/Selected", E_DFILTER_TE_KEY,
4715 set_menu_object_data("/Analyze/Prepare a Filter/Not Selected", E_DFILTER_TE_KEY,
4717 set_menu_object_data("/Analyze/Prepare a Filter/... and Selected", E_DFILTER_TE_KEY,
4719 set_menu_object_data("/Analyze/Prepare a Filter/... or Selected", E_DFILTER_TE_KEY,
4721 set_menu_object_data("/Analyze/Prepare a Filter/... and not Selected", E_DFILTER_TE_KEY,
4723 set_menu_object_data("/Analyze/Prepare a Filter/... or not Selected", E_DFILTER_TE_KEY,
4725 set_menu_object_data("/Conversation Filter/Ethernet", E_DFILTER_TE_KEY,
4727 set_menu_object_data("/Conversation Filter/IP", E_DFILTER_TE_KEY,
4729 set_menu_object_data("/Conversation Filter/TCP", E_DFILTER_TE_KEY,
4731 set_menu_object_data("/Conversation Filter/UDP", E_DFILTER_TE_KEY,
4733 set_menu_object_data("/Conversation Filter/PN-CBA Server", E_DFILTER_TE_KEY,
4735 set_toolbar_object_data(E_DFILTER_TE_KEY, filter_te);
4736 OBJECT_SET_DATA(popup_menu_object, E_DFILTER_TE_KEY, filter_te);
4737 OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_KEY, packet_list);
4739 /* info (main) statusbar */
4740 info_bar = info_bar_new();
4741 gtk_widget_show(info_bar);
4743 /* packets statusbar */
4744 packets_bar = packets_bar_new();
4745 gtk_widget_show(packets_bar);
4747 /* Filter/status hbox */
4748 stat_hbox = gtk_hbox_new(FALSE, 1);
4749 gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
4750 gtk_widget_show(stat_hbox);
4752 /* Pane for the statusbar */
4753 status_pane = gtk_hpaned_new();
4754 gtk_widget_show(status_pane);
4756 /* Pane for the welcome screen */
4757 welcome_pane = welcome_new();
4758 gtk_widget_show(welcome_pane);
4763 driver_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
4767 r = simple_dialog_check_get(dialog);
4768 recent.airpcap_driver_check_show = !r;
4773 show_main_window(gboolean doing_work)
4775 main_set_for_capture_file(doing_work);
4777 /*** we have finished all init things, show the main window ***/
4778 gtk_widget_show(top_level);
4780 /* the window can be maximized only, if it's visible, so do it after show! */
4781 main_load_window_geometry(top_level);
4783 /* process all pending GUI events before continue */
4784 while (gtk_events_pending()) gtk_main_iteration();
4786 /* Pop up any queued-up alert boxes. */
4787 display_queued_messages();
4791 * This will read the decryption keys from the preferences file, and will
4792 * store them into the registry...
4794 if(airpcap_if_list != NULL && g_list_length(airpcap_if_list) > 0){
4795 if (!airpcap_check_decryption_keys(airpcap_if_list)) {
4796 /* Ask the user what to do ...*/
4797 airpcap_keys_check_w(NULL,NULL);
4799 /* Keys from lists are equals, or wireshark has got no keys */
4800 airpcap_load_decryption_keys(airpcap_if_list);
4804 switch (airpcap_dll_ret_val) {
4806 case AIRPCAP_DLL_OK:
4809 case AIRPCAP_DLL_OLD:
4810 if(recent.airpcap_driver_check_show) {
4811 driver_warning_dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s",
4812 "WARNING: The version of AirPcap on this system\n"
4813 "does not support driver-level decryption. Please\n"
4814 "download a more recent version from\n" "http://www.cacetech.com/support/downloads.htm \n");
4815 simple_dialog_check_set(driver_warning_dialog,"Don't show this message again.");
4816 simple_dialog_set_cb(driver_warning_dialog, driver_warning_dialog_cb, (gpointer) driver_warning_dialog);
4822 * XXX - Maybe we need to warn the user if one of the following happens???
4824 case AIRPCAP_DLL_ERROR:
4825 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
4828 case AIRPCAP_DLL_NOT_FOUND:
4829 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
4833 #endif /* HAVE_AIRPCAP */
4836 /* Fill in capture options with values from the preferences */
4838 prefs_to_capture_opts(void)
4841 /* Set promiscuous mode from the preferences setting. */
4842 /* the same applies to other preferences settings as well. */
4843 capture_opts->promisc_mode = prefs.capture_prom_mode;
4844 capture_opts->show_info = prefs.capture_show_info;
4845 capture_opts->real_time_mode = prefs.capture_real_time;
4846 auto_scroll_live = prefs.capture_auto_scroll;
4847 #endif /* HAVE_LIBPCAP */
4849 /* Set the name resolution code's flags from the preferences. */
4850 g_resolv_flags = prefs.name_resolve;