refactoring and renaming finished
[obnox/wireshark/wip.git] / gtk / conversations_table.c
1 /* mem leak   should free the column_arrows when the table is destroyed */
2
3 /* conversations_table.c
4  * conversations_table   2003 Ronnie Sahlberg
5  * Helper routines common to all endpoint conversations tap.
6  *
7  * $Id$
8  *
9  * Ethereal - Network traffic analyzer
10  * By Gerald Combs <gerald@ethereal.com>
11  * Copyright 1998 Gerald Combs
12  *
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.
17  *
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.
22  *
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.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <math.h>
36
37 #include <gtk/gtk.h>
38
39 #include "compat_macros.h"
40 #include "epan/packet_info.h"
41 #include "epan/to_str.h"
42 #include "epan/resolv.h"
43 #include "sat.h"
44 #include "conversations_table.h"
45 #include "image/clist_ascend.xpm"
46 #include "image/clist_descend.xpm"
47 #include "simple_dialog.h"
48 #include "globals.h"
49 #include "tap.h"
50 #include "gtk/find_dlg.h"
51 #include "color.h"
52 #include "gtk/color_dlg.h"
53 #include "gtkglobals.h"
54 #include "main.h"
55 #include "ui_util.h"
56 #include "dlg_utils.h"
57
58
59 #define GTK_MENU_FUNC(a) ((GtkItemFactoryCallback)(a))
60
61 #define NUM_COLS 10
62
63
64 /* convert a port number into a string */
65 static char *
66 ct_port_to_str(int port_type, guint32 port)
67 {
68         static int i=0;
69         static gchar *strp, str[4][12];
70
71         i++;
72         if(i>=4){
73                 i=0;
74         }
75         strp=str[i];
76
77         switch(port_type){
78         case PT_TCP:
79         case PT_UDP:
80                 g_snprintf(strp, 11, "%d", port);
81                 return strp;
82         }
83         return NULL;
84 }
85
86
87 #define FN_SRC_ADDRESS          0
88 #define FN_DST_ADDRESS          1
89 #define FN_ANY_ADDRESS          2
90 #define FN_SRC_PORT             3
91 #define FN_DST_PORT             4
92 #define FN_ANY_PORT             5
93 /* given an address (to distinguis between ipv4 and ipv6 for tcp/udp
94    a port_type and a name_type (FN_...)
95    return a string for the filter name
96
97    some addresses, like AT_ETHER may actually be any of multiple types
98    of protocols,   either ethernet, tokenring, fddi etc so we must be more
99    specific there  thats why we need specific_addr_type
100 */
101 static char *
102 ct_get_filter_name(address *addr, int specific_addr_type, int port_type, int name_type)
103 {
104         switch(name_type){
105         case FN_SRC_ADDRESS:
106                 switch(addr->type){
107                 case AT_ETHER:
108                         switch(specific_addr_type){
109                         case SAT_ETHER:
110                                 return "eth.src";
111                         case SAT_FDDI:
112                                 return "fddi.src";
113                         case SAT_TOKENRING:
114                                 return "tr.src";
115                         }
116                 case AT_IPv4:
117                         return "ip.src";
118                 case AT_IPv6:
119                         return "ipv6.src";
120                 case AT_IPX:
121                         return "ipx.src";
122                 case AT_FC:
123                         return "fc.s_id";
124                 default:
125                         ;
126                 }
127         case FN_DST_ADDRESS:
128                 switch(addr->type){
129                 case AT_ETHER:
130                         switch(specific_addr_type){
131                         case SAT_ETHER:
132                                 return "eth.dst";
133                         case SAT_FDDI:
134                                 return "fddi.dst";
135                         case SAT_TOKENRING:
136                                 return "tr.dst";
137                         }
138                 case AT_IPv4:
139                         return "ip.dst";
140                 case AT_IPv6:
141                         return "ipv6.dst";
142                 case AT_IPX:
143                         return "ipx.dst";
144                 case AT_FC:
145                         return "fc.d_id";
146                 default:
147                         ;
148                 }
149         case FN_ANY_ADDRESS:
150                 switch(addr->type){
151                 case AT_ETHER:
152                         switch(specific_addr_type){
153                         case SAT_ETHER:
154                                 return "eth.addr";
155                         case SAT_FDDI:
156                                 return "fddi.addr";
157                         case SAT_TOKENRING:
158                                 return "tr.addr";
159                         }
160                 case AT_IPv4:
161                         return "ip.addr";
162                 case AT_IPv6:
163                         return "ipv6.addr";
164                 case AT_IPX:
165                         return "ipx.addr";
166                 case AT_FC:
167                         return "fc.id";
168                 default:
169                         ;
170                 }
171         case FN_SRC_PORT:
172                 switch(port_type){
173                 case PT_TCP:
174                         return "tcp.srcport";
175                 case PT_UDP:
176                         return "udp.srcport";
177                 }
178                 break;
179         case FN_DST_PORT:
180                 switch(port_type){
181                 case PT_TCP:
182                         return "tcp.dstport";
183                 case PT_UDP:
184                         return "udp.dstport";
185                 }
186                 break;
187         case FN_ANY_PORT:
188                 switch(port_type){
189                 case PT_TCP:
190                         return "tcp.port";
191                 case PT_UDP:
192                         return "udp.port";
193                 }
194                 break;
195         }
196
197         g_assert_not_reached();
198         return NULL;
199 }
200
201
202 typedef struct column_arrows {
203         GtkWidget *table;
204         GtkWidget *ascend_pm;
205         GtkWidget *descend_pm;
206 } column_arrows;
207
208
209
210 static void
211 reset_ct_table_data(conversations_table *ct)
212 {
213     guint32 i;
214     char title[256];
215
216     if(ct->page_lb) {
217         g_snprintf(title, 255, "Conversations: %s", cf_get_display_name(&cfile));
218         gtk_window_set_title(GTK_WINDOW(ct->win), title);
219         g_snprintf(title, 255, "%s", ct->name);
220         gtk_label_set_text(GTK_LABEL(ct->page_lb), title);
221         gtk_widget_set_sensitive(ct->page_lb, FALSE);
222     } else {
223         g_snprintf(title, 255, "%s Conversations: %s", ct->name, cf_get_display_name(&cfile));
224         gtk_window_set_title(GTK_WINDOW(ct->win), title);
225     }
226
227     /* remove all entries from the clist */
228     gtk_clist_clear(ct->table);
229
230     /* delete all conversations */
231     for(i=0;i<ct->num_conversations;i++){
232         g_free((gpointer)ct->conversations[i].src_address.data);
233         g_free((gpointer)ct->conversations[i].dst_address.data);
234     }
235     g_free(ct->conversations);
236     ct->conversations=NULL;
237     ct->num_conversations=0;
238 }
239
240
241 void protect_thread_critical_region(void);
242 void unprotect_thread_critical_region(void);
243 static void
244 ct_win_destroy_cb(GtkWindow *win _U_, gpointer data)
245 {
246         conversations_table *conversations=(conversations_table *)data;
247
248         protect_thread_critical_region();
249         remove_tap_listener(conversations);
250         unprotect_thread_critical_region();
251
252         reset_ct_table_data(conversations);
253         g_free(conversations);
254 }
255
256
257
258 static gint
259 ct_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
260 {
261         char *text1 = NULL;
262         char *text2 = NULL;
263         int i1, i2;
264
265         GtkCListRow *row1 = (GtkCListRow *) ptr1;
266         GtkCListRow *row2 = (GtkCListRow *) ptr2;
267
268         text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
269         text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
270
271         switch(clist->sort_column){
272         case 0:
273         case 2:
274                 return strcmp (text1, text2);
275         case 1:
276         case 3:
277         case 4:
278         case 5:
279         case 6:
280         case 7:
281         case 8:
282         case 9:
283                 i1=atoi(text1);
284                 i2=atoi(text2);
285                 return i1-i2;
286         }
287         g_assert_not_reached();
288         return 0;
289 }
290
291
292 static void
293 ct_click_column_cb(GtkCList *clist, gint column, gpointer data)
294 {
295         column_arrows *col_arrows = (column_arrows *) data;
296         int i;
297
298         gtk_clist_freeze(clist);
299
300         for (i = 0; i < NUM_COLS; i++) {
301                 gtk_widget_hide(col_arrows[i].ascend_pm);
302                 gtk_widget_hide(col_arrows[i].descend_pm);
303         }
304
305         if (column == clist->sort_column) {
306                 if (clist->sort_type == GTK_SORT_ASCENDING) {
307                         clist->sort_type = GTK_SORT_DESCENDING;
308                         gtk_widget_show(col_arrows[column].descend_pm);
309                 } else {
310                         clist->sort_type = GTK_SORT_ASCENDING;
311                         gtk_widget_show(col_arrows[column].ascend_pm);
312                 }
313         } else {
314                 clist->sort_type = GTK_SORT_DESCENDING;
315                 gtk_widget_show(col_arrows[column].descend_pm);
316                 gtk_clist_set_sort_column(clist, column);
317         }
318
319         gtk_clist_sort(clist);
320
321         gtk_clist_thaw(clist);
322
323 }
324
325
326 /* action is encoded as
327    filter_action*65536+filter_type*256+filter_direction
328
329    filter_action:
330         0: Match
331         1: Prepare
332         2: Find Frame
333         3:   Find Next
334         4:   Find Previous
335         5: Colorize Conversation
336    filter_type:
337         0: Selected
338         1: Not Selected
339         2: And Selected
340         3: Or Selected
341         4: And Not Selected
342         5: Or Not Selected
343    filter_direction:
344         0: A To/From B
345         1: A To B
346         2: A From B
347         3: A To/From ANY
348         4: A To ANY
349         5: A From ANY
350         6: A To/From ANY
351         7: B To ANY
352         8: B From ANY
353 */
354 static void
355 ct_select_filter_cb(GtkWidget *widget _U_, gpointer callback_data, guint callback_action)
356 {
357         int action, type, direction;
358         int selection;
359         conversations_table *ct = (conversations_table *)callback_data;
360         char dirstr[128];
361         char str[256];
362         const char *current_filter;
363         char *sport, *dport;
364
365         action=(callback_action>>16)&0xff;
366         type=(callback_action>>8)&0xff;
367         direction=callback_action&0xff;
368
369
370         selection=GPOINTER_TO_INT(g_list_nth_data(GTK_CLIST(ct->table)->selection, 0));
371         if(selection>=(int)ct->num_conversations){
372                 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No conversation selected");
373                 return;
374         }
375         /* translate it back from row index to index in enndpoint array */
376         selection=GPOINTER_TO_INT(gtk_clist_get_row_data(ct->table, selection));
377
378         sport=ct_port_to_str(ct->conversations[selection].port_type, ct->conversations[selection].src_port);
379         dport=ct_port_to_str(ct->conversations[selection].port_type, ct->conversations[selection].dst_port);
380
381         switch(direction){
382         case 0:
383                 /* A <-> B */
384                 g_snprintf(dirstr, 127, "%s==%s %s%s%s%s && %s==%s %s%s%s%s",
385                         ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_ANY_ADDRESS),
386                         address_to_str(&ct->conversations[selection].src_address),
387                         sport?" && ":"",
388                         sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_ANY_PORT):"",
389                         sport?"==":"",
390                         sport?sport:"",
391                         ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_ANY_ADDRESS),
392                         address_to_str(&ct->conversations[selection].dst_address),
393                         dport?" && ":"",
394                         dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_ANY_PORT):"",
395                         dport?"==":"",
396                         dport?dport:""
397                 );
398                 break;
399         case 1:
400                 /* A --> B */
401                 g_snprintf(dirstr, 127, "%s==%s %s%s%s%s && %s==%s %s%s%s%s",
402                         ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_SRC_ADDRESS),
403                         address_to_str(&ct->conversations[selection].src_address),
404                         sport?" && ":"",
405                         sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_SRC_PORT):"",
406                         sport?"==":"",
407                         sport?sport:"",
408                         ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_DST_ADDRESS),
409                         address_to_str(&ct->conversations[selection].dst_address),
410                         dport?" && ":"",
411                         dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_DST_PORT):"",
412                         dport?"==":"",
413                         dport?dport:""
414                 );
415                 break;
416         case 2:
417                 /* A <-- B */
418                 g_snprintf(dirstr, 127, "%s==%s %s%s%s%s && %s==%s %s%s%s%s",
419                         ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_DST_ADDRESS),
420                         address_to_str(&ct->conversations[selection].src_address),
421                         sport?" && ":"",
422                         sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_DST_PORT):"",
423                         sport?"==":"",
424                         sport?sport:"",
425                         ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_SRC_ADDRESS),
426                         address_to_str(&ct->conversations[selection].dst_address),
427                         dport?" && ":"",
428                         dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_SRC_PORT):"",
429                         dport?"==":"",
430                         dport?dport:""
431                 );
432                 break;
433         case 3:
434                 /* A <-> ANY */
435                 g_snprintf(dirstr, 127, "%s==%s %s%s%s%s",
436                         ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_ANY_ADDRESS),
437                         address_to_str(&ct->conversations[selection].src_address),
438                         sport?" && ":"",
439                         sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_ANY_PORT):"",
440                         sport?"==":"",
441                         sport?sport:""
442                 );
443                 break;
444         case 4:
445                 /* A --> ANY */
446                 g_snprintf(dirstr, 127, "%s==%s %s%s%s%s",
447                         ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_SRC_ADDRESS),
448                         address_to_str(&ct->conversations[selection].src_address),
449                         sport?" && ":"",
450                         sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_SRC_PORT):"",
451                         sport?"==":"",
452                         sport?sport:""
453                 );
454                 break;
455         case 5:
456                 /* A <-- ANY */
457                 g_snprintf(dirstr, 127, "%s==%s %s%s%s%s",
458                         ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_DST_ADDRESS),
459                         address_to_str(&ct->conversations[selection].src_address),
460                         sport?" && ":"",
461                         sport?ct_get_filter_name(&ct->conversations[selection].src_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_DST_PORT):"",
462                         sport?"==":"",
463                         sport?sport:""
464                 );
465                 break;
466         case 6:
467                 /* B <-> ANY */
468                 g_snprintf(dirstr, 127, "%s==%s %s%s%s%s",
469                         ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_ANY_ADDRESS),
470                         address_to_str(&ct->conversations[selection].dst_address),
471                         dport?" && ":"",
472                         dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_ANY_PORT):"",
473                         dport?"==":"",
474                         dport?dport:""
475                 );
476                 break;
477         case 7:
478                 /* B --> ANY */
479                 g_snprintf(dirstr, 127, "%s==%s %s%s%s%s",
480                         ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_SRC_ADDRESS),
481                         address_to_str(&ct->conversations[selection].dst_address),
482                         dport?" && ":"",
483                         dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_SRC_PORT):"",
484                         dport?"==":"",
485                         dport?dport:""
486                 );
487                 break;
488         case 8:
489                 /* B <-- ANY */
490                 g_snprintf(dirstr, 127, "%s==%s %s%s%s%s",
491                         ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_DST_ADDRESS),
492                         address_to_str(&ct->conversations[selection].dst_address),
493                         dport?" && ":"",
494                         dport?ct_get_filter_name(&ct->conversations[selection].dst_address, ct->conversations[selection].sat, ct->conversations[selection].port_type,  FN_DST_PORT):"",
495                         dport?"==":"",
496                         dport?dport:""
497                 );
498                 break;
499     default:
500         g_assert_not_reached();
501         }
502
503         current_filter=gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
504         switch(type){
505         case 0:
506                 /* selected */
507                 g_snprintf(str, 255, "%s", dirstr);
508                 break;
509         case 1:
510                 /* not selected */
511                 g_snprintf(str, 255, "!(%s)", dirstr);
512                 break;
513         case 2:
514                 /* and selected */
515                 g_snprintf(str, 255, "(%s) && (%s)", current_filter, dirstr);
516                 break;
517         case 3:
518                 /* or selected */
519                 g_snprintf(str, 255, "(%s) || (%s)", current_filter, dirstr);
520                 break;
521         case 4:
522                 /* and not selected */
523                 g_snprintf(str, 255, "(%s) && !(%s)", current_filter, dirstr);
524                 break;
525         case 5:
526                 /* or not selected */
527                 g_snprintf(str, 255, "(%s) || !(%s)", current_filter, dirstr);
528                 break;
529         }
530
531         switch(action){
532         case 0:
533                 /* match */
534                 gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget), str);
535                 main_filter_packets(&cfile, str, FALSE);
536                 gdk_window_raise(top_level->window);
537                 break;
538         case 1:
539                 /* prepare */
540                 gtk_entry_set_text(GTK_ENTRY(main_display_filter_widget), str);
541                 break;
542         case 2:
543                 /* find packet */
544                 find_frame_with_filter(str);
545                 break;
546         case 3:
547                 /* find next */
548                 find_previous_next_frame_with_filter(str, FALSE);
549                 break;
550         case 4:
551                 /* find previous */
552                 find_previous_next_frame_with_filter(str, TRUE);
553                 break;
554         case 5:
555                 /* colorize conversation */
556                 color_display_with_filter(str);
557                 break;
558         }
559
560 }
561
562 static gint
563 ct_show_popup_menu_cb(void *widg _U_, GdkEvent *event, conversations_table *ct)
564 {
565         GdkEventButton *bevent = (GdkEventButton *)event;
566     gint row;
567     gint column;
568
569
570     /* To qoute the "Gdk Event Structures" doc:
571      * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
572         if(event->type==GDK_BUTTON_PRESS && bevent->button==3){
573         /* if this is a right click on one of our columns, select it and popup the context menu */
574         if(gtk_clist_get_selection_info(ct->table,
575                                           (gint) (((GdkEventButton *)event)->x),
576                                           (gint) (((GdkEventButton *)event)->y),
577                                              &row, &column)) {
578             gtk_clist_unselect_all(ct->table);
579             gtk_clist_select_row(ct->table, row, -1);
580
581                     gtk_menu_popup(GTK_MENU(ct->menu), NULL, NULL, NULL, NULL,
582                             bevent->button, bevent->time);
583         }
584     }
585
586         return FALSE;
587 }
588
589 static GtkItemFactoryEntry ct_list_menu_items[] =
590 {
591         /* Match */
592         ITEM_FACTORY_ENTRY("/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL),
593         ITEM_FACTORY_ENTRY("/Apply as Filter/Selected", NULL, NULL, 0, "<Branch>", NULL),
594         ITEM_FACTORY_ENTRY("/Apply as Filter/Selected/A <-> B", NULL,
595                 ct_select_filter_cb, 0*65536+0*256+0, NULL, NULL),
596         ITEM_FACTORY_ENTRY("/Apply as Filter/Selected/A --> B", NULL,
597                 ct_select_filter_cb, 0*65536+0*256+1, NULL, NULL),
598         ITEM_FACTORY_ENTRY("/Apply as Filter/Selected/A <-- B", NULL,
599                 ct_select_filter_cb, 0*65536+0*256+2, NULL, NULL),
600         ITEM_FACTORY_ENTRY("/Apply as Filter/Selected/A <-> ANY", NULL,
601                 ct_select_filter_cb, 0*65536+0*256+3, NULL, NULL),
602         ITEM_FACTORY_ENTRY("/Apply as Filter/Selected/A --> ANY", NULL,
603                 ct_select_filter_cb, 0*65536+0*256+4, NULL, NULL),
604         ITEM_FACTORY_ENTRY("/Apply as Filter/Selected/A <-- ANY", NULL,
605                 ct_select_filter_cb, 0*65536+0*256+5, NULL, NULL),
606         ITEM_FACTORY_ENTRY("/Apply as Filter/Selected/ANY <-> B", NULL,
607                 ct_select_filter_cb, 0*65536+0*256+6, NULL, NULL),
608         ITEM_FACTORY_ENTRY("/Apply as Filter/Selected/ANY <-- B", NULL,
609                 ct_select_filter_cb, 0*65536+0*256+7, NULL, NULL),
610         ITEM_FACTORY_ENTRY("/Apply as Filter/Selected/ANY --> B", NULL,
611                 ct_select_filter_cb, 0*65536+0*256+8, NULL, NULL),
612
613         ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected", NULL, NULL, 0, "<Branch>", NULL),
614         ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected/A <-> B", NULL,
615                 ct_select_filter_cb, 0*65536+1*256+0, NULL, NULL),
616         ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected/A --> B", NULL,
617                 ct_select_filter_cb, 0*65536+1*256+1, NULL, NULL),
618         ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected/A <-- B", NULL,
619                 ct_select_filter_cb, 0*65536+1*256+2, NULL, NULL),
620         ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected/A --> ANY", NULL,
621                 ct_select_filter_cb, 0*65536+1*256+3, NULL, NULL),
622         ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected/A <-> ANY", NULL,
623                 ct_select_filter_cb, 0*65536+1*256+4, NULL, NULL),
624         ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected/A <-- ANY", NULL,
625                 ct_select_filter_cb, 0*65536+1*256+5, NULL, NULL),
626         ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected/ANY <-> B", NULL,
627                 ct_select_filter_cb, 0*65536+1*256+6, NULL, NULL),
628         ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected/ANY <-- B", NULL,
629                 ct_select_filter_cb, 0*65536+1*256+7, NULL, NULL),
630         ITEM_FACTORY_ENTRY("/Apply as Filter/Not Selected/ANY --> B", NULL,
631                 ct_select_filter_cb, 0*65536+1*256+8, NULL, NULL),
632
633
634         ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected", NULL, NULL, 0, "<Branch>", NULL),
635         ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected/A <-> B", NULL,
636                 ct_select_filter_cb, 0*65536+2*256+0, NULL, NULL),
637         ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected/A --> B", NULL,
638                 ct_select_filter_cb, 0*65536+2*256+1, NULL, NULL),
639         ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected/A <-- B", NULL,
640                 ct_select_filter_cb, 0*65536+2*256+2, NULL, NULL),
641         ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected/A <-> ANY", NULL,
642                 ct_select_filter_cb, 0*65536+2*256+3, NULL, NULL),
643         ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected/A --> ANY", NULL,
644                 ct_select_filter_cb, 0*65536+2*256+4, NULL, NULL),
645         ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected/A <-- ANY", NULL,
646                 ct_select_filter_cb, 0*65536+2*256+5, NULL, NULL),
647         ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected/ANY <-> B", NULL,
648                 ct_select_filter_cb, 0*65536+2*256+6, NULL, NULL),
649         ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected/ANY <-- B", NULL,
650                 ct_select_filter_cb, 0*65536+2*256+7, NULL, NULL),
651         ITEM_FACTORY_ENTRY("/Apply as Filter/... and Selected/ANY --> B", NULL,
652                 ct_select_filter_cb, 0*65536+2*256+8, NULL, NULL),
653
654         ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected", NULL, NULL, 0, "<Branch>", NULL),
655         ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected/A <-> B", NULL,
656                 ct_select_filter_cb, 0*65536+3*256+0, NULL, NULL),
657         ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected/A --> B", NULL,
658                 ct_select_filter_cb, 0*65536+3*256+1, NULL, NULL),
659         ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected/A <-- B", NULL,
660                 ct_select_filter_cb, 0*65536+3*256+2, NULL, NULL),
661         ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected/A <-> ANY", NULL,
662                 ct_select_filter_cb, 0*65536+3*256+3, NULL, NULL),
663         ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected/A --> ANY", NULL,
664                 ct_select_filter_cb, 0*65536+3*256+4, NULL, NULL),
665         ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected/A <-- ANY", NULL,
666                 ct_select_filter_cb, 0*65536+3*256+5, NULL, NULL),
667         ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected/ANY <-> B", NULL,
668                 ct_select_filter_cb, 0*65536+3*256+6, NULL, NULL),
669         ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected/ANY <-- B", NULL,
670                 ct_select_filter_cb, 0*65536+3*256+7, NULL, NULL),
671         ITEM_FACTORY_ENTRY("/Apply as Filter/... or Selected/ANY --> B", NULL,
672                 ct_select_filter_cb, 0*65536+3*256+8, NULL, NULL),
673
674         ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected", NULL, NULL, 0, "<Branch>", NULL),
675         ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected/A <-> B", NULL,
676                 ct_select_filter_cb, 0*65536+4*256+0, NULL, NULL),
677         ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected/A --> B", NULL,
678                 ct_select_filter_cb, 0*65536+4*256+1, NULL, NULL),
679         ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected/A <-- B", NULL,
680                 ct_select_filter_cb, 0*65536+4*256+2, NULL, NULL),
681         ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected/A <-> ANY", NULL,
682                 ct_select_filter_cb, 0*65536+4*256+3, NULL, NULL),
683         ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected/A --> ANY", NULL,
684                 ct_select_filter_cb, 0*65536+4*256+4, NULL, NULL),
685         ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected/A <-- ANY", NULL,
686                 ct_select_filter_cb, 0*65536+4*256+5, NULL, NULL),
687         ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected/ANY <-> B", NULL,
688                 ct_select_filter_cb, 0*65536+4*256+6, NULL, NULL),
689         ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected/ANY <-- B", NULL,
690                 ct_select_filter_cb, 0*65536+4*256+7, NULL, NULL),
691         ITEM_FACTORY_ENTRY("/Apply as Filter/... and not Selected/ANY --> B", NULL,
692                 ct_select_filter_cb, 0*65536+4*256+8, NULL, NULL),
693
694         ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected", NULL, NULL, 0, "<Branch>", NULL),
695         ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected/A <-> B", NULL,
696                 ct_select_filter_cb, 0*65536+5*256+0, NULL, NULL),
697         ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected/A --> B", NULL,
698                 ct_select_filter_cb, 0*65536+5*256+1, NULL, NULL),
699         ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected/A <-- B", NULL,
700                 ct_select_filter_cb, 0*65536+5*256+2, NULL, NULL),
701         ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected/A <-> ANY", NULL,
702                 ct_select_filter_cb, 0*65536+5*256+3, NULL, NULL),
703         ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected/A --> ANY", NULL,
704                 ct_select_filter_cb, 0*65536+5*256+4, NULL, NULL),
705         ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected/A <-- ANY", NULL,
706                 ct_select_filter_cb, 0*65536+5*256+5, NULL, NULL),
707         ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected/ANY <-> B", NULL,
708                 ct_select_filter_cb, 0*65536+5*256+6, NULL, NULL),
709         ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected/ANY <-- B", NULL,
710                 ct_select_filter_cb, 0*65536+5*256+7, NULL, NULL),
711         ITEM_FACTORY_ENTRY("/Apply as Filter/... or not Selected/ANY --> B", NULL,
712                 ct_select_filter_cb, 0*65536+5*256+8, NULL, NULL),
713
714         /* Prepare */
715         ITEM_FACTORY_ENTRY("/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL),
716         ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected", NULL, NULL, 0, "<Branch>", NULL),
717         ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected/A <-> B", NULL,
718                 ct_select_filter_cb, 1*65536+0*256+0, NULL, NULL),
719         ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected/A --> B", NULL,
720                 ct_select_filter_cb, 1*65536+0*256+1, NULL, NULL),
721         ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected/A <-- B", NULL,
722                 ct_select_filter_cb, 1*65536+0*256+2, NULL, NULL),
723         ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected/A <-> ANY", NULL,
724                 ct_select_filter_cb, 1*65536+0*256+3, NULL, NULL),
725         ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected/A --> ANY", NULL,
726                 ct_select_filter_cb, 1*65536+0*256+4, NULL, NULL),
727         ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected/A <-- ANY", NULL,
728                 ct_select_filter_cb, 1*65536+0*256+5, NULL, NULL),
729         ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected/ANY <-> B", NULL,
730                 ct_select_filter_cb, 1*65536+0*256+6, NULL, NULL),
731         ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected/ANY <-- B", NULL,
732                 ct_select_filter_cb, 1*65536+0*256+7, NULL, NULL),
733         ITEM_FACTORY_ENTRY("/Prepare a Filter/Selected/ANY --> B", NULL,
734                 ct_select_filter_cb, 1*65536+0*256+8, NULL, NULL),
735
736         ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected", NULL, NULL, 0, "<Branch>", NULL),
737         ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected/A <-> B", NULL,
738                 ct_select_filter_cb, 1*65536+1*256+0, NULL, NULL),
739         ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected/A --> B", NULL,
740                 ct_select_filter_cb, 1*65536+1*256+1, NULL, NULL),
741         ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected/A <-- B", NULL,
742                 ct_select_filter_cb, 1*65536+1*256+2, NULL, NULL),
743         ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected/A <-> ANY", NULL,
744                 ct_select_filter_cb, 1*65536+1*256+3, NULL, NULL),
745         ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected/A --> ANY", NULL,
746                 ct_select_filter_cb, 1*65536+1*256+4, NULL, NULL),
747         ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected/A <-- ANY", NULL,
748                 ct_select_filter_cb, 1*65536+1*256+5, NULL, NULL),
749         ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected/ANY <-> B", NULL,
750                 ct_select_filter_cb, 1*65536+1*256+6, NULL, NULL),
751         ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected/ANY <-- B", NULL,
752                 ct_select_filter_cb, 1*65536+1*256+7, NULL, NULL),
753         ITEM_FACTORY_ENTRY("/Prepare a Filter/Not Selected/ANY --> B", NULL,
754                 ct_select_filter_cb, 1*65536+1*256+8, NULL, NULL),
755
756         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected", NULL, NULL, 0, "<Branch>", NULL),
757         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected/A <-> B", NULL,
758                 ct_select_filter_cb, 1*65536+2*256+0, NULL, NULL),
759         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected/A --> B", NULL,
760                 ct_select_filter_cb, 1*65536+2*256+1, NULL, NULL),
761         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected/A <-- B", NULL,
762                 ct_select_filter_cb, 1*65536+2*256+2, NULL, NULL),
763         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected/A <-> ANY", NULL,
764                 ct_select_filter_cb, 1*65536+2*256+3, NULL, NULL),
765         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected/A --> ANY", NULL,
766                 ct_select_filter_cb, 1*65536+2*256+4, NULL, NULL),
767         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected/A <-- ANY", NULL,
768                 ct_select_filter_cb, 1*65536+2*256+5, NULL, NULL),
769         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected/ANY <-> B", NULL,
770                 ct_select_filter_cb, 1*65536+2*256+6, NULL, NULL),
771         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected/ANY <-- B", NULL,
772                 ct_select_filter_cb, 1*65536+2*256+7, NULL, NULL),
773         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and Selected/ANY --> B", NULL,
774                 ct_select_filter_cb, 1*65536+2*256+8, NULL, NULL),
775
776         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected", NULL, NULL, 0, "<Branch>", NULL),
777         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected/A <-> B", NULL,
778                 ct_select_filter_cb, 1*65536+3*256+0, NULL, NULL),
779         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected/A --> B", NULL,
780                 ct_select_filter_cb, 1*65536+3*256+1, NULL, NULL),
781         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected/A <-- B", NULL,
782                 ct_select_filter_cb, 1*65536+3*256+2, NULL, NULL),
783         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected/A <-> ANY", NULL,
784                 ct_select_filter_cb, 1*65536+3*256+3, NULL, NULL),
785         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected/A --> ANY", NULL,
786                 ct_select_filter_cb, 1*65536+3*256+4, NULL, NULL),
787         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected/A <-- ANY", NULL,
788                 ct_select_filter_cb, 1*65536+3*256+5, NULL, NULL),
789         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected/ANY <-> B", NULL,
790                 ct_select_filter_cb, 1*65536+3*256+6, NULL, NULL),
791         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected/ANY <-- B", NULL,
792                 ct_select_filter_cb, 1*65536+3*256+7, NULL, NULL),
793         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or Selected/ANY --> B", NULL,
794                 ct_select_filter_cb, 1*65536+3*256+8, NULL, NULL),
795
796         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected", NULL, NULL, 0, "<Branch>", NULL),
797         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected/A <-> B", NULL,
798                 ct_select_filter_cb, 1*65536+4*256+0, NULL, NULL),
799         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected/A --> B", NULL,
800                 ct_select_filter_cb, 1*65536+4*256+1, NULL, NULL),
801         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected/A <-- B", NULL,
802                 ct_select_filter_cb, 1*65536+4*256+2, NULL, NULL),
803         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected/A <-> ANY", NULL,
804                 ct_select_filter_cb, 1*65536+4*256+3, NULL, NULL),
805         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected/A --> ANY", NULL,
806                 ct_select_filter_cb, 1*65536+4*256+4, NULL, NULL),
807         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected/A <-- ANY", NULL,
808                 ct_select_filter_cb, 1*65536+4*256+5, NULL, NULL),
809         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected/ANY <-> B", NULL,
810                 ct_select_filter_cb, 1*65536+4*256+6, NULL, NULL),
811         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected/ANY <-- B", NULL,
812                 ct_select_filter_cb, 1*65536+4*256+7, NULL, NULL),
813         ITEM_FACTORY_ENTRY("/Prepare a Filter/... and not Selected/ANY --> B", NULL,
814                 ct_select_filter_cb, 1*65536+4*256+8, NULL, NULL),
815
816         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected", NULL, NULL, 0, "<Branch>", NULL),
817         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected/A <-> B", NULL,
818                 ct_select_filter_cb, 1*65536+5*256+0, NULL, NULL),
819         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected/A --> B", NULL,
820                 ct_select_filter_cb, 1*65536+5*256+1, NULL, NULL),
821         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected/A <-- B", NULL,
822                 ct_select_filter_cb, 1*65536+5*256+2, NULL, NULL),
823         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected/A <-> ANY", NULL,
824                 ct_select_filter_cb, 1*65536+5*256+3, NULL, NULL),
825         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected/A --> ANY", NULL,
826                 ct_select_filter_cb, 1*65536+5*256+4, NULL, NULL),
827         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected/A <-- ANY", NULL,
828                 ct_select_filter_cb, 1*65536+5*256+5, NULL, NULL),
829         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected/ANY <-> B", NULL,
830                 ct_select_filter_cb, 1*65536+5*256+6, NULL, NULL),
831         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected/ANY <-- B", NULL,
832                 ct_select_filter_cb, 1*65536+5*256+7, NULL, NULL),
833         ITEM_FACTORY_ENTRY("/Prepare a Filter/... or not Selected/ANY --> B", NULL,
834                 ct_select_filter_cb, 1*65536+5*256+8, NULL, NULL),
835
836         /* Find Packet */
837         ITEM_FACTORY_ENTRY("/Find Packet", NULL, NULL, 0, "<Branch>", NULL),
838         ITEM_FACTORY_ENTRY("/Find Packet/Find Packet", NULL, NULL, 0, "<Branch>", NULL),
839         ITEM_FACTORY_ENTRY("/Find Packet/Find Packet/A <-> B", NULL,
840                 ct_select_filter_cb, 2*65536+0*256+0, NULL, NULL),
841         ITEM_FACTORY_ENTRY("/Find Packet/Find Packet/A --> B", NULL,
842                 ct_select_filter_cb, 2*65536+0*256+1, NULL, NULL),
843         ITEM_FACTORY_ENTRY("/Find Packet/Find Packet/A <-- B", NULL,
844                 ct_select_filter_cb, 2*65536+0*256+2, NULL, NULL),
845         ITEM_FACTORY_ENTRY("/Find Packet/Find Packet/A <-> ANY", NULL,
846                 ct_select_filter_cb, 2*65536+0*256+3, NULL, NULL),
847         ITEM_FACTORY_ENTRY("/Find Packet/Find Packet/A --> ANY", NULL,
848                 ct_select_filter_cb, 2*65536+0*256+4, NULL, NULL),
849         ITEM_FACTORY_ENTRY("/Find Packet/Find Packet/A <-- ANY", NULL,
850                 ct_select_filter_cb, 2*65536+0*256+5, NULL, NULL),
851         ITEM_FACTORY_ENTRY("/Find Packet/Find Packet/ANY <-> B", NULL,
852                 ct_select_filter_cb, 2*65536+0*256+6, NULL, NULL),
853         ITEM_FACTORY_ENTRY("/Find Packet/Find Packet/ANY <-- B", NULL,
854                 ct_select_filter_cb, 2*65536+0*256+7, NULL, NULL),
855         ITEM_FACTORY_ENTRY("/Find Packet/Find Packet/ANY --> B", NULL,
856                 ct_select_filter_cb, 2*65536+0*256+8, NULL, NULL),
857         /* Find Next */
858         ITEM_FACTORY_ENTRY("/Find Packet/Find Next", NULL, NULL, 0, "<Branch>", NULL),
859         ITEM_FACTORY_ENTRY("/Find Packet/Find Next/A <-> B", NULL,
860                 ct_select_filter_cb, 3*65536+0*256+0, NULL, NULL),
861         ITEM_FACTORY_ENTRY("/Find Packet/Find Next/A --> B", NULL,
862                 ct_select_filter_cb, 3*65536+0*256+1, NULL, NULL),
863         ITEM_FACTORY_ENTRY("/Find Packet/Find Next/A <-- B", NULL,
864                 ct_select_filter_cb, 3*65536+0*256+2, NULL, NULL),
865         ITEM_FACTORY_ENTRY("/Find Packet/Find Next/A <-> ANY", NULL,
866                 ct_select_filter_cb, 3*65536+0*256+3, NULL, NULL),
867         ITEM_FACTORY_ENTRY("/Find Packet/Find Next/A --> ANY", NULL,
868                 ct_select_filter_cb, 3*65536+0*256+4, NULL, NULL),
869         ITEM_FACTORY_ENTRY("/Find Packet/Find Next/A <-- ANY", NULL,
870                 ct_select_filter_cb, 3*65536+0*256+5, NULL, NULL),
871         ITEM_FACTORY_ENTRY("/Find Packet/Find Next/ANY <-> B", NULL,
872                 ct_select_filter_cb, 3*65536+0*256+6, NULL, NULL),
873         ITEM_FACTORY_ENTRY("/Find Packet/Find Next/ANY <-- B", NULL,
874                 ct_select_filter_cb, 3*65536+0*256+7, NULL, NULL),
875         ITEM_FACTORY_ENTRY("/Find Packet/Find Next/ANY --> B", NULL,
876                 ct_select_filter_cb, 3*65536+0*256+8, NULL, NULL),
877         /* Find Previous */
878         ITEM_FACTORY_ENTRY("/Find Packet/Find Previous", NULL, NULL, 0, "<Branch>", NULL),
879         ITEM_FACTORY_ENTRY("/Find Packet/Find Previous/A <-> B", NULL,
880                 ct_select_filter_cb, 4*65536+0*256+0, NULL, NULL),
881         ITEM_FACTORY_ENTRY("/Find Packet/Find Previous/A --> B", NULL,
882                 ct_select_filter_cb, 4*65536+0*256+1, NULL, NULL),
883         ITEM_FACTORY_ENTRY("/Find Packet/Find Previous/A <-- B", NULL,
884                 ct_select_filter_cb, 4*65536+0*256+2, NULL, NULL),
885         ITEM_FACTORY_ENTRY("/Find Packet/Find Previous/A <-> ANY", NULL,
886                 ct_select_filter_cb, 4*65536+0*256+3, NULL, NULL),
887         ITEM_FACTORY_ENTRY("/Find Packet/Find Previous/A --> ANY", NULL,
888                 ct_select_filter_cb, 4*65536+0*256+4, NULL, NULL),
889         ITEM_FACTORY_ENTRY("/Find Packet/Find Previous/A <-- ANY", NULL,
890                 ct_select_filter_cb, 4*65536+0*256+5, NULL, NULL),
891         ITEM_FACTORY_ENTRY("/Find Packet/Find Previous/ANY <-> B", NULL,
892                 ct_select_filter_cb, 4*65536+0*256+6, NULL, NULL),
893         ITEM_FACTORY_ENTRY("/Find Packet/Find Previous/ANY <-- B", NULL,
894                 ct_select_filter_cb, 4*65536+0*256+7, NULL, NULL),
895         ITEM_FACTORY_ENTRY("/Find Packet/Find Previous/ANY --> B", NULL,
896                 ct_select_filter_cb, 4*65536+0*256+8, NULL, NULL),
897         /* Colorize Conversation */
898         ITEM_FACTORY_ENTRY("/Colorize Conversation", NULL, NULL, 0, "<Branch>", NULL),
899         ITEM_FACTORY_ENTRY("/Colorize Conversation/A <-> B", NULL,
900                 ct_select_filter_cb, 5*65536+0*256+0, NULL, NULL),
901         ITEM_FACTORY_ENTRY("/Colorize Conversation/A --> B", NULL,
902                 ct_select_filter_cb, 5*65536+0*256+1, NULL, NULL),
903         ITEM_FACTORY_ENTRY("/Colorize Conversation/A <-- B", NULL,
904                 ct_select_filter_cb, 5*65536+0*256+2, NULL, NULL),
905         ITEM_FACTORY_ENTRY("/Colorize Conversation/A <-> ANY", NULL,
906                 ct_select_filter_cb, 5*65536+0*256+3, NULL, NULL),
907         ITEM_FACTORY_ENTRY("/Colorize Conversation/A --> ANY", NULL,
908                 ct_select_filter_cb, 5*65536+0*256+4, NULL, NULL),
909         ITEM_FACTORY_ENTRY("/Colorize Conversation/A <-- ANY", NULL,
910                 ct_select_filter_cb, 5*65536+0*256+5, NULL, NULL),
911         ITEM_FACTORY_ENTRY("/Colorize Conversation/ANY <-> B", NULL,
912                 ct_select_filter_cb, 5*65536+0*256+6, NULL, NULL),
913         ITEM_FACTORY_ENTRY("/Colorize Conversation/ANY <-- B", NULL,
914                 ct_select_filter_cb, 5*65536+0*256+7, NULL, NULL),
915         ITEM_FACTORY_ENTRY("/Colorize Conversation/ANY --> B", NULL,
916                 ct_select_filter_cb, 5*65536+0*256+8, NULL, NULL),
917
918
919 };
920
921 static void
922 ct_create_popup_menu(conversations_table *ct)
923 {
924         GtkItemFactory *item_factory;
925
926         item_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
927
928         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);
929
930         ct->menu = gtk_item_factory_get_widget(item_factory, "<main>");
931         SIGNAL_CONNECT(ct->table, "button_press_event", ct_show_popup_menu_cb, ct);
932 }
933
934
935 /* XXX should freeze/thaw table here and in the srt thingy? */
936 static void
937 draw_ct_table_addresses(conversations_table *ct)
938 {
939     guint32 i;
940     int j;
941
942
943     for(i=0;i<ct->num_conversations;i++){
944         char *entry;
945         char *port;
946         address_type  at;
947         guint32 pt;
948
949         j=gtk_clist_find_row_from_data(ct->table, (gpointer)i);
950
951         at = ct->conversations[i].src_address.type;
952         if(!ct->resolve_names) at = AT_NONE;
953         switch(at) {
954         case(AT_IPv4):
955             entry=get_hostname((*(guint *)ct->conversations[i].src_address.data));
956             break;
957         case(AT_ETHER):
958             entry=get_ether_name(ct->conversations[i].src_address.data);
959             break;
960         default:
961             entry=address_to_str(&ct->conversations[i].src_address);
962         }
963         gtk_clist_set_text(ct->table, j, 0, entry);
964
965         pt = ct->conversations[i].port_type;
966         if(!ct->resolve_names) pt = PT_NONE;
967         switch(pt) {
968         case(PT_TCP):
969             entry=get_tcp_port(ct->conversations[i].src_port);
970             break;
971         case(PT_UDP):
972             entry=get_udp_port(ct->conversations[i].src_port);
973             break;
974         default:
975             port=ct_port_to_str(ct->conversations[i].port_type, ct->conversations[i].src_port);
976             entry=port?port:"";
977         }
978         gtk_clist_set_text(ct->table, j, 1, entry);
979
980         at = ct->conversations[i].dst_address.type;
981         if(!ct->resolve_names) at = AT_NONE;
982         switch(at) {
983         case(AT_IPv4):
984             entry=get_hostname((*(guint *)ct->conversations[i].dst_address.data));
985             break;
986         case(AT_ETHER):
987             entry=get_ether_name(ct->conversations[i].dst_address.data);
988             break;
989         default:
990             entry=address_to_str(&ct->conversations[i].dst_address);
991         }
992         gtk_clist_set_text(ct->table, j, 2, entry);
993
994         switch(pt) {
995         case(PT_TCP):
996             entry=get_tcp_port(ct->conversations[i].dst_port);
997             break;
998         case(PT_UDP):
999             entry=get_udp_port(ct->conversations[i].dst_port);
1000             break;
1001         default:
1002             port=ct_port_to_str(ct->conversations[i].port_type, ct->conversations[i].dst_port);
1003             entry=port?port:"";
1004         }
1005         gtk_clist_set_text(ct->table, j, 3, entry);
1006     }
1007 }
1008
1009
1010 static void
1011 draw_ct_table_data(conversations_table *ct)
1012 {
1013     guint32 i;
1014     int j;
1015     char title[256];
1016
1017     /* Freeze the table since quite a few changes will occur */
1018     gtk_clist_freeze(ct->table);
1019
1020     if (ct->page_lb) {
1021         if(ct->num_conversations) {
1022             g_snprintf(title, 255, "%s: %u", ct->name, ct->num_conversations);
1023         } else {
1024             g_snprintf(title, 255, "%s", ct->name);
1025         }
1026         gtk_label_set_text(GTK_LABEL(ct->page_lb), title);
1027         gtk_widget_set_sensitive(ct->page_lb, ct->num_conversations);
1028     }
1029
1030     for(i=0;i<ct->num_conversations;i++){
1031         char str[16];
1032
1033         j=gtk_clist_find_row_from_data(ct->table, (gpointer)i);
1034
1035         g_snprintf(str, 16, "%u", ct->conversations[i].tx_frames+ct->conversations[i].rx_frames);
1036         gtk_clist_set_text(ct->table, j, 4, str);
1037         g_snprintf(str, 16, "%u", ct->conversations[i].tx_bytes+ct->conversations[i].rx_bytes);
1038         gtk_clist_set_text(ct->table, j, 5, str);
1039
1040
1041         g_snprintf(str, 16, "%u", ct->conversations[i].tx_frames);
1042         gtk_clist_set_text(ct->table, j, 6, str);
1043         g_snprintf(str, 16, "%u", ct->conversations[i].tx_bytes);
1044         gtk_clist_set_text(ct->table, j, 7, str);
1045
1046
1047         g_snprintf(str, 16, "%u", ct->conversations[i].rx_frames);
1048         gtk_clist_set_text(ct->table, j, 8, str);
1049         g_snprintf(str, 16, "%u", ct->conversations[i].rx_bytes);
1050         gtk_clist_set_text(ct->table, j, 9, str);
1051
1052     }
1053     gtk_clist_sort(ct->table);
1054
1055     /* update table, so resolved addresses will be shown now */
1056     draw_ct_table_addresses(ct);
1057
1058     gtk_clist_thaw(ct->table);
1059 }
1060
1061
1062 gboolean
1063 init_ct_table_page(conversations_table *conversations, GtkWidget *vbox, gboolean hide_ports, char *table_name, char *tap_name, char *filter, void *packet_func)
1064 {
1065     int i;
1066     column_arrows *col_arrows;
1067     GtkStyle *win_style;
1068     GtkWidget *column_lb;
1069     GString *error_string;
1070     GtkWidget *label;
1071     char title[256];
1072     char *default_titles[] = { "Address A", "Port A", "Address B", "Port B", "Packets", "Bytes", "Packets A->B", "Bytes A->B", "Packets A<-B", "Bytes A<-B" };
1073
1074
1075     g_snprintf(title, 255, "%s Conversations", table_name);
1076     label=gtk_label_new(title);
1077     gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
1078
1079
1080     conversations->scrolled_window=scrolled_window_new(NULL, NULL);
1081     gtk_box_pack_start(GTK_BOX(vbox), conversations->scrolled_window, TRUE, TRUE, 0);
1082
1083     conversations->table=(GtkCList *)gtk_clist_new(NUM_COLS);
1084
1085     col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_COLS);
1086     win_style = gtk_widget_get_style(conversations->scrolled_window);
1087     for (i = 0; i < NUM_COLS; i++) {
1088         col_arrows[i].table = gtk_table_new(2, 2, FALSE);
1089         gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
1090         column_lb = gtk_label_new(default_titles[i]);
1091         gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
1092         gtk_widget_show(column_lb);
1093
1094         col_arrows[i].ascend_pm = xpm_to_widget((const char **) clist_ascend_xpm);
1095         gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
1096         col_arrows[i].descend_pm = xpm_to_widget((const char **) clist_descend_xpm);
1097         gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
1098         /* make total frames be the default sort order */
1099         if (i == 4) {
1100             gtk_widget_show(col_arrows[i].descend_pm);
1101         }
1102         gtk_clist_set_column_widget(GTK_CLIST(conversations->table), i, col_arrows[i].table);
1103         gtk_widget_show(col_arrows[i].table);
1104     }
1105     gtk_clist_column_titles_show(GTK_CLIST(conversations->table));
1106
1107     gtk_clist_set_compare_func(conversations->table, ct_sort_column);
1108     gtk_clist_set_sort_column(conversations->table, 4);
1109     gtk_clist_set_sort_type(conversations->table, GTK_SORT_DESCENDING);
1110
1111
1112     gtk_clist_set_column_auto_resize(conversations->table, 0, TRUE);
1113     gtk_clist_set_column_auto_resize(conversations->table, 1, TRUE);
1114     gtk_clist_set_column_auto_resize(conversations->table, 2, TRUE);
1115     gtk_clist_set_column_auto_resize(conversations->table, 3, TRUE);
1116     gtk_clist_set_column_auto_resize(conversations->table, 4, TRUE);
1117     gtk_clist_set_column_auto_resize(conversations->table, 5, TRUE);
1118     gtk_clist_set_column_auto_resize(conversations->table, 6, TRUE);
1119     gtk_clist_set_column_auto_resize(conversations->table, 7, TRUE);
1120     gtk_clist_set_column_auto_resize(conversations->table, 8, TRUE);
1121     gtk_clist_set_column_auto_resize(conversations->table, 9, TRUE);
1122
1123 #if 0
1124     /*XXX instead of this we should probably have some code to
1125         dynamically adjust the width of the columns */
1126     gtk_clist_set_column_width(conversations->table, 0, 100);
1127     gtk_clist_set_column_width(conversations->table, 1, 40);
1128     gtk_clist_set_column_width(conversations->table, 2, 100);
1129     gtk_clist_set_column_width(conversations->table, 3, 40);
1130     gtk_clist_set_column_width(conversations->table, 4, 70);
1131     gtk_clist_set_column_width(conversations->table, 5, 60);
1132     gtk_clist_set_column_width(conversations->table, 6, 70);
1133     gtk_clist_set_column_width(conversations->table, 7, 60);
1134     gtk_clist_set_column_width(conversations->table, 8, 70);
1135     gtk_clist_set_column_width(conversations->table, 9, 60);
1136 #endif
1137
1138     gtk_clist_set_shadow_type(conversations->table, GTK_SHADOW_IN);
1139     gtk_clist_column_titles_show(conversations->table);
1140     gtk_container_add(GTK_CONTAINER(conversations->scrolled_window), (GtkWidget *)conversations->table);
1141
1142     SIGNAL_CONNECT(conversations->table, "click-column", ct_click_column_cb, col_arrows);
1143
1144     conversations->num_conversations=0;
1145     conversations->conversations=NULL;
1146
1147     /* hide srcport and dstport if we don't use ports */
1148     if(hide_ports){
1149         gtk_clist_set_column_visibility(conversations->table, 1, FALSE);
1150         gtk_clist_set_column_visibility(conversations->table, 3, FALSE);
1151     }
1152
1153     /* create popup menu for this table */
1154     ct_create_popup_menu(conversations);
1155
1156
1157     /* register the tap and rerun the taps on the packet list */
1158     error_string=register_tap_listener(tap_name, conversations, filter, (void *)reset_ct_table_data, packet_func, (void *)draw_ct_table_data);
1159     if(error_string){
1160         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, error_string->str);
1161         g_string_free(error_string, TRUE);
1162         return FALSE;
1163     }
1164
1165     return TRUE;
1166 }
1167
1168
1169 void
1170 init_conversation_table(gboolean hide_ports, char *table_name, char *tap_name, char *filter, void *packet_func)
1171 {
1172     conversations_table *conversations;
1173     char title[256];
1174     GtkWidget *vbox;
1175     GtkWidget *bbox;
1176     GtkWidget *close_bt;
1177     gboolean ret;
1178
1179
1180     conversations=g_malloc(sizeof(conversations_table));
1181
1182     conversations->name=table_name;
1183     g_snprintf(title, 255, "%s Conversations: %s", table_name, cf_get_display_name(&cfile));
1184     conversations->win=window_new(GTK_WINDOW_TOPLEVEL, title);
1185     conversations->page_lb=NULL;
1186     conversations->resolve_names=TRUE;
1187     gtk_window_set_default_size(GTK_WINDOW(conversations->win), 750, 400);
1188
1189     vbox=gtk_vbox_new(FALSE, 3);
1190     gtk_container_add(GTK_CONTAINER(conversations->win), vbox);
1191     gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
1192
1193     ret = init_ct_table_page(conversations, vbox, hide_ports, table_name, tap_name, filter, packet_func);
1194     if(ret == FALSE) {
1195         g_free(conversations);
1196         return;
1197     }
1198
1199     /* Button row. */
1200     bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
1201     gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
1202
1203     close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
1204     window_set_cancel_button(conversations->win, close_bt, window_cancel_button_cb);
1205
1206     SIGNAL_CONNECT(conversations->win, "delete_event", window_delete_event_cb, NULL);
1207     SIGNAL_CONNECT(conversations->win, "destroy", ct_win_destroy_cb, conversations);
1208
1209     gtk_widget_show_all(conversations->win);
1210     window_present(conversations->win);
1211
1212     retap_packets(&cfile);
1213
1214     /* after retapping, redraw table */
1215     draw_ct_table_data(conversations);
1216 }
1217
1218
1219
1220 static void
1221 ct_win_destroy_notebook_cb(GtkWindow *win _U_, gpointer data)
1222 {
1223     void ** pages = data;
1224     int page;
1225
1226     /* first "page" contains the number of pages */
1227     for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1228         ct_win_destroy_cb(NULL, pages[page]);
1229     }
1230 }
1231
1232
1233
1234
1235 static conversations_table *
1236 init_ct_notebook_page_cb(gboolean hide_ports, char *table_name, char *tap_name, char *filter, void *packet_func)
1237 {
1238     gboolean ret;
1239     GtkWidget *page_vbox;
1240     conversations_table *conversations;
1241
1242     conversations=g_malloc(sizeof(conversations_table));
1243     conversations->name=table_name;
1244     conversations->resolve_names=TRUE;
1245
1246     page_vbox=gtk_vbox_new(FALSE, 6);
1247     conversations->win = page_vbox;
1248     gtk_container_set_border_width(GTK_CONTAINER(page_vbox), 6);
1249
1250     ret = init_ct_table_page(conversations, page_vbox, hide_ports, table_name, tap_name, filter, packet_func);
1251     if(ret == FALSE) {
1252         g_free(conversations);
1253         return NULL;
1254     }
1255
1256     return conversations;
1257 }
1258
1259
1260 typedef struct {
1261     gboolean hide_ports;    /* hide TCP / UDP port columns */
1262     char *table_name;       /* GUI output name */
1263     char *tap_name;         /* internal name */
1264     char *filter;           /* display filter string (unused) */
1265     void *packet_func;      /* function to be called for new incoming packets */
1266 } register_ct_t;
1267
1268
1269 static GSList *registered_ct_tables = NULL;
1270
1271 void
1272 register_conversation_table(gboolean hide_ports, char *table_name, char *tap_name, char *filter, void *packet_func)
1273 {
1274     register_ct_t *table;
1275
1276     table = g_malloc(sizeof(register_ct_t));
1277
1278     table->hide_ports   = hide_ports;
1279     table->table_name   = table_name;
1280     table->tap_name     = tap_name;
1281     table->filter       = filter;
1282     table->packet_func  = packet_func;
1283
1284     registered_ct_tables = g_slist_append(registered_ct_tables, table);
1285 }
1286
1287
1288 static void
1289 ct_resolve_toggle_dest(GtkWidget *widget, gpointer data)
1290 {
1291     int page;
1292     void ** pages = data;
1293     gboolean resolve_names;
1294     conversations_table *conversations;
1295
1296
1297     resolve_names = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1298
1299     for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1300         conversations = pages[page];
1301         conversations->resolve_names = resolve_names;
1302
1303         draw_ct_table_addresses(conversations);
1304     }
1305 }
1306
1307 void
1308 init_conversation_notebook_cb(GtkWidget *w _U_, gpointer d _U_)
1309 {
1310     conversations_table *conversations;
1311     char title[256];
1312     GtkWidget *vbox;
1313     GtkWidget *hbox;
1314     GtkWidget *bbox;
1315     GtkWidget *close_bt;
1316     GtkWidget *win;
1317     GtkWidget *resolv_cb;
1318     int page;
1319     void ** pages;
1320     GtkWidget *nb;
1321     GtkWidget *page_lb;
1322     GSList  *current_table;
1323     register_ct_t *registered;
1324     GtkTooltips *tooltips = gtk_tooltips_new();
1325
1326
1327     pages = g_malloc(sizeof(void *) * (g_slist_length(registered_ct_tables) + 1));
1328
1329     g_snprintf(title, 255, "Conversations: %s", cf_get_display_name(&cfile));
1330     win=window_new(GTK_WINDOW_TOPLEVEL, title);
1331     gtk_window_set_default_size(GTK_WINDOW(win), 750, 400);
1332
1333     vbox=gtk_vbox_new(FALSE, 6);
1334     gtk_container_add(GTK_CONTAINER(win), vbox);
1335     gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
1336
1337     nb = gtk_notebook_new();
1338     gtk_container_add(GTK_CONTAINER(vbox), nb);
1339
1340     page = 0;
1341
1342     current_table = registered_ct_tables;
1343     while(current_table) {
1344         registered = current_table->data;
1345         page_lb = gtk_label_new("");
1346         conversations = init_ct_notebook_page_cb(registered->hide_ports, registered->table_name, registered->tap_name,
1347             registered->filter, registered->packet_func);
1348         gtk_notebook_append_page(GTK_NOTEBOOK(nb), conversations->win, page_lb);
1349         conversations->win = win;
1350         conversations->page_lb = page_lb;
1351         pages[++page] = conversations;
1352
1353         current_table = g_slist_next(current_table);
1354     }
1355
1356     pages[0] = GINT_TO_POINTER(page);
1357
1358     hbox = gtk_hbox_new(FALSE, 3);
1359     gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1360
1361     resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Name resolution", NULL);
1362     gtk_container_add(GTK_CONTAINER(hbox), resolv_cb);
1363     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(resolv_cb), TRUE);
1364     gtk_tooltips_set_tip(tooltips, resolv_cb, "Show results of name resolutions rather than the \"raw\" values. "
1365         "Please note: The corresponding name resolution must be enabled.", NULL);
1366
1367     SIGNAL_CONNECT(resolv_cb, "toggled", ct_resolve_toggle_dest, pages);
1368
1369     /* Button row. */
1370     bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
1371     gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
1372
1373     close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
1374     window_set_cancel_button(win, close_bt, window_cancel_button_cb);
1375
1376     SIGNAL_CONNECT(win, "delete_event", window_delete_event_cb, NULL);
1377     SIGNAL_CONNECT(win, "destroy", ct_win_destroy_notebook_cb, pages);
1378
1379     gtk_widget_show_all(win);
1380     window_present(win);
1381
1382     retap_packets(&cfile);
1383
1384     /* after retapping, redraw table */
1385     for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1386         draw_ct_table_data(pages[page]);
1387     }
1388 }
1389
1390
1391 void
1392 add_conversation_table_data(conversations_table *ct, address *src, address *dst, guint32 src_port, guint32 dst_port, int num_frames, int num_bytes, SAT_E sat, int port_type)
1393 {
1394     address *addr1, *addr2;
1395     guint32 port1, port2;
1396     conversation_t *conversation=NULL;
1397     int conversation_idx=0;
1398     gboolean new_conversation;
1399
1400     if(src_port>dst_port){
1401         addr1=src;
1402         addr2=dst;
1403         port1=src_port;
1404         port2=dst_port;
1405     } else if(src_port<dst_port){
1406         addr2=src;
1407         addr1=dst;
1408         port2=src_port;
1409         port1=dst_port;
1410     } else if(CMP_ADDRESS(src, dst)<0){
1411         addr1=src;
1412         addr2=dst;
1413         port1=src_port;
1414         port2=dst_port;
1415     } else {
1416         addr2=src;
1417         addr1=dst;
1418         port2=src_port;
1419         port1=dst_port;
1420     }
1421
1422
1423     new_conversation=FALSE;
1424     /* XXX should be optimized to allocate n extra entries at a time
1425        instead of just one */
1426     /* if we dont have any entries at all yet */
1427     if(ct->conversations==NULL){
1428         ct->conversations=g_malloc(sizeof(conversation_t));
1429         ct->num_conversations=1;
1430         conversation=&ct->conversations[0];
1431         conversation_idx=0;
1432         new_conversation=TRUE;
1433     }
1434
1435     /* try to find it among the existing known conversations */
1436     if(conversation==NULL){
1437         guint32 i;
1438         for(i=0;i<ct->num_conversations;i++){
1439             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) ){
1440                 conversation=&ct->conversations[i];
1441                 conversation_idx=i;
1442                 break;
1443             }
1444             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) ){
1445                 conversation=&ct->conversations[i];
1446                 conversation_idx=i;
1447                 break;
1448             }
1449         }
1450     }
1451
1452     /* if we still dont know what conversation this is it has to be a new one
1453        and we have to allocate it and append it to the end of the list */
1454     if(conversation==NULL){
1455         new_conversation=TRUE;
1456         ct->num_conversations++;
1457         ct->conversations=g_realloc(ct->conversations, ct->num_conversations*sizeof(conversation_t));
1458         conversation=&ct->conversations[ct->num_conversations-1];
1459         conversation_idx=ct->num_conversations-1;
1460     }
1461
1462     /* if this is a new conversation we need to initialize the struct */
1463     if(new_conversation){
1464         COPY_ADDRESS(&conversation->src_address, addr1);
1465         COPY_ADDRESS(&conversation->dst_address, addr2);
1466         conversation->sat=sat;
1467         conversation->port_type=port_type;
1468         conversation->src_port=port1;
1469         conversation->dst_port=port2;
1470         conversation->rx_frames=0;
1471         conversation->tx_frames=0;
1472         conversation->rx_bytes=0;
1473         conversation->tx_bytes=0;
1474     }
1475
1476     /* update the conversation struct */
1477     if( (!CMP_ADDRESS(src, addr1))&&(!CMP_ADDRESS(dst, addr2))&&(src_port==port1)&&(dst_port==port2) ){
1478         conversation->tx_frames+=num_frames;
1479         conversation->tx_bytes+=num_bytes;
1480     } else {
1481         conversation->rx_frames+=num_frames;
1482         conversation->rx_bytes+=num_bytes;
1483     }
1484
1485     /* if this was a new conversation we have to create a clist row for it */
1486     if(new_conversation){
1487         char *entries[NUM_COLS];
1488         char frames[16],bytes[16],txframes[16],txbytes[16],rxframes[16],rxbytes[16];
1489
1490           /* Freeze the table while performing updates */
1491         gtk_clist_freeze(ct->table);
1492
1493         /* these values will be filled by call to draw_ct_table_addresses() below */
1494         entries[0] = "";
1495         entries[1] = "";
1496         entries[2] = "";
1497         entries[3] = "";
1498
1499         g_snprintf(frames, 16, "%u", conversation->tx_frames+conversation->rx_frames);
1500         entries[4]=frames;
1501         g_snprintf(bytes, 16, "%u", conversation->tx_bytes+conversation->rx_bytes);
1502         entries[5]=bytes;
1503
1504         g_snprintf(txframes, 16, "%u", conversation->tx_frames);
1505         entries[6]=txframes;
1506         g_snprintf(txbytes, 16, "%u", conversation->tx_bytes);
1507         entries[7]=txbytes;
1508
1509         g_snprintf(rxframes, 16, "%u", conversation->rx_frames);
1510         entries[8]=rxframes;
1511         g_snprintf(rxbytes, 16, "%u", conversation->rx_bytes);
1512         entries[9]=rxbytes;
1513
1514         gtk_clist_insert(ct->table, conversation_idx, entries);
1515         gtk_clist_set_row_data(ct->table, conversation_idx, (gpointer) conversation_idx);
1516
1517         gtk_clist_thaw(ct->table);
1518     }
1519 }
1520
1521