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.
31 #include <gdk/gdkkeysyms.h>
33 #include <epan/packet.h>
34 #include <epan/ipproto.h>
35 #include <epan/epan_dissect.h>
37 #include "../globals.h"
38 #include "../simple_dialog.h"
41 #include "gtk/decode_as_dlg.h"
42 #include "gtk/dlg_utils.h"
43 #include "gtk/gui_utils.h"
44 #include "gtk/decode_as_dcerpc.h"
45 #include "gtk/decode_as_ber.h"
46 #include "gtk/help_dlg.h"
50 /**************************************************/
51 /* Typedefs & Enums */
52 /**************************************************/
55 * Enum used to track which transport layer port menu item is
56 * currently selected in the dialog. These items are labeled "source",
57 * "destination", and "source/destination".
60 /* The "source port" menu item is currently selected. */
62 /* The "destination port" menu item is currently selected. */
64 /* The "source/destination port" menu item is currently selected. */
66 /* For SCTP only. This MUST be the last entry! */
70 #define E_DECODE_MIN_HEIGHT 300
71 #define E_NOTEBOOK "notebook"
73 #define E_MENU_SRCDST "menu_src_dst"
75 #define E_PAGE_DPORT "dport"
76 #define E_PAGE_SPORT "sport"
77 #define E_PAGE_PPID "ppid"
78 #define E_PAGE_ASN1 "asn1"
82 * Columns for a "Display" list
84 #define E_LIST_D_TABLE 0
85 #define E_LIST_D_SELECTOR 1
86 #define E_LIST_D_INITIAL 2
87 #define E_LIST_D_CURRENT 3
88 #define E_LIST_D_MAX E_LIST_D_CURRENT
89 #define E_LIST_D_COLUMNS (E_LIST_D_MAX + 1)
91 /**************************************************/
92 /* File Global Variables */
93 /**************************************************/
96 * Keep a static pointer to the current "Decode As" window. This is
97 * kept so that if somebody tries to do "Tools:Decode As" while
98 * there's already a "Decode As" window up, we just pop up the
99 * existing one, rather than creating a new one.
101 static GtkWidget *decode_w = NULL;
104 * A static pointer to the current "Decode As:Show" window. This is
105 * kept so that if somebody tries to do clock the "Show Current"
106 * button or select the "Display:User Specified Decodes" menu item
107 * while there's already a "Decode As:Show" window up, we just pop up
108 * the existing one, rather than creating a new one.
110 static GtkWidget *decode_show_w = NULL;
113 * A list of the dialog items that only have meaning when the user has
114 * selected the "Decode" radio button. When the "Do not decode"
115 * button is selected these items should be dimmed.
117 GSList *decode_dimmable = NULL;
120 * Remember the "action" radio button that is currently selected in
121 * the dialog. This value is initialized when the dialog is created,
122 * modified in a callback routine, and read in the routine that
123 * handles a click in the "OK" button for the dialog.
125 enum action_type requested_action = -1;
128 /**************************************************/
129 /* Global Functions */
130 /**************************************************/
132 /* init this module */
133 void decode_as_init(void) {
135 decode_dcerpc_init();
138 /**************************************************/
139 /* Reset Changed Dissectors */
140 /**************************************************/
143 * Data structure for tracking which dissector need to be reset. This
144 * structure is necessary as a hash table entry cannot be removed
145 * while a g_hash_table_foreach walk is in progress.
147 struct dissector_delete_item {
148 /* The name of the dissector table */
149 const gchar *ddi_table_name;
150 /* The type of the selector in that dissector table */
151 ftenum_t ddi_selector_type;
152 /* The selector in the dissector table */
160 * A typedef for the data structure to track the original dissector
161 * used for any given port on any given protocol.
163 typedef struct dissector_delete_item dissector_delete_item_t;
166 * A list of dissectors that need to be reset.
168 GSList *dissector_reset_list = NULL;
171 * This routine creates one entry in the list of protocol dissector
172 * that need to be reset. It is called by the g_hash_table_foreach
173 * routine once for each changed entry in a dissector table.
174 * Unfortunately it cannot delete the entry immediately as this screws
175 * up the foreach function, so it builds a list of dissectors to be
176 * reset once the foreach routine finishes.
178 * @param table_name The table name in which this dissector is found.
180 * @param key A pointer to the key for this entry in the dissector
181 * hash table. This is generally the numeric selector of the
182 * protocol, i.e. the ethernet type code, IP port number, TCP port
185 * @param value A pointer to the value for this entry in the dissector
186 * hash table. This is an opaque pointer that can only be handed back
187 * to routine in the file packet.c - but it's unused.
189 * @param user_data Unused.
192 decode_build_reset_list (const gchar *table_name, ftenum_t selector_type,
193 gpointer key, gpointer value _U_,
194 gpointer user_data _U_)
196 dissector_delete_item_t *item;
198 item = g_malloc(sizeof(dissector_delete_item_t));
199 item->ddi_table_name = table_name;
200 item->ddi_selector_type = selector_type;
201 switch (selector_type) {
207 item->ddi_selector.sel_uint = GPOINTER_TO_UINT(key);
212 item->ddi_selector.sel_string = key;
216 g_assert_not_reached();
218 dissector_reset_list = g_slist_prepend(dissector_reset_list, item);
222 /**************************************************/
223 /* Show Changed Dissectors */
224 /**************************************************/
226 #define SORT_ALPHABETICAL 0
229 sort_iter_compare_func (GtkTreeModel *model,
234 gint sortcol = GPOINTER_TO_INT(userdata);
238 case SORT_ALPHABETICAL:
240 gchar *name1, *name2;
241 gtk_tree_model_get(model, a, 0, &name1, -1);
242 gtk_tree_model_get(model, b, 0, &name2, -1);
243 if (name1 == NULL || name2 == NULL)
245 if (name1 == NULL && name2 == NULL)
246 break; /* both equal => ret = 0 */
247 ret = (name1 == NULL) ? -1 : 1;
251 ret = g_ascii_strcasecmp(name1,name2);
258 g_return_val_if_reached(0);
265 decode_add_to_show_list (
267 const gchar *table_name,
268 gchar *selector_name,
269 const gchar *initial_proto_name,
270 const gchar *current_proto_name)
272 const gchar *text[E_LIST_D_COLUMNS];
276 store = (GtkListStore *)list_data;
278 text[E_LIST_D_TABLE] = table_name;
279 text[E_LIST_D_SELECTOR] = selector_name;
280 text[E_LIST_D_INITIAL] = initial_proto_name;
281 text[E_LIST_D_CURRENT] = current_proto_name;
282 gtk_list_store_append(store, &iter);
283 gtk_list_store_set(store, &iter, E_LIST_D_TABLE, text[E_LIST_D_TABLE],
284 E_LIST_D_SELECTOR, text[E_LIST_D_SELECTOR],
285 E_LIST_D_INITIAL, text[E_LIST_D_INITIAL],
286 E_LIST_D_CURRENT, text[E_LIST_D_CURRENT], -1);
291 * This routine creates one entry in the list of protocol dissector
292 * that have been changed. It is called by the g_hash_foreach routine
293 * once for each changed entry in a dissector table.
295 * @param table_name The table name in which this dissector is found.
297 * @param key A pointer to the key for this entry in the dissector
298 * hash table. This is generally the numeric selector of the
299 * protocol, i.e. the ethernet type code, IP port number, TCP port
302 * @param value A pointer to the value for this entry in the dissector
303 * hash table. This is an opaque pointer that can only be handed back
304 * to routine in the file packet.c
306 * @param user_data A pointer to the list in which this information
310 decode_build_show_list (const gchar *table_name, ftenum_t selector_type,
311 gpointer key, gpointer value, gpointer user_data)
313 dissector_handle_t current, initial;
314 const gchar *current_proto_name, *initial_proto_name;
315 gchar *selector_name;
321 current = dtbl_entry_get_handle(value);
323 current_proto_name = "(none)";
325 current_proto_name = dissector_handle_get_short_name(current);
326 initial = dtbl_entry_get_initial_handle(value);
328 initial_proto_name = "(none)";
330 initial_proto_name = dissector_handle_get_short_name(initial);
332 switch (selector_type) {
338 switch (get_dissector_table_base(table_name)) {
341 g_snprintf(string1, sizeof(string1), "%u", GPOINTER_TO_UINT(key));
345 switch (get_dissector_table_selector_type(table_name)) {
348 g_snprintf(string1, sizeof(string1), "0x%02x", GPOINTER_TO_UINT(key));
352 g_snprintf(string1, sizeof(string1), "0x%04x", GPOINTER_TO_UINT(key));
356 g_snprintf(string1, sizeof(string1), "0x%06x", GPOINTER_TO_UINT(key));
360 g_snprintf(string1, sizeof(string1), "0x%08x", GPOINTER_TO_UINT(key));
364 g_assert_not_reached();
370 g_snprintf(string1, sizeof(string1), "%#o", GPOINTER_TO_UINT(key));
373 selector_name = string1;
382 g_assert_not_reached();
383 selector_name = NULL;
387 decode_add_to_show_list (
389 get_dissector_table_ui_name(table_name),
396 /* clear all settings */
398 decode_clear_all(void)
400 dissector_delete_item_t *item;
403 dissector_all_tables_foreach_changed(decode_build_reset_list, NULL);
405 for (tmp = dissector_reset_list; tmp; tmp = g_slist_next(tmp)) {
407 switch (item->ddi_selector_type) {
413 dissector_reset(item->ddi_table_name, item->ddi_selector.sel_uint);
418 dissector_reset_string(item->ddi_table_name,
419 item->ddi_selector.sel_string);
423 g_assert_not_reached();
427 g_slist_free(dissector_reset_list);
428 dissector_reset_list = NULL;
430 decode_dcerpc_reset_all();
437 * This routine is called when the user clicks the "OK" button in
438 * the "Decode As:Show..." dialog window. This routine destroys the
439 * dialog box and performs other housekeeping functions.
441 * @param GtkWidget * A pointer to the "OK" button.
443 * @param gpointer A pointer to the dialog window.
446 decode_show_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
448 window_destroy(GTK_WIDGET(parent_w));
453 * This routine is called when the user clicks the "Clear" button in
454 * the "Decode As:Show..." dialog window. This routine resets all the
455 * dissector values and then destroys the dialog box and performs
456 * other housekeeping functions.
458 * @param GtkWidget * A pointer to the "Clear" button.
460 * @param gpointer A pointer to the dialog window.
463 decode_show_clear_cb (GtkWidget *clear_bt _U_, gpointer parent_w)
467 window_destroy(GTK_WIDGET(parent_w));
472 * This routine is called when the user clicks the X at the top right end in
473 * the "Decode As:Show..." dialog window. This routine simply calls the
474 * ok routine as if the user had clicked the ok button.
476 * @param GtkWidget * A pointer to the dialog box.
478 * @param gpointer Unknown
481 decode_show_delete_cb (GtkWidget *decode_w _U_, gpointer dummy _U_)
483 decode_show_ok_cb(NULL, decode_show_w);
489 * This routine is called at the destruction of the "Decode As:Show"
490 * dialog box. It clears the pointer maintained by this file, so that
491 * the next time the user clicks the "Decode As:Show" button a new
492 * dialog box will be created.
494 * @param GtkWidget * A pointer to the dialog box.
496 * @param gpointer Unknown
499 decode_show_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
501 /* Note that we no longer have a "Decode As:Show" dialog box. */
502 decode_show_w = NULL;
507 * This routine creates the "Decode As:Show" dialog box. This dialog box
508 * shows the user which protocols have had their dissectors changed.
511 * @param data Unknown
514 decode_show_cb (GtkWidget * w _U_, gpointer data _U_)
516 GtkWidget *main_vb, *bbox, *ok_bt, *clear_bt, *help_bt, *scrolled_window;
517 const gchar *titles[E_LIST_D_COLUMNS] = {
518 "Table", "Value", "Initial", "Current"
523 GtkCellRenderer *renderer;
524 GtkTreeViewColumn *tc;
527 if (decode_show_w != NULL) {
528 /* There's already a "Decode As" dialog box; reactivate it. */
529 reactivate_window(decode_show_w);
533 decode_show_w = dlg_window_new("Wireshark: Decode As: Show");
534 /* Provide a minimum of a couple of rows worth of data */
535 gtk_window_set_default_size(GTK_WINDOW(decode_show_w), -1, E_DECODE_MIN_HEIGHT);
537 /* Container for each row of widgets */
538 main_vb = gtk_vbox_new(FALSE, 2);
539 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
540 gtk_container_add(GTK_CONTAINER(decode_show_w), main_vb);
542 /* Initialize list */
543 store = gtk_list_store_new(E_LIST_D_COLUMNS, G_TYPE_STRING,
544 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
545 list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
546 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
547 gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list), FALSE);
548 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(list),
551 for (column = 0; column < E_LIST_D_COLUMNS; column++) {
552 renderer = gtk_cell_renderer_text_new();
553 tc = gtk_tree_view_column_new_with_attributes(titles[column],
556 gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
557 gtk_tree_view_append_column(list, tc);
561 dissector_all_tables_foreach_changed(decode_build_show_list, store);
562 g_object_unref(G_OBJECT(store));
563 decode_dcerpc_add_show_list(store);
565 /* Put clist into a scrolled window */
566 scrolled_window = scrolled_window_new(NULL, NULL);
567 /* this will result to set the width of the dialog to the required size */
568 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
569 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
570 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
572 gtk_container_add(GTK_CONTAINER(scrolled_window),
574 gtk_box_pack_start(GTK_BOX(main_vb), scrolled_window, TRUE, TRUE, 0);
577 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CLEAR, GTK_STOCK_HELP, NULL);
578 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
579 gtk_widget_show(bbox);
581 ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
582 g_signal_connect(ok_bt, "clicked", G_CALLBACK(decode_show_ok_cb), decode_show_w);
584 clear_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLEAR);
585 g_signal_connect(clear_bt, "clicked", G_CALLBACK(decode_show_clear_cb), decode_show_w);
587 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
588 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_DECODE_AS_SHOW_DIALOG);
590 /* set ok as default, this button won't change anything */
591 window_set_cancel_button(decode_show_w, ok_bt, NULL);
593 g_signal_connect(decode_show_w, "delete_event", G_CALLBACK(decode_show_delete_cb), NULL);
594 g_signal_connect(decode_show_w, "destroy", G_CALLBACK(decode_show_destroy_cb), NULL);
596 gtk_widget_set_sensitive(clear_bt,
597 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter));
599 gtk_widget_show_all(decode_show_w);
600 window_present(decode_show_w);
604 /**************************************************/
605 /* Modify the dissector routines */
606 /**************************************************/
609 * Modify a single dissector. This routine first takes care of
610 * updating the internal table of original protocol/port/dissector
611 * combinations by adding a new entry (or removing an existing entry
612 * if the value is being set back to its default). This routine then
613 * performs the actual modification to the packet dissector tables.
615 * @param s Pointer to a string buffer. This buffer is used to build
616 * up a message indicating which ports have had their dissector
617 * changed. This output will be displayed all at once after all
618 * dissectors have been modified.
620 * @param table_name The table name in which the dissector should be
623 * @param selector An enum value indication which selector value
624 * (i.e. IP protocol number, TCP port number, etc.)is to be changed.
626 * @param list The List in which all the selection information can
629 * @return gchar * Pointer to the next free location in the string
633 decode_change_one_dissector(gchar *table_name, guint selector, GtkWidget *list)
635 dissector_handle_t handle;
637 GtkTreeSelection *selection;
641 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
642 if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
647 gtk_tree_model_get(model, &iter, E_LIST_S_PROTO_NAME, &abbrev,
648 E_LIST_S_TABLE+1, &handle, -1);
651 if (abbrev != NULL && strcmp(abbrev, "(default)") == 0) {
652 dissector_reset(table_name, selector);
654 dissector_change(table_name, selector, handle);
660 /**************************************************/
661 /* Action routines for the "Decode As..." dialog */
662 /* - called when the OK button pressed */
663 /* - one per notebook page */
664 /**************************************************/
669 * Print debugging information about clist selection. Extract all
670 * information from the clist entry that was selected and print it to
673 * @param clist The clist to dump.
675 * @param leadin A string to print at the start of each line.
678 decode_debug (GtkCList *clist, gchar *leadin)
680 gchar *string, *text[E_LIST_S_COLUMNS];
681 dissector_handle_t handle;
684 if (clist->selection) {
685 row = GPOINTER_TO_INT(clist->selection->data);
686 gtk_clist_get_text(clist, row, E_LIST_S_PROTO_NAME, &text[E_LIST_S_PROTO_NAME]);
687 gtk_clist_get_text(clist, row, E_LIST_S_TABLE, &text[E_LIST_S_TABLE]);
688 handle = gtk_clist_get_row_data(clist, row);
689 string = g_strdup_printf("%s clist row %d: <put handle here>, name %s, table %s",
690 leadin, row, text[E_LIST_S_PROTO_NAME],
691 text[E_LIST_S_TABLE]);
693 string = g_strdup_printf("%s clist row (none), aka do not decode", leadin);
695 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, string);
702 * This routine is called when the user clicks the "OK" button in the
703 * "Decode As..." dialog window and a 'simple' page is foremost.
704 * This routine takes care of making any changes requested to the
705 * dissector tables. This routine is currently used for IP and
706 * Ethertypes. Any 'single change' notebook page can use this
709 * @param notebook_pg A pointer to the "network" notebook page.
712 decode_simple (GtkWidget *notebook_pg)
721 list = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_LIST);
722 if (requested_action == E_DECODE_NO)
723 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
726 string = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TITLE);
727 decode_debug(GTK_CLIST(list), string);
730 table_name = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TABLE);
731 value = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_VALUE));
732 decode_change_one_dissector(table_name, value, list);
737 * This routine is called when the user clicks the "OK" button in the
738 * "Decode As..." dialog window and the transport page is foremost.
739 * This routine takes care of making any changes requested to the TCP
740 * or UDP dissector tables.
742 * @param notebook_pg A pointer to the "transport" notebook page.
745 decode_transport(GtkWidget *notebook_pg)
747 GtkWidget *menu, *menuitem;
750 gint requested_srcdst, requested_port, ppid;
753 list = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_LIST);
754 if (requested_action == E_DECODE_NO)
755 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
757 menu = g_object_get_data(G_OBJECT(notebook_pg), E_MENU_SRCDST);
759 menuitem = gtk_menu_get_active(GTK_MENU(menu));
760 requested_srcdst = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem), "user_data"));
763 string = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TITLE);
764 decode_debug(GTK_CLIST(list), string);
767 table_name = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TABLE);
768 if (requested_srcdst >= E_DECODE_PPID) {
769 if (requested_srcdst == E_DECODE_PPID)
772 if (requested_srcdst - E_DECODE_PPID - 1 < MAX_NUMBER_OF_PPIDS)
773 ppid = cfile.edt->pi.ppids[requested_srcdst - E_DECODE_PPID - 1];
776 decode_change_one_dissector(table_name, ppid, list);
779 if (requested_srcdst != E_DECODE_DPORT) {
780 portp = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_SPORT);
782 requested_port = GPOINTER_TO_INT(portp);
783 decode_change_one_dissector(table_name, requested_port, list);
786 if (requested_srcdst != E_DECODE_SPORT) {
787 portp = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_DPORT);
789 requested_port = GPOINTER_TO_INT(portp);
790 decode_change_one_dissector(table_name, requested_port, list);
796 /**************************************************/
797 /* Signals from the "Decode As..." dialog */
798 /**************************************************/
801 * This routine is called when the user clicks the "OK" button in the
802 * "Decode As..." dialog window. This routine calls various helper
803 * routines to set/clear dissector values as requested by the user.
804 * These routines accumulate information on what actions they have
805 * taken, and this summary information is printed by this routine.
806 * This routine then destroys the dialog box and performs other
807 * housekeeping functions.
809 * @param ok_bt A pointer to the "OK" button.
811 * @param parent_w A pointer to the dialog window.
814 decode_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
816 GtkWidget *notebook, *notebook_pg;
817 void (* func)(GtkWidget *);
819 void *binding = NULL;
821 /* Call the right routine for the page that was currently in front. */
822 notebook = g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
823 page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
824 notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
826 func = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_ACTION);
829 /* Now destroy the "Decode As" dialog. */
830 notebook_pg = g_object_get_data(G_OBJECT(parent_w), E_PAGE_DCERPC);
832 binding = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_BINDING);
835 decode_dcerpc_binding_free(binding);
837 window_destroy(GTK_WIDGET(parent_w));
838 g_slist_free(decode_dimmable);
839 decode_dimmable = NULL;
845 * This routine is called when the user clicks the "Apply" button in the
846 * "Decode As..." dialog window. This routine calls various helper
847 * routines to set/clear dissector values as requested by the user.
848 * These routines accumulate information on what actions they have
849 * taken, and this summary information is printed by this routine.
851 * @param apply_bt A pointer to the "Apply" button.
853 * @param parent_w A pointer to the dialog window.
856 decode_apply_cb (GtkWidget *apply_bt _U_, gpointer parent_w)
858 GtkWidget *notebook, *notebook_pg;
859 void (* func)(GtkWidget *);
862 /* Call the right routine for the page that was currently in front. */
863 notebook = g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
864 page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
865 notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
867 func = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_ACTION);
874 * This routine is called when the user clicks the "Close" button in
875 * the "Decode As..." dialog window. This routine then destroys the
876 * dialog box and performs other housekeeping functions.
878 * @param close_bt A pointer to the "Close" button.
880 * @param parent_w A pointer to the dialog window.
883 decode_close_cb (GtkWidget *close_bt _U_, gpointer parent_w)
885 GtkWidget *notebook_pg = NULL;
886 void *binding = NULL;
889 notebook_pg = g_object_get_data(G_OBJECT(parent_w), E_PAGE_DCERPC);
891 binding = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_BINDING);
894 decode_dcerpc_binding_free(binding);
896 window_destroy(GTK_WIDGET(parent_w));
897 g_slist_free(decode_dimmable);
898 decode_dimmable = NULL;
903 * This routine is called when the user clicks the "Close" button in
904 * the "Decode As..." dialog window. This routine simply calls the
905 * close routine as if the user had clicked the close button instead
906 * of the close button.
908 * @param decode_w A pointer to the dialog box.
910 * @param dummy Unknown
913 decode_delete_cb (GtkWidget *decode_w, gpointer dummy _U_)
915 decode_close_cb(NULL, decode_w);
921 * This routine is called at the destruction of the "Decode As..."
922 * dialog box. It clears the pointer maintained by this file, so that
923 * the next time the user selects the "Decode As..." menu item a new
924 * dialog box will be created.
926 * @param decode_w A pointer to the dialog box.
928 * @param user_data Unknown
933 decode_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
935 /* Note that we no longer have a "Decode As" dialog box. */
941 * This routine is called when the user clicks the "Clear" button in
942 * the "Decode As..." dialog window. This routine resets all the
943 * dissector values and performs other housekeeping functions.
945 * @param GtkWidget * A pointer to the "Clear" button.
946 * @param gpointer A pointer to the dialog window.
949 decode_clear_cb(GtkWidget *clear_bt _U_, gpointer parent_w _U_)
956 /**************************************************/
957 /* Dialog setup - radio buttons */
958 /**************************************************/
961 * Update the requested action field of the dialog. This routine is
962 * called by GTK when either of the two radio buttons in the dialog is
965 * @param w The radio button that was clicked.
967 * @param data The enum value assigned to this radio button. This
968 * will be either E_DECODE_YES or E_DECODE_NO
971 decode_update_action (GtkWidget *w _U_, gpointer data)
976 requested_action = GPOINTER_TO_INT(data);
977 enable = (requested_action == E_DECODE_YES);
978 for (tmp = decode_dimmable; tmp; tmp = g_slist_next(tmp)) {
979 gtk_widget_set_sensitive(tmp->data, enable);
984 * This routine is called to create the "Decode" and "Do not decode"
985 * radio buttons. These buttons are installed into a vbox, and set up
988 * @return GtkWidget * A pointer to the vbox containing the buttons
991 decode_add_yes_no (void)
993 GtkWidget *format_vb, *radio_button;
996 format_vb = gtk_vbox_new(FALSE, 2);
998 radio_button = gtk_radio_button_new_with_label(NULL, "Decode");
999 format_grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio_button));
1000 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1001 g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_update_action),
1002 GINT_TO_POINTER(E_DECODE_YES));
1003 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1005 radio_button = gtk_radio_button_new_with_label(format_grp, "Do not decode");
1006 format_grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio_button));
1007 g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_update_action),
1008 GINT_TO_POINTER(E_DECODE_NO));
1009 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1014 /**************************************************/
1015 /* Dialog setup - simple menus */
1016 /**************************************************/
1019 * This routine is called to pack an option menu into an aligment, so
1020 * that it doesn't expand vertically to fill up the space available to
1023 * @param optmenu A pointer to the option menu to be so packed.
1025 * @return GtkWidget * A pointer to the newly created alignment.
1028 decode_add_pack_menu (GtkWidget *optmenu)
1030 GtkWidget *alignment;
1032 alignment = gtk_alignment_new(0.0f, 0.5f, 0.0f, 0.0f);
1033 gtk_container_add(GTK_CONTAINER(alignment), optmenu);
1040 * This routine is called to add the transport port selection menu to
1041 * the dialog box. This is a three choice menu: source, destination
1042 * and both. The default choice for the menu is set to the source
1043 * port number of the currently selected packet.
1045 * @param page A pointer notebook page that will contain all
1046 * widgets created by this routine.
1048 * @return GtkWidget * A pointer to the newly created alignment into
1049 * which we've packed the newly created option menu.
1052 decode_add_srcdst_menu (GtkWidget *page)
1054 GtkWidget *optmenu, *menu, *menuitem, *alignment;
1057 optmenu = gtk_option_menu_new();
1058 menu = gtk_menu_new();
1059 g_snprintf(tmp, sizeof(tmp), "source (%u)", cfile.edt->pi.srcport);
1060 menuitem = gtk_menu_item_new_with_label(tmp);
1061 g_object_set_data(G_OBJECT(menuitem), "user_data", GINT_TO_POINTER(E_DECODE_SPORT));
1062 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1063 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1065 g_snprintf(tmp, sizeof(tmp), "destination (%u)", cfile.edt->pi.destport);
1066 menuitem = gtk_menu_item_new_with_label(tmp);
1067 g_object_set_data(G_OBJECT(menuitem), "user_data", GINT_TO_POINTER(E_DECODE_DPORT));
1068 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1069 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1071 menuitem = gtk_menu_item_new_with_label("both");
1072 g_object_set_data(G_OBJECT(menuitem), "user_data", GINT_TO_POINTER(E_DECODE_BPORT));
1073 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1074 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1076 g_object_set_data(G_OBJECT(page), E_MENU_SRCDST, menu);
1077 gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
1078 g_object_set_data(G_OBJECT(page), E_PAGE_SPORT, GINT_TO_POINTER(cfile.edt->pi.srcport));
1079 g_object_set_data(G_OBJECT(page), E_PAGE_DPORT, GINT_TO_POINTER(cfile.edt->pi.destport));
1081 alignment = decode_add_pack_menu(optmenu);
1087 decode_add_ppid_menu (GtkWidget *page)
1089 GtkWidget *optmenu, *menu, *menuitem;
1091 guint number_of_ppid;
1093 optmenu = gtk_option_menu_new();
1094 menu = gtk_menu_new();
1096 g_snprintf(tmp, sizeof(tmp), "PPID (%u)", 0);
1097 menuitem = gtk_menu_item_new_with_label(tmp);
1098 g_object_set_data(G_OBJECT(menuitem), "user_data", GINT_TO_POINTER(E_DECODE_PPID));
1099 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1100 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1102 for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++)
1103 if (cfile.edt->pi.ppids[number_of_ppid] != 0) {
1104 g_snprintf(tmp, sizeof(tmp), "PPID (%u)", cfile.edt->pi.ppids[number_of_ppid]);
1105 menuitem = gtk_menu_item_new_with_label(tmp);
1106 g_object_set_data(G_OBJECT(menuitem), "user_data", GINT_TO_POINTER(E_DECODE_PPID + 1 + number_of_ppid));
1107 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1108 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1112 g_object_set_data(G_OBJECT(page), E_MENU_SRCDST, menu);
1113 gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
1118 /*************************************************/
1119 /* Dialog setup - list based menus */
1120 /*************************************************/
1122 struct handle_lookup_info {
1123 dissector_handle_t handle;
1128 lookup_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
1131 dissector_handle_t handle;
1132 struct handle_lookup_info *hli = (struct handle_lookup_info *)data;
1134 gtk_tree_model_get(model, iter, E_LIST_S_TABLE+1, &handle, -1);
1135 if (hli->handle == handle) {
1143 * This routine creates one entry in the list of protocol dissector
1144 * that can be used. It is called by the dissector_table_foreach_handle
1145 * routine once for each entry in a dissector table's list of handles
1146 * for dissectors that could be used in that table. It guarantees unique
1147 * entries by iterating over the list of entries build up to this point,
1148 * looking for a duplicate name. If there is no duplicate, then this
1149 * entry is added to the list of possible dissectors.
1151 * @param table_name The name of the dissector table currently
1154 * @param value The dissector handle for this entry. This is an opaque
1155 * pointer that can only be handed back to routines in the file packet.c
1157 * @param user_data A data block passed into each instance of this
1158 * routine. It contains information from the caller of the foreach
1159 * routine, specifying information about the dissector table and where
1160 * to store any information generated by this routine.
1163 decode_add_to_list (const gchar *table_name, const gchar *proto_name, gpointer value, gpointer user_data)
1165 const gchar *text[E_LIST_S_COLUMNS];
1167 GtkListStore *store;
1169 struct handle_lookup_info hli;
1171 g_assert(user_data);
1178 store = GTK_LIST_STORE(gtk_tree_view_get_model(list));
1179 gtk_tree_model_foreach(GTK_TREE_MODEL(store), lookup_handle, &hli);
1180 /* We already have an entry for this handle.
1181 * XXX - will this ever happen? */
1182 if (hli.found) return;
1184 text[E_LIST_S_PROTO_NAME] = proto_name;
1185 text[E_LIST_S_TABLE] = table_name;
1186 gtk_list_store_append(store, &iter);
1187 gtk_list_store_set(store, &iter,
1188 E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1189 E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1190 E_LIST_S_TABLE+1, value, -1);
1194 decode_proto_add_to_list (const gchar *table_name, gpointer value, gpointer user_data)
1196 const gchar *proto_name;
1198 dissector_handle_t handle;
1202 proto_name = dissector_handle_get_short_name(handle);
1204 i = dissector_handle_get_protocol_index(handle);
1205 if (i >= 0 && !proto_is_protocol_enabled(find_protocol_by_id(i)))
1208 decode_add_to_list (table_name, proto_name, value, user_data);
1213 decode_list_button_press_cb(GtkWidget *list, GdkEventButton *event, gpointer data _U_)
1215 if (event->type == GDK_2BUTTON_PRESS) {
1216 GtkWidget *main_w = gtk_widget_get_toplevel(list);
1218 decode_ok_cb (NULL, main_w);
1225 decode_list_key_release_cb(GtkWidget *list, GdkEventKey *event, gpointer data _U_)
1227 if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) {
1228 GtkWidget *main_w = gtk_widget_get_toplevel(list);
1230 decode_ok_cb (NULL, main_w);
1237 * This routine starts the creation of a List on a notebook page. It
1238 * creates both a scrolled window and a list, adds the list to the
1239 * window, and attaches the list as a data object on the page.
1241 * @param page A pointer to the notebook page being created.
1243 * @param list_p Will be filled in with the address of a newly
1246 * @param scrolled_win_p Will be filled in with the address of a newly
1247 * created GtkScrolledWindow.
1250 decode_list_menu_start(GtkWidget *page, GtkWidget **list_p,
1251 GtkWidget **scrolled_win_p)
1254 GtkListStore *store;
1255 GtkCellRenderer *renderer;
1256 GtkTreeViewColumn *tc;
1257 GtkTreeSortable *sortable;
1259 store = gtk_list_store_new(E_LIST_S_COLUMNS+1, G_TYPE_STRING,
1260 G_TYPE_STRING, G_TYPE_POINTER);
1261 g_object_set_data(G_OBJECT(decode_w), "sctp_data", store);
1262 list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
1263 g_object_unref(G_OBJECT(store));
1264 sortable = GTK_TREE_SORTABLE(store);
1265 gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
1266 gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
1267 gtk_tree_view_set_headers_clickable(list, FALSE);
1269 gtk_tree_view_set_headers_visible(list, FALSE);
1271 renderer = gtk_cell_renderer_text_new();
1272 tc = gtk_tree_view_column_new_with_attributes("Short Name", renderer,
1273 "text", E_LIST_S_PROTO_NAME,
1275 gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1276 gtk_tree_view_append_column(list, tc);
1277 g_object_set_data(G_OBJECT(page), E_PAGE_LIST, list);
1279 *scrolled_win_p = scrolled_window_new(NULL, NULL);
1280 /* this will result to set the width of the dialog to the required size */
1281 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1282 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1283 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1285 gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
1287 *list_p = GTK_WIDGET(list);
1291 * This routine finishes the creation of a List on a notebook page.
1292 * It adds the default entry, sets the default entry as the
1293 * highlighted entry, and sorts the List.
1295 * @param list A pointer the the List to finish.
1298 decode_list_menu_finish(GtkWidget *list)
1300 const gchar *text[E_LIST_S_COLUMNS];
1301 GtkListStore *store;
1304 text[E_LIST_S_PROTO_NAME] = "(default)";
1305 text[E_LIST_S_TABLE] = "(none)";
1306 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
1307 gtk_list_store_prepend(store, &iter);
1308 gtk_list_store_set(store, &iter,
1309 E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1310 E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1311 E_LIST_S_TABLE+1, NULL, -1);
1313 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), &iter);
1314 g_signal_connect(list, "button_press_event", G_CALLBACK(decode_list_button_press_cb), NULL);
1315 g_signal_connect(list, "key_release_event", G_CALLBACK(decode_list_key_release_cb), NULL);
1319 * This routine is called to add the dissector selection list to a
1320 * notebook page. This scrolled list contains an entry labeled
1321 * "default", and an entry for each protocol that has had a dissector
1322 * registered. The default choice for the list is set to the
1323 * "default" choice, which will return the protocol/port selections to
1324 * their original dissector(s).
1326 * @param page A pointer to the notebook page currently being created.
1328 * @param table_name The name of the dissector table to use to build
1331 * @return GtkWidget * A pointer to the newly created list within a
1335 decode_add_simple_menu (GtkWidget *page, const gchar *table_name)
1337 GtkWidget *scrolled_window;
1340 decode_list_menu_start(page, &list, &scrolled_window);
1341 dissector_table_foreach_handle(table_name, decode_proto_add_to_list, list);
1342 decode_list_menu_finish(list);
1343 return(scrolled_window);
1347 /**************************************************/
1349 /**************************************************/
1352 * This routine creates a sample notebook page in the dialog box.
1353 * This notebook page provides a prompt specifying what is being
1354 * changed and its current value (e.g. "IP Protocol number (17)"), and
1355 * a list specifying all the available choices. The list of choices
1356 * is conditionally enabled, based upon the setting of the
1357 * "decode"/"do not decode" radio buttons.
1359 * @param prompt The prompt for this notebook page
1361 * @param title A title for this page to use when debugging.
1363 * @param table_name The name of the dissector table to use to
1366 * @param value The protocol/port value that is to be changed.
1368 * @return GtkWidget * A pointer to the notebook page created by this
1372 decode_add_simple_page (const gchar *prompt, const gchar *title, const gchar *table_name,
1375 GtkWidget *page, *label, *scrolled_window;
1377 page = gtk_hbox_new(FALSE, 5);
1378 g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_simple);
1379 g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) table_name);
1380 g_object_set_data(G_OBJECT(page), E_PAGE_TITLE, (gchar *) title);
1381 g_object_set_data(G_OBJECT(page), E_PAGE_VALUE, GUINT_TO_POINTER(value));
1383 /* Always enabled */
1384 label = gtk_label_new(prompt);
1385 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1387 /* Conditionally enabled - only when decoding packets */
1388 label = gtk_label_new("as");
1389 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1390 decode_dimmable = g_slist_prepend(decode_dimmable, label);
1391 scrolled_window = decode_add_simple_menu(page, table_name);
1392 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1393 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1400 * This routine creates the TCP or UDP notebook page in the dialog box.
1401 * All items created by this routine are packed into a single
1402 * horizontal box. First is a label indicating whether the port(s) for
1403 * which the user can set the dissection is a TCP port or a UDP port.
1404 * Second is a menu allowing the user to select whether the source port,
1405 * destination port, or both ports will have dissectors added for them.
1406 * Last is a (conditionally enabled) popup menu listing all possible
1407 * dissectors that can be used to decode the packets, and the choice
1408 * or returning to the default dissector for these ports.
1410 * The defaults for these items are the transport layer protocol of
1411 * the currently selected packet, the source port of the currently
1412 * selected packet, and the "default dissector".
1414 * @param prompt The prompt for this notebook page
1416 * @param table_name The name of the dissector table to use to
1419 * @return GtkWidget * A pointer to the notebook page created by
1423 decode_add_tcpudp_page (const gchar *prompt, const gchar *table_name)
1425 GtkWidget *page, *label, *scrolled_window, *optmenu;
1427 page = gtk_hbox_new(FALSE, 5);
1428 g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_transport);
1429 g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) table_name);
1430 g_object_set_data(G_OBJECT(page), E_PAGE_TITLE, "Transport");
1432 /* Always enabled */
1433 label = gtk_label_new(prompt);
1434 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1435 optmenu = decode_add_srcdst_menu(page);
1436 gtk_box_pack_start(GTK_BOX(page), optmenu, TRUE, TRUE, 0);
1437 label = gtk_label_new("port(s)");
1438 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1440 /* Conditionally enabled - only when decoding packets */
1441 label = gtk_label_new("as");
1442 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1443 decode_dimmable = g_slist_prepend(decode_dimmable, label);
1444 scrolled_window = decode_add_simple_menu(page, table_name);
1445 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1446 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1452 decode_sctp_list_menu_start(GtkWidget **list_p, GtkWidget **scrolled_win_p)
1455 GtkListStore *sctp_store;
1456 GtkCellRenderer *renderer;
1457 GtkTreeViewColumn *tc;
1458 GtkTreeSortable *sortable;
1460 sctp_store = g_object_get_data(G_OBJECT(decode_w), "sctp_data");
1461 list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(sctp_store)));
1462 g_object_unref(G_OBJECT(sctp_store));
1463 sortable = GTK_TREE_SORTABLE(sctp_store);
1464 gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
1465 gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
1466 gtk_tree_view_set_headers_clickable(list, FALSE);
1468 gtk_tree_view_set_headers_visible(list, FALSE);
1470 renderer = gtk_cell_renderer_text_new();
1471 tc = gtk_tree_view_column_new_with_attributes("Short Name", renderer,
1472 "text", E_LIST_S_PROTO_NAME,
1474 gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1475 gtk_tree_view_append_column(list, tc);
1477 *scrolled_win_p = scrolled_window_new(NULL, NULL);
1478 /* this will result to set the width of the dialog to the required size */
1479 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1480 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p), GTK_SHADOW_IN);
1481 gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
1482 *list_p = GTK_WIDGET(list);
1486 decode_sctp_update_ppid_menu(GtkWidget *w _U_, GtkWidget *page)
1488 GtkWidget *menu, *menuitem, *list, *scrolled_window, *sctpmenu;
1490 guint number_of_ppid;
1491 GtkListStore *sctp_store;
1493 menu = gtk_menu_new();
1495 g_snprintf(tmp, sizeof(tmp), "PPID (%u)", 0);
1496 menuitem = gtk_menu_item_new_with_label(tmp);
1497 g_object_set_data(G_OBJECT(menuitem), "user_data", GINT_TO_POINTER(E_DECODE_PPID));
1498 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1499 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1500 for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++)
1501 if (cfile.edt->pi.ppids[number_of_ppid] != 0) {
1502 g_snprintf(tmp, sizeof(tmp), "PPID (%u)", cfile.edt->pi.ppids[number_of_ppid]);
1503 menuitem = gtk_menu_item_new_with_label(tmp);
1504 g_object_set_data(G_OBJECT(menuitem), "user_data", GINT_TO_POINTER(E_DECODE_PPID + 1 + number_of_ppid));
1505 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1506 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1510 g_object_set_data(G_OBJECT(page), E_MENU_SRCDST, menu);
1511 g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, "sctp.ppi");
1512 sctpmenu = g_object_get_data(G_OBJECT(decode_w), "user_data");
1513 gtk_option_menu_set_menu(GTK_OPTION_MENU(sctpmenu), menu);
1515 sctp_store = g_object_get_data(G_OBJECT(G_OBJECT(decode_w)), "sctp_data");
1516 gtk_list_store_clear(sctp_store);
1517 decode_sctp_list_menu_start(&list, &scrolled_window);
1518 dissector_table_foreach_handle("sctp.ppi", decode_proto_add_to_list, list);
1519 decode_list_menu_finish(list);
1524 decode_sctp_update_srcdst_menu(GtkWidget *w _U_, GtkWidget *page)
1526 GtkWidget *menu, *menuitem, *scrolled_window, *list, *sctpmenu;
1528 GtkListStore *sctp_store;
1530 menu = gtk_menu_new();
1531 g_snprintf(tmp, sizeof(tmp), "source (%u)", cfile.edt->pi.srcport);
1532 menuitem = gtk_menu_item_new_with_label(tmp);
1533 g_object_set_data(G_OBJECT(menuitem), "user_data", GINT_TO_POINTER(E_DECODE_SPORT));
1534 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1535 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1537 g_snprintf(tmp, sizeof(tmp), "destination (%u)", cfile.edt->pi.destport);
1538 menuitem = gtk_menu_item_new_with_label(tmp);
1539 g_object_set_data(G_OBJECT(menuitem), "user_data", GINT_TO_POINTER(E_DECODE_DPORT));
1540 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1541 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1543 menuitem = gtk_menu_item_new_with_label("both");
1544 g_object_set_data(G_OBJECT(menuitem), "user_data", GINT_TO_POINTER(E_DECODE_BPORT));
1545 gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
1546 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
1548 g_object_set_data(G_OBJECT(page), E_MENU_SRCDST, menu);
1549 g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, "sctp.port");
1550 sctpmenu = g_object_get_data(G_OBJECT(decode_w), "user_data");
1551 gtk_option_menu_set_menu(GTK_OPTION_MENU(sctpmenu), menu);
1552 g_object_set_data(G_OBJECT(page), E_PAGE_SPORT, GINT_TO_POINTER(cfile.edt->pi.srcport));
1553 g_object_set_data(G_OBJECT(page), E_PAGE_DPORT, GINT_TO_POINTER(cfile.edt->pi.destport));
1554 sctp_store = g_object_get_data(G_OBJECT(G_OBJECT(decode_w)), "sctp_data");
1555 gtk_list_store_clear(sctp_store);
1556 decode_sctp_list_menu_start(&list, &scrolled_window);
1557 dissector_table_foreach_handle("sctp.port", decode_proto_add_to_list, list);
1558 decode_list_menu_finish(list);
1564 decode_sctp_add_port_ppid (GtkWidget *page)
1566 GtkWidget *format_vb, *radio_button;
1569 format_vb = gtk_vbox_new(FALSE, 2);
1571 radio_button = gtk_radio_button_new_with_label(NULL, "PPID");
1572 format_grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio_button));
1573 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1574 g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_sctp_update_ppid_menu), page);
1576 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1578 radio_button = gtk_radio_button_new_with_label(format_grp, "Port");
1579 format_grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio_button));
1580 g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_sctp_update_srcdst_menu), page);
1582 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1589 decode_add_sctp_page (const gchar *prompt, const gchar *table_name)
1591 GtkWidget *page, *label, *scrolled_window, *radio, *vbox, *alignment, *sctpbox, *sctpmenu;
1593 page = gtk_hbox_new(FALSE, 5);
1594 g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_transport);
1595 g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) table_name);
1596 g_object_set_data(G_OBJECT(page), E_PAGE_TITLE, "Transport");
1598 vbox = gtk_vbox_new(FALSE, 5);
1599 radio = decode_sctp_add_port_ppid(page);
1600 gtk_box_pack_start(GTK_BOX(vbox), radio, TRUE, TRUE, 0);
1602 /* Always enabled */
1603 sctpbox = gtk_hbox_new(FALSE, 5);
1604 label = gtk_label_new(prompt);
1605 gtk_box_pack_start(GTK_BOX(sctpbox), label, TRUE, TRUE, 0);
1606 sctpmenu = decode_add_ppid_menu(page);
1607 g_object_set_data(G_OBJECT(decode_w), "user_data", sctpmenu);
1608 alignment = decode_add_pack_menu(sctpmenu);
1610 gtk_box_pack_start(GTK_BOX(sctpbox), alignment, TRUE, TRUE, 0);
1612 /* Conditionally enabled - only when decoding packets */
1613 label = gtk_label_new("as");
1614 gtk_box_pack_start(GTK_BOX(sctpbox), label, TRUE, TRUE, 0);
1615 decode_dimmable = g_slist_prepend(decode_dimmable, label);
1616 gtk_box_pack_start(GTK_BOX(vbox), sctpbox, TRUE, TRUE, 0);
1617 gtk_box_pack_start(GTK_BOX(page), vbox, TRUE, TRUE, 0);
1619 scrolled_window = decode_add_simple_menu(page, table_name);
1620 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1621 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1628 * This routine indicates whether we'd actually have any pages in the
1629 * notebook in a "Decode As" dialog box; if there wouldn't be, we
1630 * inactivate the menu item for "Decode As".
1635 return cfile.edt->pi.ethertype || cfile.edt->pi.ipproto ||
1636 cfile.edt->pi.ptype == PT_TCP || cfile.edt->pi.ptype == PT_UDP ||
1637 cfile.cd_t == WTAP_FILE_BER;
1642 * This routine creates the bulk of the "Decode As" dialog box. All
1643 * items created by this routine are packed as pages into a notebook.
1644 * There will be a page for each protocol layer that can be change.
1646 * @param GtkWidget * A pointer to the widget in which the notebook
1647 * should be installed.
1650 decode_add_notebook (GtkWidget *format_hb)
1652 GtkWidget *notebook, *page, *label;
1655 /* Start a nootbook for flipping between sets of changes */
1656 notebook = gtk_notebook_new();
1657 gtk_container_add(GTK_CONTAINER(format_hb), notebook);
1658 g_object_set_data(G_OBJECT(decode_w), E_NOTEBOOK, notebook);
1660 /* Add link level selection page */
1661 if (cfile.edt->pi.ethertype) {
1662 g_snprintf(buffer, sizeof(buffer), "Ethertype 0x%04x", cfile.edt->pi.ethertype);
1663 page = decode_add_simple_page(buffer, "Link", "ethertype", cfile.edt->pi.ethertype);
1664 label = gtk_label_new("Link");
1665 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1668 /* Add mpls selection page */
1669 if (cfile.edt->pi.mpls_label) {
1670 g_snprintf(buffer, sizeof(buffer), "Data after label %u", cfile.edt->pi.mpls_label);
1671 page = decode_add_simple_page(buffer, "MPLS", "mpls.label", cfile.edt->pi.mpls_label);
1672 label = gtk_label_new("MPLS");
1673 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1676 /* Add network selection page */
1677 if (cfile.edt->pi.ipproto) {
1679 * The network-layer protocol is IP.
1681 g_snprintf(buffer, sizeof(buffer), "IP protocol %u", cfile.edt->pi.ipproto);
1682 page = decode_add_simple_page(buffer, "Network", "ip.proto", cfile.edt->pi.ipproto);
1683 g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_simple);
1684 label = gtk_label_new("Network");
1685 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1688 /* Add transport selection page */
1689 switch (cfile.edt->pi.ptype) {
1692 page = decode_add_tcpudp_page("TCP", "tcp.port");
1696 page = decode_add_tcpudp_page("UDP", "udp.port");
1700 page = decode_add_sctp_page("SCTP", "sctp.ppi");
1708 label = gtk_label_new("Transport");
1709 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1712 if(cfile.edt->pi.dcetransporttype != -1) {
1713 page = decode_dcerpc_add_page(&cfile.edt->pi);
1714 label = gtk_label_new("DCE-RPC");
1715 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1716 g_object_set_data(G_OBJECT(decode_w), E_PAGE_DCERPC, page);
1719 if(cfile.cd_t == WTAP_FILE_BER) {
1720 page = decode_ber_add_page(&cfile.edt->pi);
1721 label = gtk_label_new("ASN.1");
1722 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1723 g_object_set_data(G_OBJECT(decode_w), E_PAGE_ASN1, page);
1726 /* Select the last added page (selects first by default) */
1727 /* Notebook must be visible for set_page to work. */
1728 gtk_widget_show_all(notebook);
1729 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);
1735 * This routine creates the "Decode As" dialog box. This dialog box
1736 * asks the user which protocol to use for decoding the currently
1737 * selected packet. This will affect the last packet that we called a
1738 * dissection routine on belongs (this might be the most recently
1739 * selected packet, or it might be the last packet in the file).
1741 * This routine uses an auxiliary function to create the bulk of the
1742 * dialog box, and then hand crafts the button box at the bottom of
1746 * @param data Unknown
1749 decode_as_cb (GtkWidget * w _U_, gpointer data _U_)
1751 GtkWidget *main_vb, *format_hb, *bbox, *ok_bt, *close_bt, *help_bt, *button;
1752 GtkWidget *button_vb, *apply_bt;
1753 GtkTooltips *tooltips = gtk_tooltips_new();
1755 if (decode_w != NULL) {
1756 /* There's already a "Decode As" dialog box; reactivate it. */
1757 reactivate_window(decode_w);
1761 requested_action = E_DECODE_YES;
1762 decode_w = dlg_window_new("Wireshark: Decode As");
1763 /* Provide a minimum of a couple of rows worth of data */
1764 gtk_window_set_default_size(GTK_WINDOW(decode_w), -1, E_DECODE_MIN_HEIGHT);
1766 /* Container for each row of widgets */
1767 main_vb = gtk_vbox_new(FALSE, 2);
1768 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
1769 gtk_container_add(GTK_CONTAINER(decode_w), main_vb);
1771 /* First row - Buttons and Notebook */
1772 format_hb = gtk_hbox_new(FALSE, 5);
1773 gtk_box_pack_start(GTK_BOX(main_vb), format_hb, TRUE, TRUE, 10);
1775 button_vb = decode_add_yes_no();
1776 gtk_box_pack_start(GTK_BOX(format_hb), button_vb, TRUE, TRUE, 10);
1778 button = gtk_button_new_with_label("Show Current");
1779 g_signal_connect(button, "clicked", G_CALLBACK(decode_show_cb), decode_w);
1780 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1781 gtk_box_pack_start(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1782 gtk_tooltips_set_tip(tooltips, button,
1783 "Open a dialog showing the current settings.", NULL);
1785 button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
1786 g_signal_connect(button, "clicked", G_CALLBACK(decode_clear_cb), decode_w);
1787 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1788 gtk_box_pack_start(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1789 gtk_tooltips_set_tip(tooltips, button,
1790 "Clear ALL settings.", NULL);
1792 decode_add_notebook(format_hb);
1795 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
1796 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
1797 gtk_widget_show(bbox);
1799 ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
1800 g_signal_connect(ok_bt, "clicked", G_CALLBACK(decode_ok_cb), decode_w);
1801 gtk_tooltips_set_tip(tooltips, ok_bt,
1802 "Apply current setting, close dialog and redissect packets.", NULL);
1804 apply_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
1805 g_signal_connect(apply_bt, "clicked", G_CALLBACK(decode_apply_cb), decode_w);
1806 gtk_tooltips_set_tip(tooltips, apply_bt,
1807 "Apply current setting, redissect packets and keep dialog open.", NULL);
1809 close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
1810 window_set_cancel_button(decode_w, close_bt, NULL);
1811 g_signal_connect(close_bt, "clicked", G_CALLBACK(decode_close_cb), decode_w);
1812 gtk_tooltips_set_tip(tooltips, close_bt,
1813 "Close the dialog, don't redissect packets.", NULL);
1815 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
1816 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_DECODE_AS_DIALOG);
1818 gtk_widget_grab_default(ok_bt);
1820 g_signal_connect(decode_w, "delete_event", G_CALLBACK(decode_delete_cb), NULL);
1821 g_signal_connect(decode_w, "destroy", G_CALLBACK(decode_destroy_cb), NULL);
1823 gtk_widget_show_all(decode_w);
1824 window_present(decode_w);