3 * $Id: decode_as_dlg.c,v 1.21 2001/12/18 19:09:07 gram Exp $
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.
37 #ifdef HAVE_SYS_TYPES_H
38 #include <sys/types.h>
41 #include "decode_as_dlg.h"
42 #include "dlg_utils.h"
44 #include "simple_dialog.h"
48 #include "epan_dissect.h"
52 /**************************************************/
53 /* Typedefs & Enums */
54 /**************************************************/
57 * Enum used to track which radio button is currently selected in the
58 * dialog. These buttons are labeled "Decode" and "Do not decode".
61 /* The "Decode" button is currently selected. */
64 /* The "Do not decode" button is currently selected. */
69 * Enum used to track which transport layer port menu item is
70 * currently selected in the dialog. These items are labeled "source",
71 * "destination", and "source/destination".
74 /* The "source port" menu item is currently selected. */
76 /* The "destination port" menu item is currently selected. */
78 /* The "source/destination port" menu item is currently selected. */
82 #define E_DECODE_MIN_HEIGHT 100
83 #define E_NOTEBOOK "notebook"
85 #define E_MENU_SRCDST "menu_src_dst"
87 #define E_PAGE_ACTION "notebook_page_action"
88 #define E_PAGE_CLIST "notebook_page_clist"
89 #define E_PAGE_TABLE "notebook_page_table_name"
90 #define E_PAGE_TITLE "notebook_page_title"
91 #define E_PAGE_VALUE "notebook_page_value"
94 * Clist columns for a "Select" clist.
95 * Note that most of these columns aren't displayed; they're attached
96 * to the row of the table as additional information.
98 #define E_CLIST_S_PROTO_NAME 0
99 #define E_CLIST_S_TABLE 1
100 /* The following is for debugging in decode_add_to_clist */
101 #define E_CLIST_S_MAX E_CLIST_S_TABLE
102 #define E_CLIST_S_COLUMNS (E_CLIST_S_MAX + 1)
105 * Clist columns for a "Display" clist
107 #define E_CLIST_D_TABLE 0
108 #define E_CLIST_D_PORT 1
109 #define E_CLIST_D_INITIAL 2
110 #define E_CLIST_D_CURRENT 3
111 #define E_CLIST_D_MAX E_CLIST_D_CURRENT
112 #define E_CLIST_D_COLUMNS (E_CLIST_D_MAX + 1)
114 /**************************************************/
115 /* File Global Variables */
116 /**************************************************/
119 * Keep a static pointer to the current "Decode As" window. This is
120 * kept so that if somebody tries to do "Tools:Decode As" while
121 * there's already a "Decode As" window up, we just pop up the
122 * existing one, rather than creating a new one.
124 static GtkWidget *decode_w = NULL;
127 * A static pointer to the current "Decode As:Show" window. This is
128 * kept so that if somebody tries to do clock the "Show Current"
129 * button or slect the "Display:User Specified Decodes" menu item
130 * while there's already a "Decode As:Show" window up, we just pop up
131 * the existing one, rather than creating a new one.
133 static GtkWidget *decode_show_w = NULL;
136 * A list of the dialog items that only have meaning when the user has
137 * selected the "Decode" radio button. When the "Do not decode"
138 * button is selected these items should be dimmed.
140 static GSList *decode_dimmable = NULL;
143 * Remember the "action" radio button that is currently selected in
144 * the dialog. This value is initialized when the dialog is created,
145 * modified in a callback routine, and read in the routine that
146 * handles a click in the "OK" button for the dialog.
148 static enum action_type requested_action = -1;
150 /**************************************************/
151 /* Resett Changed Dissectors */
152 /**************************************************/
155 * Data structure for tracking which dissector need to be reset. This
156 * structure is necessary as a hash table entry cannot be removed
157 * while a g_hash_table_foreach walk is in progress.
159 struct dissector_delete_item {
160 /* The name of the dissector table */
161 const gchar *ddi_table_name;
162 /* The port number in the dissector table */
167 * A typedef for the data structure to track the original dissector
168 * used for any given port on any given protocol.
170 typedef struct dissector_delete_item dissector_delete_item_t;
173 * A list of dissectors that need to be reset.
175 GSList *dissector_reset_list = NULL;
178 * This routine creates one entry in the list of protocol dissector
179 * that need to be reset. It is called by the g_hash_table_foreach
180 * routine once for each changed entry in a dissector table.
181 * Unfortunately it cannot delete the entry immediately as this screws
182 * up the foreach function, so it builds a list of dissectors to be
183 * reset once the foreach routine finishes.
185 * @param table_name The table name in which this dissector is found.
187 * @param key A pointer to the key for this entry in the dissector
188 * hash table. This is generally the numeric selector of the
189 * protocol, i.e. the ethernet type code, IP port number, TCP port
192 * @param value A pointer to the value for this entry in the dissector
193 * hash table. This is an opaque pointer that can only be handed back
194 * to routine in the file packet.c
196 * @param user_data Unused.
199 decode_build_reset_list (gchar *table_name, gpointer key,
200 gpointer value, gpointer user_data)
202 dissector_delete_item_t *item;
204 item = g_malloc(sizeof(dissector_delete_item_t));
205 item->ddi_table_name = table_name;
206 item->ddi_port = GPOINTER_TO_UINT(key);
207 dissector_reset_list = g_slist_prepend(dissector_reset_list, item);
211 /**************************************************/
212 /* Show Changed Dissectors */
213 /**************************************************/
216 * This routine creates one entry in the list of protocol dissector
217 * that have been changed. It is called by the g_hash_foreach routine
218 * once for each changed entry in a dissector table.
220 * @param table_name The table name in which this dissector is found.
222 * @param key A pointer to the key for this entry in the dissector
223 * hash table. This is generally the numeric selector of the
224 * protocol, i.e. the ethernet type code, IP port number, TCP port
227 * @param value A pointer to the value for this entry in the dissector
228 * hash table. This is an opaque pointer that can only be handed back
229 * to routine in the file packet.c
231 * @param user_data A pointer to the clist in which this information
235 decode_build_show_list (gchar *table_name, gpointer key,
236 gpointer value, gpointer user_data)
239 dissector_handle_t current, initial;
240 gchar *current_proto_name, *initial_proto_name, *text[E_CLIST_D_COLUMNS];
247 clist = (GtkCList *)user_data;
248 current = dtbl_entry_get_handle(value);
250 current_proto_name = "(none)";
252 current_proto_name = dissector_handle_get_short_name(current);
253 initial = dtbl_entry_get_initial_handle(value);
255 initial_proto_name = "(none)";
257 initial_proto_name = dissector_handle_get_short_name(initial);
259 text[E_CLIST_D_TABLE] = get_dissector_table_ui_name(table_name);
260 switch (get_dissector_table_base(table_name)) {
263 sprintf(string1, "%u", GPOINTER_TO_UINT(key));
267 switch (get_dissector_table_type(table_name)) {
270 sprintf(string1, "0x%02x", GPOINTER_TO_UINT(key));
274 sprintf(string1, "0x%04x", GPOINTER_TO_UINT(key));
278 sprintf(string1, "0x%06x", GPOINTER_TO_UINT(key));
282 sprintf(string1, "0x%08x", GPOINTER_TO_UINT(key));
286 g_assert_not_reached();
292 sprintf(string1, "%#o", GPOINTER_TO_UINT(key));
295 text[E_CLIST_D_PORT] = string1;
296 text[E_CLIST_D_INITIAL] = initial_proto_name;
297 text[E_CLIST_D_CURRENT] = current_proto_name;
298 row = gtk_clist_prepend(clist, text);
303 * This routine is called when the user clicks the "OK" button in
304 * the "Decode As:Show..." dialog window. This routine destroys the
305 * dialog box and performs other housekeeping functions.
307 * @param GtkWidget * A pointer to the "OK" button.
309 * @param gpointer A pointer to the dialog window.
312 decode_show_ok_cb (GtkWidget *ok_bt, gpointer parent_w)
314 gtk_widget_destroy(GTK_WIDGET(parent_w));
319 * This routine is called when the user clicks the "Reset" button in
320 * the "Decode As:Show..." dialog window. This routine resets all the
321 * dissector values and then destroys the dialog box and performs
322 * other housekeeping functions.
324 * @param GtkWidget * A pointer to the "Reset" button.
326 * @param gpointer A pointer to the dialog window.
329 decode_show_reset_cb (GtkWidget *reset_bt, gpointer parent_w)
331 dissector_delete_item_t *item;
334 dissector_all_tables_foreach_changed(decode_build_reset_list, NULL);
336 for (tmp = dissector_reset_list; tmp; tmp = g_slist_next(tmp)) {
338 dissector_reset(item->ddi_table_name, item->ddi_port);
341 g_slist_free(dissector_reset_list);
342 dissector_reset_list = NULL;
344 redissect_packets(&cfile);
346 gtk_widget_destroy(GTK_WIDGET(parent_w));
351 * This routine is called when the user clicks the "Close" button in
352 * the "Decode As:Show..." dialog window. This routine simply calls the
353 * cancel routine as if the user had clicked the cancel button instead
354 * of the close button.
356 * @param GtkWidget * A pointer to the dialog box.
358 * @param gpointer Unknown
361 decode_show_delete_cb (GtkWidget *decode_w, gpointer dummy)
363 decode_show_ok_cb(NULL, decode_show_w);
369 * This routine is called at the destruction of the "Decode As:Show"
370 * dialog box. It clears the pointer maintained by this file, so that
371 * the next time the user clicks the "Decode As:Show" button a new
372 * dialog box will be created.
374 * @param GtkWidget * A pointer to the dialog box.
376 * @param gpointer Unknown
379 decode_show_destroy_cb (GtkWidget *win, gpointer user_data)
381 /* Note that we no longer have a "Decode As:Show" dialog box. */
382 decode_show_w = NULL;
387 * This routine creates the "Decode As:Show" dialog box. This dialog box
388 * shows the user which protocols have had their dissectors changed.
391 * @param data Unknown
394 decode_show_cb (GtkWidget * w, gpointer data)
396 GtkWidget *main_vb, *bbox, *ok_bt, *button, *scrolled_window;
398 gchar *titles[E_CLIST_D_COLUMNS] = {"Table", "Port", "Initial", "Current"};
401 if (decode_show_w != NULL) {
402 /* There's already a "Decode As" dialog box; reactivate it. */
403 reactivate_window(decode_show_w);
407 decode_show_w = dlg_window_new("Ethereal: Decode As: Show");
408 gtk_signal_connect(GTK_OBJECT(decode_show_w), "delete_event",
409 GTK_SIGNAL_FUNC(decode_show_delete_cb), NULL);
410 gtk_signal_connect(GTK_OBJECT(decode_show_w), "destroy",
411 GTK_SIGNAL_FUNC(decode_show_destroy_cb), NULL);
413 /* Container for each row of widgets */
414 main_vb = gtk_vbox_new(FALSE, 2);
415 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
416 gtk_container_add(GTK_CONTAINER(decode_show_w), main_vb);
419 /* Initialize clist */
420 clist = GTK_CLIST(gtk_clist_new_with_titles(E_CLIST_D_COLUMNS, titles));
421 gtk_clist_column_titles_passive(clist);
422 for (column = 0; column < E_CLIST_D_COLUMNS; column++)
423 gtk_clist_set_column_auto_resize(clist, column, TRUE);
424 gtk_clist_set_selection_mode(clist, GTK_SELECTION_EXTENDED);
427 dissector_all_tables_foreach_changed(decode_build_show_list, clist);
428 gtk_clist_sort(clist);
430 /* Put clist into a scrolled window */
431 scrolled_window = gtk_scrolled_window_new(NULL, NULL);
432 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
433 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
434 gtk_container_add(GTK_CONTAINER(scrolled_window),
436 gtk_box_pack_start(GTK_BOX(main_vb), scrolled_window, TRUE, TRUE, 0);
437 /* Provide a minimum of a couple of rows worth of data */
438 gtk_widget_set_usize(scrolled_window, 0, E_DECODE_MIN_HEIGHT);
441 /* Button row: OK and reset buttons */
442 bbox = gtk_hbutton_box_new();
443 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
444 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
445 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 10);
447 button = gtk_button_new_with_label("Reset Changes");
448 gtk_signal_connect(GTK_OBJECT(button), "clicked",
449 GTK_SIGNAL_FUNC(decode_show_reset_cb),
450 GTK_OBJECT(decode_show_w));
451 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
452 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
453 gtk_widget_set_sensitive(button, (clist->rows != 0));
455 ok_bt = gtk_button_new_with_label("OK");
456 gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
457 GTK_SIGNAL_FUNC(decode_show_ok_cb),
458 GTK_OBJECT(decode_show_w));
459 GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
460 gtk_box_pack_start(GTK_BOX(bbox), ok_bt, FALSE, FALSE, 0);
461 gtk_widget_grab_default(ok_bt);
462 dlg_set_cancel(decode_show_w, ok_bt);
464 gtk_widget_show_all(decode_show_w);
468 /**************************************************/
469 /* Modify the dissector routines */
470 /**************************************************/
473 * Modify a single dissector. This routine first takes care of
474 * updating the internal table of original protocol/port/dissector
475 * combinations by adding a new entry (or removing an existing entry
476 * if the value is being set back to its default). This routine then
477 * performs the actual modification to the packet dissector tables.
479 * @param s Pointer to a string buffer. This buffer is used to build
480 * up a message indicating which ports have had their dissector
481 * changed. This output will be displayed all at once after all
482 * dissectors have been modified.
484 * @param table_name The table name in which the dissector should be
487 * @param selector An enum value indication which selector value
488 * (i.e. IP protocol number, TCP port number, etc.)is to be changed.
490 * @param clist The CList in which all the selection information can
493 * @return gchar * Pointer to the next free location in the string
497 decode_change_one_dissector (gchar *table_name, gint selector, GtkCList *clist)
499 dissector_handle_t handle;
503 if (!clist->selection) {
507 row = GPOINTER_TO_INT(clist->selection->data);
508 handle = gtk_clist_get_row_data(clist, row);
509 gtk_clist_get_text(clist, row, E_CLIST_S_PROTO_NAME, &abbrev);
512 if (strcmp(abbrev, "(default)") == 0) {
513 dissector_reset(table_name, selector);
515 dissector_change(table_name, selector, handle);
521 /**************************************************/
522 /* Action routines for the "Decode As..." dialog */
523 /* - called when the OK button pressed */
524 /* - one per notebook page */
525 /**************************************************/
530 * Print debugging information about clist selection. Extract all
531 * information from the clist entry that was selected and print it to
534 * @param clist The clist to dump.
536 * @param leadin A string to print at the start of each line.
539 decode_debug (GtkCList *clist, gchar *leadin)
541 gchar *string, *text[E_CLIST_S_COLUMNS];
542 dissector_handle_t handle;
545 string = g_malloc(1024);
546 if (clist->selection) {
547 row = GPOINTER_TO_INT(clist->selection->data);
548 gtk_clist_get_text(clist, row, E_CLIST_S_PROTO_NAME, &text[E_CLIST_S_PROTO_NAME]);
549 gtk_clist_get_text(clist, row, E_CLIST_S_TABLE, &text[E_CLIST_S_TABLE]);
550 handle = gtk_clist_get_row_data(clist, row);
551 sprintf(string, "%s clist row %d: <put handle here>, name %s, table %s",
552 leadin, row, text[E_CLIST_S_PROTO_NAME],
553 text[E_CLIST_S_TABLE]);
555 sprintf(string, "%s clist row (none), aka do not decode", leadin);
557 simple_dialog(ESD_TYPE_INFO, NULL, string);
564 * This routine is called when the user clicks the "OK" button in the
565 * "Decode As..." dialog window and a 'simple' page is foremost.
566 * This routine takes care of making any changes requested to the
567 * dissector tables. This routine is currently used for IP and
568 * Ethertypes. Any 'single change' notebook page can use this
571 * @param notebook_pg A pointer to the "network" notebook page.
574 decode_simple (GtkWidget *notebook_pg)
583 clist = GTK_CLIST(gtk_object_get_data(GTK_OBJECT(notebook_pg), E_PAGE_CLIST));
584 if (requested_action == E_DECODE_NO)
585 gtk_clist_unselect_all(clist);
588 string = gtk_object_get_data(GTK_OBJECT(notebook_pg), E_PAGE_TITLE);
589 decode_debug(clist, string);
592 table_name = gtk_object_get_data(GTK_OBJECT(notebook_pg), E_PAGE_TABLE);
593 value = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(notebook_pg),
595 decode_change_one_dissector(table_name, value, clist);
600 * This routine is called when the user clicks the "OK" button in the
601 * "Decode As..." dialog window and the transport page is foremost.
602 * This routine takes care of making any changes requested to the TCP
603 * or UDP dissector tables.
605 * @param notebook_pg A pointer to the "transport" notebook page.
608 decode_transport (GtkObject *notebook_pg)
610 GtkWidget *menu, *menuitem;
613 gint requested_srcdst;
615 clist = GTK_CLIST(gtk_object_get_data(notebook_pg, E_PAGE_CLIST));
616 if (requested_action == E_DECODE_NO)
617 gtk_clist_unselect_all(clist);
619 menu = gtk_object_get_data(notebook_pg, E_MENU_SRCDST);
620 menuitem = gtk_menu_get_active(GTK_MENU(menu));
621 requested_srcdst = GPOINTER_TO_INT(gtk_object_get_user_data(GTK_OBJECT(menuitem)));
624 string = gtk_object_get_data(GTK_OBJECT(notebook_pg), E_PAGE_TITLE);
625 decode_debug(clist, string);
628 table_name = gtk_object_get_data(GTK_OBJECT(notebook_pg), E_PAGE_TABLE);
629 if (requested_srcdst != E_DECODE_DPORT)
630 decode_change_one_dissector(table_name, cfile.edt->pi.srcport, clist);
631 if (requested_srcdst != E_DECODE_SPORT)
632 decode_change_one_dissector(table_name, cfile.edt->pi.destport, clist);
635 /**************************************************/
636 /* Signals from the "Decode As..." dialog */
637 /**************************************************/
640 * This routine is called when the user clicks the "OK" button in the
641 * "Decode As..." dialog window. This routine calls various helper
642 * routines to set/clear dissector values as requested by the user.
643 * These routines accumulate information on what actions they have
644 * taken, and this summary information is printed by this routine.
645 * This routine then destroys the dialog box and performs other
646 * housekeeping functions.
648 * @param ok_bt A pointer to the "OK" button.
650 * @param parent_w A pointer to the dialog window.
653 decode_ok_cb (GtkWidget *ok_bt, gpointer parent_w)
655 GtkWidget *notebook, *notebook_pg;
659 /* Call the right routine for the page that was currently in front. */
660 notebook = gtk_object_get_data(GTK_OBJECT(parent_w), E_NOTEBOOK);
661 page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
662 notebook_pg = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
664 func = gtk_object_get_data(GTK_OBJECT(notebook_pg), E_PAGE_ACTION);
667 /* Now destroy the "Decode As" dialog. */
668 gtk_widget_destroy(GTK_WIDGET(parent_w));
669 g_slist_free(decode_dimmable);
670 decode_dimmable = NULL;
672 redissect_packets(&cfile);
677 * This routine is called when the user clicks the "Cancel" button in
678 * the "Decode As..." dialog window. This routine then destroys the
679 * dialog box and performs other housekeeping functions.
681 * @param cancel_bt A pointer to the "Cancel" button.
683 * @param parent_w A pointer to the dialog window.
686 decode_cancel_cb (GtkWidget *cancel_bt, gpointer parent_w)
688 gtk_widget_destroy(GTK_WIDGET(parent_w));
689 g_slist_free(decode_dimmable);
690 decode_dimmable = NULL;
695 * This routine is called when the user clicks the "Close" button in
696 * the "Decode As..." dialog window. This routine simply calls the
697 * cancel routine as if the user had clicked the cancel button instead
698 * of the close button.
700 * @param decode_w A pointer to the dialog box.
702 * @param dummy Unknown
705 decode_delete_cb (GtkWidget *decode_w, gpointer dummy)
707 decode_cancel_cb(NULL, decode_w);
713 * This routine is called at the destruction of the "Decode As..."
714 * dialog box. It clears the pointer maintained by this file, so that
715 * the next time the user selects the "Decode As..." menu item a new
716 * dialog box will be created.
718 * @param decode_w A pointer to the dialog box.
720 * @param user_data Unknown
725 decode_destroy_cb (GtkWidget *win, gpointer user_data)
727 /* Note that we no longer have a "Decode As" dialog box. */
732 /**************************************************/
733 /* Dialog setup - radio buttons */
734 /**************************************************/
737 * Update the requested action field of the dialog. This routine is
738 * called by GTK when either of the two radio buttons in the dialog is
741 * @param w The radio button that was clicked.
743 * @param data The enum value assigned to this radio button. This
744 * will be either E_DECODE_YES or E_DECODE_NO
747 decode_update_action (GtkWidget *w, gpointer data)
752 requested_action = GPOINTER_TO_INT(data);
753 enable = (requested_action == E_DECODE_YES);
754 for (tmp = decode_dimmable; tmp; tmp = g_slist_next(tmp)) {
755 gtk_widget_set_sensitive(tmp->data, enable);
760 * This routine is called to create the "Decode" and "Do not decode"
761 * radio buttons. These buttons are installed into a vbox, and set up
764 * @return GtkWidget * A pointer to the vbox containing the buttons
767 decode_add_yes_no (void)
769 GtkWidget *format_vb, *radio_button;
772 format_vb = gtk_vbox_new(FALSE, 2);
774 radio_button = gtk_radio_button_new_with_label(NULL, "Decode");
775 format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
776 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio_button), TRUE);
777 gtk_signal_connect(GTK_OBJECT(radio_button), "clicked",
778 GTK_SIGNAL_FUNC(decode_update_action),
779 GINT_TO_POINTER(E_DECODE_YES));
780 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
782 radio_button = gtk_radio_button_new_with_label(format_grp, "Do not decode");
783 format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(radio_button));
784 gtk_signal_connect(GTK_OBJECT(radio_button), "clicked",
785 GTK_SIGNAL_FUNC(decode_update_action),
786 GINT_TO_POINTER(E_DECODE_NO));
787 gtk_box_pack_start(GTK_BOX(format_vb), radio_button, TRUE, TRUE, 0);
792 /**************************************************/
793 /* Dialog setup - simple menus */
794 /**************************************************/
797 * This routine is called to pack an option menu into an aligment, so
798 * that it doesn't expand vertically to fill up the space available to
801 * @param optmenu A pointer to the option menu to be so packed.
803 * @return GtkWidget * A pointer to the newly created alignment.
806 decode_add_pack_menu (GtkWidget *optmenu)
808 GtkWidget *alignment;
810 alignment = gtk_alignment_new(0.0, 0.5, 0.0, 0.0);
811 gtk_container_add(GTK_CONTAINER(alignment), optmenu);
818 * This routine is called to add the transport port selection menu to
819 * the dialog box. This is a three choice menu: source, destination
820 * and both. The default choice for the menu is set to the source
821 * port number of the currently selected packet.
823 * @param page A pointer notebook page that will contain all
824 * widgets created by this routine.
826 * @return GtkWidget * A pointer to the newly created alignment into
827 * which we've packed the newly created option menu.
830 decode_add_srcdst_menu (GtkWidget *page)
832 GtkWidget *optmenu, *menu, *menuitem, *alignment;
835 optmenu = gtk_option_menu_new();
836 menu = gtk_menu_new();
837 sprintf(tmp, "source (%u)", cfile.edt->pi.srcport);
838 menuitem = gtk_menu_item_new_with_label(tmp);
839 gtk_object_set_user_data(GTK_OBJECT(menuitem),
840 GINT_TO_POINTER(E_DECODE_SPORT));
841 gtk_menu_append(GTK_MENU(menu), menuitem);
842 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
844 sprintf(tmp, "destination (%u)", cfile.edt->pi.destport);
845 menuitem = gtk_menu_item_new_with_label(tmp);
846 gtk_object_set_user_data(GTK_OBJECT(menuitem),
847 GINT_TO_POINTER(E_DECODE_DPORT));
848 gtk_menu_append(GTK_MENU(menu), menuitem);
849 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
851 menuitem = gtk_menu_item_new_with_label("both");
852 gtk_object_set_user_data(GTK_OBJECT(menuitem),
853 GINT_TO_POINTER(E_DECODE_BPORT));
854 gtk_menu_append(GTK_MENU(menu), menuitem);
855 gtk_widget_show(menuitem); /* gtk_widget_show_all() doesn't show this */
857 gtk_object_set_data(GTK_OBJECT(page), E_MENU_SRCDST, menu);
858 gtk_option_menu_set_menu(GTK_OPTION_MENU(optmenu), menu);
860 alignment = decode_add_pack_menu(optmenu);
865 /**************************************************/
866 /* Dialog setup - clist based menus */
867 /**************************************************/
871 * This routine creates one entry in the list of protocol dissector
872 * that can be used. It is called by the dissector_table_foreach_handle
873 * routine once for each entry in a dissector table's list of handles
874 * for dissectors that could be used in that table. It guarantees unique
875 * entries by iterating over the list of entries build up to this point,
876 * looking for a duplicate name. If there is no duplicate, then this
877 * entry is added to the list of possible dissectors.
879 * @param table_name The name of the dissector table currently
882 * @param value The dissector handle for this entry. This is an opaque
883 * pointer that can only be handed back to routines in the file packet.c
885 * @param user_data A data block passed into each instance of this
886 * routine. It contains information from the caller of the foreach
887 * routine, specifying information about the dissector table and where
888 * to store any information generated by this routine.
891 decode_add_to_clist (gchar *table_name, gpointer value, gpointer user_data)
895 gchar *text[E_CLIST_S_COLUMNS];
896 dissector_handle_t handle;
904 proto_name = dissector_handle_get_short_name(handle);
906 row = gtk_clist_find_row_from_data(clist, handle);
909 * We already have an entry for this handle.
910 * XXX - will this ever happen?
915 text[E_CLIST_S_PROTO_NAME] = proto_name;
916 text[E_CLIST_S_TABLE] = table_name;
917 row = gtk_clist_prepend(clist, text);
918 gtk_clist_set_row_data(clist, row, handle);
923 * This routine starts the creation of a CList on a notebook page. It
924 * creates both a scrolled window and a clist, adds the clist to the
925 * window, and attaches the clist as a data object on the page.
927 * @param page A pointer to the notebook page being created.
929 * @param clist_p Will be filled in with the address of a newly
932 * @param scrolled_win_p Will be filled in with the address of a newly
933 * created GtkScrolledWindow.
936 decode_clist_menu_start (GtkWidget *page, GtkCList **clist_p,
937 GtkWidget **scrolled_win_p)
939 gchar *titles[E_CLIST_S_COLUMNS] = {"Short Name", "Table Name"};
945 GTK_CLIST(gtk_clist_new_with_titles(E_CLIST_S_COLUMNS, titles));
946 gtk_clist_column_titles_passive(clist);
948 gtk_clist_column_titles_hide(clist);
949 for (column = 1; column < E_CLIST_S_COLUMNS; column++)
950 gtk_clist_set_column_visibility (clist, column, FALSE);
952 for (column = 0; column < E_CLIST_S_COLUMNS; column++)
953 gtk_clist_set_column_auto_resize(clist, column, TRUE);
954 gtk_object_set_data(GTK_OBJECT(page), E_PAGE_CLIST, clist);
956 *scrolled_win_p = window = gtk_scrolled_window_new(NULL, NULL);
957 /* Provide a minimum of a couple of rows worth of data */
958 gtk_widget_set_usize(window, 0, E_DECODE_MIN_HEIGHT);
959 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(window),
960 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
961 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(window),
966 * This routine finishes the creation of a CList on a notebook page.
967 * It adds the default entry, sets the default entry as the
968 * highlighted entry, and sorts the CList.
970 * @param clist A pointer the the CList to finish.
973 decode_clist_menu_finish (GtkCList *clist)
975 gchar *text[E_CLIST_S_COLUMNS];
978 text[E_CLIST_S_PROTO_NAME] = "(default)";
979 text[E_CLIST_S_TABLE] = "(none)";
980 row = gtk_clist_prepend(clist, text);
981 gtk_clist_set_row_data(clist, row, NULL);
983 gtk_clist_select_row(clist, 0, -1);
984 gtk_clist_sort(clist);
988 * This routine is called to add the dissector selection list to a
989 * notebook page. This scrolled list contains an entry labeled
990 * "default", and an entry for each protocol that has had a dissector
991 * registered. The default choice for the list is set to the
992 * "default" choice, which will return the protocol/port selections to
993 * their original dissector(s).
995 * @param page A pointer to the notebook page currently being created.
997 * @param table_name The name of the dissector table to use to build
1000 * @return GtkWidget * A pointer to the newly created clist within a
1004 decode_add_simple_menu (GtkWidget *page, gchar *table_name)
1006 GtkWidget *scrolled_window;
1009 decode_clist_menu_start(page, &clist, &scrolled_window);
1010 dissector_table_foreach_handle(table_name, decode_add_to_clist, clist);
1011 decode_clist_menu_finish(clist);
1012 return(scrolled_window);
1015 /**************************************************/
1017 /**************************************************/
1020 * This routine creates a sample notebook page in the dialog box.
1021 * This notebook page provides a prompt specifying what is being
1022 * changed and its current value (e.g. "IP Protocol number (17)"), and
1023 * a clist specifying all the available choices. The list of choices
1024 * is conditionally enabled, based upon the setting of the
1025 * "decode"/"do not decode" radio buttons.
1027 * @param prompt The prompt for this notebook page
1029 * @param title A title for this page to use when debugging.
1031 * @param table_name The name of the dissector table to use to
1034 * @param value The protocol/port value that is to be changed.
1036 * @return GtkWidget * A pointer to the notebook page created by this
1040 decode_add_simple_page (gchar *prompt, gchar *title, gchar *table_name,
1043 GtkWidget *page, *label, *scrolled_window;
1045 page = gtk_hbox_new(FALSE, 5);
1046 gtk_object_set_data(GTK_OBJECT(page), E_PAGE_ACTION, decode_simple);
1047 gtk_object_set_data(GTK_OBJECT(page), E_PAGE_TABLE, table_name);
1048 gtk_object_set_data(GTK_OBJECT(page), E_PAGE_TITLE, title);
1049 gtk_object_set_data(GTK_OBJECT(page), E_PAGE_VALUE, GINT_TO_POINTER(value));
1051 /* Always enabled */
1052 label = gtk_label_new(prompt);
1053 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1055 /* Conditionally enabled - only when decoding packets */
1056 label = gtk_label_new("as");
1057 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1058 decode_dimmable = g_slist_prepend(decode_dimmable, label);
1059 scrolled_window = decode_add_simple_menu(page, table_name);
1060 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1061 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1068 * This routine creates the TCP or UDP notebook page in the dialog box.
1069 * All items created by this routine are packed into a single
1070 * horizontal box. First is a label indicating whether the port(s) for
1071 * which the user can set the dissection is a TCP port or a UDP port.
1072 * Second is a menu allowing the user to select whether the source port,
1073 * destination port, or both ports will have dissectors added for them.
1074 * Last is a (conditionally enabled) popup menu listing all possible
1075 * dissectors that can be used to decode the packets, and the choice
1076 * or returning to the default dissector for these ports.
1078 * The defaults for these items are the transport layer protocol of
1079 * the currently selected packet, the source port of the currently
1080 * selected packet, and the "default dissector".
1082 * @param prompt The prompt for this notebook page
1084 * @param table_name The name of the dissector table to use to
1087 * @return GtkWidget * A pointer to the notebook page created by
1091 decode_add_tcpudp_page (gchar *prompt, gchar *table_name)
1093 GtkWidget *page, *label, *scrolled_window, *optmenu;
1095 page = gtk_hbox_new(FALSE, 5);
1096 gtk_object_set_data(GTK_OBJECT(page), E_PAGE_ACTION, decode_transport);
1097 gtk_object_set_data(GTK_OBJECT(page), E_PAGE_TABLE, table_name);
1098 gtk_object_set_data(GTK_OBJECT(page), E_PAGE_TITLE, "Transport");
1100 /* Always enabled */
1101 label = gtk_label_new(prompt);
1102 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1103 optmenu = decode_add_srcdst_menu(page);
1104 gtk_box_pack_start(GTK_BOX(page), optmenu, TRUE, TRUE, 0);
1105 label = gtk_label_new("port(s)");
1106 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1108 /* Conditionally enabled - only when decoding packets */
1109 label = gtk_label_new("as");
1110 gtk_box_pack_start(GTK_BOX(page), label, TRUE, TRUE, 0);
1111 decode_dimmable = g_slist_prepend(decode_dimmable, label);
1112 scrolled_window = decode_add_simple_menu(page, table_name);
1113 gtk_box_pack_start(GTK_BOX(page), scrolled_window, TRUE, TRUE, 0);
1114 decode_dimmable = g_slist_prepend(decode_dimmable, scrolled_window);
1120 * This routine indicates whether we'd actually have any pages in the
1121 * notebook in a "Decode As" dialog box; if there wouldn't be, we
1122 * inactivate the menu item for "Decode As".
1127 return cfile.edt->pi.ethertype || cfile.edt->pi.ipproto ||
1128 cfile.edt->pi.ptype == PT_TCP || cfile.edt->pi.ptype == PT_UDP;
1133 * This routine creates the bulk of the "Decode As" dialog box. All
1134 * items created by this routine are packed as pages into a notebook.
1135 * There will be a page for each protocol layer that can be change.
1137 * @param GtkWidget * A pointer to the widget in which the notebook
1138 * should be installed.
1141 decode_add_notebook (GtkWidget *format_hb)
1143 GtkWidget *notebook, *page, *label;
1146 /* Start a nootbook for flipping between sets of changes */
1147 notebook = gtk_notebook_new();
1148 gtk_container_add(GTK_CONTAINER(format_hb), notebook);
1149 gtk_object_set_data(GTK_OBJECT(decode_w), E_NOTEBOOK, notebook);
1151 /* Add link level selection page */
1152 if (cfile.edt->pi.ethertype) {
1153 sprintf(buffer, "Ethertype 0x%04x", cfile.edt->pi.ethertype);
1154 page = decode_add_simple_page(buffer, "Link", "ethertype", cfile.edt->pi.ethertype);
1155 label = gtk_label_new("Link");
1156 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1159 /* Add network selection page */
1160 if (cfile.edt->pi.ipproto) {
1162 * The network-layer protocol is IP.
1164 sprintf(buffer, "IP protocol %u", cfile.edt->pi.ipproto);
1165 page = decode_add_simple_page(buffer, "Network", "ip.proto", cfile.edt->pi.ipproto);
1166 gtk_object_set_data(GTK_OBJECT(page), E_PAGE_ACTION, decode_simple);
1167 label = gtk_label_new("Network");
1168 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1171 /* Add transport selection page */
1172 switch (cfile.edt->pi.ptype) {
1175 page = decode_add_tcpudp_page("TCP", "tcp.port");
1179 page = decode_add_tcpudp_page("UDP", "udp.port");
1187 label = gtk_label_new("Transport");
1188 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, label);
1191 /* Select the last added page (selects first by default) */
1192 /* Notebook must be visible for set_page to work. */
1193 gtk_widget_show_all(notebook);
1194 gtk_notebook_set_page(GTK_NOTEBOOK(notebook), -1);
1199 * This routine creates the "Decode As" dialog box. This dialog box
1200 * asks the user which protocol to use for decoding the currently
1201 * selected packet. This will affect the last packet that we called a
1202 * dissection routine on belongs (this might be the most recently
1203 * selected packet, or it might be the last packet in the file).
1205 * This routine uses an auxiliary function to create the bulk of the
1206 * dialog box, and then hand crafts the button box at the bottom of
1210 * @param data Unknown
1213 decode_as_cb (GtkWidget * w, gpointer data)
1215 GtkWidget *main_vb, *format_hb, *bbox, *ok_bt, *cancel_bt, *button;
1216 GtkWidget *button_vb;
1218 if (decode_w != NULL) {
1219 /* There's already a "Decode As" dialog box; reactivate it. */
1220 reactivate_window(decode_w);
1224 requested_action = E_DECODE_YES;
1225 decode_w = dlg_window_new("Ethereal: Decode As");
1226 gtk_signal_connect(GTK_OBJECT(decode_w), "delete_event",
1227 GTK_SIGNAL_FUNC(decode_delete_cb), NULL);
1228 gtk_signal_connect(GTK_OBJECT(decode_w), "destroy",
1229 GTK_SIGNAL_FUNC(decode_destroy_cb), NULL);
1231 /* Container for each row of widgets */
1232 main_vb = gtk_vbox_new(FALSE, 2);
1233 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1234 gtk_container_add(GTK_CONTAINER(decode_w), main_vb);
1236 /* First row - Buttons and Notebook */
1238 format_hb = gtk_hbox_new(FALSE, 5);
1239 gtk_box_pack_start(GTK_BOX(main_vb), format_hb, TRUE, TRUE, 10);
1241 button_vb = decode_add_yes_no();
1242 gtk_box_pack_start(GTK_BOX(format_hb), button_vb, TRUE, TRUE, 10);
1244 decode_add_notebook(format_hb);
1247 /* Button row: OK and cancel buttons */
1248 bbox = gtk_hbutton_box_new();
1249 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1250 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
1251 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 10);
1253 ok_bt = gtk_button_new_with_label("OK");
1254 gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
1255 GTK_SIGNAL_FUNC(decode_ok_cb),
1256 GTK_OBJECT(decode_w));
1257 GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
1258 gtk_box_pack_start(GTK_BOX(bbox), ok_bt, FALSE, FALSE, 0);
1259 gtk_widget_grab_default(ok_bt);
1261 button = gtk_button_new_with_label("Show Current");
1262 gtk_signal_connect(GTK_OBJECT(button), "clicked",
1263 GTK_SIGNAL_FUNC(decode_show_cb),
1264 GTK_OBJECT(decode_w));
1265 GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
1266 gtk_box_pack_start(GTK_BOX(bbox), button, FALSE, FALSE, 0);
1268 cancel_bt = gtk_button_new_with_label("Cancel");
1269 gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
1270 GTK_SIGNAL_FUNC(decode_cancel_cb),
1271 GTK_OBJECT(decode_w));
1272 GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
1273 gtk_box_pack_start(GTK_BOX(bbox), cancel_bt, FALSE, FALSE, 0);
1276 * Catch the "key_press_event" signal in the window, so that
1277 * we can catch the ESC key being pressed and act as if the
1278 * "Cancel" button had been selected.
1280 dlg_set_cancel(decode_w, cancel_bt);
1282 gtk_widget_show_all(decode_w);