5 * Routines to modify dissector tables on the fly.
7 * By David Hampton <dhampton@mac.com>
8 * Copyright 2001 David Hampton
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32 #include "decode_as_dlg.h"
33 #include "dlg_utils.h"
35 #include "simple_dialog.h"
36 #include <epan/packet.h>
37 #include <epan/ipproto.h>
38 #include "gui_utils.h"
39 #include <epan/epan_dissect.h>
40 #include "compat_macros.h"
41 #include "decode_as_dcerpc.h"
46 /**************************************************/
47 /* Typedefs & Enums */
48 /**************************************************/
51 * Enum used to track which transport layer port menu item is
52 * currently selected in the dialog. These items are labeled "source",
53 * "destination", and "source/destination".
56 /* The "source port" menu item is currently selected. */
58 /* The "destination port" menu item is currently selected. */
60 /* The "source/destination port" menu item is currently selected. */
62 /* For SCTP only. This MUST be the last entry! */
66 #define E_DECODE_MIN_HEIGHT 300
67 #define E_NOTEBOOK "notebook"
69 #define E_MENU_SRCDST "menu_src_dst"
71 #define E_PAGE_DPORT "dport"
72 #define E_PAGE_SPORT "sport"
73 #define E_PAGE_PPID "ppid"
76 * Columns for a "Display" list
78 #define E_LIST_D_TABLE 0
79 #define E_LIST_D_SELECTOR 1
80 #define E_LIST_D_INITIAL 2
81 #define E_LIST_D_CURRENT 3
82 #define E_LIST_D_MAX E_LIST_D_CURRENT
83 #define E_LIST_D_COLUMNS (E_LIST_D_MAX + 1)
85 /**************************************************/
86 /* File Global Variables */
87 /**************************************************/
90 * Keep a static pointer to the current "Decode As" window. This is
91 * kept so that if somebody tries to do "Tools:Decode As" while
92 * there's already a "Decode As" window up, we just pop up the
93 * existing one, rather than creating a new one.
95 static GtkWidget *decode_w = NULL;
98 * A static pointer to the current "Decode As:Show" window. This is
99 * kept so that if somebody tries to do clock the "Show Current"
100 * button or select the "Display:User Specified Decodes" menu item
101 * while there's already a "Decode As:Show" window up, we just pop up
102 * the existing one, rather than creating a new one.
104 static GtkWidget *decode_show_w = NULL;
107 * A list of the dialog items that only have meaning when the user has
108 * selected the "Decode" radio button. When the "Do not decode"
109 * button is selected these items should be dimmed.
111 GSList *decode_dimmable = NULL;
114 * Remember the "action" radio button that is currently selected in
115 * the dialog. This value is initialized when the dialog is created,
116 * modified in a callback routine, and read in the routine that
117 * handles a click in the "OK" button for the dialog.
119 enum action_type requested_action = -1;
122 /**************************************************/
123 /* Global Functions */
124 /**************************************************/
126 /* init this module */
127 void decode_as_init(void) {
129 decode_dcerpc_init();
132 /**************************************************/
133 /* Reset Changed Dissectors */
134 /**************************************************/
137 * Data structure for tracking which dissector need to be reset. This
138 * structure is necessary as a hash table entry cannot be removed
139 * while a g_hash_table_foreach walk is in progress.
141 struct dissector_delete_item {
142 /* The name of the dissector table */
143 const gchar *ddi_table_name;
144 /* The type of the selector in that dissector table */
145 ftenum_t ddi_selector_type;
146 /* The selector in the dissector table */
154 * A typedef for the data structure to track the original dissector
155 * used for any given port on any given protocol.
157 typedef struct dissector_delete_item dissector_delete_item_t;
160 * A list of dissectors that need to be reset.
162 GSList *dissector_reset_list = NULL;
165 * This routine creates one entry in the list of protocol dissector
166 * that need to be reset. It is called by the g_hash_table_foreach
167 * routine once for each changed entry in a dissector table.
168 * Unfortunately it cannot delete the entry immediately as this screws
169 * up the foreach function, so it builds a list of dissectors to be
170 * reset once the foreach routine finishes.
172 * @param table_name The table name in which this dissector is found.
174 * @param key A pointer to the key for this entry in the dissector
175 * hash table. This is generally the numeric selector of the
176 * protocol, i.e. the ethernet type code, IP port number, TCP port
179 * @param value A pointer to the value for this entry in the dissector
180 * hash table. This is an opaque pointer that can only be handed back
181 * to routine in the file packet.c - but it's unused.
183 * @param user_data Unused.
186 decode_build_reset_list (gchar *table_name, ftenum_t selector_type,
187 gpointer key, gpointer value _U_,
188 gpointer user_data _U_)
190 dissector_delete_item_t *item;
192 item = g_malloc(sizeof(dissector_delete_item_t));
193 item->ddi_table_name = table_name;
194 item->ddi_selector_type = selector_type;
195 switch (selector_type) {
201 item->ddi_selector.sel_uint = GPOINTER_TO_UINT(key);
206 item->ddi_selector.sel_string = key;
210 g_assert_not_reached();
212 dissector_reset_list = g_slist_prepend(dissector_reset_list, item);
216 /**************************************************/
217 /* Show Changed Dissectors */
218 /**************************************************/
220 #if GTK_MAJOR_VERSION >= 2
221 #define SORT_ALPHABETICAL 0
224 sort_iter_compare_func (GtkTreeModel *model,
229 gint sortcol = GPOINTER_TO_INT(userdata);
233 case SORT_ALPHABETICAL:
235 gchar *name1, *name2;
236 gtk_tree_model_get(model, a, 0, &name1, -1);
237 gtk_tree_model_get(model, b, 0, &name2, -1);
238 if (name1 == NULL || name2 == NULL)
240 if (name1 == NULL && name2 == NULL)
241 break; /* both equal => ret = 0 */
242 ret = (name1 == NULL) ? -1 : 1;
246 ret = g_ascii_strcasecmp(name1,name2);
253 g_return_val_if_reached(0);
261 decode_add_to_show_list (
263 const gchar *table_name,
264 gchar *selector_name,
265 const gchar *initial_proto_name,
266 const gchar *current_proto_name)
268 const gchar *text[E_LIST_D_COLUMNS];
269 #if GTK_MAJOR_VERSION < 2
277 #if GTK_MAJOR_VERSION < 2
278 clist = (GtkCList *)list_data;
280 store = (GtkListStore *)list_data;
283 text[E_LIST_D_TABLE] = table_name;
284 text[E_LIST_D_SELECTOR] = selector_name;
285 text[E_LIST_D_INITIAL] = initial_proto_name;
286 text[E_LIST_D_CURRENT] = current_proto_name;
287 #if GTK_MAJOR_VERSION < 2
288 row = gtk_clist_prepend(clist, (gchar **) text);
290 gtk_list_store_append(store, &iter);
291 gtk_list_store_set(store, &iter, E_LIST_D_TABLE, text[E_LIST_D_TABLE],
292 E_LIST_D_SELECTOR, text[E_LIST_D_SELECTOR],
293 E_LIST_D_INITIAL, text[E_LIST_D_INITIAL],
294 E_LIST_D_CURRENT, text[E_LIST_D_CURRENT], -1);
300 * This routine creates one entry in the list of protocol dissector
301 * that have been changed. It is called by the g_hash_foreach routine
302 * once for each changed entry in a dissector table.
304 * @param table_name The table name in which this dissector is found.
306 * @param key A pointer to the key for this entry in the dissector
307 * hash table. This is generally the numeric selector of the
308 * protocol, i.e. the ethernet type code, IP port number, TCP port
311 * @param value A pointer to the value for this entry in the dissector
312 * hash table. This is an opaque pointer that can only be handed back
313 * to routine in the file packet.c
315 * @param user_data A pointer to the list in which this information
319 decode_build_show_list (gchar *table_name, ftenum_t selector_type,
320 gpointer key, gpointer value, gpointer user_data)
322 dissector_handle_t current, initial;
323 const gchar *current_proto_name, *initial_proto_name;
324 gchar *selector_name;
330 current = dtbl_entry_get_handle(value);
332 current_proto_name = "(none)";
334 current_proto_name = dissector_handle_get_short_name(current);
335 initial = dtbl_entry_get_initial_handle(value);
337 initial_proto_name = "(none)";
339 initial_proto_name = dissector_handle_get_short_name(initial);
341 switch (selector_type) {
347 switch (get_dissector_table_base(table_name)) {
350 g_snprintf(string1, sizeof(string1), "%u", GPOINTER_TO_UINT(key));
354 switch (get_dissector_table_selector_type(table_name)) {
357 g_snprintf(string1, sizeof(string1), "0x%02x", GPOINTER_TO_UINT(key));
361 g_snprintf(string1, sizeof(string1), "0x%04x", GPOINTER_TO_UINT(key));
365 g_snprintf(string1, sizeof(string1), "0x%06x", GPOINTER_TO_UINT(key));
369 g_snprintf(string1, sizeof(string1), "0x%08x", GPOINTER_TO_UINT(key));
373 g_assert_not_reached();
379 g_snprintf(string1, sizeof(string1), "%#o", GPOINTER_TO_UINT(key));
382 selector_name = string1;
391 g_assert_not_reached();
392 selector_name = NULL;
396 decode_add_to_show_list (
398 get_dissector_table_ui_name(table_name),
405 /* clear all settings */
407 decode_clear_all(void)
409 dissector_delete_item_t *item;
412 dissector_all_tables_foreach_changed(decode_build_reset_list, NULL);
414 for (tmp = dissector_reset_list; tmp; tmp = g_slist_next(tmp)) {
416 switch (item->ddi_selector_type) {
422 dissector_reset(item->ddi_table_name, item->ddi_selector.sel_uint);
427 dissector_reset_string(item->ddi_table_name,
428 item->ddi_selector.sel_string);
432 g_assert_not_reached();
436 g_slist_free(dissector_reset_list);
437 dissector_reset_list = NULL;
439 decode_dcerpc_reset_all();
441 cf_redissect_packets(&cfile);
446 * This routine is called when the user clicks the "OK" button in
447 * the "Decode As:Show..." dialog window. This routine destroys the
448 * dialog box and performs other housekeeping functions.
450 * @param GtkWidget * A pointer to the "OK" button.
452 * @param gpointer A pointer to the dialog window.
455 decode_show_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
457 window_destroy(GTK_WIDGET(parent_w));
462 * This routine is called when the user clicks the "Clear" button in
463 * the "Decode As:Show..." dialog window. This routine resets all the
464 * dissector values and then destroys the dialog box and performs
465 * other housekeeping functions.
467 * @param GtkWidget * A pointer to the "Clear" button.
469 * @param gpointer A pointer to the dialog window.
472 decode_show_clear_cb (GtkWidget *clear_bt _U_, gpointer parent_w)
476 window_destroy(GTK_WIDGET(parent_w));
481 * This routine is called when the user clicks the X at the top right end in
482 * the "Decode As:Show..." dialog window. This routine simply calls the
483 * ok routine as if the user had clicked the ok button.
485 * @param GtkWidget * A pointer to the dialog box.
487 * @param gpointer Unknown
490 decode_show_delete_cb (GtkWidget *decode_w _U_, gpointer dummy _U_)
492 decode_show_ok_cb(NULL, decode_show_w);
498 * This routine is called at the destruction of the "Decode As:Show"
499 * dialog box. It clears the pointer maintained by this file, so that
500 * the next time the user clicks the "Decode As:Show" button a new
501 * dialog box will be created.
503 * @param GtkWidget * A pointer to the dialog box.
505 * @param gpointer Unknown
508 decode_show_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
510 /* Note that we no longer have a "Decode As:Show" dialog box. */
511 decode_show_w = NULL;
516 * This routine creates the "Decode As:Show" dialog box. This dialog box
517 * shows the user which protocols have had their dissectors changed.
520 * @param data Unknown
523 decode_show_cb (GtkWidget * w _U_, gpointer data _U_)
525 GtkWidget *main_vb, *bbox, *ok_bt, *clear_bt, *help_bt, *scrolled_window;
526 const gchar *titles[E_LIST_D_COLUMNS] = {
527 "Table", "Value", "Initial", "Current"
530 #if GTK_MAJOR_VERSION < 2
535 GtkCellRenderer *renderer;
536 GtkTreeViewColumn *tc;
540 if (decode_show_w != NULL) {
541 /* There's already a "Decode As" dialog box; reactivate it. */
542 reactivate_window(decode_show_w);
546 decode_show_w = dlg_window_new("Wireshark: Decode As: Show");
547 /* Provide a minimum of a couple of rows worth of data */
548 gtk_window_set_default_size(GTK_WINDOW(decode_show_w), -1, E_DECODE_MIN_HEIGHT);
550 /* Container for each row of widgets */
551 main_vb = gtk_vbox_new(FALSE, 2);
552 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
553 gtk_container_add(GTK_CONTAINER(decode_show_w), main_vb);
556 /* Initialize list */
557 #if GTK_MAJOR_VERSION < 2
558 list = GTK_CLIST(gtk_clist_new_with_titles(E_LIST_D_COLUMNS, (gchar **) titles));
559 gtk_clist_column_titles_passive(list);
560 for (column = 0; column < E_LIST_D_COLUMNS; column++)
561 gtk_clist_set_column_auto_resize(list, column, TRUE);
562 gtk_clist_set_selection_mode(list, GTK_SELECTION_EXTENDED);
564 store = gtk_list_store_new(E_LIST_D_COLUMNS, G_TYPE_STRING,
565 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
566 list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
567 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
568 gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list), FALSE);
569 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(list),
570 GTK_SELECTION_MULTIPLE);
572 for (column = 0; column < E_LIST_D_COLUMNS; column++) {
573 renderer = gtk_cell_renderer_text_new();
574 tc = gtk_tree_view_column_new_with_attributes(titles[column],
577 gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
578 gtk_tree_view_append_column(list, tc);
583 #if GTK_MAJOR_VERSION < 2
584 dissector_all_tables_foreach_changed(decode_build_show_list, list);
585 gtk_clist_sort(list);
586 decode_dcerpc_add_show_list(list);
588 dissector_all_tables_foreach_changed(decode_build_show_list, store);
589 g_object_unref(G_OBJECT(store));
590 decode_dcerpc_add_show_list(store);
593 /* Put clist into a scrolled window */
594 scrolled_window = scrolled_window_new(NULL, NULL);
595 /* this will result to set the width of the dialog to the required size */
596 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
597 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
598 #if GTK_MAJOR_VERSION >= 2
599 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
602 gtk_container_add(GTK_CONTAINER(scrolled_window),
604 gtk_box_pack_start(GTK_BOX(main_vb), scrolled_window, TRUE, TRUE, 0);
608 if(topic_available(HELP_DECODE_AS_SHOW_DIALOG)) {
609 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CLEAR, GTK_STOCK_HELP, NULL);
611 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CLEAR, NULL);
613 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
614 gtk_widget_show(bbox);
616 ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
617 SIGNAL_CONNECT(ok_bt, "clicked", decode_show_ok_cb, decode_show_w);
619 clear_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLEAR);
620 SIGNAL_CONNECT(clear_bt, "clicked", decode_show_clear_cb, decode_show_w);
622 if(topic_available(HELP_DECODE_AS_SHOW_DIALOG)) {
623 help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
624 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_DECODE_AS_SHOW_DIALOG);
627 /* set ok as default, this button won't change anything */
628 window_set_cancel_button(decode_show_w, ok_bt, NULL);
630 SIGNAL_CONNECT(decode_show_w, "delete_event", decode_show_delete_cb, NULL);
631 SIGNAL_CONNECT(decode_show_w, "destroy", decode_show_destroy_cb, NULL);
633 #if GTK_MAJOR_VERSION < 2
634 gtk_widget_set_sensitive(clear_bt, (list->rows != 0));
636 gtk_widget_set_sensitive(clear_bt,
637 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter));
640 gtk_widget_show_all(decode_show_w);
641 window_present(decode_show_w);
645 /**************************************************/
646 /* Modify the dissector routines */
647 /**************************************************/
650 * Modify a single dissector. This routine first takes care of
651 * updating the internal table of original protocol/port/dissector
652 * combinations by adding a new entry (or removing an existing entry
653 * if the value is being set back to its default). This routine then
654 * performs the actual modification to the packet dissector tables.
656 * @param s Pointer to a string buffer. This buffer is used to build
657 * up a message indicating which ports have had their dissector
658 * changed. This output will be displayed all at once after all
659 * dissectors have been modified.
661 * @param table_name The table name in which the dissector should be
664 * @param selector An enum value indication which selector value
665 * (i.e. IP protocol number, TCP port number, etc.)is to be changed.
667 * @param list The List in which all the selection information can
670 * @return gchar * Pointer to the next free location in the string
674 decode_change_one_dissector(gchar *table_name, guint selector, GtkWidget *list)
676 dissector_handle_t handle;
678 #if GTK_MAJOR_VERSION < 2
681 GtkTreeSelection *selection;
686 #if GTK_MAJOR_VERSION < 2
687 if (!GTK_CLIST(list)->selection)
692 row = GPOINTER_TO_INT(GTK_CLIST(list)->selection->data);
693 handle = gtk_clist_get_row_data(GTK_CLIST(list), row);
694 gtk_clist_get_text(GTK_CLIST(list), row, E_LIST_S_PROTO_NAME, &abbrev);
697 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
698 if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
703 gtk_tree_model_get(model, &iter, E_LIST_S_PROTO_NAME, &abbrev,
704 E_LIST_S_TABLE+1, &handle, -1);
708 if (abbrev != NULL && strcmp(abbrev, "(default)") == 0) {
709 dissector_reset(table_name, selector);
711 dissector_change(table_name, selector, handle);
713 #if GTK_MAJOR_VERSION >= 2
720 /**************************************************/
721 /* Action routines for the "Decode As..." dialog */
722 /* - called when the OK button pressed */
723 /* - one per notebook page */
724 /**************************************************/
729 * Print debugging information about clist selection. Extract all
730 * information from the clist entry that was selected and print it to
733 * @param clist The clist to dump.
735 * @param leadin A string to print at the start of each line.
738 decode_debug (GtkCList *clist, gchar *leadin)
740 gchar *string, *text[E_LIST_S_COLUMNS];
741 dissector_handle_t handle;
744 if (clist->selection) {
745 row = GPOINTER_TO_INT(clist->selection->data);
746 gtk_clist_get_text(clist, row, E_LIST_S_PROTO_NAME, &text[E_LIST_S_PROTO_NAME]);
747 gtk_clist_get_text(clist, row, E_LIST_S_TABLE, &text[E_LIST_S_TABLE]);
748 handle = gtk_clist_get_row_data(clist, row);
749 string = g_strdup_printf("%s clist row %d: <put handle here>, name %s, table %s",
750 leadin, row, text[E_LIST_S_PROTO_NAME],
751 text[E_LIST_S_TABLE]);
753 string = g_strdup_printf("%s clist row (none), aka do not decode", leadin);
755 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, string);
762 * This routine is called when the user clicks the "OK" button in the
763 * "Decode As..." dialog window and a 'simple' page is foremost.
764 * This routine takes care of making any changes requested to the
765 * dissector tables. This routine is currently used for IP and
766 * Ethertypes. Any 'single change' notebook page can use this
769 * @param notebook_pg A pointer to the "network" notebook page.
772 decode_simple (GtkWidget *notebook_pg)
781 list = OBJECT_GET_DATA(notebook_pg, E_PAGE_LIST);
782 if (requested_action == E_DECODE_NO)
783 #if GTK_MAJOR_VERSION < 2
784 gtk_clist_unselect_all(GTK_CLIST(list));
786 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
790 string = OBJECT_GET_DATA(notebook_pg, E_PAGE_TITLE);
791 decode_debug(GTK_CLIST(list), string);
794 table_name = OBJECT_GET_DATA(notebook_pg, E_PAGE_TABLE);
795 value = GPOINTER_TO_UINT(OBJECT_GET_DATA(notebook_pg, E_PAGE_VALUE));
796 decode_change_one_dissector(table_name, value, list);
801 * This routine is called when the user clicks the "OK" button in the
802 * "Decode As..." dialog window and the transport page is foremost.
803 * This routine takes care of making any changes requested to the TCP
804 * or UDP dissector tables.
806 * @param notebook_pg A pointer to the "transport" notebook page.
809 decode_transport(GtkWidget *notebook_pg)
811 GtkWidget *menu, *menuitem;
814 gint requested_srcdst, requested_port, ppid;
817 list = OBJECT_GET_DATA(notebook_pg, E_PAGE_LIST);
818 if (requested_action == E_DECODE_NO)
819 #if GTK_MAJOR_VERSION < 2
820 gtk_clist_unselect_all(GTK_CLIST(list));
822 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
825 menu = OBJECT_GET_DATA(notebook_pg, E_MENU_SRCDST);
827 menuitem = gtk_menu_get_active(GTK_MENU(menu));
828 requested_srcdst = GPOINTER_TO_INT(OBJECT_GET_DATA(menuitem, "user_data"));
831 string = OBJECT_GET_DATA(notebook_pg, E_PAGE_TITLE);
832 decode_debug(GTK_CLIST(list), string);
835 table_name = OBJECT_GET_DATA(notebook_pg, E_PAGE_TABLE);
836 if (requested_srcdst >= E_DECODE_PPID) {
837 if (requested_srcdst == E_DECODE_PPID)
840 if (requested_srcdst - E_DECODE_PPID - 1 < MAX_NUMBER_OF_PPIDS)
841 ppid = cfile.edt->pi.ppid[requested_srcdst - E_DECODE_PPID - 1];
844 decode_change_one_dissector(table_name, ppid, list);
847 if (requested_srcdst != E_DECODE_DPORT) {
848 portp = OBJECT_GET_DATA(notebook_pg, E_PAGE_SPORT);
850 requested_port = GPOINTER_TO_INT(portp);
851 decode_change_one_dissector(table_name, requested_port, list);
854 if (requested_srcdst != E_DECODE_SPORT) {
855 portp = OBJECT_GET_DATA(notebook_pg, E_PAGE_DPORT);
857 requested_port = GPOINTER_TO_INT(portp);
858 decode_change_one_dissector(table_name, requested_port, list);
864 /**************************************************/
865 /* Signals from the "Decode As..." dialog */
866 /**************************************************/
869 * This routine is called when the user clicks the "OK" button in the
870 * "Decode As..." dialog window. This routine calls various helper
871 * routines to set/clear dissector values as requested by the user.
872 * These routines accumulate information on what actions they have
873 * taken, and this summary information is printed by this routine.
874 * This routine then destroys the dialog box and performs other
875 * housekeeping functions.
877 * @param ok_bt A pointer to the "OK" button.
879 * @param parent_w A pointer to the dialog window.
882 decode_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
884 GtkWidget *notebook, *notebook_pg;
885 void (* func)(GtkWidget *);
887 void *binding = NULL;
889 /* Call the right routine for the page that was currently in front. */
890 notebook = OBJECT_GET_DATA(parent_w, E_NOTEBOOK);
891 page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
892 notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
894 func = OBJECT_GET_DATA(notebook_pg, E_PAGE_ACTION);
897 /* Now destroy the "Decode As" dialog. */
898 notebook_pg = OBJECT_GET_DATA(parent_w, E_PAGE_DCERPC);
900 binding = OBJECT_GET_DATA(notebook_pg, E_PAGE_BINDING);
903 decode_dcerpc_binding_free(binding);
905 window_destroy(GTK_WIDGET(parent_w));
906 g_slist_free(decode_dimmable);
907 decode_dimmable = NULL;
909 cf_redissect_packets(&cfile);
913 * This routine is called when the user clicks the "Apply" button in the
914 * "Decode As..." dialog window. This routine calls various helper
915 * routines to set/clear dissector values as requested by the user.
916 * These routines accumulate information on what actions they have
917 * taken, and this summary information is printed by this routine.
919 * @param apply_bt A pointer to the "Apply" button.
921 * @param parent_w A pointer to the dialog window.
924 decode_apply_cb (GtkWidget *apply_bt _U_, gpointer parent_w)
926 GtkWidget *notebook, *notebook_pg;
927 void (* func)(GtkWidget *);
930 /* Call the right routine for the page that was currently in front. */
931 notebook = OBJECT_GET_DATA(parent_w, E_NOTEBOOK);
932 page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
933 notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
935 func = OBJECT_GET_DATA(notebook_pg, E_PAGE_ACTION);
938 cf_redissect_packets(&cfile);
942 * This routine is called when the user clicks the "Close" button in
943 * the "Decode As..." dialog window. This routine then destroys the
944 * dialog box and performs other housekeeping functions.
946 * @param close_bt A pointer to the "Close" button.
948 * @param parent_w A pointer to the dialog window.
951 decode_close_cb (GtkWidget *close_bt _U_, gpointer parent_w)
953 GtkWidget *notebook_pg = NULL;
954 void *binding = NULL;
957 notebook_pg = OBJECT_GET_DATA(parent_w, E_PAGE_DCERPC);
959 binding = OBJECT_GET_DATA(notebook_pg, E_PAGE_BINDING);
962 decode_dcerpc_binding_free(binding);
964 window_destroy(GTK_WIDGET(parent_w));
965 g_slist_free(decode_dimmable);
966 decode_dimmable = NULL;
971 * This routine is called when the user clicks the "Close" button in
972 * the "Decode As..." dialog window. This routine simply calls the
973 * close routine as if the user had clicked the close button instead
974 * of the close button.
976 * @param decode_w A pointer to the dialog box.
978 * @param dummy Unknown
981 decode_delete_cb (GtkWidget *decode_w, gpointer dummy _U_)
983 decode_close_cb(NULL, decode_w);
989 * This routine is called at the destruction of the "Decode As..."
990 * dialog box. It clears the pointer maintained by this file, so that
991 * the next time the user selects the "Decode As..." menu item a new
992 * dialog box will be created.
994 * @param decode_w A pointer to the dialog box.
996 * @param user_data Unknown
1001 decode_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
1003 /* Note that we no longer have a "Decode As" dialog box. */
1009 * This routine is called when the user clicks the "Clear" button in
1010 * the "Decode As..." dialog window. This routine resets all the
1011 * dissector values and performs other housekeeping functions.
1013 * @param GtkWidget * A pointer to the "Clear" button.
1014 * @param gpointer A pointer to the dialog window.
1017 decode_clear_cb(GtkWidget *clear_bt _U_, gpointer parent_w _U_)
1024 /**************************************************/
1025 /* Dialog setup - radio buttons */
1026 /**************************************************/
1029 * Update the requested action field of the dialog. This routine is
1030 * called by GTK when either of the two radio buttons in the dialog is
1033 * @param w The radio button that was clicked.
1035 * @param data The enum value assigned to this radio button. This
1036 * will be either E_DECODE_YES or E_DECODE_NO
1039 decode_update_action (GtkWidget *w _U_, gpointer data)
1044 requested_action = GPOINTER_TO_INT(data);
1045 enable = (requested_action == E_DECODE_YES);
1046 for (tmp = decode_dimmable; tmp; tmp = g_slist_next(tmp)) {
1047 gtk_widget_set_sensitive(tmp->data, enable);
1052 * This routine is called to create the "Decode" and "Do not decode"
1053 * radio buttons. These buttons are installed into a vbox, and set up
1054 * as a format group.
1056 * @return GtkWidget * A pointer to the vbox containing the buttons
1059 decode_add_yes_no (void)
1061 GtkWidget *format_vb, *radio_button;
1064 format_vb = gtk_vbox_new(FALSE, 2);
1066 radio_button = gtk_radio_button_new_with_label(NULL, "Decode");
1067 format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
1068 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1069 SIGNAL_CONNECT(radio_button, "clicked", decode_update_action,
1070 GINT_TO_POINTER(E_DECODE_YES));
1071 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1073 radio_button = gtk_radio_button_new_with_label(format_grp, "Do not decode");
1074 format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
1075 SIGNAL_CONNECT(radio_button, "clicked", decode_update_action,
1076 GINT_TO_POINTER(E_DECODE_NO));
1077 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1082 /**************************************************/
1083 /* Dialog setup - simple menus */
1084 /**************************************************/
1087 * This routine is called to pack an option menu into an aligment, so
1088 * that it doesn't expand vertically to fill up the space available to
1091 * @param optmenu A pointer to the option menu to be so packed.
1093 * @return GtkWidget * A pointer to the newly created alignment.
1096 decode_add_pack_menu (GtkWidget *optmenu)
1098 GtkWidget *alignment;
1100 alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
1101 gtk_container_add(GTK_CONTAINER(alignment), optmenu);
1108 * This routine is called to add the transport port selection menu to
1109 * the dialog box. This is a three choice menu: source, destination
1110 * and both. The default choice for the menu is set to the source
1111 * port number of the currently selected packet.
1113 * @param page A pointer notebook page that will contain all
1114 * widgets created by this routine.
1116 * @return GtkWidget * A pointer to the newly created alignment into
1117 * which we've packed the newly created option menu.
1120 decode_add_srcdst_menu (GtkWidget *page)
1122 GtkWidget *optmenu, *menu, *menuitem, *alignment;
1125 optmenu = gtk_option_menu_new();
1126 menu = gtk_menu_new();
1127 g_snprintf(tmp, 100, "source (%u)", cfile.edt->pi.srcport);
1128 menuitem = gtk_menu_item_new_with_label(tmp);
1129 OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_SPORT));
1130 gtk_menu_append(GTK_MENU(menu), menuitem);
1131 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1133 g_snprintf(tmp, 100, "destination (%u)", cfile.edt->pi.destport);
1134 menuitem = gtk_menu_item_new_with_label(tmp);
1135 OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_DPORT));
1136 gtk_menu_append(GTK_MENU(menu), menuitem);
1137 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1139 menuitem = gtk_menu_item_new_with_label("both");
1140 OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_BPORT));
1141 gtk_menu_append(GTK_MENU(menu), menuitem);
1142 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1144 OBJECT_SET_DATA(page, E_MENU_SRCDST, menu);
1145 gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
1146 OBJECT_SET_DATA(page, E_PAGE_SPORT, GINT_TO_POINTER(cfile.edt->pi.srcport));
1147 OBJECT_SET_DATA(page, E_PAGE_DPORT, GINT_TO_POINTER(cfile.edt->pi.destport));
1149 alignment = decode_add_pack_menu(optmenu);
1155 decode_add_ppid_menu (GtkWidget *page)
1157 GtkWidget *optmenu, *menu, *menuitem;
1159 guint number_of_ppid;
1161 optmenu = gtk_option_menu_new();
1162 menu = gtk_menu_new();
1164 g_snprintf(tmp, 100, "PPID (%u)", 0);
1165 menuitem = gtk_menu_item_new_with_label(tmp);
1166 OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_PPID));
1167 gtk_menu_append(GTK_MENU(menu), menuitem);
1168 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1170 for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++)
1171 if (cfile.edt->pi.ppid[number_of_ppid] != 0) {
1172 g_snprintf(tmp, 100, "PPID (%u)", cfile.edt->pi.ppid[number_of_ppid]);
1173 menuitem = gtk_menu_item_new_with_label(tmp);
1174 OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_PPID + 1 + number_of_ppid));
1175 gtk_menu_append(GTK_MENU(menu), menuitem);
1176 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1180 OBJECT_SET_DATA(page, E_MENU_SRCDST, menu);
1181 gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
1186 /*************************************************/
1187 /* Dialog setup - list based menus */
1188 /*************************************************/
1190 #if GTK_MAJOR_VERSION >= 2
1191 struct handle_lookup_info {
1192 dissector_handle_t handle;
1197 lookup_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
1200 dissector_handle_t handle;
1201 struct handle_lookup_info *hli = (struct handle_lookup_info *)data;
1203 gtk_tree_model_get(model, iter, E_LIST_S_TABLE+1, &handle, -1);
1204 if (hli->handle == handle) {
1213 * This routine creates one entry in the list of protocol dissector
1214 * that can be used. It is called by the dissector_table_foreach_handle
1215 * routine once for each entry in a dissector table's list of handles
1216 * for dissectors that could be used in that table. It guarantees unique
1217 * entries by iterating over the list of entries build up to this point,
1218 * looking for a duplicate name. If there is no duplicate, then this
1219 * entry is added to the list of possible dissectors.
1221 * @param table_name The name of the dissector table currently
1224 * @param value The dissector handle for this entry. This is an opaque
1225 * pointer that can only be handed back to routines in the file packet.c
1227 * @param user_data A data block passed into each instance of this
1228 * routine. It contains information from the caller of the foreach
1229 * routine, specifying information about the dissector table and where
1230 * to store any information generated by this routine.
1233 decode_add_to_list (const gchar *table_name, const gchar *proto_name, gpointer value, gpointer user_data)
1235 const gchar *text[E_LIST_S_COLUMNS];
1236 #if GTK_MAJOR_VERSION < 2
1241 GtkListStore *store;
1243 struct handle_lookup_info hli;
1246 g_assert(user_data);
1251 #if GTK_MAJOR_VERSION < 2
1252 row = gtk_clist_find_row_from_data(list, value);
1253 /* We already have an entry for this handle.
1254 * XXX - will this ever happen? */
1255 if (row != -1) return;
1259 store = GTK_LIST_STORE(gtk_tree_view_get_model(list));
1260 gtk_tree_model_foreach(GTK_TREE_MODEL(store), lookup_handle, &hli);
1261 /* We already have an entry for this handle.
1262 * XXX - will this ever happen? */
1263 if (hli.found) return;
1266 text[E_LIST_S_PROTO_NAME] = proto_name;
1267 text[E_LIST_S_TABLE] = table_name;
1268 #if GTK_MAJOR_VERSION < 2
1269 row = gtk_clist_prepend(list, (gchar **) text);
1270 gtk_clist_set_row_data(list, row, value);
1272 gtk_list_store_append(store, &iter);
1273 gtk_list_store_set(store, &iter,
1274 E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1275 E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1276 E_LIST_S_TABLE+1, value, -1);
1281 decode_proto_add_to_list (const gchar *table_name, gpointer value, gpointer user_data)
1283 const gchar *proto_name;
1285 dissector_handle_t handle;
1289 proto_name = dissector_handle_get_short_name(handle);
1291 i = dissector_handle_get_protocol_index(handle);
1292 if (i >= 0 && !proto_is_protocol_enabled(find_protocol_by_id(i)))
1295 decode_add_to_list (table_name, proto_name, value, user_data);
1300 * This routine starts the creation of a List on a notebook page. It
1301 * creates both a scrolled window and a list, adds the list to the
1302 * window, and attaches the list as a data object on the page.
1304 * @param page A pointer to the notebook page being created.
1306 * @param list_p Will be filled in with the address of a newly
1309 * @param scrolled_win_p Will be filled in with the address of a newly
1310 * created GtkScrolledWindow.
1313 decode_list_menu_start(GtkWidget *page, GtkWidget **list_p,
1314 GtkWidget **scrolled_win_p)
1316 #if GTK_MAJOR_VERSION < 2
1317 gchar *titles[E_LIST_S_COLUMNS] = {"Short Name", "Table Name"};
1322 GtkListStore *store;
1323 GtkCellRenderer *renderer;
1324 GtkTreeViewColumn *tc;
1325 GtkTreeSortable *sortable;
1328 #if GTK_MAJOR_VERSION < 2
1329 list = GTK_CLIST(gtk_clist_new_with_titles(E_LIST_S_COLUMNS, titles));
1331 OBJECT_SET_DATA(decode_w, "sctp_list", list);
1332 gtk_clist_column_titles_passive(list);
1334 gtk_clist_column_titles_hide(list);
1335 for (column = 1; column < E_LIST_S_COLUMNS; column++)
1336 gtk_clist_set_column_visibility (list, column, FALSE);
1338 for (column = 0; column < E_LIST_S_COLUMNS; column++)
1339 gtk_clist_set_column_auto_resize(list, column, TRUE);
1340 OBJECT_SET_DATA(page, E_PAGE_LIST, list);
1342 store = gtk_list_store_new(E_LIST_S_COLUMNS+1, G_TYPE_STRING,
1343 G_TYPE_STRING, G_TYPE_POINTER);
1344 OBJECT_SET_DATA(G_OBJECT(decode_w), "sctp_data", store);
1345 list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
1346 sortable = GTK_TREE_SORTABLE(store);
1347 gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
1348 gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
1349 gtk_tree_view_set_headers_clickable(list, FALSE);
1351 gtk_tree_view_set_headers_visible(list, FALSE);
1353 renderer = gtk_cell_renderer_text_new();
1354 tc = gtk_tree_view_column_new_with_attributes("Short Name", renderer,
1355 "text", E_LIST_S_PROTO_NAME,
1357 gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1358 gtk_tree_view_append_column(list, tc);
1359 g_object_set_data(G_OBJECT(page), E_PAGE_LIST, list);
1362 *scrolled_win_p = scrolled_window_new(NULL, NULL);
1363 /* this will result to set the width of the dialog to the required size */
1364 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1365 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1366 #if GTK_MAJOR_VERSION >= 2
1367 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1370 #if GTK_MAJOR_VERSION < 2
1371 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1374 gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
1377 *list_p = GTK_WIDGET(list);
1381 * This routine finishes the creation of a List on a notebook page.
1382 * It adds the default entry, sets the default entry as the
1383 * highlighted entry, and sorts the List.
1385 * @param list A pointer the the List to finish.
1388 decode_list_menu_finish(GtkWidget *list)
1390 const gchar *text[E_LIST_S_COLUMNS];
1391 #if GTK_MAJOR_VERSION < 2
1394 GtkListStore *store;
1398 text[E_LIST_S_PROTO_NAME] = "(default)";
1399 text[E_LIST_S_TABLE] = "(none)";
1400 #if GTK_MAJOR_VERSION < 2
1401 row = gtk_clist_prepend(GTK_CLIST(list), (gchar **) text);
1402 gtk_clist_set_row_data(GTK_CLIST(list), row, NULL);
1404 gtk_clist_select_row(GTK_CLIST(list), 0, -1);
1405 gtk_clist_sort(GTK_CLIST(list));
1407 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
1408 gtk_list_store_prepend(store, &iter);
1409 gtk_list_store_set(store, &iter,
1410 E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1411 E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1412 E_LIST_S_TABLE+1, NULL, -1);
1414 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), &iter);
1419 * This routine is called to add the dissector selection list to a
1420 * notebook page. This scrolled list contains an entry labeled
1421 * "default", and an entry for each protocol that has had a dissector
1422 * registered. The default choice for the list is set to the
1423 * "default" choice, which will return the protocol/port selections to
1424 * their original dissector(s).
1426 * @param page A pointer to the notebook page currently being created.
1428 * @param table_name The name of the dissector table to use to build
1431 * @return GtkWidget * A pointer to the newly created list within a
1435 decode_add_simple_menu (GtkWidget *page, const gchar *table_name)
1437 GtkWidget *scrolled_window;
1440 decode_list_menu_start(page, &list, &scrolled_window);
1441 dissector_table_foreach_handle(table_name, decode_proto_add_to_list, list);
1442 decode_list_menu_finish(list);
1443 return(scrolled_window);
1447 /**************************************************/
1449 /**************************************************/
1452 * This routine creates a sample notebook page in the dialog box.
1453 * This notebook page provides a prompt specifying what is being
1454 * changed and its current value (e.g. "IP Protocol number (17)"), and
1455 * a list specifying all the available choices. The list of choices
1456 * is conditionally enabled, based upon the setting of the
1457 * "decode"/"do not decode" radio buttons.
1459 * @param prompt The prompt for this notebook page
1461 * @param title A title for this page to use when debugging.
1463 * @param table_name The name of the dissector table to use to
1466 * @param value The protocol/port value that is to be changed.
1468 * @return GtkWidget * A pointer to the notebook page created by this
1472 decode_add_simple_page (const gchar *prompt, const gchar *title, const gchar *table_name,
1475 GtkWidget *page, *label, *scrolled_window;
1477 page = gtk_hbox_new(FALSE, 5);
1478 OBJECT_SET_DATA(page, E_PAGE_ACTION, decode_simple);
1479 OBJECT_SET_DATA(page, E_PAGE_TABLE, (gchar *) table_name);
1480 OBJECT_SET_DATA(page, E_PAGE_TITLE, (gchar *) title);
1481 OBJECT_SET_DATA(page, E_PAGE_VALUE, GUINT_TO_POINTER(value));
1483 /* Always enabled */
1484 label = gtk_label_new(prompt);
1485 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1487 /* Conditionally enabled - only when decoding packets */
1488 label = gtk_label_new("as");
1489 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1490 decode_dimmable = g_slist_prepend(decode_dimmable, label);
1491 scrolled_window = decode_add_simple_menu(page, table_name);
1492 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1493 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1500 * This routine creates the TCP or UDP notebook page in the dialog box.
1501 * All items created by this routine are packed into a single
1502 * horizontal box. First is a label indicating whether the port(s) for
1503 * which the user can set the dissection is a TCP port or a UDP port.
1504 * Second is a menu allowing the user to select whether the source port,
1505 * destination port, or both ports will have dissectors added for them.
1506 * Last is a (conditionally enabled) popup menu listing all possible
1507 * dissectors that can be used to decode the packets, and the choice
1508 * or returning to the default dissector for these ports.
1510 * The defaults for these items are the transport layer protocol of
1511 * the currently selected packet, the source port of the currently
1512 * selected packet, and the "default dissector".
1514 * @param prompt The prompt for this notebook page
1516 * @param table_name The name of the dissector table to use to
1519 * @return GtkWidget * A pointer to the notebook page created by
1523 decode_add_tcpudp_page (const gchar *prompt, const gchar *table_name)
1525 GtkWidget *page, *label, *scrolled_window, *optmenu;
1527 page = gtk_hbox_new(FALSE, 5);
1528 OBJECT_SET_DATA(page, E_PAGE_ACTION, decode_transport);
1529 OBJECT_SET_DATA(page, E_PAGE_TABLE, (gchar *) table_name);
1530 OBJECT_SET_DATA(page, E_PAGE_TITLE, "Transport");
1532 /* Always enabled */
1533 label = gtk_label_new(prompt);
1534 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1535 optmenu = decode_add_srcdst_menu(page);
1536 gtk_box_pack_start(GTK_BOX(page), optmenu, TRUE, TRUE, 0);
1537 label = gtk_label_new("port(s)");
1538 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1540 /* Conditionally enabled - only when decoding packets */
1541 label = gtk_label_new("as");
1542 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1543 decode_dimmable = g_slist_prepend(decode_dimmable, label);
1544 scrolled_window = decode_add_simple_menu(page, table_name);
1545 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1546 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1552 decode_sctp_list_menu_start(GtkWidget **list_p, GtkWidget **scrolled_win_p)
1554 #if GTK_MAJOR_VERSION < 2
1555 /* gchar *titles[E_LIST_S_COLUMNS] = {"Short Name", "Table Name"};*/
1560 GtkListStore *sctp_store;
1561 GtkCellRenderer *renderer;
1562 GtkTreeViewColumn *tc;
1563 GtkTreeSortable *sortable;
1566 #if GTK_MAJOR_VERSION < 2
1567 list=OBJECT_GET_DATA(decode_w, "sctp_list");
1568 gtk_clist_column_titles_passive(list);
1570 gtk_clist_column_titles_hide(list);
1571 for (column = 1; column < E_LIST_S_COLUMNS; column++)
1572 gtk_clist_set_column_visibility (list, column, FALSE);
1574 for (column = 0; column < E_LIST_S_COLUMNS; column++)
1575 gtk_clist_set_column_auto_resize(list, column, TRUE);
1577 sctp_store = OBJECT_GET_DATA(decode_w, "sctp_data");
1578 list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(sctp_store)));
1579 sortable = GTK_TREE_SORTABLE(sctp_store);
1580 gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
1581 gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
1582 gtk_tree_view_set_headers_clickable(list, FALSE);
1584 gtk_tree_view_set_headers_visible(list, FALSE);
1586 renderer = gtk_cell_renderer_text_new();
1587 tc = gtk_tree_view_column_new_with_attributes("Short Name", renderer,
1588 "text", E_LIST_S_PROTO_NAME,
1590 gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1591 gtk_tree_view_append_column(list, tc);
1594 *scrolled_win_p = scrolled_window_new(NULL, NULL);
1595 /* this will result to set the width of the dialog to the required size */
1596 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1597 #if GTK_MAJOR_VERSION >= 2
1598 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p), GTK_SHADOW_IN);
1599 gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
1601 *list_p = GTK_WIDGET(list);
1605 decode_sctp_update_ppid_menu(GtkWidget *w _U_, GtkWidget *page)
1607 GtkWidget *menu, *menuitem, *list, *scrolled_window, *sctpmenu;
1609 guint number_of_ppid;
1610 #if GTK_MAJOR_VERSION < 2
1611 GtkCList *sctp_list;
1613 GtkListStore *sctp_store;
1616 menu = gtk_menu_new();
1618 g_snprintf(tmp, 100, "PPID (%u)", 0);
1619 menuitem = gtk_menu_item_new_with_label(tmp);
1620 OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_PPID));
1621 gtk_menu_append(GTK_MENU(menu), menuitem);
1622 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1623 for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++)
1624 if (cfile.edt->pi.ppid[number_of_ppid] != 0) {
1625 g_snprintf(tmp, 100, "PPID (%u)", cfile.edt->pi.ppid[number_of_ppid]);
1626 menuitem = gtk_menu_item_new_with_label(tmp);
1627 OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_PPID + 1 + number_of_ppid));
1628 gtk_menu_append(GTK_MENU(menu), menuitem);
1629 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1633 OBJECT_SET_DATA(page, E_MENU_SRCDST, menu);
1634 OBJECT_SET_DATA(page, E_PAGE_TABLE, "sctp.ppi");
1635 sctpmenu = OBJECT_GET_DATA(decode_w, "user_data");
1636 gtk_option_menu_set_menu(GTK_OPTION_MENU(sctpmenu), menu);
1638 #if GTK_MAJOR_VERSION < 2
1639 sctp_list = OBJECT_GET_DATA(decode_w, "sctp_list");
1640 gtk_clist_clear(sctp_list);
1642 sctp_store = OBJECT_GET_DATA(G_OBJECT(decode_w), "sctp_data");
1643 gtk_list_store_clear(sctp_store);
1645 decode_sctp_list_menu_start(&list, &scrolled_window);
1646 dissector_table_foreach_handle("sctp.ppi", decode_proto_add_to_list, list);
1647 decode_list_menu_finish(list);
1652 decode_sctp_update_srcdst_menu(GtkWidget *w _U_, GtkWidget *page)
1654 GtkWidget *menu, *menuitem, *scrolled_window, *list, *sctpmenu;
1656 #if GTK_MAJOR_VERSION < 2
1657 GtkCList *sctp_list;
1659 GtkListStore *sctp_store;
1662 menu = gtk_menu_new();
1663 g_snprintf(tmp, 100, "source (%u)", cfile.edt->pi.srcport);
1664 menuitem = gtk_menu_item_new_with_label(tmp);
1665 OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_SPORT));
1666 gtk_menu_append(GTK_MENU(menu), menuitem);
1667 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1669 g_snprintf(tmp, 100, "destination (%u)", cfile.edt->pi.destport);
1670 menuitem = gtk_menu_item_new_with_label(tmp);
1671 OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_DPORT));
1672 gtk_menu_append(GTK_MENU(menu), menuitem);
1673 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1675 menuitem = gtk_menu_item_new_with_label("both");
1676 OBJECT_SET_DATA(menuitem, "user_data", GINT_TO_POINTER(E_DECODE_BPORT));
1677 gtk_menu_append(GTK_MENU(menu), menuitem);
1678 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1680 OBJECT_SET_DATA(page, E_MENU_SRCDST, menu);
1681 OBJECT_SET_DATA(page, E_PAGE_TABLE, "sctp.port");
1682 sctpmenu = OBJECT_GET_DATA(decode_w, "user_data");
1683 gtk_option_menu_set_menu(GTK_OPTION_MENU(sctpmenu), menu);
1684 OBJECT_SET_DATA(page, E_PAGE_SPORT, GINT_TO_POINTER(cfile.edt->pi.srcport));
1685 OBJECT_SET_DATA(page, E_PAGE_DPORT, GINT_TO_POINTER(cfile.edt->pi.destport));
1686 #if GTK_MAJOR_VERSION < 2
1687 sctp_list = OBJECT_GET_DATA(decode_w, "sctp_list");
1688 gtk_clist_clear(sctp_list);
1690 sctp_store = OBJECT_GET_DATA(G_OBJECT(decode_w), "sctp_data");
1691 gtk_list_store_clear(sctp_store);
1693 decode_sctp_list_menu_start(&list, &scrolled_window);
1694 dissector_table_foreach_handle("sctp.port", decode_proto_add_to_list, list);
1695 decode_list_menu_finish(list);
1701 decode_sctp_add_port_ppid (GtkWidget *page)
1703 GtkWidget *format_vb, *radio_button;
1706 format_vb = gtk_vbox_new(FALSE, 2);
1708 radio_button = gtk_radio_button_new_with_label(NULL, "PPID");
1709 format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
1710 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1711 SIGNAL_CONNECT(radio_button, "clicked", decode_sctp_update_ppid_menu, page);
1713 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1715 radio_button = gtk_radio_button_new_with_label(format_grp, "Port");
1716 format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
1717 SIGNAL_CONNECT(radio_button, "clicked", decode_sctp_update_srcdst_menu, page);
1719 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1726 decode_add_sctp_page (const gchar *prompt, const gchar *table_name)
1728 GtkWidget *page, *label, *scrolled_window, *radio, *vbox, *alignment, *sctpbox, *sctpmenu;
1730 page = gtk_hbox_new(FALSE, 5);
1731 OBJECT_SET_DATA(page, E_PAGE_ACTION, decode_transport);
1732 OBJECT_SET_DATA(page, E_PAGE_TABLE, (gchar *) table_name);
1733 OBJECT_SET_DATA(page, E_PAGE_TITLE, "Transport");
1735 vbox = gtk_vbox_new(FALSE, 5);
1736 radio = decode_sctp_add_port_ppid(page);
1737 gtk_box_pack_start(GTK_BOX(vbox), radio, TRUE, TRUE, 0);
1739 /* Always enabled */
1740 sctpbox = gtk_hbox_new(FALSE, 5);
1741 label = gtk_label_new(prompt);
1742 gtk_box_pack_start(GTK_BOX(sctpbox), label, TRUE, TRUE, 0);
1743 sctpmenu = decode_add_ppid_menu(page);
1744 OBJECT_SET_DATA(decode_w, "user_data", sctpmenu);
1745 alignment = decode_add_pack_menu(sctpmenu);
1747 gtk_box_pack_start(GTK_BOX(sctpbox), alignment, TRUE, TRUE, 0);
1749 /* Conditionally enabled - only when decoding packets */
1750 label = gtk_label_new("as");
1751 gtk_box_pack_start(GTK_BOX(sctpbox), label, TRUE, TRUE, 0);
1752 decode_dimmable = g_slist_prepend(decode_dimmable, label);
1753 gtk_box_pack_start(GTK_BOX(vbox), sctpbox, TRUE, TRUE, 0);
1754 gtk_box_pack_start(GTK_BOX(page), vbox, TRUE, TRUE, 0);
1756 scrolled_window = decode_add_simple_menu(page, table_name);
1757 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1758 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1765 * This routine indicates whether we'd actually have any pages in the
1766 * notebook in a "Decode As" dialog box; if there wouldn't be, we
1767 * inactivate the menu item for "Decode As".
1772 return cfile.edt->pi.ethertype || cfile.edt->pi.ipproto ||
1773 cfile.edt->pi.ptype == PT_TCP || cfile.edt->pi.ptype == PT_UDP;
1778 * This routine creates the bulk of the "Decode As" dialog box. All
1779 * items created by this routine are packed as pages into a notebook.
1780 * There will be a page for each protocol layer that can be change.
1782 * @param GtkWidget * A pointer to the widget in which the notebook
1783 * should be installed.
1786 decode_add_notebook (GtkWidget *format_hb)
1788 GtkWidget *notebook, *page, *label;
1791 /* Start a nootbook for flipping between sets of changes */
1792 notebook = gtk_notebook_new();
1793 gtk_container_add(GTK_CONTAINER(format_hb), notebook);
1794 OBJECT_SET_DATA(decode_w, E_NOTEBOOK, notebook);
1796 /* Add link level selection page */
1797 if (cfile.edt->pi.ethertype) {
1798 g_snprintf(buffer, 40, "Ethertype 0x%04x", cfile.edt->pi.ethertype);
1799 page = decode_add_simple_page(buffer, "Link", "ethertype", cfile.edt->pi.ethertype);
1800 label = gtk_label_new("Link");
1801 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1804 /* Add network selection page */
1805 if (cfile.edt->pi.ipproto) {
1807 * The network-layer protocol is IP.
1809 g_snprintf(buffer, 40, "IP protocol %u", cfile.edt->pi.ipproto);
1810 page = decode_add_simple_page(buffer, "Network", "ip.proto", cfile.edt->pi.ipproto);
1811 OBJECT_SET_DATA(page, E_PAGE_ACTION, decode_simple);
1812 label = gtk_label_new("Network");
1813 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1816 /* Add transport selection page */
1817 switch (cfile.edt->pi.ptype) {
1820 page = decode_add_tcpudp_page("TCP", "tcp.port");
1824 page = decode_add_tcpudp_page("UDP", "udp.port");
1828 page = decode_add_sctp_page("SCTP", "sctp.ppi");
1836 label = gtk_label_new("Transport");
1837 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1840 if(cfile.edt->pi.dcetransporttype != -1) {
1841 page = decode_dcerpc_add_page(&cfile.edt->pi);
1842 label = gtk_label_new("DCE-RPC");
1843 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1844 OBJECT_SET_DATA(decode_w, E_PAGE_DCERPC, page);
1847 /* Select the last added page (selects first by default) */
1848 /* Notebook must be visible for set_page to work. */
1849 gtk_widget_show_all(notebook);
1850 gtk_notebook_set_page(GTK_NOTEBOOK(notebook), -1);
1856 * This routine creates the "Decode As" dialog box. This dialog box
1857 * asks the user which protocol to use for decoding the currently
1858 * selected packet. This will affect the last packet that we called a
1859 * dissection routine on belongs (this might be the most recently
1860 * selected packet, or it might be the last packet in the file).
1862 * This routine uses an auxiliary function to create the bulk of the
1863 * dialog box, and then hand crafts the button box at the bottom of
1867 * @param data Unknown
1870 decode_as_cb (GtkWidget * w _U_, gpointer data _U_)
1872 GtkWidget *main_vb, *format_hb, *bbox, *ok_bt, *close_bt, *help_bt, *button;
1873 GtkWidget *button_vb, *apply_bt;
1874 GtkTooltips *tooltips = gtk_tooltips_new();
1876 if (decode_w != NULL) {
1877 /* There's already a "Decode As" dialog box; reactivate it. */
1878 reactivate_window(decode_w);
1882 requested_action = E_DECODE_YES;
1883 decode_w = dlg_window_new("Wireshark: Decode As");
1884 /* Provide a minimum of a couple of rows worth of data */
1885 gtk_window_set_default_size(GTK_WINDOW(decode_w), -1, E_DECODE_MIN_HEIGHT);
1887 /* Container for each row of widgets */
1888 main_vb = gtk_vbox_new(FALSE, 2);
1889 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1890 gtk_container_add(GTK_CONTAINER(decode_w), main_vb);
1892 /* First row - Buttons and Notebook */
1894 format_hb = gtk_hbox_new(FALSE, 5);
1895 gtk_box_pack_start(GTK_BOX(main_vb), format_hb, TRUE, TRUE, 10);
1897 button_vb = decode_add_yes_no();
1898 gtk_box_pack_start(GTK_BOX(format_hb), button_vb, TRUE, TRUE, 10);
1900 button = gtk_button_new_with_label("Show Current");
1901 SIGNAL_CONNECT(button, "clicked", decode_show_cb, decode_w);
1902 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1903 gtk_box_pack_start(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1904 gtk_tooltips_set_tip(tooltips, button,
1905 "Open a dialog showing the current settings.", NULL);
1907 button = gtk_button_new_with_label("Clear");
1908 SIGNAL_CONNECT(button, "clicked", decode_clear_cb, decode_w);
1909 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1910 gtk_box_pack_start(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1911 gtk_tooltips_set_tip(tooltips, button,
1912 "Clear ALL settings.", NULL);
1914 decode_add_notebook(format_hb);
1918 if(topic_available(HELP_DECODE_AS_DIALOG)) {
1919 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
1921 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CLOSE, NULL);
1923 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
1924 gtk_widget_show(bbox);
1926 ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
1927 SIGNAL_CONNECT(ok_bt, "clicked", decode_ok_cb, decode_w);
1928 gtk_tooltips_set_tip(tooltips, ok_bt,
1929 "Apply current setting, close dialog and redissect packets.", NULL);
1931 apply_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_APPLY);
1932 SIGNAL_CONNECT(apply_bt, "clicked", decode_apply_cb, decode_w);
1933 gtk_tooltips_set_tip(tooltips, apply_bt,
1934 "Apply current setting, redissect packets and keep dialog open.", NULL);
1936 close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
1937 window_set_cancel_button(decode_w, close_bt, NULL);
1938 SIGNAL_CONNECT(close_bt, "clicked", decode_close_cb, decode_w);
1939 gtk_tooltips_set_tip(tooltips, close_bt,
1940 "Close the dialog, don't redissect packets.", NULL);
1942 if(topic_available(HELP_DECODE_AS_DIALOG)) {
1943 help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
1944 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_DECODE_AS_DIALOG);
1947 gtk_widget_grab_default(ok_bt);
1949 SIGNAL_CONNECT(decode_w, "delete_event", decode_delete_cb, NULL);
1950 SIGNAL_CONNECT(decode_w, "destroy", decode_destroy_cb, NULL);
1952 gtk_widget_show_all(decode_w);
1953 window_present(decode_w);