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>
32 #if GTK_CHECK_VERSION(3,0,0)
33 # include <gdk/gdkkeysyms-compat.h>
36 #include <epan/packet.h>
37 #include <epan/epan_dissect.h>
39 #include "../simple_dialog.h"
42 #include "gtk/decode_as_dlg.h"
43 #include "gtk/dlg_utils.h"
44 #include "gtk/gui_utils.h"
45 #include "gtk/decode_as_dcerpc.h"
46 #include "gtk/decode_as_ber.h"
47 #include "gtk/help_dlg.h"
48 #include "utf8_entities.h"
52 /**************************************************/
53 /* Typedefs & Enums */
54 /**************************************************/
57 * Enum used to track which transport layer port combo_box item is
58 * currently selected in the dialog. These items are labeled "source",
59 * "destination", and "source/destination".
62 /* The "source port" combo_box item is currently selected. */
64 /* The "destination port" combo_box item is currently selected. */
66 /* The "source/destination port" combo_box item is currently selected. */
68 /* For SCTP only. This MUST be the last entry! */
72 #define E_DECODE_MIN_HEIGHT 300
73 #define E_NOTEBOOK "notebook"
75 #define E_COMBO_BOX_SRCDST "combo_box_src_dst"
77 #define E_PAGE_DPORT "dport"
78 #define E_PAGE_SPORT "sport"
79 #define E_PAGE_PPID "ppid"
80 #define E_PAGE_ASN1 "asn1"
84 * Columns for a "Display" list
86 #define E_LIST_D_TABLE 0
87 #define E_LIST_D_SELECTOR 1
88 #define E_LIST_D_INITIAL 2
89 #define E_LIST_D_CURRENT 3
90 #define E_LIST_D_MAX E_LIST_D_CURRENT
91 #define E_LIST_D_COLUMNS (E_LIST_D_MAX + 1)
93 /**************************************************/
94 /* File Global Variables */
95 /**************************************************/
98 * Keep a static pointer to the current "Decode As" window. This is
99 * kept so that if somebody tries to do "Tools:Decode As" while
100 * there's already a "Decode As" window up, we just pop up the
101 * existing one, rather than creating a new one.
103 static GtkWidget *decode_w = NULL;
106 * A static pointer to the current "Decode As:Show" window. This is
107 * kept so that if somebody tries to do clock the "Show Current"
108 * button or select the "Display:User Specified Decodes" menu item
109 * while there's already a "Decode As:Show" window up, we just pop up
110 * the existing one, rather than creating a new one.
112 static GtkWidget *decode_show_w = NULL;
115 * A list of the dialog items that only have meaning when the user has
116 * selected the "Decode" radio button. When the "Do not decode"
117 * button is selected these items should be dimmed.
119 GSList *decode_dimmable = NULL;
122 * Remember the "action" radio button that is currently selected in
123 * the dialog. This value is initialized when the dialog is created,
124 * modified in a callback routine, and read in the routine that
125 * handles a click in the "OK" button for the dialog.
127 enum action_type requested_action = -1;
130 /**************************************************/
131 /* Global Functions */
132 /**************************************************/
134 /* init this module */
135 void decode_as_init(void) {
137 decode_dcerpc_init();
140 /**************************************************/
141 /* Reset Changed Dissectors */
142 /**************************************************/
145 * Data structure for tracking which dissector need to be reset. This
146 * structure is necessary as a hash table entry cannot be removed
147 * while a g_hash_table_foreach walk is in progress.
149 struct dissector_delete_item {
150 /* The name of the dissector table */
151 const gchar *ddi_table_name;
152 /* The type of the selector in that dissector table */
153 ftenum_t ddi_selector_type;
154 /* The selector in the dissector table */
162 * A typedef for the data structure to track the original dissector
163 * used for any given port on any given protocol.
165 typedef struct dissector_delete_item dissector_delete_item_t;
168 * A list of dissectors that need to be reset.
170 GSList *dissector_reset_list = NULL;
173 * This routine creates one entry in the list of protocol dissector
174 * that need to be reset. It is called by the g_hash_table_foreach
175 * routine once for each changed entry in a dissector table.
176 * Unfortunately it cannot delete the entry immediately as this screws
177 * up the foreach function, so it builds a list of dissectors to be
178 * reset once the foreach routine finishes.
180 * @param table_name The table name in which this dissector is found.
182 * @param key A pointer to the key for this entry in the dissector
183 * hash table. This is generally the numeric selector of the
184 * protocol, i.e. the ethernet type code, IP port number, TCP port
187 * @param value A pointer to the value for this entry in the dissector
188 * hash table. This is an opaque pointer that can only be handed back
189 * to routine in the file packet.c - but it's unused.
191 * @param user_data Unused.
194 decode_build_reset_list (const gchar *table_name, ftenum_t selector_type,
195 gpointer key, gpointer value _U_,
196 gpointer user_data _U_)
198 dissector_delete_item_t *item;
200 item = g_malloc(sizeof(dissector_delete_item_t));
201 item->ddi_table_name = table_name;
202 item->ddi_selector_type = selector_type;
203 switch (selector_type) {
209 item->ddi_selector.sel_uint = GPOINTER_TO_UINT(key);
214 item->ddi_selector.sel_string = key;
218 g_assert_not_reached();
220 dissector_reset_list = g_slist_prepend(dissector_reset_list, item);
224 /**************************************************/
225 /* Show Changed Dissectors */
226 /**************************************************/
228 #define SORT_ALPHABETICAL 0
231 sort_iter_compare_func (GtkTreeModel *model,
236 gint sortcol = GPOINTER_TO_INT(user_data);
240 case SORT_ALPHABETICAL:
242 gchar *name1, *name2;
243 gtk_tree_model_get(model, a, 0, &name1, -1);
244 gtk_tree_model_get(model, b, 0, &name2, -1);
245 if (name1 == NULL || name2 == NULL)
247 if (name1 == NULL && name2 == NULL)
248 break; /* both equal => ret = 0 */
249 ret = (name1 == NULL) ? -1 : 1;
253 ret = g_ascii_strcasecmp(name1,name2);
260 g_return_val_if_reached(0);
267 decode_add_to_show_list (gpointer list_data,
268 const gchar *table_name,
269 gchar *selector_name,
270 const gchar *initial_proto_name,
271 const gchar *current_proto_name)
273 const gchar *text[E_LIST_D_COLUMNS];
277 store = (GtkListStore *)list_data;
279 text[E_LIST_D_TABLE] = table_name;
280 text[E_LIST_D_SELECTOR] = selector_name;
281 text[E_LIST_D_INITIAL] = initial_proto_name;
282 text[E_LIST_D_CURRENT] = current_proto_name;
283 gtk_list_store_append(store, &iter);
284 gtk_list_store_set(store, &iter, E_LIST_D_TABLE, text[E_LIST_D_TABLE],
285 E_LIST_D_SELECTOR, text[E_LIST_D_SELECTOR],
286 E_LIST_D_INITIAL, text[E_LIST_D_INITIAL],
287 E_LIST_D_CURRENT, text[E_LIST_D_CURRENT], -1);
292 * This routine creates one entry in the list of protocol dissector
293 * that have been changed. It is called by the g_hash_foreach routine
294 * once for each changed entry in a dissector table.
296 * @param table_name The table name in which this dissector is found.
298 * @param key A pointer to the key for this entry in the dissector
299 * hash table. This is generally the numeric selector of the
300 * protocol, i.e. the ethernet type code, IP port number, TCP port
303 * @param value A pointer to the value for this entry in the dissector
304 * hash table. This is an opaque pointer that can only be handed back
305 * to routine in the file packet.c
307 * @param user_data A pointer to the list in which this information
311 decode_build_show_list (const gchar *table_name, ftenum_t selector_type,
312 gpointer key, gpointer value, gpointer user_data)
314 dissector_handle_t current, initial;
315 const gchar *current_proto_name, *initial_proto_name;
316 gchar *selector_name;
322 current = dtbl_entry_get_handle(value);
324 current_proto_name = "(none)";
326 current_proto_name = dissector_handle_get_short_name(current);
327 initial = dtbl_entry_get_initial_handle(value);
329 initial_proto_name = "(none)";
331 initial_proto_name = dissector_handle_get_short_name(initial);
333 switch (selector_type) {
339 switch (get_dissector_table_base(table_name)) {
342 g_snprintf(string1, sizeof(string1), "%u", GPOINTER_TO_UINT(key));
346 switch (get_dissector_table_selector_type(table_name)) {
349 g_snprintf(string1, sizeof(string1), "0x%02x", GPOINTER_TO_UINT(key));
353 g_snprintf(string1, sizeof(string1), "0x%04x", GPOINTER_TO_UINT(key));
357 g_snprintf(string1, sizeof(string1), "0x%06x", GPOINTER_TO_UINT(key));
361 g_snprintf(string1, sizeof(string1), "0x%08x", GPOINTER_TO_UINT(key));
365 g_assert_not_reached();
371 g_snprintf(string1, sizeof(string1), "%#o", GPOINTER_TO_UINT(key));
374 selector_name = string1;
383 g_assert_not_reached();
384 selector_name = NULL;
388 decode_add_to_show_list (
390 get_dissector_table_ui_name(table_name),
397 /* clear all settings */
399 decode_clear_all(void)
401 dissector_delete_item_t *item;
404 dissector_all_tables_foreach_changed(decode_build_reset_list, NULL);
406 for (tmp = dissector_reset_list; tmp; tmp = g_slist_next(tmp)) {
408 switch (item->ddi_selector_type) {
414 dissector_reset_uint(item->ddi_table_name,
415 item->ddi_selector.sel_uint);
420 dissector_reset_string(item->ddi_table_name,
421 item->ddi_selector.sel_string);
425 g_assert_not_reached();
429 g_slist_free(dissector_reset_list);
430 dissector_reset_list = NULL;
432 decode_dcerpc_reset_all();
439 * This routine is called when the user clicks the "OK" button in
440 * the "Decode As:Show..." dialog window. This routine destroys the
441 * dialog box and performs other housekeeping functions.
443 * @param ok_bt A pointer to the "OK" button.
445 * @param parent_w A pointer to the dialog window.
448 decode_show_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
450 window_destroy(GTK_WIDGET(parent_w));
455 * This routine is called when the user clicks the "Clear" button in
456 * the "Decode As:Show..." dialog window. This routine resets all the
457 * dissector values and then destroys the dialog box and performs
458 * other housekeeping functions.
460 * @param clear_bt A pointer to the "Clear" button.
462 * @param parent_w A pointer to the dialog window.
465 decode_show_clear_cb (GtkWidget *clear_bt _U_, gpointer parent_w)
469 window_destroy(GTK_WIDGET(parent_w));
474 * This routine is called when the user clicks the X at the top right end in
475 * the "Decode As:Show..." dialog window. This routine simply calls the
476 * ok routine as if the user had clicked the ok button.
478 * @param win A pointer to the dialog box.
480 * @param event A pointer to the event struct
482 * @param user_data Unused
485 decode_show_delete_cb (GtkWidget *win _U_, GdkEvent *event _U_, gpointer user_data _U_)
487 decode_show_ok_cb(NULL, decode_show_w);
493 * This routine is called at the destruction of the "Decode As:Show"
494 * dialog box. It clears the pointer maintained by this file, so that
495 * the next time the user clicks the "Decode As:Show" button a new
496 * dialog box will be created.
498 * @param win A pointer to the dialog box.
500 * @param user_data Unused
503 decode_show_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
505 /* Note that we no longer have a "Decode As:Show" dialog box. */
506 decode_show_w = NULL;
511 * This routine creates the "Decode As:Show" dialog box. This dialog box
512 * shows the user which protocols have had their dissectors changed.
516 * @param user_data Unused
519 decode_show_cb (GtkWidget *w _U_, gpointer user_data _U_)
521 GtkWidget *main_vb, *bbox, *ok_bt, *clear_bt, *help_bt, *scrolled_window;
522 const gchar *titles[E_LIST_D_COLUMNS] = {
523 "Table", "Value", "Initial", "Current"
528 GtkCellRenderer *renderer;
529 GtkTreeViewColumn *tc;
532 if (decode_show_w != NULL) {
533 /* There's already a "Decode As" dialog box; reactivate it. */
534 reactivate_window(decode_show_w);
538 decode_show_w = dlg_window_new("Wireshark: Decode As: Show");
539 /* Provide a minimum of a couple of rows worth of data */
540 gtk_window_set_default_size(GTK_WINDOW(decode_show_w), -1, E_DECODE_MIN_HEIGHT);
542 /* Container for each row of widgets */
543 main_vb = gtk_vbox_new(FALSE, 2);
544 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
545 gtk_container_add(GTK_CONTAINER(decode_show_w), main_vb);
547 /* Initialize list */
548 store = gtk_list_store_new(E_LIST_D_COLUMNS, G_TYPE_STRING,
549 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
550 list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
551 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
552 gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(list), FALSE);
553 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(list),
556 for (column = 0; column < E_LIST_D_COLUMNS; column++) {
557 renderer = gtk_cell_renderer_text_new();
558 tc = gtk_tree_view_column_new_with_attributes(titles[column],
561 gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
562 gtk_tree_view_append_column(list, tc);
566 dissector_all_tables_foreach_changed(decode_build_show_list, store);
567 g_object_unref(G_OBJECT(store));
568 decode_dcerpc_add_show_list(store);
570 /* Put list into a scrolled window */
571 scrolled_window = scrolled_window_new(NULL, NULL);
572 /* this will result to set the width of the dialog to the required size */
573 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
574 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
575 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window),
577 gtk_container_add(GTK_CONTAINER(scrolled_window),
579 gtk_box_pack_start(GTK_BOX(main_vb), scrolled_window, TRUE, TRUE, 0);
582 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CLEAR, GTK_STOCK_HELP, NULL);
583 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
584 gtk_widget_show(bbox);
586 ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
587 g_signal_connect(ok_bt, "clicked", G_CALLBACK(decode_show_ok_cb), decode_show_w);
589 clear_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLEAR);
590 g_signal_connect(clear_bt, "clicked", G_CALLBACK(decode_show_clear_cb), decode_show_w);
592 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
593 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_DECODE_AS_SHOW_DIALOG);
595 /* set ok as default, this button won't change anything */
596 window_set_cancel_button(decode_show_w, ok_bt, NULL);
598 g_signal_connect(decode_show_w, "delete_event", G_CALLBACK(decode_show_delete_cb), NULL);
599 g_signal_connect(decode_show_w, "destroy", G_CALLBACK(decode_show_destroy_cb), NULL);
601 gtk_widget_set_sensitive(clear_bt,
602 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter));
604 gtk_widget_show_all(decode_show_w);
605 window_present(decode_show_w);
609 /**************************************************/
610 /* Modify the dissector routines */
611 /**************************************************/
614 * Modify a single dissector. This routine first takes care of
615 * updating the internal table of original protocol/port/dissector
616 * combinations by adding a new entry (or removing an existing entry
617 * if the value is being set back to its default). This routine then
618 * performs the actual modification to the packet dissector tables.
620 * @param s Pointer to a string buffer. This buffer is used to build
621 * up a message indicating which ports have had their dissector
622 * changed. This output will be displayed all at once after all
623 * dissectors have been modified.
625 * @param table_name The table name in which the dissector should be
628 * @param selector An enum value indication which selector value
629 * (i.e. IP protocol number, TCP port number, etc.)is to be changed.
631 * @param list The List in which all the selection information can
634 * @return gchar * Pointer to the next free location in the string
638 decode_change_one_dissector(gchar *table_name, guint selector, GtkWidget *list)
640 dissector_handle_t handle;
642 GtkTreeSelection *selection;
646 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(list));
647 if (gtk_tree_selection_get_selected(selection, &model, &iter) == FALSE)
652 gtk_tree_model_get(model, &iter, E_LIST_S_PROTO_NAME, &abbrev,
653 E_LIST_S_TABLE+1, &handle, -1);
656 if (abbrev != NULL && strcmp(abbrev, "(default)") == 0) {
657 dissector_reset_uint(table_name, selector);
659 dissector_change_uint(table_name, selector, handle);
665 /**************************************************/
666 /* Action routines for the "Decode As..." dialog */
667 /* - called when the OK button pressed */
668 /* - one per notebook page */
669 /**************************************************/
674 * Print debugging information about tree view selection. Extract all
675 * information from the tree view entry that was selected and print it to
678 * @param tree_view The tree view to dump.
680 * @param leadin A string to print at the start of each line.
683 decode_debug (GtkTreeView *tree_view, gchar *leadin)
686 GtkTreeSelection *selection;
688 char *string, *text[E_LIST_S_COLUMNS];
689 dissector_handle_t handle;
691 selection = gtk_tree_view_get_selection(tree_view);
693 if (gtk_tree_selection_get_selected(selection, NULL, &iter)){
694 store = GTK_LIST_STORE(gtk_tree_view_get_model(tree_view));
695 gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
696 E_LIST_S_PROTO_NAME, &text[E_LIST_S_PROTO_NAME],
697 E_LIST_S_TABLE, &text[E_LIST_S_TABLE],
698 E_LIST_S_TABLE+1, &handle,
700 string = g_strdup_printf("%s list: <put handle here>, name %s, table %s",
701 leadin, text[E_LIST_S_PROTO_NAME],
702 text[E_LIST_S_TABLE]);
704 string = g_strdup_printf("%s list row (none), aka do not decode", leadin);
706 simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, string);
713 * This routine is called when the user clicks the "OK" button in the
714 * "Decode As..." dialog window and a 'simple' page is foremost.
715 * This routine takes care of making any changes requested to the
716 * dissector tables. This routine is currently used for IP and
717 * Ethertypes. Any 'single change' notebook page can use this
720 * @param notebook_pg A pointer to the "network" notebook page.
723 decode_simple (GtkWidget *notebook_pg)
732 list = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_LIST);
733 if (requested_action == E_DECODE_NO)
734 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
737 string = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TITLE);
738 decode_debug(GTK_TREE_VIEW(list), string);
741 table_name = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TABLE);
742 value = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_VALUE));
743 decode_change_one_dissector(table_name, value, list);
748 * This routine is called when the user clicks the "OK" button in the
749 * "Decode As..." dialog window and the transport page is foremost.
750 * This routine takes care of making any changes requested to the TCP
751 * or UDP dissector tables.
753 * @param notebook_pg A pointer to the "transport" notebook page.
756 decode_transport(GtkWidget *notebook_pg)
758 GtkWidget *combo_box;
761 gint requested_srcdst, requested_port, ppid;
768 list = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_LIST);
769 if (requested_action == E_DECODE_NO)
770 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)));
772 combo_box = g_object_get_data(G_OBJECT(notebook_pg), E_COMBO_BOX_SRCDST);
773 if (!ws_combo_box_get_active_pointer(GTK_COMBO_BOX(combo_box), &ptr))
774 g_assert_not_reached(); /* Programming error if no active item in combo_box */
775 requested_srcdst = GPOINTER_TO_INT(ptr);
778 string = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TITLE);
779 decode_debug(GTK_TREE_VIEW(list), string);
782 table_name = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_TABLE);
783 if (requested_srcdst >= E_DECODE_PPID) {
784 if (requested_srcdst == E_DECODE_PPID)
787 if (requested_srcdst - E_DECODE_PPID - 1 < MAX_NUMBER_OF_PPIDS)
788 ppid = cfile.edt->pi.ppids[requested_srcdst - E_DECODE_PPID - 1];
791 decode_change_one_dissector(table_name, ppid, list);
794 if (requested_srcdst != E_DECODE_DPORT) {
795 portp = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_SPORT);
797 requested_port = GPOINTER_TO_INT(portp);
798 decode_change_one_dissector(table_name, requested_port, list);
801 if (requested_srcdst != E_DECODE_SPORT) {
802 portp = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_DPORT);
804 requested_port = GPOINTER_TO_INT(portp);
805 decode_change_one_dissector(table_name, requested_port, list);
811 /**************************************************/
812 /* Signals from the "Decode As..." dialog */
813 /**************************************************/
816 * This routine is called when the user clicks the "OK" button in the
817 * "Decode As..." dialog window. This routine calls various helper
818 * routines to set/clear dissector values as requested by the user.
819 * These routines accumulate information on what actions they have
820 * taken, and this summary information is printed by this routine.
821 * This routine then destroys the dialog box and performs other
822 * housekeeping functions.
824 * @param ok_bt A pointer to the "OK" button.
826 * @param parent_w A pointer to the dialog window.
829 decode_ok_cb (GtkWidget *ok_bt _U_, gpointer parent_w)
831 GtkWidget *notebook, *notebook_pg;
832 void (* func)(GtkWidget *);
834 void *binding = NULL;
836 /* Call the right routine for the page that was currently in front. */
837 notebook = g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
838 page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
839 notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
841 func = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_ACTION);
844 /* Now destroy the "Decode As" dialog. */
845 notebook_pg = g_object_get_data(G_OBJECT(parent_w), E_PAGE_DCERPC);
847 binding = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_BINDING);
850 decode_dcerpc_binding_free(binding);
852 window_destroy(GTK_WIDGET(parent_w));
853 g_slist_free(decode_dimmable);
854 decode_dimmable = NULL;
860 * This routine is called when the user clicks the "Apply" button in the
861 * "Decode As..." dialog window. This routine calls various helper
862 * routines to set/clear dissector values as requested by the user.
863 * These routines accumulate information on what actions they have
864 * taken, and this summary information is printed by this routine.
866 * @param apply_bt A pointer to the "Apply" button.
868 * @param parent_w A pointer to the dialog window.
871 decode_apply_cb (GtkWidget *apply_bt _U_, gpointer parent_w)
873 GtkWidget *notebook, *notebook_pg;
874 void (* func)(GtkWidget *);
877 /* Call the right routine for the page that was currently in front. */
878 notebook = g_object_get_data(G_OBJECT(parent_w), E_NOTEBOOK);
879 page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
880 notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
882 func = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_ACTION);
889 * This routine is called when the user clicks the "Close" button in
890 * the "Decode As..." dialog window. This routine then destroys the
891 * dialog box and performs other housekeeping functions.
893 * @param close_bt A pointer to the "Close" button.
895 * @param parent_w A pointer to the dialog window.
898 decode_close_cb (GtkWidget *close_bt _U_, gpointer parent_w)
900 GtkWidget *notebook_pg = NULL;
901 void *binding = NULL;
904 notebook_pg = g_object_get_data(G_OBJECT(parent_w), E_PAGE_DCERPC);
906 binding = g_object_get_data(G_OBJECT(notebook_pg), E_PAGE_BINDING);
909 decode_dcerpc_binding_free(binding);
911 window_destroy(GTK_WIDGET(parent_w));
912 g_slist_free(decode_dimmable);
913 decode_dimmable = NULL;
918 * This routine is called when the user clicks the "Close" button in
919 * the "Decode As..." dialog window. This routine simply calls the
920 * close routine as if the user had clicked the close button instead
921 * of the close button.
923 * @param decode_w_lcl A pointer to the dialog box.
925 * @param event A pointer to the GdkEvent struct
927 * @param user_data Unused
930 decode_delete_cb (GtkWidget *decode_w_lcl, GdkEvent *event _U_, gpointer user_data _U_)
932 decode_close_cb(NULL, decode_w_lcl);
938 * This routine is called at the destruction of the "Decode As..."
939 * dialog box. It clears the pointer maintained by this file, so that
940 * the next time the user selects the "Decode As..." menu item a new
941 * dialog box will be created.
943 * @param win A pointer to the dialog box.
945 * @param user_data Unused
950 decode_destroy_cb (GtkWidget *win _U_, gpointer user_data _U_)
952 /* Note that we no longer have a "Decode As" dialog box. */
958 * This routine is called when the user clicks the "Clear" button in
959 * the "Decode As..." dialog window. This routine resets all the
960 * dissector values and performs other housekeeping functions.
962 * @param clear_bt A pointer to the "Clear" button.
964 * @param user_data Unused
967 decode_clear_cb(GtkWidget *clear_bt _U_, gpointer user_data _U_)
974 /**************************************************/
975 /* Dialog setup - radio buttons */
976 /**************************************************/
979 * Update the requested action field of the dialog. This routine is
980 * called by GTK when either of the two radio buttons in the dialog is
983 * @param w The radio button that was clicked.
985 * @param user_data The enum value assigned to this radio button. This
986 * will be either E_DECODE_YES or E_DECODE_NO
989 decode_update_action (GtkWidget *w _U_, gpointer user_data)
994 requested_action = GPOINTER_TO_INT(user_data);
995 enable = (requested_action == E_DECODE_YES);
996 for (tmp = decode_dimmable; tmp; tmp = g_slist_next(tmp)) {
997 gtk_widget_set_sensitive(tmp->data, enable);
1002 * This routine is called to create the "Decode" and "Do not decode"
1003 * radio buttons. These buttons are installed into a vbox, and set up
1004 * as a format group.
1006 * @return GtkWidget * A pointer to the vbox containing the buttons
1009 decode_add_yes_no (void)
1011 GtkWidget *format_vb, *radio_button;
1014 format_vb = gtk_vbox_new(FALSE, 2);
1016 radio_button = gtk_radio_button_new_with_label(NULL, "Decode");
1017 format_grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio_button));
1018 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1019 g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_update_action),
1020 GINT_TO_POINTER(E_DECODE_YES));
1021 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1023 radio_button = gtk_radio_button_new_with_label(format_grp, "Do not decode");
1024 g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_update_action),
1025 GINT_TO_POINTER(E_DECODE_NO));
1026 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1031 /**************************************************/
1032 /* Dialog setup - simple combo_boxes */
1033 /**************************************************/
1036 * This routine is called to pack an combo_box into an aligment, so
1037 * that it doesn't expand vertically to fill up the space available to
1040 * @param combo_box A pointer to the option menu to be so packed.
1042 * @return GtkWidget * A pointer to the newly created alignment.
1045 decode_add_pack_combo_box (GtkWidget *combo_box)
1047 GtkWidget *alignment;
1049 alignment = gtk_alignment_new(0.0f, 0.5f, 0.0f, 0.0f);
1050 gtk_container_add(GTK_CONTAINER(alignment), combo_box);
1057 * This routine is called to add the transport port selection combo_box to
1058 * the dialog box. This is a three choice combo_box: source, destination
1059 * and both. The default choice for the combo_box is set to the source
1060 * port number of the currently selected packet.
1062 * @param page A pointer notebook page that will contain all
1063 * widgets created by this routine.
1065 * @return GtkWidget * A pointer to the newly created alignment into
1066 * which we've packed the newly created combo_box.
1069 decode_add_srcdst_combo_box (GtkWidget *page)
1071 GtkWidget *combo_box, *alignment;
1074 combo_box = ws_combo_box_new_text_and_pointer();
1076 g_snprintf(tmp, sizeof(tmp), "Source (%u%s)", cfile.edt->pi.srcport, UTF8_RIGHTWARDS_ARROW);
1077 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box), tmp, GINT_TO_POINTER(E_DECODE_SPORT));
1079 g_snprintf(tmp, sizeof(tmp), "Destination (%s%u)", UTF8_RIGHTWARDS_ARROW, cfile.edt->pi.destport);
1080 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box), tmp, GINT_TO_POINTER(E_DECODE_DPORT));
1082 g_snprintf(tmp, sizeof(tmp), "Both (%u%s%u)", cfile.edt->pi.srcport,UTF8_LEFT_RIGHT_ARROW, cfile.edt->pi.destport);
1083 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box), tmp, GINT_TO_POINTER(E_DECODE_BPORT));
1084 ws_combo_box_set_active(GTK_COMBO_BOX(combo_box), 2); /* default "both" */
1085 g_object_set_data(G_OBJECT(page), E_COMBO_BOX_SRCDST, combo_box);
1087 g_object_set_data(G_OBJECT(page), E_PAGE_SPORT, GINT_TO_POINTER(cfile.edt->pi.srcport));
1088 g_object_set_data(G_OBJECT(page), E_PAGE_DPORT, GINT_TO_POINTER(cfile.edt->pi.destport));
1090 alignment = decode_add_pack_combo_box(combo_box);
1095 decode_add_ppid_combo_box (GtkWidget *page)
1097 GtkWidget *combo_box;
1099 guint number_of_ppid;
1101 combo_box = ws_combo_box_new_text_and_pointer();
1103 g_snprintf(tmp, sizeof(tmp), "PPID (%u)", 0);
1104 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box),
1105 tmp, GINT_TO_POINTER(E_DECODE_PPID));
1106 ws_combo_box_set_active(GTK_COMBO_BOX(combo_box), 0); /* default */
1108 for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++) {
1109 if (cfile.edt->pi.ppids[number_of_ppid] != 0) {
1110 g_snprintf(tmp, sizeof(tmp), "PPID (%u)", cfile.edt->pi.ppids[number_of_ppid]);
1111 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(combo_box),
1112 tmp, GINT_TO_POINTER(E_DECODE_PPID + 1 + number_of_ppid));
1116 g_object_set_data(G_OBJECT(page), E_COMBO_BOX_SRCDST, combo_box);
1120 /*************************************************/
1121 /* Dialog setup - list based menus */
1122 /*************************************************/
1124 struct handle_lookup_info {
1125 dissector_handle_t handle;
1130 lookup_handle(GtkTreeModel *model, GtkTreePath *path _U_, GtkTreeIter *iter,
1133 dissector_handle_t handle;
1134 struct handle_lookup_info *hli = user_data;
1136 gtk_tree_model_get(model, iter, E_LIST_S_TABLE+1, &handle, -1);
1137 if (hli->handle == handle) {
1145 * This routine creates one entry in the list of protocol dissector
1146 * that can be used. It is called by the dissector_table_foreach_handle
1147 * routine once for each entry in a dissector table's list of handles
1148 * for dissectors that could be used in that table. It guarantees unique
1149 * entries by iterating over the list of entries build up to this point,
1150 * looking for a duplicate name. If there is no duplicate, then this
1151 * entry is added to the list of possible dissectors.
1153 * @param table_name The name of the dissector table currently
1156 * @param proto_name The protocol name
1158 * @param value The dissector handle for this entry. This is an opaque
1159 * pointer that can only be handed back to routines in the file packet.c
1161 * @param user_data A data block passed into each instance of this
1162 * routine. It contains information from the caller of the foreach
1163 * routine, specifying information about the dissector table and where
1164 * to store any information generated by this routine.
1167 decode_add_to_list (const gchar *table_name, const gchar *proto_name, gpointer value, gpointer user_data)
1169 const gchar *text[E_LIST_S_COLUMNS];
1171 GtkListStore *store;
1173 struct handle_lookup_info hli;
1175 g_assert(user_data);
1182 store = GTK_LIST_STORE(gtk_tree_view_get_model(list));
1183 gtk_tree_model_foreach(GTK_TREE_MODEL(store), lookup_handle, &hli);
1184 /* We already have an entry for this handle.
1185 * XXX - will this ever happen? */
1186 if (hli.found) return;
1188 text[E_LIST_S_PROTO_NAME] = proto_name;
1189 text[E_LIST_S_TABLE] = table_name;
1190 gtk_list_store_append(store, &iter);
1191 gtk_list_store_set(store, &iter,
1192 E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1193 E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1194 E_LIST_S_TABLE+1, value, -1);
1198 decode_proto_add_to_list (const gchar *table_name, gpointer value, gpointer user_data)
1200 const gchar *proto_name;
1202 dissector_handle_t handle;
1206 proto_name = dissector_handle_get_short_name(handle);
1208 i = dissector_handle_get_protocol_index(handle);
1209 if (i >= 0 && !proto_is_protocol_enabled(find_protocol_by_id(i)))
1212 decode_add_to_list (table_name, proto_name, value, user_data);
1217 decode_list_button_press_cb(GtkWidget *list, GdkEventButton *event, gpointer user_data _U_)
1219 if (event->type == GDK_2BUTTON_PRESS) {
1220 GtkWidget *main_w = gtk_widget_get_toplevel(list);
1222 decode_ok_cb (NULL, main_w);
1229 decode_list_key_release_cb(GtkWidget *list, GdkEventKey *event, gpointer user_data _U_)
1231 if (event->keyval == GDK_Return || event->keyval == GDK_KP_Enter) {
1232 GtkWidget *main_w = gtk_widget_get_toplevel(list);
1234 decode_ok_cb (NULL, main_w);
1241 * This routine starts the creation of a List on a notebook page. It
1242 * creates both a scrolled window and a list, adds the list to the
1243 * window, and attaches the list as a data object on the page.
1245 * @param page A pointer to the notebook page being created.
1247 * @param list_p Will be filled in with the address of a newly
1250 * @param scrolled_win_p Will be filled in with the address of a newly
1251 * created GtkScrolledWindow.
1254 decode_list_menu_start(GtkWidget *page, GtkWidget **list_p,
1255 GtkWidget **scrolled_win_p)
1258 GtkListStore *store;
1259 GtkCellRenderer *renderer;
1260 GtkTreeViewColumn *tc;
1261 GtkTreeSortable *sortable;
1263 store = gtk_list_store_new(E_LIST_S_COLUMNS+1, G_TYPE_STRING,
1264 G_TYPE_STRING, G_TYPE_POINTER);
1265 g_object_set_data(G_OBJECT(decode_w), "sctp_data", store);
1266 list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(store)));
1267 g_object_unref(G_OBJECT(store));
1268 sortable = GTK_TREE_SORTABLE(store);
1269 gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
1270 gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
1271 gtk_tree_view_set_headers_clickable(list, FALSE);
1273 gtk_tree_view_set_headers_visible(list, FALSE);
1275 renderer = gtk_cell_renderer_text_new();
1276 tc = gtk_tree_view_column_new_with_attributes("Short Name", renderer,
1277 "text", E_LIST_S_PROTO_NAME,
1279 gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1280 gtk_tree_view_append_column(list, tc);
1281 g_object_set_data(G_OBJECT(page), E_PAGE_LIST, list);
1283 *scrolled_win_p = scrolled_window_new(NULL, NULL);
1284 /* this will result to set the width of the dialog to the required size */
1285 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1286 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1287 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p),
1289 gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
1291 *list_p = GTK_WIDGET(list);
1295 * This routine finishes the creation of a List on a notebook page.
1296 * It adds the default entry, sets the default entry as the
1297 * highlighted entry, and sorts the List.
1299 * @param list A pointer the the List to finish.
1302 decode_list_menu_finish(GtkWidget *list)
1304 const gchar *text[E_LIST_S_COLUMNS];
1305 GtkListStore *store;
1308 text[E_LIST_S_PROTO_NAME] = "(default)";
1309 text[E_LIST_S_TABLE] = "(none)";
1310 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
1311 gtk_list_store_prepend(store, &iter);
1312 gtk_list_store_set(store, &iter,
1313 E_LIST_S_PROTO_NAME, text[E_LIST_S_PROTO_NAME],
1314 E_LIST_S_TABLE, text[E_LIST_S_TABLE],
1315 E_LIST_S_TABLE+1, NULL, -1);
1317 gtk_tree_selection_select_iter(gtk_tree_view_get_selection(GTK_TREE_VIEW(list)), &iter);
1318 g_signal_connect(list, "button_press_event", G_CALLBACK(decode_list_button_press_cb), NULL);
1319 g_signal_connect(list, "key_release_event", G_CALLBACK(decode_list_key_release_cb), NULL);
1323 * This routine is called to add the dissector selection list to a
1324 * notebook page. This scrolled list contains an entry labeled
1325 * "default", and an entry for each protocol that has had a dissector
1326 * registered. The default choice for the list is set to the
1327 * "default" choice, which will return the protocol/port selections to
1328 * their original dissector(s).
1330 * @param page A pointer to the notebook page currently being created.
1332 * @param table_name The name of the dissector table to use to build
1335 * @return GtkWidget * A pointer to the newly created list within a
1339 decode_add_simple_menu (GtkWidget *page, const gchar *table_name)
1341 GtkWidget *scrolled_window;
1344 decode_list_menu_start(page, &list, &scrolled_window);
1345 dissector_table_foreach_handle(table_name, decode_proto_add_to_list, list);
1346 decode_list_menu_finish(list);
1347 return(scrolled_window);
1351 /**************************************************/
1353 /**************************************************/
1356 * This routine creates a sample notebook page in the dialog box.
1357 * This notebook page provides a prompt specifying what is being
1358 * changed and its current value (e.g. "IP Protocol number (17)"), and
1359 * a list specifying all the available choices. The list of choices
1360 * is conditionally enabled, based upon the setting of the
1361 * "decode"/"do not decode" radio buttons.
1363 * @param prompt The prompt for this notebook page
1365 * @param title A title for this page to use when debugging.
1367 * @param table_name The name of the dissector table to use to
1370 * @param value The protocol/port value that is to be changed.
1372 * @return GtkWidget * A pointer to the notebook page created by this
1376 decode_add_simple_page (const gchar *prompt, const gchar *title, const gchar *table_name,
1379 GtkWidget *page, *label, *scrolled_window;
1381 page = gtk_hbox_new(FALSE, 5);
1382 g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_simple);
1383 g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) table_name);
1384 g_object_set_data(G_OBJECT(page), E_PAGE_TITLE, (gchar *) title);
1385 g_object_set_data(G_OBJECT(page), E_PAGE_VALUE, GUINT_TO_POINTER(value));
1387 /* Always enabled */
1388 label = gtk_label_new(prompt);
1389 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1391 /* Conditionally enabled - only when decoding packets */
1392 label = gtk_label_new("as");
1393 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1394 decode_dimmable = g_slist_prepend(decode_dimmable, label);
1395 scrolled_window = decode_add_simple_menu(page, table_name);
1396 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1397 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1404 * This routine creates the TCP or UDP notebook page in the dialog box.
1405 * All items created by this routine are packed into a single
1406 * horizontal box. First is a label indicating whether the port(s) for
1407 * which the user can set the dissection is a TCP port or a UDP port.
1408 * Second is a combo_box allowing the user to select whether the source port,
1409 * destination port, or both ports will have dissectors added for them.
1410 * Last is a (conditionally enabled) popup menu listing all possible
1411 * dissectors that can be used to decode the packets, and the choice
1412 * or returning to the default dissector for these ports.
1414 * The defaults for these items are the transport layer protocol of
1415 * the currently selected packet, the source port of the currently
1416 * selected packet, and the "default dissector".
1418 * @param prompt The prompt for this notebook page
1420 * @param table_name The name of the dissector table to use to
1423 * @return GtkWidget * A pointer to the notebook page created by
1427 decode_add_tcpudp_page (const gchar *prompt, const gchar *table_name)
1429 GtkWidget *page, *label, *scrolled_window, *combo_box;
1431 page = gtk_hbox_new(FALSE, 5);
1432 g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_transport);
1433 g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) table_name);
1434 g_object_set_data(G_OBJECT(page), E_PAGE_TITLE, "Transport");
1436 /* Always enabled */
1437 label = gtk_label_new(prompt);
1438 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1439 combo_box = decode_add_srcdst_combo_box(page);
1440 gtk_box_pack_start(GTK_BOX(page), combo_box, TRUE, TRUE, 0);
1441 label = gtk_label_new("port(s)");
1442 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1444 /* Conditionally enabled - only when decoding packets */
1445 label = gtk_label_new("as");
1446 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1447 decode_dimmable = g_slist_prepend(decode_dimmable, label);
1448 scrolled_window = decode_add_simple_menu(page, table_name);
1449 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1450 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1456 decode_sctp_list_menu_start(GtkWidget **list_p, GtkWidget **scrolled_win_p)
1459 GtkListStore *sctp_store;
1460 GtkCellRenderer *renderer;
1461 GtkTreeViewColumn *tc;
1462 GtkTreeSortable *sortable;
1464 sctp_store = g_object_get_data(G_OBJECT(decode_w), "sctp_data");
1465 list = GTK_TREE_VIEW(tree_view_new(GTK_TREE_MODEL(sctp_store)));
1466 g_object_unref(G_OBJECT(sctp_store));
1467 sortable = GTK_TREE_SORTABLE(sctp_store);
1468 gtk_tree_sortable_set_sort_func(sortable, SORT_ALPHABETICAL, sort_iter_compare_func, GINT_TO_POINTER(SORT_ALPHABETICAL), NULL);
1469 gtk_tree_sortable_set_sort_column_id(sortable, SORT_ALPHABETICAL, GTK_SORT_ASCENDING);
1470 gtk_tree_view_set_headers_clickable(list, FALSE);
1472 gtk_tree_view_set_headers_visible(list, FALSE);
1474 renderer = gtk_cell_renderer_text_new();
1475 tc = gtk_tree_view_column_new_with_attributes("Short Name", renderer,
1476 "text", E_LIST_S_PROTO_NAME,
1478 gtk_tree_view_column_set_sizing(tc, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
1479 gtk_tree_view_append_column(list, tc);
1481 *scrolled_win_p = scrolled_window_new(NULL, NULL);
1482 /* this will result to set the width of the dialog to the required size */
1483 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(*scrolled_win_p), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1484 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(*scrolled_win_p), GTK_SHADOW_IN);
1485 gtk_container_add(GTK_CONTAINER(*scrolled_win_p), GTK_WIDGET(list));
1486 *list_p = GTK_WIDGET(list);
1490 decode_sctp_update_ppid_combo_box(GtkWidget *w _U_, GtkWidget *page)
1492 GtkWidget *list, *scrolled_window;
1493 GtkWidget *sctp_combo_box;
1495 guint number_of_ppid;
1496 GtkListStore *sctp_store;
1498 sctp_combo_box = g_object_get_data(G_OBJECT(page), E_COMBO_BOX_SRCDST);
1499 ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box));
1501 g_snprintf(tmp, sizeof(tmp), "PPID (%u)", 0);
1502 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box), tmp, GINT_TO_POINTER(E_DECODE_PPID));
1503 ws_combo_box_set_active(GTK_COMBO_BOX(sctp_combo_box), 0); /* default */
1505 for(number_of_ppid = 0; number_of_ppid < MAX_NUMBER_OF_PPIDS; number_of_ppid++) {
1506 if (cfile.edt->pi.ppids[number_of_ppid] != 0) {
1507 g_snprintf(tmp, sizeof(tmp), "PPID (%u)", cfile.edt->pi.ppids[number_of_ppid]);
1508 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box),
1509 tmp, GINT_TO_POINTER(E_DECODE_PPID + 1 + number_of_ppid));
1513 g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, "sctp.ppi");
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_combo_box(GtkWidget *w _U_, GtkWidget *page)
1526 GtkWidget *scrolled_window, *list;
1527 GtkWidget *sctp_combo_box;
1529 GtkListStore *sctp_store;
1531 sctp_combo_box = g_object_get_data(G_OBJECT(page), E_COMBO_BOX_SRCDST);
1532 ws_combo_box_clear_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box));
1534 g_snprintf(tmp, sizeof(tmp), "source (%u)", cfile.edt->pi.srcport);
1535 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box), tmp, GINT_TO_POINTER(E_DECODE_SPORT));
1536 g_snprintf(tmp, sizeof(tmp), "destination (%u)", cfile.edt->pi.destport);
1537 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box), tmp, GINT_TO_POINTER(E_DECODE_DPORT));
1538 ws_combo_box_append_text_and_pointer(GTK_COMBO_BOX(sctp_combo_box), "both", GINT_TO_POINTER(E_DECODE_BPORT));
1539 ws_combo_box_set_active(GTK_COMBO_BOX(sctp_combo_box), 0);
1541 g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, "sctp.port");
1542 g_object_set_data(G_OBJECT(page), E_PAGE_SPORT, GINT_TO_POINTER(cfile.edt->pi.srcport));
1543 g_object_set_data(G_OBJECT(page), E_PAGE_DPORT, GINT_TO_POINTER(cfile.edt->pi.destport));
1544 sctp_store = g_object_get_data(G_OBJECT(G_OBJECT(decode_w)), "sctp_data");
1545 gtk_list_store_clear(sctp_store);
1546 decode_sctp_list_menu_start(&list, &scrolled_window);
1547 dissector_table_foreach_handle("sctp.port", decode_proto_add_to_list, list);
1548 decode_list_menu_finish(list);
1554 decode_sctp_add_port_ppid (GtkWidget *page)
1556 GtkWidget *format_vb, *radio_button;
1559 format_vb = gtk_vbox_new(FALSE, 2);
1561 radio_button = gtk_radio_button_new_with_label(NULL, "PPID");
1562 format_grp = gtk_radio_button_get_group(GTK_RADIO_BUTTON(radio_button));
1563 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
1564 g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_sctp_update_ppid_combo_box), page);
1566 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1568 radio_button = gtk_radio_button_new_with_label(format_grp, "Port");
1569 g_signal_connect(radio_button, "clicked", G_CALLBACK(decode_sctp_update_srcdst_combo_box), page);
1571 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
1578 decode_add_sctp_page (const gchar *prompt, const gchar *table_name)
1580 GtkWidget *page, *label, *scrolled_window, *radio, *vbox, *alignment, *sctpbox, *sctp_combo_box;
1582 page = gtk_hbox_new(FALSE, 5);
1583 g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_transport);
1584 g_object_set_data(G_OBJECT(page), E_PAGE_TABLE, (gchar *) table_name);
1585 g_object_set_data(G_OBJECT(page), E_PAGE_TITLE, "Transport");
1587 vbox = gtk_vbox_new(FALSE, 5);
1588 radio = decode_sctp_add_port_ppid(page);
1589 gtk_box_pack_start(GTK_BOX(vbox), radio, TRUE, TRUE, 0);
1591 /* Always enabled */
1592 sctpbox = gtk_hbox_new(FALSE, 5);
1593 label = gtk_label_new(prompt);
1594 gtk_box_pack_start(GTK_BOX(sctpbox), label, TRUE, TRUE, 0);
1595 sctp_combo_box = decode_add_ppid_combo_box(page);
1596 alignment = decode_add_pack_combo_box(sctp_combo_box);
1598 gtk_box_pack_start(GTK_BOX(sctpbox), alignment, TRUE, TRUE, 0);
1600 /* Conditionally enabled - only when decoding packets */
1601 label = gtk_label_new("as");
1602 gtk_box_pack_start(GTK_BOX(sctpbox), label, TRUE, TRUE, 0);
1603 decode_dimmable = g_slist_prepend(decode_dimmable, label);
1604 gtk_box_pack_start(GTK_BOX(vbox), sctpbox, TRUE, TRUE, 0);
1605 gtk_box_pack_start(GTK_BOX(page), vbox, TRUE, TRUE, 0);
1607 scrolled_window = decode_add_simple_menu(page, table_name);
1608 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1609 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1616 * This routine indicates whether we'd actually have any pages in the
1617 * notebook in a "Decode As" dialog box; if there wouldn't be, we
1618 * inactivate the menu item for "Decode As".
1623 return (cfile.edt->pi.ethertype != G_MAXINT) || cfile.edt->pi.ipproto ||
1624 cfile.edt->pi.ptype == PT_TCP || cfile.edt->pi.ptype == PT_UDP ||
1625 cfile.edt->pi.mpls_label ||
1626 cfile.cd_t == WTAP_FILE_BER;
1631 * This routine creates the bulk of the "Decode As" dialog box. All
1632 * items created by this routine are packed as pages into a notebook.
1633 * There will be a page for each protocol layer that can be changed.
1635 * @param format_hb A pointer to the widget in which the notebook
1636 * should be installed.
1639 decode_add_notebook (GtkWidget *format_hb)
1641 GtkWidget *notebook, *page, *label;
1644 /* Start a nootbook for flipping between sets of changes */
1645 notebook = gtk_notebook_new();
1646 gtk_container_add(GTK_CONTAINER(format_hb), notebook);
1647 g_object_set_data(G_OBJECT(decode_w), E_NOTEBOOK, notebook);
1649 /* Add link level selection page */
1650 if (cfile.edt->pi.ethertype != G_MAXINT) {
1651 g_snprintf(buffer, sizeof(buffer), "Ethertype 0x%04x", cfile.edt->pi.ethertype);
1652 page = decode_add_simple_page(buffer, "Link", "ethertype", cfile.edt->pi.ethertype);
1653 label = gtk_label_new("Link");
1654 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1657 /* Add mpls selection page */
1658 if (cfile.edt->pi.mpls_label) {
1659 g_snprintf(buffer, sizeof(buffer), "Data after label %u", cfile.edt->pi.mpls_label);
1660 page = decode_add_simple_page(buffer, "MPLS", "mpls.label", cfile.edt->pi.mpls_label);
1661 label = gtk_label_new("MPLS");
1662 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1665 /* Add network selection page */
1666 if (cfile.edt->pi.ipproto) {
1668 * The network-layer protocol is IP.
1670 g_snprintf(buffer, sizeof(buffer), "IP protocol %u", cfile.edt->pi.ipproto);
1671 page = decode_add_simple_page(buffer, "Network", "ip.proto", cfile.edt->pi.ipproto);
1672 g_object_set_data(G_OBJECT(page), E_PAGE_ACTION, decode_simple);
1673 label = gtk_label_new("Network");
1674 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1677 /* Add transport selection page */
1678 switch (cfile.edt->pi.ptype) {
1681 page = decode_add_tcpudp_page("TCP", "tcp.port");
1685 page = decode_add_tcpudp_page("UDP", "udp.port");
1689 page = decode_add_sctp_page("SCTP", "sctp.ppi");
1697 label = gtk_label_new("Transport");
1698 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1701 if(cfile.edt->pi.dcetransporttype != -1) {
1702 page = decode_dcerpc_add_page(&cfile.edt->pi);
1703 label = gtk_label_new("DCE-RPC");
1704 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1705 g_object_set_data(G_OBJECT(decode_w), E_PAGE_DCERPC, page);
1708 if(cfile.cd_t == WTAP_FILE_BER) {
1709 page = decode_ber_add_page(&cfile.edt->pi);
1710 label = gtk_label_new("ASN.1");
1711 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1712 g_object_set_data(G_OBJECT(decode_w), E_PAGE_ASN1, page);
1715 /* Select the last added page (selects first by default) */
1716 /* Notebook must be visible for set_page to work. */
1717 gtk_widget_show_all(notebook);
1718 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), -1);
1724 * This routine creates the "Decode As" dialog box. This dialog box
1725 * asks the user which protocol to use for decoding the currently
1726 * selected packet. This will affect the last packet that we called a
1727 * dissection routine on belongs (this might be the most recently
1728 * selected packet, or it might be the last packet in the file).
1730 * This routine uses an auxiliary function to create the bulk of the
1731 * dialog box, and then hand crafts the button box at the bottom of
1736 * @param user_data Unused
1739 decode_as_cb (GtkWidget * w _U_, gpointer user_data _U_)
1741 GtkWidget *main_vb, *format_hb, *bbox, *ok_bt, *close_bt, *help_bt, *button;
1742 GtkWidget *button_vb, *apply_bt;
1744 if (decode_w != NULL) {
1745 /* There's already a "Decode As" dialog box; reactivate it. */
1746 reactivate_window(decode_w);
1750 requested_action = E_DECODE_YES;
1751 decode_w = dlg_window_new("Wireshark: Decode As");
1752 /* Provide a minimum of a couple of rows worth of data */
1753 gtk_window_set_default_size(GTK_WINDOW(decode_w), -1, E_DECODE_MIN_HEIGHT);
1755 /* Container for each row of widgets */
1756 main_vb = gtk_vbox_new(FALSE, 2);
1757 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
1758 gtk_container_add(GTK_CONTAINER(decode_w), main_vb);
1760 /* First row - Buttons and Notebook */
1761 format_hb = gtk_hbox_new(FALSE, 5);
1762 gtk_box_pack_start(GTK_BOX(main_vb), format_hb, TRUE, TRUE, 10);
1764 button_vb = decode_add_yes_no();
1765 gtk_box_pack_start(GTK_BOX(format_hb), button_vb, TRUE, TRUE, 10);
1767 button = gtk_button_new_with_label("Show Current");
1768 g_signal_connect(button, "clicked", G_CALLBACK(decode_show_cb), NULL);
1769 #if GTK_CHECK_VERSION(2,18,0)
1770 gtk_widget_set_can_default(button, TRUE);
1772 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1774 gtk_box_pack_start(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1775 gtk_widget_set_tooltip_text(button, "Open a dialog showing the current settings.");
1777 button = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
1778 g_signal_connect(button, "clicked", G_CALLBACK(decode_clear_cb), NULL);
1779 #if GTK_CHECK_VERSION(2,18,0)
1780 gtk_widget_set_can_default(button, TRUE);
1782 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1784 gtk_box_pack_start(GTK_BOX(button_vb), button, FALSE, FALSE, 0);
1785 gtk_widget_set_tooltip_text(button, "Clear ALL settings.");
1787 decode_add_notebook(format_hb);
1790 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_APPLY, GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
1791 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
1792 gtk_widget_show(bbox);
1794 ok_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_OK);
1795 g_signal_connect(ok_bt, "clicked", G_CALLBACK(decode_ok_cb), decode_w);
1796 gtk_widget_set_tooltip_text(ok_bt, "Apply current setting, close dialog and redissect packets.");
1798 apply_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_APPLY);
1799 g_signal_connect(apply_bt, "clicked", G_CALLBACK(decode_apply_cb), decode_w);
1800 gtk_widget_set_tooltip_text(apply_bt, "Apply current setting, redissect packets and keep dialog open.");
1802 close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
1803 window_set_cancel_button(decode_w, close_bt, NULL);
1804 g_signal_connect(close_bt, "clicked", G_CALLBACK(decode_close_cb), decode_w);
1805 gtk_widget_set_tooltip_text(close_bt, "Close the dialog, don't redissect packets.");
1807 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
1808 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_DECODE_AS_DIALOG);
1810 gtk_widget_grab_default(ok_bt);
1812 g_signal_connect(decode_w, "delete_event", G_CALLBACK(decode_delete_cb), NULL);
1813 g_signal_connect(decode_w, "destroy", G_CALLBACK(decode_destroy_cb), NULL);
1815 gtk_widget_show_all(decode_w);
1816 window_present(decode_w);