1 /* mem leak should free the column_arrows when the table is destroyed */
3 /* conversations_table.c
4 * conversations_table 2003 Ronnie Sahlberg
5 * Helper routines common to all endpoint conversations tap.
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
40 #include <epan/packet_info.h>
41 #include <epan/to_str.h>
42 #include <epan/address.h>
43 #include <epan/addr_resolv.h>
45 #include <epan/nstime.h>
47 #include "../simple_dialog.h"
48 #include "../globals.h"
52 #include "gtk/conversations_table.h"
53 #include "gtk/filter_utils.h"
54 #include "gtk/gtkglobals.h"
55 #include "gtk/gui_utils.h"
56 #include "gtk/dlg_utils.h"
57 #include "gtk/help_dlg.h"
60 #include "image/clist_ascend.xpm"
61 #include "image/clist_descend.xpm"
65 #define COL_STR_LEN 16
66 #define CONV_PTR_KEY "conversations-pointer"
67 #define NB_PAGES_KEY "notebook-pages"
68 #define NO_BPS_STR "N/A"
70 #define CMP_NUM(n1, n2) \
73 else if ((n1) < (n2)) \
78 /* convert a port number into a string */
80 ct_port_to_str(int port_type, guint32 port)
83 static gchar str[4][12];
91 g_snprintf(str[i], sizeof(str[0]), "%d", port);
98 #define FN_SRC_ADDRESS 0
99 #define FN_DST_ADDRESS 1
100 #define FN_ANY_ADDRESS 2
101 #define FN_SRC_PORT 3
102 #define FN_DST_PORT 4
103 #define FN_ANY_PORT 5
104 /* given an address (to distinguis between ipv4 and ipv6 for tcp/udp
105 a port_type and a name_type (FN_...)
106 return a string for the filter name
108 some addresses, like AT_ETHER may actually be any of multiple types
109 of protocols, either ethernet, tokenring, fddi, wlan etc so we must be
110 more specific there thats why we need specific_addr_type
113 ct_get_filter_name(address *addr, int specific_addr_type, int port_type, int name_type)
119 switch(specific_addr_type){
141 switch(specific_addr_type){
143 return "jxta.message.src";
157 switch(specific_addr_type){
179 switch(specific_addr_type){
181 return "jxta.message.dst";
195 switch(specific_addr_type){
217 switch(specific_addr_type){
219 return "jxta.message.address";
233 return "tcp.srcport";
235 return "udp.srcport";
237 return "sctp.srcport";
239 return "ncp.connection";
247 return "tcp.dstport";
249 return "udp.dstport";
251 return "sctp.dstport";
253 return "ncp.connection";
267 return "ncp.connection";
274 g_assert_not_reached();
279 typedef struct column_arrows {
281 GtkWidget *ascend_pm;
282 GtkWidget *descend_pm;
288 reset_ct_table_data(conversations_table *ct)
292 GString *error_string;
295 if (ct->use_dfilter) {
296 filter = gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
301 error_string = set_tap_dfilter (ct, filter);
303 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
304 g_string_free(error_string, TRUE);
308 /* Allow clist to update */
309 gtk_clist_thaw(ct->table);
312 g_snprintf(title, sizeof(title), "Conversations: %s", cf_get_display_name(&cfile));
313 gtk_window_set_title(GTK_WINDOW(ct->win), title);
314 g_snprintf(title, sizeof(title), "%s", ct->name);
315 gtk_label_set_text(GTK_LABEL(ct->page_lb), title);
316 gtk_widget_set_sensitive(ct->page_lb, FALSE);
318 if (ct->use_dfilter) {
319 if (filter && strlen(filter)) {
320 g_snprintf(title, sizeof(title), "%s Conversations - Filter: %s", ct->name, filter);
322 g_snprintf(title, sizeof(title), "%s Conversations - No Filter", ct->name);
325 g_snprintf(title, sizeof(title), "%s Conversations", ct->name);
327 gtk_label_set_text(GTK_LABEL(ct->name_lb), title);
329 g_snprintf(title, sizeof(title), "%s Conversations: %s", ct->name, cf_get_display_name(&cfile));
330 gtk_window_set_title(GTK_WINDOW(ct->win), title);
333 /* remove all entries from the clist */
334 gtk_clist_clear(ct->table);
336 /* delete all conversations */
337 for(i=0;i<ct->num_conversations;i++){
338 g_free((gpointer)ct->conversations[i].src_address.data);
339 g_free((gpointer)ct->conversations[i].dst_address.data);
341 g_free(ct->conversations);
342 ct->conversations=NULL;
343 ct->num_conversations=0;
347 reset_ct_table_data_cb(void *arg)
349 reset_ct_table_data(arg);
353 ct_win_destroy_cb(GtkWindow *win _U_, gpointer data)
355 conversations_table *conversations=(conversations_table *)data;
357 protect_thread_critical_region();
358 remove_tap_listener(conversations);
359 unprotect_thread_critical_region();
361 reset_ct_table_data(conversations);
362 g_free(conversations);
368 ct_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
371 conversations_table *ct = g_object_get_data(G_OBJECT(clist), CONV_PTR_KEY);
372 conv_t *conv1 = NULL;
373 conv_t *conv2 = NULL;
374 double duration1, duration2;
376 const GtkCListRow *row1 = ptr1;
377 const GtkCListRow *row2 = ptr2;
379 idx1 = GPOINTER_TO_INT(row1->data);
380 idx2 = GPOINTER_TO_INT(row2->data);
382 if (!ct || idx1 >= ct->num_conversations || idx2 >= ct->num_conversations)
385 conv1 = &ct->conversations[idx1];
386 conv2 = &ct->conversations[idx2];
388 duration1 = nstime_to_sec(&conv1->stop_time) - nstime_to_sec(&conv1->start_time);
389 duration2 = nstime_to_sec(&conv2->stop_time) - nstime_to_sec(&conv2->start_time);
391 switch(clist->sort_column){
392 case 0: /* Source address */
393 return(CMP_ADDRESS(&conv1->src_address, &conv2->src_address));
394 case 2: /* Destination address */
395 return(CMP_ADDRESS(&conv1->dst_address, &conv2->dst_address));
396 case 1: /* Source port */
397 CMP_NUM(conv1->src_port, conv2->src_port);
398 case 3: /* Destination port */
399 CMP_NUM(conv1->dst_port, conv2->dst_port);
400 case 4: /* Packets */
401 CMP_NUM(conv1->tx_frames+conv1->rx_frames,
402 conv2->tx_frames+conv2->rx_frames);
404 CMP_NUM(conv1->tx_bytes+conv1->rx_bytes,
405 conv2->tx_bytes+conv2->rx_bytes);
406 case 6: /* Packets A->B */
407 CMP_NUM(conv1->tx_frames, conv2->tx_frames);
408 case 7: /* Bytes A->B */
409 CMP_NUM(conv1->tx_bytes, conv2->tx_bytes);
410 case 8: /* Packets A<-B */
411 CMP_NUM(conv1->rx_frames, conv2->rx_frames);
412 case 9: /* Bytes A<-B */
413 CMP_NUM(conv1->rx_bytes, conv2->rx_bytes);
414 case 10: /* Start time */
415 return nstime_cmp(&conv1->start_time, &conv2->start_time);
416 case 11: /* Duration */
417 CMP_NUM(duration1, duration2);
418 case 12: /* bps A->B */
419 if (duration1 > 0 && conv1->tx_frames > 1 && duration2 > 0 && conv2->tx_frames > 1) {
420 CMP_NUM((gint64) conv1->tx_bytes / duration1, (gint64) conv2->tx_bytes / duration2);
422 CMP_NUM(conv1->tx_bytes, conv2->tx_bytes);
424 case 13: /* bps A<-B */
425 if (duration1 > 0 && conv1->rx_frames > 1 && duration2 > 0 && conv2->rx_frames > 1) {
426 CMP_NUM((gint64) conv1->rx_bytes / duration1, (gint64) conv2->rx_bytes / duration2);
428 CMP_NUM(conv1->rx_bytes, conv2->rx_bytes);
431 g_assert_not_reached();
439 ct_click_column_cb(GtkCList *clist, gint column, gpointer data)
441 column_arrows *col_arrows = (column_arrows *) data;
444 for (i = 0; i < NUM_COLS; i++) {
445 gtk_widget_hide(col_arrows[i].ascend_pm);
446 gtk_widget_hide(col_arrows[i].descend_pm);
449 if (column == clist->sort_column) {
450 if (clist->sort_type == GTK_SORT_ASCENDING) {
451 clist->sort_type = GTK_SORT_DESCENDING;
452 gtk_widget_show(col_arrows[column].descend_pm);
454 clist->sort_type = GTK_SORT_ASCENDING;
455 gtk_widget_show(col_arrows[column].ascend_pm);
458 clist->sort_type = GTK_SORT_ASCENDING;
459 gtk_widget_show(col_arrows[column].ascend_pm);
460 gtk_clist_set_sort_column(clist, column);
463 gtk_clist_sort(clist);
465 /* Allow update of clist */
466 gtk_clist_thaw(clist);
467 gtk_clist_freeze(clist);
472 /* Filter direction */
473 #define DIR_A_TO_FROM_B 0
475 #define DIR_A_FROM_B 2
476 #define DIR_A_TO_FROM_ANY 3
477 #define DIR_A_TO_ANY 4
478 #define DIR_A_FROM_ANY 5
479 #define DIR_ANY_TO_FROM_B 6
480 #define DIR_ANY_FROM_B 7
481 #define DIR_ANY_TO_B 8
484 ct_select_filter_cb(GtkWidget *widget _U_, gpointer callback_data, guint callback_action)
488 conversations_table *ct = (conversations_table *)callback_data;
492 direction=FILTER_EXTRA(callback_action);
494 selection=GPOINTER_TO_INT(g_list_nth_data(GTK_CLIST(ct->table)->selection, 0));
495 if(selection>=(int)ct->num_conversations){
496 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No conversation selected");
499 /* translate it back from row index to index in enndpoint array */
500 selection=GPOINTER_TO_INT(gtk_clist_get_row_data(ct->table, selection));
502 sport=ct_port_to_str(ct->conversations[selection].port_type, ct->conversations[selection].src_port);
503 dport=ct_port_to_str(ct->conversations[selection].port_type, ct->conversations[selection].dst_port);
506 case DIR_A_TO_FROM_B:
508 str = g_strdup_printf("%s==%s%s%s%s%s && %s==%s%s%s%s%s",
509 ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_ANY_ADDRESS),
510 address_to_str(&ct->conversations[selection].src_address),
512 sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_ANY_PORT):"",
515 ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_ANY_ADDRESS),
516 address_to_str(&ct->conversations[selection].dst_address),
518 dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_ANY_PORT):"",
525 str = g_strdup_printf("%s==%s%s%s%s%s && %s==%s%s%s%s%s",
526 ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_SRC_ADDRESS),
527 address_to_str(&ct->conversations[selection].src_address),
529 sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_SRC_PORT):"",
532 ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_DST_ADDRESS),
533 address_to_str(&ct->conversations[selection].dst_address),
535 dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_DST_PORT):"",
542 str = g_strdup_printf("%s==%s%s%s%s%s && %s==%s%s%s%s%s",
543 ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_DST_ADDRESS),
544 address_to_str(&ct->conversations[selection].src_address),
546 sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_DST_PORT):"",
549 ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_SRC_ADDRESS),
550 address_to_str(&ct->conversations[selection].dst_address),
552 dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_SRC_PORT):"",
557 case DIR_A_TO_FROM_ANY:
559 str = g_strdup_printf("%s==%s%s%s%s%s",
560 ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_ANY_ADDRESS),
561 address_to_str(&ct->conversations[selection].src_address),
563 sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_ANY_PORT):"",
570 str = g_strdup_printf("%s==%s%s%s%s%s",
571 ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_SRC_ADDRESS),
572 address_to_str(&ct->conversations[selection].src_address),
574 sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_SRC_PORT):"",
581 str = g_strdup_printf("%s==%s%s%s%s%s",
582 ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_DST_ADDRESS),
583 address_to_str(&ct->conversations[selection].src_address),
585 sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_DST_PORT):"",
590 case DIR_ANY_TO_FROM_B:
592 str = g_strdup_printf("%s==%s%s%s%s%s",
593 ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_ANY_ADDRESS),
594 address_to_str(&ct->conversations[selection].dst_address),
596 dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_ANY_PORT):"",
603 str = g_strdup_printf("%s==%s%s%s%s%s",
604 ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_SRC_ADDRESS),
605 address_to_str(&ct->conversations[selection].dst_address),
607 dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_SRC_PORT):"",
614 str = g_strdup_printf("%s==%s%s%s%s%s",
615 ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_DST_ADDRESS),
616 address_to_str(&ct->conversations[selection].dst_address),
618 dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type, FN_DST_PORT):"",
624 g_assert_not_reached();
627 apply_selected_filter (callback_action, str);
633 ct_show_popup_menu_cb(void *widg _U_, GdkEvent *event, conversations_table *ct)
635 GdkEventButton *bevent = (GdkEventButton *)event;
640 /* To quote the "Gdk Event Structures" doc:
641 * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
642 if(event->type==GDK_BUTTON_PRESS && bevent->button==3){
643 /* if this is a right click on one of our columns, select it and popup the context menu */
644 if(gtk_clist_get_selection_info(ct->table,
645 (gint) (((GdkEventButton *)event)->x),
646 (gint) (((GdkEventButton *)event)->y),
648 gtk_clist_unselect_all(ct->table);
649 gtk_clist_select_row(ct->table, row, -1);
651 gtk_menu_popup(GTK_MENU(ct->menu), NULL, NULL, NULL, NULL,
652 bevent->button, bevent->time);
659 static GtkItemFactoryEntry ct_list_menu_items[] =
662 {"/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL,},
663 {"/Apply as Filter/Selected", NULL, NULL, 0, "<Branch>", NULL,},
664 {"/Apply as Filter/Selected/A <-> B", NULL,
665 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
666 {"/Apply as Filter/Selected/A --> B", NULL,
667 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_TO_B), NULL, NULL,},
668 {"/Apply as Filter/Selected/A <-- B", NULL,
669 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_FROM_B), NULL, NULL,},
670 {"/Apply as Filter/Selected/A <-> ANY", NULL,
671 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
672 {"/Apply as Filter/Selected/A --> ANY", NULL,
673 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
674 {"/Apply as Filter/Selected/A <-- ANY", NULL,
675 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
676 {"/Apply as Filter/Selected/ANY <-> B", NULL,
677 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
678 {"/Apply as Filter/Selected/ANY <-- B", NULL,
679 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
680 {"/Apply as Filter/Selected/ANY --> B", NULL,
681 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
683 {"/Apply as Filter/Not Selected", NULL, NULL, 0, "<Branch>", NULL,},
684 {"/Apply as Filter/Not Selected/A <-> B", NULL,
685 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
686 {"/Apply as Filter/Not Selected/A --> B", NULL,
687 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_TO_B), NULL, NULL,},
688 {"/Apply as Filter/Not Selected/A <-- B", NULL,
689 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_FROM_B), NULL, NULL,},
690 {"/Apply as Filter/Not Selected/A --> ANY", NULL,
691 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
692 {"/Apply as Filter/Not Selected/A <-> ANY", NULL,
693 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
694 {"/Apply as Filter/Not Selected/A <-- ANY", NULL,
695 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
696 {"/Apply as Filter/Not Selected/ANY <-> B", NULL,
697 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
698 {"/Apply as Filter/Not Selected/ANY <-- B", NULL,
699 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
700 {"/Apply as Filter/Not Selected/ANY --> B", NULL,
701 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_NOT_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
704 {"/Apply as Filter/... and Selected", NULL, NULL, 0, "<Branch>", NULL,},
705 {"/Apply as Filter/... and Selected/A <-> B", NULL,
706 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
707 {"/Apply as Filter/... and Selected/A --> B", NULL,
708 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_TO_B), NULL, NULL,},
709 {"/Apply as Filter/... and Selected/A <-- B", NULL,
710 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_FROM_B), NULL, NULL,},
711 {"/Apply as Filter/... and Selected/A <-> ANY", NULL,
712 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
713 {"/Apply as Filter/... and Selected/A --> ANY", NULL,
714 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
715 {"/Apply as Filter/... and Selected/A <-- ANY", NULL,
716 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
717 {"/Apply as Filter/... and Selected/ANY <-> B", NULL,
718 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
719 {"/Apply as Filter/... and Selected/ANY <-- B", NULL,
720 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
721 {"/Apply as Filter/... and Selected/ANY --> B", NULL,
722 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
724 {"/Apply as Filter/... or Selected", NULL, NULL, 0, "<Branch>", NULL,},
725 {"/Apply as Filter/... or Selected/A <-> B", NULL,
726 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
727 {"/Apply as Filter/... or Selected/A --> B", NULL,
728 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_TO_B), NULL, NULL,},
729 {"/Apply as Filter/... or Selected/A <-- B", NULL,
730 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_FROM_B), NULL, NULL,},
731 {"/Apply as Filter/... or Selected/A <-> ANY", NULL,
732 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
733 {"/Apply as Filter/... or Selected/A --> ANY", NULL,
734 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
735 {"/Apply as Filter/... or Selected/A <-- ANY", NULL,
736 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
737 {"/Apply as Filter/... or Selected/ANY <-> B", NULL,
738 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
739 {"/Apply as Filter/... or Selected/ANY <-- B", NULL,
740 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
741 {"/Apply as Filter/... or Selected/ANY --> B", NULL,
742 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
744 {"/Apply as Filter/... and not Selected", NULL, NULL, 0, "<Branch>", NULL,},
745 {"/Apply as Filter/... and not Selected/A <-> B", NULL,
746 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
747 {"/Apply as Filter/... and not Selected/A --> B", NULL,
748 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_B), NULL, NULL,},
749 {"/Apply as Filter/... and not Selected/A <-- B", NULL,
750 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_FROM_B), NULL, NULL,},
751 {"/Apply as Filter/... and not Selected/A <-> ANY", NULL,
752 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
753 {"/Apply as Filter/... and not Selected/A --> ANY", NULL,
754 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
755 {"/Apply as Filter/... and not Selected/A <-- ANY", NULL,
756 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
757 {"/Apply as Filter/... and not Selected/ANY <-> B", NULL,
758 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
759 {"/Apply as Filter/... and not Selected/ANY <-- B", NULL,
760 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
761 {"/Apply as Filter/... and not Selected/ANY --> B", NULL,
762 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
764 {"/Apply as Filter/... or not Selected", NULL, NULL, 0, "<Branch>", NULL,},
765 {"/Apply as Filter/... or not Selected/A <-> B", NULL,
766 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
767 {"/Apply as Filter/... or not Selected/A --> B", NULL,
768 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_B), NULL, NULL,},
769 {"/Apply as Filter/... or not Selected/A <-- B", NULL,
770 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_A_FROM_B), NULL, NULL,},
771 {"/Apply as Filter/... or not Selected/A <-> ANY", NULL,
772 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
773 {"/Apply as Filter/... or not Selected/A --> ANY", NULL,
774 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
775 {"/Apply as Filter/... or not Selected/A <-- ANY", NULL,
776 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
777 {"/Apply as Filter/... or not Selected/ANY <-> B", NULL,
778 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
779 {"/Apply as Filter/... or not Selected/ANY <-- B", NULL,
780 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
781 {"/Apply as Filter/... or not Selected/ANY --> B", NULL,
782 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
785 {"/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
786 {"/Prepare a Filter/Selected", NULL, NULL, 0, "<Branch>", NULL,},
787 {"/Prepare a Filter/Selected/A <-> B", NULL,
788 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
789 {"/Prepare a Filter/Selected/A --> B", NULL,
790 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_TO_B), NULL, NULL,},
791 {"/Prepare a Filter/Selected/A <-- B", NULL,
792 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_FROM_B), NULL, NULL,},
793 {"/Prepare a Filter/Selected/A <-> ANY", NULL,
794 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
795 {"/Prepare a Filter/Selected/A --> ANY", NULL,
796 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
797 {"/Prepare a Filter/Selected/A <-- ANY", NULL,
798 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
799 {"/Prepare a Filter/Selected/ANY <-> B", NULL,
800 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
801 {"/Prepare a Filter/Selected/ANY <-- B", NULL,
802 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
803 {"/Prepare a Filter/Selected/ANY --> B", NULL,
804 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
806 {"/Prepare a Filter/Not Selected", NULL, NULL, 0, "<Branch>", NULL,},
807 {"/Prepare a Filter/Not Selected/A <-> B", NULL,
808 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
809 {"/Prepare a Filter/Not Selected/A --> B", NULL,
810 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_TO_B), NULL, NULL,},
811 {"/Prepare a Filter/Not Selected/A <-- B", NULL,
812 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_FROM_B), NULL, NULL,},
813 {"/Prepare a Filter/Not Selected/A <-> ANY", NULL,
814 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
815 {"/Prepare a Filter/Not Selected/A --> ANY", NULL,
816 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
817 {"/Prepare a Filter/Not Selected/A <-- ANY", NULL,
818 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
819 {"/Prepare a Filter/Not Selected/ANY <-> B", NULL,
820 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
821 {"/Prepare a Filter/Not Selected/ANY <-- B", NULL,
822 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
823 {"/Prepare a Filter/Not Selected/ANY --> B", NULL,
824 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
826 {"/Prepare a Filter/... and Selected", NULL, NULL, 0, "<Branch>", NULL,},
827 {"/Prepare a Filter/... and Selected/A <-> B", NULL,
828 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
829 {"/Prepare a Filter/... and Selected/A --> B", NULL,
830 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_TO_B), NULL, NULL,},
831 {"/Prepare a Filter/... and Selected/A <-- B", NULL,
832 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_FROM_B), NULL, NULL,},
833 {"/Prepare a Filter/... and Selected/A <-> ANY", NULL,
834 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
835 {"/Prepare a Filter/... and Selected/A --> ANY", NULL,
836 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
837 {"/Prepare a Filter/... and Selected/A <-- ANY", NULL,
838 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
839 {"/Prepare a Filter/... and Selected/ANY <-> B", NULL,
840 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
841 {"/Prepare a Filter/... and Selected/ANY <-- B", NULL,
842 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
843 {"/Prepare a Filter/... and Selected/ANY --> B", NULL,
844 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
846 {"/Prepare a Filter/... or Selected", NULL, NULL, 0, "<Branch>", NULL,},
847 {"/Prepare a Filter/... or Selected/A <-> B", NULL,
848 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
849 {"/Prepare a Filter/... or Selected/A --> B", NULL,
850 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_TO_B), NULL, NULL,},
851 {"/Prepare a Filter/... or Selected/A <-- B", NULL,
852 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_FROM_B), NULL, NULL,},
853 {"/Prepare a Filter/... or Selected/A <-> ANY", NULL,
854 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
855 {"/Prepare a Filter/... or Selected/A --> ANY", NULL,
856 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
857 {"/Prepare a Filter/... or Selected/A <-- ANY", NULL,
858 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
859 {"/Prepare a Filter/... or Selected/ANY <-> B", NULL,
860 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
861 {"/Prepare a Filter/... or Selected/ANY <-- B", NULL,
862 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
863 {"/Prepare a Filter/... or Selected/ANY --> B", NULL,
864 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
866 {"/Prepare a Filter/... and not Selected", NULL, NULL, 0, "<Branch>", NULL,},
867 {"/Prepare a Filter/... and not Selected/A <-> B", NULL,
868 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
869 {"/Prepare a Filter/... and not Selected/A --> B", NULL,
870 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_B), NULL, NULL,},
871 {"/Prepare a Filter/... and not Selected/A <-- B", NULL,
872 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_FROM_B), NULL, NULL,},
873 {"/Prepare a Filter/... and not Selected/A <-> ANY", NULL,
874 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
875 {"/Prepare a Filter/... and not Selected/A --> ANY", NULL,
876 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
877 {"/Prepare a Filter/... and not Selected/A <-- ANY", NULL,
878 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
879 {"/Prepare a Filter/... and not Selected/ANY <-> B", NULL,
880 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
881 {"/Prepare a Filter/... and not Selected/ANY <-- B", NULL,
882 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
883 {"/Prepare a Filter/... and not Selected/ANY --> B", NULL,
884 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
886 {"/Prepare a Filter/... or not Selected", NULL, NULL, 0, "<Branch>", NULL,},
887 {"/Prepare a Filter/... or not Selected/A <-> B", NULL,
888 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
889 {"/Prepare a Filter/... or not Selected/A --> B", NULL,
890 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_B), NULL, NULL,},
891 {"/Prepare a Filter/... or not Selected/A <-- B", NULL,
892 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_A_FROM_B), NULL, NULL,},
893 {"/Prepare a Filter/... or not Selected/A <-> ANY", NULL,
894 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
895 {"/Prepare a Filter/... or not Selected/A --> ANY", NULL,
896 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
897 {"/Prepare a Filter/... or not Selected/A <-- ANY", NULL,
898 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
899 {"/Prepare a Filter/... or not Selected/ANY <-> B", NULL,
900 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
901 {"/Prepare a Filter/... or not Selected/ANY <-- B", NULL,
902 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
903 {"/Prepare a Filter/... or not Selected/ANY --> B", NULL,
904 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
907 {"/Find Packet", NULL, NULL, 0, "<Branch>", NULL,},
908 {"/Find Packet/Find Packet", NULL, NULL, 0, "<Branch>", NULL,},
909 {"/Find Packet/Find Packet/A <-> B", NULL,
910 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
911 {"/Find Packet/Find Packet/A --> B", NULL,
912 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_TO_B), NULL, NULL,},
913 {"/Find Packet/Find Packet/A <-- B", NULL,
914 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_FROM_B), NULL, NULL,},
915 {"/Find Packet/Find Packet/A <-> ANY", NULL,
916 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
917 {"/Find Packet/Find Packet/A --> ANY", NULL,
918 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
919 {"/Find Packet/Find Packet/A <-- ANY", NULL,
920 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
921 {"/Find Packet/Find Packet/ANY <-> B", NULL,
922 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
923 {"/Find Packet/Find Packet/ANY <-- B", NULL,
924 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
925 {"/Find Packet/Find Packet/ANY --> B", NULL,
926 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_FRAME(ACTYPE_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
928 {"/Find Packet/Find Next", NULL, NULL, 0, "<Branch>", NULL,},
929 {"/Find Packet/Find Next/A <-> B", NULL,
930 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_NEXT(ACTYPE_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
931 {"/Find Packet/Find Next/A --> B", NULL,
932 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_NEXT(ACTYPE_SELECTED, DIR_A_TO_B), NULL, NULL,},
933 {"/Find Packet/Find Next/A <-- B", NULL,
934 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_NEXT(ACTYPE_SELECTED, DIR_A_FROM_B), NULL, NULL,},
935 {"/Find Packet/Find Next/A <-> ANY", NULL,
936 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_NEXT(ACTYPE_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
937 {"/Find Packet/Find Next/A --> ANY", NULL,
938 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_NEXT(ACTYPE_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
939 {"/Find Packet/Find Next/A <-- ANY", NULL,
940 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_NEXT(ACTYPE_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
941 {"/Find Packet/Find Next/ANY <-> B", NULL,
942 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_NEXT(ACTYPE_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
943 {"/Find Packet/Find Next/ANY <-- B", NULL,
944 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_NEXT(ACTYPE_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
945 {"/Find Packet/Find Next/ANY --> B", NULL,
946 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_NEXT(ACTYPE_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
948 {"/Find Packet/Find Previous", NULL, NULL, 0, "<Branch>", NULL,},
949 {"/Find Packet/Find Previous/A <-> B", NULL,
950 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
951 {"/Find Packet/Find Previous/A --> B", NULL,
952 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, DIR_A_TO_B), NULL, NULL,},
953 {"/Find Packet/Find Previous/A <-- B", NULL,
954 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, DIR_A_FROM_B), NULL, NULL,},
955 {"/Find Packet/Find Previous/A <-> ANY", NULL,
956 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
957 {"/Find Packet/Find Previous/A --> ANY", NULL,
958 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
959 {"/Find Packet/Find Previous/A <-- ANY", NULL,
960 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
961 {"/Find Packet/Find Previous/ANY <-> B", NULL,
962 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
963 {"/Find Packet/Find Previous/ANY <-- B", NULL,
964 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
965 {"/Find Packet/Find Previous/ANY --> B", NULL,
966 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, DIR_ANY_TO_B), NULL, NULL,},
968 /* Colorize Conversation */
969 {"/Colorize Conversation", NULL, NULL, 0, "<Branch>", NULL,},
970 {"/Colorize Conversation/A <-> B", NULL,
971 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_TO_FROM_B), NULL, NULL,},
972 {"/Colorize Conversation/A --> B", NULL,
973 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_TO_B), NULL, NULL,},
974 {"/Colorize Conversation/A <-- B", NULL,
975 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_FROM_B), NULL, NULL,},
976 {"/Colorize Conversation/A <-> ANY", NULL,
977 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_TO_FROM_ANY), NULL, NULL,},
978 {"/Colorize Conversation/A --> ANY", NULL,
979 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_TO_ANY), NULL, NULL,},
980 {"/Colorize Conversation/A <-- ANY", NULL,
981 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_A_FROM_ANY), NULL, NULL,},
982 {"/Colorize Conversation/ANY <-> B", NULL,
983 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_ANY_TO_FROM_B), NULL, NULL,},
984 {"/Colorize Conversation/ANY <-- B", NULL,
985 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_ANY_FROM_B), NULL, NULL,},
986 {"/Colorize Conversation/ANY --> B", NULL,
987 GTK_MENU_FUNC(ct_select_filter_cb), CALLBACK_COLORIZE(ACTYPE_SELECTED, DIR_ANY_TO_B), NULL, NULL,}
991 ct_create_popup_menu(conversations_table *ct)
993 GtkItemFactory *item_factory;
995 item_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
997 gtk_item_factory_create_items_ac(item_factory, sizeof(ct_list_menu_items)/sizeof(ct_list_menu_items[0]), ct_list_menu_items, ct, 2);
999 ct->menu = gtk_item_factory_get_widget(item_factory, "<main>");
1000 g_signal_connect(ct->table, "button_press_event", G_CALLBACK(ct_show_popup_menu_cb), ct);
1003 /* Draw/refresh the address fields of a single entry at the specified index */
1005 draw_ct_table_address(conversations_table *ct, int conversation_idx)
1012 rownum=gtk_clist_find_row_from_data(ct->table, (gpointer)(long)conversation_idx);
1014 if(!ct->resolve_names)
1015 entry=address_to_str(&ct->conversations[conversation_idx].src_address);
1017 entry=get_addr_name(&ct->conversations[conversation_idx].src_address);
1019 gtk_clist_set_text(ct->table, rownum, 0, entry);
1021 pt = ct->conversations[conversation_idx].port_type;
1022 if(!ct->resolve_names) pt = PT_NONE;
1025 entry=get_tcp_port(ct->conversations[conversation_idx].src_port);
1028 entry=get_udp_port(ct->conversations[conversation_idx].src_port);
1031 entry=get_sctp_port(ct->conversations[conversation_idx].src_port);
1034 port=ct_port_to_str(ct->conversations[conversation_idx].port_type, ct->conversations[conversation_idx].src_port);
1037 gtk_clist_set_text(ct->table, rownum, 1, entry);
1039 if(!ct->resolve_names)
1040 entry=address_to_str(&ct->conversations[conversation_idx].dst_address);
1042 entry=get_addr_name(&ct->conversations[conversation_idx].dst_address);
1044 gtk_clist_set_text(ct->table, rownum, 2, entry);
1048 entry=get_tcp_port(ct->conversations[conversation_idx].dst_port);
1051 entry=get_udp_port(ct->conversations[conversation_idx].dst_port);
1054 entry=get_sctp_port(ct->conversations[conversation_idx].dst_port);
1057 port=ct_port_to_str(ct->conversations[conversation_idx].port_type, ct->conversations[conversation_idx].dst_port);
1060 gtk_clist_set_text(ct->table, rownum, 3, entry);
1063 /* Refresh the address fields of all entries in the list */
1065 draw_ct_table_addresses(conversations_table *ct)
1069 for(i=0;i<ct->num_conversations;i++){
1070 draw_ct_table_address(ct, i);
1076 draw_ct_table_data(conversations_table *ct)
1084 if(ct->num_conversations) {
1085 g_snprintf(title, sizeof(title), "%s: %u", ct->name, ct->num_conversations);
1087 g_snprintf(title, sizeof(title), "%s", ct->name);
1089 gtk_label_set_text(GTK_LABEL(ct->page_lb), title);
1090 gtk_widget_set_sensitive(ct->page_lb, ct->num_conversations);
1092 if(ct->num_conversations) {
1093 g_snprintf(title, sizeof(title), "%s Conversations: %u", ct->name, ct->num_conversations);
1095 g_snprintf(title, sizeof(title), "%s Conversations", ct->name);
1097 gtk_label_set_text(GTK_LABEL(ct->name_lb), title);
1100 for(i=0;i<ct->num_conversations;i++){
1101 char str[COL_STR_LEN];
1103 j=gtk_clist_find_row_from_data(ct->table, (gpointer)(unsigned long)i);
1105 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_frames+ct->conversations[i].rx_frames);
1106 gtk_clist_set_text(ct->table, j, 4, str);
1107 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_bytes+ct->conversations[i].rx_bytes);
1108 gtk_clist_set_text(ct->table, j, 5, str);
1111 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_frames);
1112 gtk_clist_set_text(ct->table, j, 6, str);
1113 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].tx_bytes);
1114 gtk_clist_set_text(ct->table, j, 7, str);
1117 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].rx_frames);
1118 gtk_clist_set_text(ct->table, j, 8, str);
1119 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", ct->conversations[i].rx_bytes);
1120 gtk_clist_set_text(ct->table, j, 9, str);
1122 duration_s = nstime_to_sec(&ct->conversations[i].stop_time) - nstime_to_sec(&ct->conversations[i].start_time);
1123 g_snprintf(str, COL_STR_LEN, "%s", rel_time_to_secs_str(&ct->conversations[i].start_time));
1124 gtk_clist_set_text(ct->table, j, 10, str);
1125 g_snprintf(str, COL_STR_LEN, "%.4f", duration_s);
1126 gtk_clist_set_text(ct->table, j, 11, str);
1127 if (duration_s > 0 && ct->conversations[i].tx_frames > 1) {
1128 /* XXX - The gint64 casts below are needed for MSVC++ 6.0 */
1129 g_snprintf(str, COL_STR_LEN, "%.2f", (gint64) ct->conversations[i].tx_bytes * 8 / duration_s);
1130 gtk_clist_set_text(ct->table, j, 12, str);
1132 gtk_clist_set_text(ct->table, j, 12, NO_BPS_STR);
1134 if (duration_s > 0 && ct->conversations[i].rx_frames > 1) {
1135 /* XXX - The gint64 casts below are needed for MSVC++ 6.0 */
1136 g_snprintf(str, COL_STR_LEN, "%.2f", (gint64) ct->conversations[i].rx_bytes * 8 / duration_s);
1137 gtk_clist_set_text(ct->table, j, 13, str);
1139 gtk_clist_set_text(ct->table, j, 13, NO_BPS_STR);
1143 draw_ct_table_addresses(ct);
1145 gtk_clist_sort(ct->table);
1147 /* Allow table to redraw */
1148 gtk_clist_thaw(ct->table);
1149 gtk_clist_freeze(ct->table);
1153 draw_ct_table_data_cb(void *arg)
1155 draw_ct_table_data(arg);
1159 copy_as_csv_cb(GtkWindow *copy_bt, gpointer data _U_)
1164 GString *CSV_str = g_string_new("");
1166 conversations_table *talkers=g_object_get_data(G_OBJECT(copy_bt), CONV_PTR_KEY);
1170 /* Add the column headers to the CSV data */
1171 for(i=0;i<talkers->num_columns;i++){ /* all columns */
1172 if((i==1 || i==3) && !talkers->has_ports) continue; /* Don't add the port column if it's empty */
1173 g_string_append(CSV_str,talkers->default_titles[i]);/* add the column heading to the CSV string */
1174 if(i!=talkers->num_columns-1)
1175 g_string_append(CSV_str,",");
1177 g_string_append(CSV_str,"\n"); /* new row */
1179 /* Add the column values to the CSV data */
1180 for(i=0;i<talkers->num_conversations;i++){ /* all rows */
1181 for(j=0;j<talkers->num_columns;j++){ /* all columns */
1182 if((j==1 || j==3) && !talkers->has_ports) continue; /* Don't add the port column if it's empty */
1183 gtk_clist_get_text(talkers->table,i,j,&table_entry);/* copy table item into string */
1184 g_string_append(CSV_str,table_entry); /* add the table entry to the CSV string */
1185 if(j!=talkers->num_columns-1)
1186 g_string_append(CSV_str,",");
1188 g_string_append(CSV_str,"\n"); /* new row */
1191 /* Now that we have the CSV data, copy it into the default clipboard */
1192 cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); /* Get the default clipboard */
1193 gtk_clipboard_set_text(cb, CSV_str->str, -1); /* Copy the CSV data into the clipboard */
1194 g_string_free(CSV_str, TRUE); /* Free the memory */
1199 init_ct_table_page(conversations_table *conversations, GtkWidget *vbox, gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
1202 column_arrows *col_arrows;
1203 GtkStyle *win_style;
1204 GtkWidget *column_lb;
1205 GString *error_string;
1208 conversations->page_lb=NULL;
1209 conversations->resolve_names=TRUE;
1210 conversations->has_ports=!hide_ports;
1211 conversations->num_columns=NUM_COLS;
1212 conversations->default_titles[0]="Address A",
1213 conversations->default_titles[1]="Port A";
1214 conversations->default_titles[2]="Address B";
1215 conversations->default_titles[3]="Port B";
1216 conversations->default_titles[4]="Packets";
1217 conversations->default_titles[5]="Bytes";
1218 conversations->default_titles[6]="Packets A->B";
1219 conversations->default_titles[7]="Bytes A->B";
1220 conversations->default_titles[8]="Packets A<-B";
1221 conversations->default_titles[9]="Bytes A<-B";
1222 conversations->default_titles[10]="Rel Start";
1223 conversations->default_titles[11]="Duration";
1224 conversations->default_titles[12]="bps A->B";
1225 conversations->default_titles[13]="bps A<-B";
1226 if (strcmp(table_name, "NCP")==0) {
1227 conversations->default_titles[1]="Connection A";
1228 conversations->default_titles[3]="Connection B";
1231 g_snprintf(title, sizeof(title), "%s Conversations", table_name);
1232 conversations->name_lb=gtk_label_new(title);
1233 gtk_box_pack_start(GTK_BOX(vbox), conversations->name_lb, FALSE, FALSE, 0);
1236 conversations->scrolled_window=scrolled_window_new(NULL, NULL);
1237 gtk_box_pack_start(GTK_BOX(vbox), conversations->scrolled_window, TRUE, TRUE, 0);
1239 conversations->table=(GtkCList *)gtk_clist_new(NUM_COLS);
1240 g_object_set_data(G_OBJECT(conversations->table), CONV_PTR_KEY, conversations);
1242 col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS);
1243 win_style = gtk_widget_get_style(conversations->scrolled_window);
1244 for (i = 0; i < NUM_COLS; i++) {
1245 col_arrows[i].table = gtk_table_new(2, 2, FALSE);
1246 gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
1247 column_lb = gtk_label_new(conversations->default_titles[i]);
1248 gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
1249 gtk_widget_show(column_lb);
1251 col_arrows[i].ascend_pm = xpm_to_widget((const char **) clist_ascend_xpm);
1252 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
1253 col_arrows[i].descend_pm = xpm_to_widget((const char **) clist_descend_xpm);
1254 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
1255 /* make total frames be the default sort order */
1257 gtk_widget_show(col_arrows[i].ascend_pm);
1259 gtk_clist_set_column_widget(GTK_CLIST(conversations->table), i, col_arrows[i].table);
1260 gtk_widget_show(col_arrows[i].table);
1262 gtk_clist_column_titles_show(GTK_CLIST(conversations->table));
1264 gtk_clist_set_compare_func(conversations->table, ct_sort_column);
1265 gtk_clist_set_sort_column(conversations->table, 4);
1266 gtk_clist_set_sort_type(conversations->table, GTK_SORT_ASCENDING);
1269 for (i = 0; i < NUM_COLS; i++) {
1270 gtk_clist_set_column_auto_resize(conversations->table, i, TRUE);
1273 gtk_clist_set_shadow_type(conversations->table, GTK_SHADOW_IN);
1274 gtk_clist_column_titles_show(conversations->table);
1275 gtk_container_add(GTK_CONTAINER(conversations->scrolled_window), (GtkWidget *)conversations->table);
1277 g_signal_connect(conversations->table, "click-column", G_CALLBACK(ct_click_column_cb), col_arrows);
1279 conversations->num_conversations=0;
1280 conversations->conversations=NULL;
1282 /* hide srcport and dstport if we don't use ports */
1284 gtk_clist_set_column_visibility(conversations->table, 1, FALSE);
1285 gtk_clist_set_column_visibility(conversations->table, 3, FALSE);
1288 /* create popup menu for this table */
1289 ct_create_popup_menu(conversations);
1291 /* register the tap and rerun the taps on the packet list */
1292 error_string=register_tap_listener(tap_name, conversations, filter, reset_ct_table_data_cb, packet_func, draw_ct_table_data_cb);
1294 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
1295 g_string_free(error_string, TRUE);
1304 init_conversation_table(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
1306 conversations_table *conversations;
1310 GtkWidget *close_bt, *help_bt;
1313 GtkTooltips *tooltips = gtk_tooltips_new();
1315 conversations=g_malloc(sizeof(conversations_table));
1317 conversations->name=table_name;
1318 conversations->filter=filter;
1319 conversations->use_dfilter=FALSE;
1320 g_snprintf(title, sizeof(title), "%s Conversations: %s", table_name, cf_get_display_name(&cfile));
1321 conversations->win=window_new(GTK_WINDOW_TOPLEVEL, title);
1323 gtk_window_set_default_size(GTK_WINDOW(conversations->win), 750, 400);
1325 vbox=gtk_vbox_new(FALSE, 3);
1326 gtk_container_add(GTK_CONTAINER(conversations->win), vbox);
1327 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
1329 ret = init_ct_table_page(conversations, vbox, hide_ports, table_name, tap_name, filter, packet_func);
1331 g_free(conversations);
1336 /* XXX - maybe we want to have a "Copy as CSV" stock button here? */
1337 /*copy_bt = gtk_button_new_with_label ("Copy content to clipboard as CSV");*/
1338 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, GTK_STOCK_HELP, NULL);
1339 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
1341 close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
1342 window_set_cancel_button(conversations->win, close_bt, window_cancel_button_cb);
1344 copy_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_COPY);
1345 gtk_tooltips_set_tip(tooltips, copy_bt,
1346 "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.", NULL);
1347 g_object_set_data(G_OBJECT(copy_bt), CONV_PTR_KEY, conversations);
1348 g_signal_connect(copy_bt, "clicked", G_CALLBACK(copy_as_csv_cb), NULL);
1350 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
1351 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_STATS_CONVERSATIONS_DIALOG);
1353 g_signal_connect(conversations->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
1354 g_signal_connect(conversations->win, "destroy", G_CALLBACK(ct_win_destroy_cb), conversations);
1356 gtk_widget_show_all(conversations->win);
1357 window_present(conversations->win);
1359 cf_retap_packets(&cfile, FALSE);
1360 gdk_window_raise(conversations->win->window);
1362 /* Keep clist frozen to cause modifications to the clist (inserts, appends, others that are extremely slow
1363 in GTK2) to not be drawn, allow refreshes to occur at strategic points for performance */
1364 gtk_clist_freeze(conversations->table);
1366 /* after retapping, redraw table */
1367 draw_ct_table_data(conversations);
1373 ct_nb_switch_page_cb(GtkNotebook *nb, GtkNotebookPage *pg _U_, guint page, gpointer data)
1375 GtkWidget *copy_bt = (GtkWidget *) data;
1376 void ** pages = g_object_get_data(G_OBJECT(nb), NB_PAGES_KEY);
1380 if (pages && page > 0 && (int) page <= GPOINTER_TO_INT(pages[0]) && copy_bt) {
1381 g_object_set_data(G_OBJECT(copy_bt), CONV_PTR_KEY, pages[page]);
1386 ct_win_destroy_notebook_cb(GtkWindow *win _U_, gpointer data)
1388 void ** pages = data;
1391 /* first "page" contains the number of pages */
1392 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1393 ct_win_destroy_cb(NULL, pages[page]);
1398 static conversations_table *
1399 init_ct_notebook_page_cb(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
1402 GtkWidget *page_vbox;
1403 conversations_table *conversations;
1405 conversations=g_malloc(sizeof(conversations_table));
1406 conversations->name=table_name;
1407 conversations->filter=filter;
1408 conversations->resolve_names=TRUE;
1409 conversations->use_dfilter=FALSE;
1411 page_vbox=gtk_vbox_new(FALSE, 6);
1412 conversations->win = page_vbox;
1413 gtk_container_set_border_width(GTK_CONTAINER(page_vbox), 6);
1415 ret = init_ct_table_page(conversations, page_vbox, hide_ports, table_name, tap_name, filter, packet_func);
1417 g_free(conversations);
1421 return conversations;
1426 gboolean hide_ports; /* hide TCP / UDP port columns */
1427 const char *table_name; /* GUI output name */
1428 const char *tap_name; /* internal name */
1429 const char *filter; /* display filter string (unused) */
1430 tap_packet_cb packet_func; /* function to be called for new incoming packets */
1434 static GSList *registered_ct_tables = NULL;
1437 register_conversation_table(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
1439 register_ct_t *table;
1441 table = g_malloc(sizeof(register_ct_t));
1443 table->hide_ports = hide_ports;
1444 table->table_name = table_name;
1445 table->tap_name = tap_name;
1446 table->filter = filter;
1447 table->packet_func = packet_func;
1449 registered_ct_tables = g_slist_append(registered_ct_tables, table);
1454 ct_resolve_toggle_dest(GtkWidget *widget, gpointer data)
1457 void ** pages = data;
1458 gboolean resolve_names;
1459 conversations_table *conversations;
1462 resolve_names = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1464 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1465 conversations = pages[page];
1466 conversations->resolve_names = resolve_names;
1468 draw_ct_table_addresses(conversations);
1470 /* Allow table to redraw */
1471 gtk_clist_thaw(conversations->table);
1472 gtk_clist_freeze(conversations->table);
1478 ct_filter_toggle_dest(GtkWidget *widget, gpointer data)
1481 void ** pages = data;
1482 gboolean use_filter;
1483 conversations_table *conversations = NULL;
1485 use_filter = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1487 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1488 conversations = pages[page];
1489 conversations->use_dfilter = use_filter;
1490 reset_ct_table_data(conversations);
1493 cf_retap_packets(&cfile, FALSE);
1494 if (conversations) {
1495 gdk_window_raise(conversations->win->window);
1498 /* after retapping, redraw table */
1499 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1500 draw_ct_table_data(pages[page]);
1506 init_conversation_notebook_cb(GtkWidget *w _U_, gpointer d _U_)
1508 conversations_table *conversations;
1513 GtkWidget *close_bt, *help_bt;
1515 GtkWidget *resolv_cb;
1516 GtkWidget *filter_cb;
1521 GSList *current_table;
1522 register_ct_t *registered;
1523 GtkTooltips *tooltips = gtk_tooltips_new();
1526 pages = g_malloc(sizeof(void *) * (g_slist_length(registered_ct_tables) + 1));
1528 g_snprintf(title, sizeof(title), "Conversations: %s", cf_get_display_name(&cfile));
1529 win=window_new(GTK_WINDOW_TOPLEVEL, title);
1530 gtk_window_set_default_size(GTK_WINDOW(win), 750, 400);
1532 vbox=gtk_vbox_new(FALSE, 6);
1533 gtk_container_add(GTK_CONTAINER(win), vbox);
1534 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
1536 nb = gtk_notebook_new();
1537 gtk_container_add(GTK_CONTAINER(vbox), nb);
1538 g_object_set_data(G_OBJECT(nb), NB_PAGES_KEY, pages);
1542 current_table = registered_ct_tables;
1543 while(current_table) {
1544 registered = current_table->data;
1545 page_lb = gtk_label_new("");
1546 conversations = init_ct_notebook_page_cb(registered->hide_ports, registered->table_name, registered->tap_name,
1547 registered->filter, registered->packet_func);
1548 g_object_set_data(G_OBJECT(conversations->win), CONV_PTR_KEY, conversations);
1549 gtk_notebook_append_page(GTK_NOTEBOOK(nb), conversations->win, page_lb);
1550 conversations->win = win;
1551 conversations->page_lb = page_lb;
1552 pages[++page] = conversations;
1554 current_table = g_slist_next(current_table);
1557 pages[0] = GINT_TO_POINTER(page);
1559 hbox = gtk_hbox_new(FALSE, 3);
1560 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1562 resolv_cb = gtk_check_button_new_with_mnemonic("Name resolution");
1563 gtk_container_add(GTK_CONTAINER(hbox), resolv_cb);
1564 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(resolv_cb), TRUE);
1565 gtk_tooltips_set_tip(tooltips, resolv_cb, "Show results of name resolutions rather than the \"raw\" values. "
1566 "Please note: The corresponding name resolution must be enabled.", NULL);
1568 g_signal_connect(resolv_cb, "toggled", G_CALLBACK(ct_resolve_toggle_dest), pages);
1570 filter_cb = gtk_check_button_new_with_mnemonic("Limit to display filter");
1571 gtk_container_add(GTK_CONTAINER(hbox), filter_cb);
1572 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_cb), FALSE);
1573 gtk_tooltips_set_tip(tooltips, filter_cb, "Limit the list to conversations matching the current display filter.", NULL);
1575 g_signal_connect(filter_cb, "toggled", G_CALLBACK(ct_filter_toggle_dest), pages);
1578 /* XXX - maybe we want to have a "Copy as CSV" stock button here? */
1579 /*copy_bt = gtk_button_new_with_label ("Copy content to clipboard as CSV");*/
1580 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, GTK_STOCK_HELP, NULL);
1582 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
1584 close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
1585 window_set_cancel_button(win, close_bt, window_cancel_button_cb);
1587 copy_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_COPY);
1588 gtk_tooltips_set_tip(tooltips, copy_bt,
1589 "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.", NULL);
1590 g_signal_connect(copy_bt, "clicked", G_CALLBACK(copy_as_csv_cb), NULL);
1591 g_object_set_data(G_OBJECT(copy_bt), CONV_PTR_KEY, pages[page]);
1593 g_signal_connect(nb, "switch-page", G_CALLBACK(ct_nb_switch_page_cb), copy_bt);
1595 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
1596 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_STATS_CONVERSATIONS_DIALOG);
1598 g_signal_connect(win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
1599 g_signal_connect(win, "destroy", G_CALLBACK(ct_win_destroy_notebook_cb), pages);
1601 gtk_widget_show_all(win);
1602 window_present(win);
1604 cf_retap_packets(&cfile, FALSE);
1605 gdk_window_raise(win->window);
1607 /* after retapping, redraw table */
1608 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1609 draw_ct_table_data(pages[page]);
1615 add_conversation_table_data(conversations_table *ct, const address *src, const address *dst, guint32 src_port, guint32 dst_port, int num_frames, int num_bytes, nstime_t *ts, SAT_E sat, int port_type)
1617 const address *addr1, *addr2;
1618 guint32 port1, port2;
1619 conv_t *conversation=NULL;
1620 int conversation_idx=0;
1621 gboolean new_conversation;
1623 if(src_port>dst_port){
1628 } else if(src_port<dst_port){
1633 } else if(CMP_ADDRESS(src, dst)<0){
1646 new_conversation=FALSE;
1647 /* XXX should be optimized to allocate n extra entries at a time
1648 instead of just one */
1649 /* if we dont have any entries at all yet */
1650 if(ct->conversations==NULL){
1651 ct->conversations=g_malloc(sizeof(conv_t));
1652 ct->num_conversations=1;
1653 conversation=&ct->conversations[0];
1655 new_conversation=TRUE;
1658 /* try to find it among the existing known conversations */
1659 if(conversation==NULL){
1661 for(i=0;i<ct->num_conversations;i++){
1662 if( (!CMP_ADDRESS(&ct->conversations[i].src_address, addr1))&&(!CMP_ADDRESS(&ct->conversations[i].dst_address, addr2))&&(ct->conversations[i].src_port==port1)&&(ct->conversations[i].dst_port==port2) ){
1663 conversation=&ct->conversations[i];
1667 if( (!CMP_ADDRESS(&ct->conversations[i].src_address, addr2))&&(!CMP_ADDRESS(&ct->conversations[i].dst_address, addr1))&&(ct->conversations[i].src_port==port2)&&(ct->conversations[i].dst_port==port1) ){
1668 conversation=&ct->conversations[i];
1675 /* if we still dont know what conversation this is it has to be a new one
1676 and we have to allocate it and append it to the end of the list */
1677 if(conversation==NULL){
1678 new_conversation=TRUE;
1679 ct->num_conversations++;
1680 ct->conversations=g_realloc(ct->conversations, ct->num_conversations*sizeof(conv_t));
1681 conversation=&ct->conversations[ct->num_conversations-1];
1682 conversation_idx=ct->num_conversations-1;
1685 /* if this is a new conversation we need to initialize the struct */
1686 if(new_conversation){
1687 COPY_ADDRESS(&conversation->src_address, addr1);
1688 COPY_ADDRESS(&conversation->dst_address, addr2);
1689 conversation->sat=sat;
1690 conversation->port_type=port_type;
1691 conversation->src_port=port1;
1692 conversation->dst_port=port2;
1693 conversation->rx_frames=0;
1694 conversation->tx_frames=0;
1695 conversation->rx_bytes=0;
1696 conversation->tx_bytes=0;
1698 memcpy(&conversation->start_time, ts, sizeof(conversation->start_time));
1699 memcpy(&conversation->stop_time, ts, sizeof(conversation->stop_time));
1701 nstime_set_unset(&conversation->start_time);
1702 nstime_set_unset(&conversation->stop_time);
1706 /* update the conversation struct */
1707 if( (!CMP_ADDRESS(src, addr1))&&(!CMP_ADDRESS(dst, addr2))&&(src_port==port1)&&(dst_port==port2) ){
1708 conversation->tx_frames+=num_frames;
1709 conversation->tx_bytes+=num_bytes;
1711 conversation->rx_frames+=num_frames;
1712 conversation->rx_bytes+=num_bytes;
1716 if (nstime_cmp(ts, &conversation->stop_time) > 0) {
1717 memcpy(&conversation->stop_time, ts, sizeof(conversation->stop_time));
1718 } else if (nstime_cmp(ts, &conversation->start_time) < 0) {
1719 memcpy(&conversation->start_time, ts, sizeof(conversation->start_time));
1723 /* if this was a new conversation we have to create a clist row for it */
1724 if(new_conversation){
1725 char *entries[NUM_COLS];
1726 char frames[COL_STR_LEN], bytes[COL_STR_LEN],
1727 txframes[COL_STR_LEN], txbytes[COL_STR_LEN],
1728 rxframes[COL_STR_LEN], rxbytes[COL_STR_LEN],
1729 start_time[COL_STR_LEN], duration[COL_STR_LEN],
1730 txbps[COL_STR_LEN], rxbps[COL_STR_LEN];
1733 /* these values will be filled by call to draw_ct_table_addresses() below */
1739 g_snprintf(frames, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->tx_frames+conversation->rx_frames);
1741 g_snprintf(bytes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->tx_bytes+conversation->rx_bytes);
1744 g_snprintf(txframes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->tx_frames);
1745 entries[6]=txframes;
1746 g_snprintf(txbytes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->tx_bytes);
1749 g_snprintf(rxframes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->rx_frames);
1750 entries[8]=rxframes;
1751 g_snprintf(rxbytes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", conversation->rx_bytes);
1754 duration_s = nstime_to_sec(&conversation->start_time) - nstime_to_sec(&conversation->stop_time);
1755 g_snprintf(start_time, COL_STR_LEN, "%s", rel_time_to_secs_str(&conversation->start_time));
1756 g_snprintf(duration, COL_STR_LEN, "%.4f", duration_s);
1757 entries[10]=start_time;
1758 entries[11]=duration;
1759 if (duration_s > 0 && conversation->tx_frames > 1) {
1760 g_snprintf(txbps, COL_STR_LEN, "%.2f", (gint64) conversation->tx_bytes * 8 / duration_s);
1763 entries[12] = NO_BPS_STR;
1765 if (duration_s > 0 && conversation->rx_frames > 1) {
1766 g_snprintf(rxbps, COL_STR_LEN, "%.2f", (gint64) conversation->rx_bytes * 8 / duration_s);
1769 entries[13] = NO_BPS_STR;
1772 gtk_clist_insert(ct->table, conversation_idx, entries);
1773 gtk_clist_set_row_data(ct->table, conversation_idx, (gpointer)(long) conversation_idx);
1775 draw_ct_table_address(ct, conversation_idx);
1785 * indent-tabs-mode: nil
1788 * ex: set shiftwidth=4 tabstop=8 expandtab
1789 * :indentSize=4:tabSize=8:noTabs=true: