1 /* hostlist_table.c 2004 Ian Schorr
2 * modified from endpoint_talkers_table.c 2003 Ronnie Sahlberg
3 * Helper routines common to all host list taps.
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 #include <epan/packet_info.h>
37 #include <epan/to_str.h>
38 #include <epan/addr_resolv.h>
40 #include <epan/strutil.h>
43 #include <epan/geoip_db.h>
44 #include <wsutil/pint.h>
45 #include <epan/filesystem.h>
48 #include <wsutil/file_util.h>
50 #include "ui/simple_dialog.h"
51 #include "ui/alert_box.h"
52 #include "ui/utf8_entities.h"
53 #include "wsutil/tempfile.h"
55 #include "ui/gtk/hostlist_table.h"
56 #include "ui/gtk/filter_utils.h"
57 #include "ui/gtk/gtkglobals.h"
59 #include "ui/gtk/gui_utils.h"
60 #include "ui/gtk/dlg_utils.h"
61 #include "ui/gtk/help_dlg.h"
62 #include "ui/gtk/main.h"
64 #include "ui/gtk/webbrowser.h"
65 #include "ui/gtk/stock_icons.h"
68 #include "ui/gtk/old-gtk-compat.h"
70 #define HOST_PTR_KEY "hostlist-pointer"
71 #define NB_PAGES_KEY "notebook-pages"
72 #define HL_DLG_HEIGHT 550
74 #define CMP_INT(i1, i2) \
77 else if ((i1) < (i2)) \
82 #define COL_STR_LEN 32
84 /* convert a port number into a string */
86 hostlist_port_to_str(int port_type_val
, guint32 port
)
89 static gchar
*strp
, str
[4][12];
92 switch(port_type_val
){
102 *--bp
= (port
% 10) +'0';
103 } while ((port
/= 10) != 0 && bp
> strp
);
110 #define FN_ANY_ADDRESS 0
111 #define FN_ANY_PORT 1
113 /* Given an address (to distinguish between ipv4 and ipv6 for tcp/udp,
114 a port_type and a name_type (FN_...)
115 return a string for the filter name.
117 Some addresses, like AT_ETHER may actually be any of multiple types
118 of protocols, either ethernet, tokenring, fddi etc so we must be more
119 specific there; that's why we need specific_addr_type.
122 hostlist_get_filter_name(address
*addr
, int specific_addr_type_val
, int port_type_val
, int name_type_val
)
124 switch(name_type_val
){
128 switch(specific_addr_type_val
){
150 switch(specific_addr_type_val
){
152 return "jxta.message.address";
164 switch(port_type_val
){
175 g_assert_not_reached();
180 reset_hostlist_table_data(hostlist_table
*hosts
)
185 GString
*error_string
;
189 if (hosts
->use_dfilter
) {
190 filter
= gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget
));
192 filter
= hosts
->filter
;
194 error_string
= set_tap_dfilter (hosts
, filter
);
196 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "%s", error_string
->str
);
197 g_string_free(error_string
, TRUE
);
203 display_name
= cf_get_display_name(&cfile
);
204 g_snprintf(title
, sizeof(title
), "Endpoints: %s", display_name
);
205 g_free(display_name
);
206 gtk_window_set_title(GTK_WINDOW(hosts
->win
), title
);
207 g_snprintf(title
, sizeof(title
), "%s", hosts
->name
);
208 gtk_label_set_text(GTK_LABEL(hosts
->page_lb
), title
);
209 gtk_widget_set_sensitive(hosts
->page_lb
, FALSE
);
211 if (hosts
->use_dfilter
) {
212 if (filter
&& strlen(filter
)) {
213 g_snprintf(title
, sizeof(title
), "%s Endpoints - Filter: %s", hosts
->name
, filter
);
215 g_snprintf(title
, sizeof(title
), "%s Endpoints - No Filter", hosts
->name
);
218 g_snprintf(title
, sizeof(title
), "%s Endpoints", hosts
->name
);
220 gtk_label_set_text(GTK_LABEL(hosts
->name_lb
), title
);
222 display_name
= cf_get_display_name(&cfile
);
223 g_snprintf(title
, sizeof(title
), "%s Endpoints: %s", hosts
->name
, display_name
);
224 g_free(display_name
);
225 gtk_window_set_title(GTK_WINDOW(hosts
->win
), title
);
228 /* remove all entries from the list */
229 store
= GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(hosts
->table
)));
230 gtk_list_store_clear(store
);
232 /* delete all hosts */
233 for(i
=0;i
<hosts
->num_hosts
;i
++){
234 hostlist_talker_t
*host
= &g_array_index(hosts
->hosts
, hostlist_talker_t
, i
);
235 g_free((gpointer
)host
->myaddress
.data
);
239 g_array_free(hosts
->hosts
, TRUE
);
241 if (hosts
->hashtable
!= NULL
)
242 g_hash_table_destroy(hosts
->hashtable
);
245 hosts
->hashtable
=NULL
;
250 reset_hostlist_table_data_cb(void *arg
)
252 reset_hostlist_table_data((hostlist_table
*)arg
);
256 hostlist_win_destroy_cb(GtkWindow
*win _U_
, gpointer data
)
258 hostlist_table
*hosts
=(hostlist_table
*)data
;
260 remove_tap_listener(hosts
);
262 reset_hostlist_table_data(hosts
);
296 hostlist_sort_column(GtkTreeModel
*model
,
303 gint data_column
= GPOINTER_TO_INT(user_data
);
304 hostlist_table
*hl
= (hostlist_table
*)g_object_get_data(G_OBJECT(model
), HOST_PTR_KEY
);
305 hostlist_talker_t
*host1
= NULL
;
306 hostlist_talker_t
*host2
= NULL
;
308 gtk_tree_model_get(model
, a
, INDEX_COLUMN
, &idx1
, -1);
309 gtk_tree_model_get(model
, b
, INDEX_COLUMN
, &idx2
, -1);
311 if (!hl
|| idx1
>= hl
->num_hosts
|| idx2
>= hl
->num_hosts
)
314 host1
= &g_array_index(hl
->hosts
, hostlist_talker_t
, idx1
);
315 host2
= &g_array_index(hl
->hosts
, hostlist_talker_t
, idx2
);
318 case 0: /* Address */
319 return(CMP_ADDRESS(&host1
->myaddress
, &host2
->myaddress
));
321 CMP_INT(host1
->port
, host2
->port
);
325 gchar
*text1
, *text2
;
326 double loc1
= 0, loc2
= 0;
328 gtk_tree_model_get(model
, a
, data_column
, &text1
, -1);
329 gtk_tree_model_get(model
, b
, data_column
, &text2
, -1);
345 g_assert_not_reached();
350 hostlist_select_filter_cb(GtkWidget
*widget _U_
, gpointer callback_data
, guint callback_action
)
353 hostlist_table
*hl
=(hostlist_table
*)callback_data
;
358 GtkTreeSelection
*sel
;
359 hostlist_talker_t
*host
= NULL
;
361 sel
= gtk_tree_view_get_selection (GTK_TREE_VIEW(hl
->table
));
362 if (!gtk_tree_selection_get_selected(sel
, &model
, &iter
))
365 gtk_tree_model_get (model
, &iter
,
369 if(idx
>= hl
->num_hosts
){
370 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "No hostlist selected");
373 host
= &g_array_index(hl
->hosts
, hostlist_talker_t
, idx
);
375 sport
=hostlist_port_to_str(host
->port_type
, host
->port
);
377 str
= g_strdup_printf("%s==%s%s%s%s%s",
378 hostlist_get_filter_name(&host
->myaddress
, host
->sat
, host
->port_type
, FN_ANY_ADDRESS
),
379 ep_address_to_str(&host
->myaddress
),
381 sport
?hostlist_get_filter_name(&host
->myaddress
, host
->sat
, host
->port_type
, FN_ANY_PORT
):"",
385 apply_selected_filter (callback_action
, str
);
390 hostlist_show_popup_menu_cb(void *widg _U_
, GdkEvent
*event
, hostlist_table
*et
)
392 GdkEventButton
*bevent
= (GdkEventButton
*)event
;
394 if(event
->type
==GDK_BUTTON_PRESS
&& bevent
->button
==3){
395 gtk_menu_popup(GTK_MENU(et
->menu
), NULL
, NULL
, NULL
, NULL
,
396 bevent
->button
, bevent
->time
);
402 /* Action callbacks */
404 apply_as_selected_cb(GtkWidget
*widget
, gpointer user_data
)
406 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_SELECTED
, 0));
409 apply_as_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
411 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_NOT_SELECTED
, 0));
414 apply_as_and_selected_cb(GtkWidget
*widget
, gpointer user_data
)
416 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_AND_SELECTED
, 0));
419 apply_as_or_selected_cb(GtkWidget
*widget
, gpointer user_data
)
421 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_OR_SELECTED
, 0));
424 apply_as_and_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
426 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED
, 0));
429 apply_as_or_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
431 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED
, 0));
435 prep_as_selected_cb(GtkWidget
*widget
, gpointer user_data
)
437 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_SELECTED
, 0));
440 prep_as_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
442 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_NOT_SELECTED
, 0));
445 prep_as_and_selected_cb(GtkWidget
*widget
, gpointer user_data
)
447 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_AND_SELECTED
, 0));
450 prep_as_or_selected_cb(GtkWidget
*widget
, gpointer user_data
)
452 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_OR_SELECTED
, 0));
455 prep_as_and_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
457 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED
, 0));
460 prep_as_or_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
462 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED
, 0));
466 find_selected_cb(GtkWidget
*widget
, gpointer user_data
)
468 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_FIND_FRAME(ACTYPE_SELECTED
, 0));
471 find_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
473 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_FIND_FRAME(ACTYPE_NOT_SELECTED
, 0));
476 find_prev_selected_cb(GtkWidget
*widget
, gpointer user_data
)
478 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED
, 0));
481 find_prev_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
483 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_FIND_PREVIOUS(ACTYPE_NOT_SELECTED
, 0));
486 find_next_selected_cb(GtkWidget
*widget
, gpointer user_data
)
488 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_FIND_NEXT(ACTYPE_SELECTED
, 0));
491 find_next_not_selected_cb(GtkWidget
*widget
, gpointer user_data
)
493 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_FIND_NEXT(ACTYPE_NOT_SELECTED
, 0));
496 color_selected_cb(GtkWidget
*widget
, gpointer user_data
)
498 hostlist_select_filter_cb( widget
, user_data
, CALLBACK_COLORIZE(ACTYPE_SELECTED
, 0));
501 static const char *ui_desc_hostlist_table_popup
=
503 " <popup name='HostlistTableFilterPopup'>\n"
504 " <menu action='/Apply as Filter'>\n"
505 " <menuitem action='/Apply as Filter/Selected'/>\n"
506 " <menuitem action='/Apply as Filter/Not Selected'/>\n"
507 " <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and Selected'/>\n"
508 " <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or Selected'/>\n"
509 " <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and not Selected'/>\n"
510 " <menuitem action='/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or not Selected'/>\n"
512 " <menu action='/Prepare a Filter'>\n"
513 " <menuitem action='/Prepare a Filter/Selected'/>\n"
514 " <menuitem action='/Prepare a Filter/Not Selected'/>\n"
515 " <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and Selected'/>\n"
516 " <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or Selected'/>\n"
517 " <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and not Selected'/>\n"
518 " <menuitem action='/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or not Selected'/>\n"
520 " <menu action='/Find Frame'>\n"
521 " <menu action='/Find Frame/Find Frame'>\n"
522 " <menuitem action='/Find Frame/Selected'/>\n"
523 " <menuitem action='/Find Frame/Not Selected'/>\n"
525 " <menu action='/Find Frame/Find Next'>\n"
526 " <menuitem action='/Find Next/Selected'/>\n"
527 " <menuitem action='/Find Next/Not Selected'/>\n"
529 " <menu action='/Find Frame/Find Previous'>\n"
530 " <menuitem action='/Find Previous/Selected'/>\n"
531 " <menuitem action='/Find Previous/Not Selected'/>\n"
534 " <menu action='/Colorize Procedure'>\n"
535 " <menuitem action='/Colorize Procedure/Colorize Host Traffic'/>\n"
544 * const gchar *stock_id;
545 * const gchar *label;
546 * const gchar *accelerator;
547 * const gchar *tooltip;
548 * GCallback callback;
550 * const gchar *name; The name of the action.
551 * const gchar *stock_id; The stock id for the action, or the name of an icon from the icon theme.
552 * const gchar *label; The label for the action. This field should typically be marked for translation,
553 * see gtk_action_group_set_translation_domain().
554 * If label is NULL, the label of the stock item with id stock_id is used.
555 * const gchar *accelerator; The accelerator for the action, in the format understood by gtk_accelerator_parse().
556 * const gchar *tooltip; The tooltip for the action. This field should typically be marked for translation,
557 * see gtk_action_group_set_translation_domain().
558 * GCallback callback; The function to call when the action is activated.
561 static const GtkActionEntry service_resp_t_popup_entries
[] = {
562 { "/Apply as Filter", NULL
, "Apply as Filter", NULL
, NULL
, NULL
},
563 { "/Prepare a Filter", NULL
, "Prepare a Filter", NULL
, NULL
, NULL
},
564 { "/Find Frame", NULL
, "Find Frame", NULL
, NULL
, NULL
},
565 { "/Find Frame/Find Frame", NULL
, "Find Frame", NULL
, NULL
, NULL
},
566 { "/Find Frame/Find Next", NULL
, "Find Next" , NULL
, NULL
, NULL
},
567 { "/Find Frame/Find Previous", NULL
, "Find Previous", NULL
, NULL
, NULL
},
568 { "/Colorize Procedure", NULL
, "Colorize Procedure", NULL
, NULL
, NULL
},
569 { "/Apply as Filter/Selected", NULL
, "Selected", NULL
, "Selected", G_CALLBACK(apply_as_selected_cb
) },
570 { "/Apply as Filter/Not Selected", NULL
, "Not Selected", NULL
, "Not Selected", G_CALLBACK(apply_as_not_selected_cb
) },
571 { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and Selected", G_CALLBACK(apply_as_and_selected_cb
) },
572 { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or Selected", G_CALLBACK(apply_as_or_selected_cb
) },
573 { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", G_CALLBACK(apply_as_and_not_selected_cb
) },
574 { "/Apply as Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", G_CALLBACK(apply_as_or_not_selected_cb
) },
575 { "/Prepare a Filter/Selected", NULL
, "Selected", NULL
, "selcted", G_CALLBACK(prep_as_selected_cb
) },
576 { "/Prepare a Filter/Not Selected", NULL
, "Not Selected", NULL
, "Not Selected", G_CALLBACK(prep_as_not_selected_cb
) },
577 { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and Selected", G_CALLBACK(prep_as_and_selected_cb
) },
578 { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or Selected", G_CALLBACK(prep_as_or_selected_cb
) },
579 { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" and not Selected", G_CALLBACK(prep_as_and_not_selected_cb
) },
580 { "/Prepare a Filter/" UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", NULL
, UTF8_HORIZONTAL_ELLIPSIS
" or not Selected", G_CALLBACK(prep_as_or_not_selected_cb
) },
581 { "/Find Frame/Selected", NULL
, "Selected", NULL
, "Selected", G_CALLBACK(find_selected_cb
) },
582 { "/Find Frame/Not Selected", NULL
, "Not Selected", NULL
, "Not Selected", G_CALLBACK(find_not_selected_cb
) },
583 { "/Find Previous/Selected", NULL
, "Selected", NULL
, "Selected", G_CALLBACK(find_prev_selected_cb
) },
584 { "/Find Previous/Not Selected", NULL
, "Not Selected", NULL
, "Not Selected", G_CALLBACK(find_prev_not_selected_cb
) },
585 { "/Find Next/Selected", NULL
, "Selected", NULL
, "Selected", G_CALLBACK(find_next_selected_cb
) },
586 { "/Find Next/Not Selected", NULL
, "Not Selected", NULL
, "Not Selected", G_CALLBACK(find_next_not_selected_cb
) },
587 { "/Colorize Procedure/Colorize Host Traffic",NULL
, "Colorize Host Traffic", NULL
, "Colorize Host Traffic", G_CALLBACK(color_selected_cb
) },
591 hostlist_create_popup_menu(hostlist_table
*hl
)
593 GtkUIManager
*ui_manager
;
594 GtkActionGroup
*action_group
;
595 GError
*error
= NULL
;
597 action_group
= gtk_action_group_new ("HostlistTablePopupActionGroup");
598 gtk_action_group_add_actions (action_group
, /* the action group */
599 service_resp_t_popup_entries
, /* an array of action descriptions */
600 G_N_ELEMENTS(service_resp_t_popup_entries
),/* the number of entries */
601 hl
); /* data to pass to the action callbacks */
603 ui_manager
= gtk_ui_manager_new ();
604 gtk_ui_manager_insert_action_group (ui_manager
,
606 0); /* the position at which the group will be inserted */
607 gtk_ui_manager_add_ui_from_string (ui_manager
,ui_desc_hostlist_table_popup
, -1, &error
);
610 fprintf (stderr
, "Warning: building hostlist table filter popup failed: %s\n",
612 g_error_free (error
);
615 hl
->menu
= gtk_ui_manager_get_widget(ui_manager
, "/HostlistTableFilterPopup");
616 g_signal_connect(hl
->table
, "button_press_event", G_CALLBACK(hostlist_show_popup_menu_cb
), hl
);
620 /* Draw/refresh the address field of a single entry at the specified index */
622 get_hostlist_table_address(hostlist_table
*hl
, hostlist_talker_t
*host
, const char **entries
)
627 if (!hl
->resolve_names
)
628 entries
[0] = ep_address_to_str(&host
->myaddress
);
630 entries
[0] = (char *)get_addr_name(&host
->myaddress
);
632 pt
= host
->port_type
;
633 if(!hl
->resolve_names
) pt
= PT_NONE
;
636 entries
[1] = get_tcp_port(host
->port
);
639 entries
[1] = get_udp_port(host
->port
);
642 entries
[1] = get_sctp_port(host
->port
);
645 port
=hostlist_port_to_str(host
->port_type
, host
->port
);
646 entries
[1] = port
?port
:"";
650 /* Refresh the address fields of all entries in the list */
652 draw_hostlist_table_addresses(hostlist_table
*hl
)
655 const char *entries
[2];
658 store
= GTK_LIST_STORE(gtk_tree_view_get_model(hl
->table
));
660 gtk_tree_view_set_model(GTK_TREE_VIEW(hl
->table
), NULL
);
662 for(i
=0;i
<hl
->num_hosts
;i
++){
663 hostlist_talker_t
*host
= &g_array_index(hl
->hosts
, hostlist_talker_t
, i
);
664 get_hostlist_table_address(hl
, host
, entries
);
665 gtk_list_store_set (store
, &host
->iter
,
666 ADR_COLUMN
, entries
[0],
667 PORT_COLUMN
, entries
[1],
670 gtk_tree_view_set_model(GTK_TREE_VIEW(hl
->table
), GTK_TREE_MODEL(store
));
671 g_object_unref(store
);
676 draw_hostlist_table_data(hostlist_table
*hl
)
681 gboolean first
= TRUE
;
685 g_snprintf(title
, sizeof(title
), "%s: %u", hl
->name
, hl
->num_hosts
);
687 g_snprintf(title
, sizeof(title
), "%s", hl
->name
);
689 gtk_label_set_text(GTK_LABEL(hl
->page_lb
), title
);
690 gtk_widget_set_sensitive(hl
->page_lb
, hl
->num_hosts
);
693 g_snprintf(title
, sizeof(title
), "%s Endpoints: %u", hl
->name
, hl
->num_hosts
);
695 g_snprintf(title
, sizeof(title
), "%s Endpoints", hl
->name
);
697 gtk_label_set_text(GTK_LABEL(hl
->name_lb
), title
);
700 store
= GTK_LIST_STORE(gtk_tree_view_get_model(hl
->table
));
701 for(i
=0;i
<hl
->num_hosts
;i
++){
702 hostlist_talker_t
*host
= &g_array_index(hl
->hosts
, hostlist_talker_t
, i
);
709 gtk_tree_view_set_model(GTK_TREE_VIEW(hl
->table
), NULL
);
713 host
->modified
= FALSE
;
714 if (!host
->iter_valid
) {
715 const char *entries
[2];
717 char *geoip
[NUM_GEOIP_COLS
];
720 if ((host
->myaddress
.type
== AT_IPv4
|| host
->myaddress
.type
== AT_IPv6
) && !hl
->geoip_visible
) {
721 GList
*columns
, *list
;
722 GtkTreeViewColumn
*column
;
723 columns
= gtk_tree_view_get_columns(GTK_TREE_VIEW(hl
->table
));
726 const gchar
*title_p
;
729 column
= (GtkTreeViewColumn
*)columns
->data
;
730 title_p
= gtk_tree_view_column_get_title(column
);
731 id
= gtk_tree_view_column_get_sort_column_id(column
);
732 if (title_p
[0] != 0 && id
>= GEOIP1_COLUMN
) {
733 gtk_tree_view_column_set_visible(column
, TRUE
);
735 columns
= g_list_next(columns
);
738 hl
->geoip_visible
= TRUE
;
741 /* Filled in from the GeoIP config, if any */
742 for (j
= 0; j
< NUM_GEOIP_COLS
; j
++) {
743 if (host
->myaddress
.type
== AT_IPv4
&& j
< geoip_db_num_dbs()) {
744 const guchar
*name
= geoip_db_lookup_ipv4(j
, pntohl(host
->myaddress
.data
), "-");
745 geoip
[j
] = g_strdup(name
);
746 } else if (host
->myaddress
.type
== AT_IPv6
&& j
< geoip_db_num_dbs()) {
748 const struct e_in6_addr
*addr
= (const struct e_in6_addr
*) host
->myaddress
.data
;
750 name
= geoip_db_lookup_ipv6(j
, *addr
, "-");
751 geoip
[j
] = g_strdup(name
);
756 #endif /* HAVE_GEOIP */
758 get_hostlist_table_address(hl
, host
, entries
);
759 host
->iter_valid
= TRUE
;
760 gtk_list_store_insert_with_values( store
, &host
->iter
, G_MAXINT
,
761 ADR_COLUMN
, entries
[0],
762 PORT_COLUMN
, entries
[1],
763 PACKETS_COLUMN
, host
->tx_frames
+host
->rx_frames
,
764 BYTES_COLUMN
, host
->tx_bytes
+host
->rx_bytes
,
765 PKT_AB_COLUMN
, host
->tx_frames
,
766 BYTES_AB_COLUMN
, host
->tx_bytes
,
767 PKT_BA_COLUMN
, host
->rx_frames
,
768 BYTES_BA_COLUMN
, host
->rx_bytes
,
770 GEOIP1_COLUMN
, geoip
[0],
771 GEOIP2_COLUMN
, geoip
[1],
772 GEOIP3_COLUMN
, geoip
[2],
773 GEOIP4_COLUMN
, geoip
[3],
774 GEOIP5_COLUMN
, geoip
[4],
775 GEOIP6_COLUMN
, geoip
[5],
776 GEOIP7_COLUMN
, geoip
[6],
777 GEOIP8_COLUMN
, geoip
[7],
778 GEOIP9_COLUMN
, geoip
[8],
779 GEOIP10_COLUMN
, geoip
[9],
780 GEOIP11_COLUMN
, geoip
[10],
781 GEOIP12_COLUMN
, geoip
[11],
782 GEOIP13_COLUMN
, geoip
[12],
788 for (j
= 0; j
< NUM_GEOIP_COLS
; j
++)
790 #endif /* HAVE_GEOIP */
793 gtk_list_store_set (store
, &host
->iter
,
794 PACKETS_COLUMN
, host
->tx_frames
+host
->rx_frames
,
795 BYTES_COLUMN
, host
->tx_bytes
+host
->rx_bytes
,
796 PKT_AB_COLUMN
, host
->tx_frames
,
797 BYTES_AB_COLUMN
, host
->tx_bytes
,
798 PKT_BA_COLUMN
, host
->rx_frames
,
799 BYTES_BA_COLUMN
, host
->rx_bytes
,
804 if (!hl
->fixed_col
&& hl
->num_hosts
>= 1000) {
805 /* finding the right size for a column isn't easy
806 * let it run in autosize a little (1000 is arbitrary)
807 * and then switch to fixed width.
809 hl
->fixed_col
= TRUE
;
810 switch_to_fixed_col(hl
->table
);
813 gtk_tree_view_set_model(GTK_TREE_VIEW(hl
->table
), GTK_TREE_MODEL(store
));
814 g_object_unref(store
);
819 draw_hostlist_table_data_cb(void *arg
)
821 draw_hostlist_table_data((hostlist_table
*)arg
);
826 gint columns_order
[N_COLUMNS
];
828 hostlist_table
*talkers
;
831 /* output in C locale */
833 csv_handle(GtkTreeModel
*model
, GtkTreePath
*path _U_
, GtkTreeIter
*iter
,
836 csv_t
*csv
= (csv_t
*)data
;
842 gtk_tree_model_get(model
, iter
, INDEX_COLUMN
, &idx
, -1);
844 for (i
=0; i
< csv
->nb_cols
; i
++) {
846 g_string_append(csv
->CSV_str
, ",");
848 switch(csv
->columns_order
[i
]) {
851 gtk_tree_model_get(model
, iter
, csv
->columns_order
[i
], &table_text
, -1);
853 g_string_append_printf(csv
->CSV_str
, "\"%s\"", table_text
);
860 case BYTES_AB_COLUMN
:
862 case BYTES_BA_COLUMN
:
863 gtk_tree_model_get(model
, iter
, csv
->columns_order
[i
], &value
, -1);
864 g_string_append_printf(csv
->CSV_str
, "\"%" G_GINT64_MODIFIER
"u\"", value
);
867 gtk_tree_model_get(model
, iter
, csv
->columns_order
[i
], &table_text
, -1);
869 g_string_append_printf(csv
->CSV_str
, "\"%s\"", table_text
);
875 g_string_append(csv
->CSV_str
,"\n");
881 copy_as_csv_cb(GtkWindow
*copy_bt
, gpointer data _U_
)
885 GList
*columns
, *list
;
886 GtkTreeViewColumn
*column
;
890 csv
.talkers
=(hostlist_table
*)g_object_get_data(G_OBJECT(copy_bt
), HOST_PTR_KEY
);
894 savelocale
= setlocale(LC_NUMERIC
, NULL
);
895 setlocale(LC_NUMERIC
, "C");
896 csv
.CSV_str
= g_string_new("");
898 columns
= gtk_tree_view_get_columns(GTK_TREE_VIEW(csv
.talkers
->table
));
902 column
= (GtkTreeViewColumn
*)columns
->data
;
903 if (gtk_tree_view_column_get_visible(column
)) {
904 csv
.columns_order
[csv
.nb_cols
] = gtk_tree_view_column_get_sort_column_id(column
);
906 g_string_append(csv
.CSV_str
, ",");
907 g_string_append_printf(csv
.CSV_str
, "\"%s\"", gtk_tree_view_column_get_title(column
));
910 columns
= g_list_next(columns
);
914 g_string_append(csv
.CSV_str
,"\n");
915 store
= GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(csv
.talkers
->table
)));
916 gtk_tree_model_foreach(GTK_TREE_MODEL(store
), csv_handle
, &csv
);
918 /* Now that we have the CSV data, copy it into the default clipboard */
919 cb
= gtk_clipboard_get(GDK_SELECTION_CLIPBOARD
); /* Get the default clipboard */
920 gtk_clipboard_set_text(cb
, csv
.CSV_str
->str
, -1); /* Copy the CSV data into the clipboard */
921 setlocale(LC_NUMERIC
, savelocale
);
922 g_string_free(csv
.CSV_str
, TRUE
); /* Free the memory */
928 gint32 col_lat
, col_lon
, col_country
, col_city
, col_as_num
, col_ip
, col_packets
, col_bytes
;
930 gboolean hosts_written
;
931 hostlist_table
*talkers
;
934 static const char *map_endpoint_opener
;
939 map_endpoint_opener
= "{\n";
942 /* XXX output in C locale */
944 map_handle(GtkTreeModel
*model
, GtkTreePath
*path _U_
, GtkTreeIter
*iter
,
947 map_t
*map
= (map_t
*)data
;
948 gchar
*table_entry
, *esc_entry
;
950 /* Add the column values to the TSV data */
952 /* check, if we have a geolocation available for this host */
953 gtk_tree_model_get(model
, iter
, map
->col_lat
, &table_entry
, -1);
954 if (strcmp(table_entry
, "-") == 0) {
959 gtk_tree_model_get(model
, iter
, map
->col_lon
, &table_entry
, -1);
960 if (strcmp(table_entry
, "-") == 0) {
967 'type': 'Feature', 'geometry': { 'type': 'Point', 'coordinates': [-122.583889, 37.898889] },
968 'properties': { 'title': 'host.example.com', 'description': 'AS: AS12345 Ewok Holdings, Inc.<br/>Country: US<br/>City: Muir Woods, CA<br/>Packets: 6<br/>Bytes: 980' }
972 fputs(map_endpoint_opener
, map
->out_file
);
973 fputs(" 'type': 'Feature', 'geometry': { 'type': 'Point', 'coordinates': [", map
->out_file
);
976 gtk_tree_model_get(model
, iter
, map
->col_lon
, &table_entry
, -1);
977 fputs(table_entry
, map
->out_file
);
979 fputs(", ", map
->out_file
);
982 gtk_tree_model_get(model
, iter
, map
->col_lat
, &table_entry
, -1);
983 fputs(table_entry
, map
->out_file
);
985 fputs("] },\n", map
->out_file
);
987 fputs(" 'properties': { 'title': '", map
->out_file
);
990 gtk_tree_model_get(model
, iter
, map
->col_ip
, &table_entry
, -1);
991 esc_entry
= string_replace(table_entry
, "'", "'");
992 fputs(esc_entry
, map
->out_file
);
995 fputs("', 'description': '", map
->out_file
);
998 if (map
->col_as_num
>= 0) {
999 gtk_tree_model_get(model
, iter
, map
->col_as_num
, &table_entry
, -1);
1000 fputs("AS: ", map
->out_file
);
1001 esc_entry
= string_replace(table_entry
, "'", "'");
1002 fputs(esc_entry
, map
->out_file
);
1003 g_free(table_entry
);
1005 fputs("<br/>", map
->out_file
);
1008 if (map
->col_country
>= 0) {
1009 gtk_tree_model_get(model
, iter
, map
->col_country
, &table_entry
, -1);
1010 fputs("Country: ", map
->out_file
);
1011 esc_entry
= string_replace(table_entry
, "'", "'");
1012 fputs(esc_entry
, map
->out_file
);
1013 g_free(table_entry
);
1015 fputs("<br/>", map
->out_file
);
1018 if (map
->col_country
>= 0) {
1019 gtk_tree_model_get(model
, iter
, map
->col_city
, &table_entry
, -1);
1020 fputs("City: ", map
->out_file
);
1021 esc_entry
= string_replace(table_entry
, "'", "'");
1022 fputs(esc_entry
, map
->out_file
);
1023 g_free(table_entry
);
1025 fputs("<br/>", map
->out_file
);
1028 gtk_tree_model_get(model
, iter
, map
->col_packets
, &value
, -1);
1029 fprintf(map
->out_file
, "Packets: %" G_GINT64_MODIFIER
"u<br/>", value
);
1031 gtk_tree_model_get(model
, iter
, map
->col_bytes
, &value
, -1);
1032 fprintf(map
->out_file
, "Bytes: %" G_GINT64_MODIFIER
"u", value
);
1034 /* XXX - we could add specific icons, e.g. depending on the amount of packets or bytes */
1036 fputs("' }\n", map
->out_file
);
1037 fputs("}", map
->out_file
);
1038 map_endpoint_opener
= ",\n{\n";
1040 map
->hosts_written
= TRUE
;
1045 #define MAX_TPL_LINE_LEN 4096
1047 open_as_map_cb(GtkWindow
*copy_bt
, gpointer data _U_
)
1052 char *map_path
, *map_filename
;
1055 GList
*columns
, *list
;
1056 GtkTreeViewColumn
*column
;
1057 GtkListStore
*store
;
1061 map
.talkers
= (hostlist_table
*)g_object_get_data(G_OBJECT(copy_bt
), HOST_PTR_KEY
);
1065 map
.col_lat
= map
.col_lon
= map
.col_country
= map
.col_city
= map
.col_as_num
= map
.col_ip
= map
.col_packets
= map
.col_bytes
= -1;
1066 map
.hosts_written
= FALSE
;
1067 /* Find the interesting columns */
1068 columns
= gtk_tree_view_get_columns(GTK_TREE_VIEW(map
.talkers
->table
));
1072 column
= (GtkTreeViewColumn
*)columns
->data
;
1073 i
= gtk_tree_view_column_get_sort_column_id(column
);
1074 if(strcmp(map
.talkers
->default_titles
[i
], "Latitude") == 0) {
1078 if(strcmp(map
.talkers
->default_titles
[i
], "Longitude") == 0) {
1082 if(strcmp(map
.talkers
->default_titles
[i
], "Country") == 0) {
1083 map
.col_country
= i
;
1086 if(strcmp(map
.talkers
->default_titles
[i
], "City") == 0) {
1090 if(strcmp(map
.talkers
->default_titles
[i
], "AS Number") == 0) {
1093 if(strcmp(map
.talkers
->default_titles
[i
], "Address") == 0) {
1097 if(strcmp(map
.talkers
->default_titles
[i
], "Packets") == 0) {
1098 map
.col_packets
= i
;
1101 if(strcmp(map
.talkers
->default_titles
[i
], "Bytes") == 0) {
1105 columns
= g_list_next(columns
);
1109 /* check for the minimum required data */
1110 if(map
.col_lat
== -1 || map
.col_lon
== -1) {
1111 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "Latitude/Longitude data not available (GeoIP installed?)");
1115 /* Create a location map HTML file from a template */
1116 /* XXX - add error handling */
1117 tpl_filename
= get_datafile_path("ipmap.html");
1118 tpl_file
= ws_fopen(tpl_filename
, "r");
1119 if(tpl_file
== NULL
) {
1120 open_failure_alert_box(tpl_filename
, errno
, FALSE
);
1121 g_free(tpl_filename
);
1124 g_free(tpl_filename
);
1126 /* We should probably create a file with a temporary name and a .html extension instead */
1127 if (! create_tempdir(&map_path
, "Wireshark IP Map ")) {
1128 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
,
1129 "Could not create temporary directory\n%s",
1135 map_filename
= g_strdup_printf("%s%cipmap.html", map_path
, G_DIR_SEPARATOR
);
1136 map
.out_file
= ws_fopen(map_filename
, "w");
1137 if(map
.out_file
== NULL
) {
1138 open_failure_alert_box(map_filename
, errno
, TRUE
);
1139 g_free(map_filename
);
1144 store
= GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(map
.talkers
->table
)));
1145 tpl_line
= (char *)g_malloc(MAX_TPL_LINE_LEN
);
1147 while (fgets(tpl_line
, MAX_TPL_LINE_LEN
, tpl_file
) != NULL
) {
1148 fputs(tpl_line
, map
.out_file
);
1149 /* MUST match ipmap.html */
1150 if (strstr(tpl_line
, "// Start endpoint list")) {
1152 gtk_tree_model_foreach(GTK_TREE_MODEL(store
), map_handle
, &map
);
1158 fclose(map
.out_file
);
1160 if(!map
.hosts_written
) {
1161 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "No latitude/longitude data found");
1162 g_free(map_filename
);
1166 /* open the webbrowser */
1167 file_uri
= g_filename_to_uri(map_filename
, NULL
, NULL
);
1168 g_free(map_filename
);
1169 uri_open
= browser_open_url (file_uri
);
1171 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "Couldn't open the file: \"%s\" in your web browser", file_uri
);
1178 #endif /* HAVE_GEOIP */
1180 static gint default_col_size
[N_COLUMNS
];
1183 init_default_col_size(GtkWidget
*view
)
1186 default_col_size
[ADR_COLUMN
] = get_default_col_size(view
, "00000000.000000000000");
1187 default_col_size
[PORT_COLUMN
] = get_default_col_size(view
, "000000");
1188 default_col_size
[PACKETS_COLUMN
] = get_default_col_size(view
, "00 000 000");
1189 default_col_size
[BYTES_COLUMN
] = get_default_col_size(view
, "0 000 000 000");
1190 default_col_size
[PKT_AB_COLUMN
] = default_col_size
[PACKETS_COLUMN
];
1191 default_col_size
[PKT_BA_COLUMN
] = default_col_size
[PACKETS_COLUMN
];
1192 default_col_size
[BYTES_AB_COLUMN
] = default_col_size
[BYTES_COLUMN
];
1193 default_col_size
[BYTES_BA_COLUMN
] = default_col_size
[BYTES_COLUMN
];
1195 default_col_size
[GEOIP1_COLUMN
] = default_col_size
[ADR_COLUMN
];
1196 default_col_size
[GEOIP2_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1197 default_col_size
[GEOIP3_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1198 default_col_size
[GEOIP4_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1199 default_col_size
[GEOIP5_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1200 default_col_size
[GEOIP6_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1201 default_col_size
[GEOIP7_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1202 default_col_size
[GEOIP8_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1203 default_col_size
[GEOIP9_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1204 default_col_size
[GEOIP10_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1205 default_col_size
[GEOIP11_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1206 default_col_size
[GEOIP12_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1207 default_col_size
[GEOIP13_COLUMN
] = default_col_size
[GEOIP1_COLUMN
];
1213 init_hostlist_table_page(hostlist_table
*hosttable
, GtkWidget
*vbox
, gboolean hide_ports
, const char *table_name
, const char *tap_name
,
1214 const char *filter
, tap_packet_cb packet_func
)
1217 GString
*error_string
;
1219 GtkListStore
*store
;
1221 GtkTreeViewColumn
*column
;
1222 GtkCellRenderer
*renderer
;
1223 GtkTreeSortable
*sortable
;
1224 GtkTreeSelection
*sel
;
1225 static gboolean col_size
= FALSE
;
1227 hosttable
->default_titles
[0] = "Address";
1228 hosttable
->default_titles
[1] = "Port";
1229 hosttable
->default_titles
[2] = "Packets";
1230 hosttable
->default_titles
[3] = "Bytes";
1231 hosttable
->default_titles
[4] = "Tx Packets";
1232 hosttable
->default_titles
[5] = "Tx Bytes";
1233 hosttable
->default_titles
[6] = "Rx Packets";
1234 hosttable
->default_titles
[7] = "Rx Bytes";
1237 for (i
= 0; i
< NUM_GEOIP_COLS
; i
++) {
1238 if (i
< geoip_db_num_dbs()) {
1239 hosttable
->default_titles
[NUM_BUILTIN_COLS
+ i
] = geoip_db_name(i
);
1241 hosttable
->default_titles
[NUM_BUILTIN_COLS
+ i
] = "";
1244 #endif /* HAVE_GEOIP */
1246 if (strcmp(table_name
, "NCP")==0) {
1247 hosttable
->default_titles
[1] = "Connection";
1250 hosttable
->has_ports
=!hide_ports
;
1251 hosttable
->num_hosts
= 0;
1252 hosttable
->resolve_names
=TRUE
;
1253 hosttable
->page_lb
= NULL
;
1254 hosttable
->fixed_col
= FALSE
;
1255 hosttable
->geoip_visible
= FALSE
;
1257 g_snprintf(title
, sizeof(title
), "%s Endpoints", table_name
);
1258 hosttable
->name_lb
= gtk_label_new(title
);
1259 gtk_box_pack_start(GTK_BOX(vbox
), hosttable
->name_lb
, FALSE
, FALSE
, 0);
1261 /* Create the store */
1262 store
= gtk_list_store_new (N_COLUMNS
, /* Total number of columns */
1263 G_TYPE_STRING
, /* Address */
1264 G_TYPE_STRING
, /* Port */
1265 G_TYPE_UINT64
, /* Packets */
1266 G_TYPE_UINT64
, /* Bytes */
1267 G_TYPE_UINT64
, /* Packets A->B */
1268 G_TYPE_UINT64
, /* Bytes A->B */
1269 G_TYPE_UINT64
, /* Packets A<-B */
1270 G_TYPE_UINT64
, /* Bytes A<-B */
1286 G_TYPE_UINT
); /* Index */
1288 hosttable
->scrolled_window
=scrolled_window_new(NULL
, NULL
);
1289 gtk_box_pack_start(GTK_BOX(vbox
), hosttable
->scrolled_window
, TRUE
, TRUE
, 0);
1290 tree
= gtk_tree_view_new_with_model (GTK_TREE_MODEL (store
));
1291 hosttable
->table
= GTK_TREE_VIEW(tree
);
1292 sortable
= GTK_TREE_SORTABLE(store
);
1293 g_object_unref (G_OBJECT (store
));
1297 init_default_col_size(GTK_WIDGET(hosttable
->table
));
1300 g_object_set_data(G_OBJECT(store
), HOST_PTR_KEY
, hosttable
);
1301 g_object_set_data(G_OBJECT(hosttable
->table
), HOST_PTR_KEY
, hosttable
);
1303 for (i
= 0; i
< N_COLUMNS
-1; i
++) {
1304 renderer
= gtk_cell_renderer_text_new ();
1305 g_object_set(renderer
, "ypad", 0, NULL
);
1307 case 0: /* address and port */
1309 column
= gtk_tree_view_column_new_with_attributes (hosttable
->default_titles
[i
], renderer
, "text",
1311 if(hide_ports
&& i
== 1){
1312 /* hide srcport and dstport if we don't use ports */
1313 gtk_tree_view_column_set_visible(column
, FALSE
);
1315 gtk_tree_sortable_set_sort_func(sortable
, i
, hostlist_sort_column
, GINT_TO_POINTER(i
), NULL
);
1317 case 2: /* counts */
1322 case 7: /* right align numbers */
1323 g_object_set(G_OBJECT(renderer
), "xalign", 1.0, NULL
);
1324 column
= gtk_tree_view_column_new_with_attributes (hosttable
->default_titles
[i
], renderer
, NULL
);
1325 gtk_tree_view_column_set_cell_data_func(column
, renderer
, u64_data_func
, GINT_TO_POINTER(i
), NULL
);
1327 default: /* GEOIP */
1328 column
= gtk_tree_view_column_new_with_attributes (hosttable
->default_titles
[i
], renderer
, "text",
1330 gtk_tree_view_column_set_visible(column
, FALSE
);
1332 if (i
>= NUM_BUILTIN_COLS
&& i
- NUM_BUILTIN_COLS
< geoip_db_num_dbs()) {
1333 int goip_type
= geoip_db_type(i
- NUM_BUILTIN_COLS
);
1334 if (goip_type
== WS_LON_FAKE_EDITION
|| goip_type
== WS_LAT_FAKE_EDITION
) {
1335 g_object_set(G_OBJECT(renderer
), "xalign", 1.0, NULL
);
1336 gtk_tree_sortable_set_sort_func(sortable
, i
, hostlist_sort_column
, GINT_TO_POINTER(i
), NULL
);
1342 gtk_tree_view_column_set_sort_column_id(column
, i
);
1343 gtk_tree_view_column_set_resizable(column
, TRUE
);
1344 gtk_tree_view_column_set_reorderable(column
, TRUE
);
1345 gtk_tree_view_column_set_min_width(column
, 40);
1346 gtk_tree_view_column_set_fixed_width(column
, default_col_size
[i
]);
1347 gtk_tree_view_append_column (hosttable
->table
, column
);
1350 /* make total frames be the default sort order, too slow */
1351 if (i
== PACKETS_COLUMN
) {
1352 gtk_tree_view_column_clicked(column
);
1357 gtk_container_add(GTK_CONTAINER(hosttable
->scrolled_window
), (GtkWidget
*)hosttable
->table
);
1359 hosttable
->num_hosts
=0;
1360 hosttable
->hosts
=NULL
;
1361 hosttable
->hashtable
=NULL
;
1363 gtk_tree_view_set_rules_hint(hosttable
->table
, TRUE
);
1364 gtk_tree_view_set_headers_clickable(hosttable
->table
, TRUE
);
1365 gtk_tree_view_set_reorderable (hosttable
->table
, TRUE
);
1367 sel
= gtk_tree_view_get_selection(GTK_TREE_VIEW(hosttable
->table
));
1368 gtk_tree_selection_set_mode(sel
, GTK_SELECTION_SINGLE
);
1370 /* create popup menu for this table */
1371 hostlist_create_popup_menu(hosttable
);
1373 /* register the tap and rerun the taps on the packet list */
1374 error_string
=register_tap_listener(tap_name
, hosttable
, filter
, 0, reset_hostlist_table_data_cb
, packet_func
, draw_hostlist_table_data_cb
);
1376 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
, "%s", error_string
->str
);
1377 g_string_free(error_string
, TRUE
);
1386 init_hostlist_table(gboolean hide_ports
, const char *table_name
, const char *tap_name
, const char *filter
, tap_packet_cb packet_func
)
1388 hostlist_table
*hosttable
;
1393 GtkWidget
*close_bt
, *help_bt
;
1399 window_geometry_t tl_geom
;
1401 hosttable
=g_new(hostlist_table
,1);
1403 hosttable
->name
=table_name
;
1404 hosttable
->filter
=filter
;
1405 hosttable
->use_dfilter
=FALSE
;
1406 display_name
= cf_get_display_name(&cfile
);
1407 g_snprintf(title
, sizeof(title
), "%s Endpoints: %s", table_name
, display_name
);
1408 g_free(display_name
);
1409 hosttable
->win
= dlg_window_new(title
); /* transient_for top_level */
1410 gtk_window_set_destroy_with_parent (GTK_WINDOW(hosttable
->win
), TRUE
);
1412 window_get_geometry(top_level
, &tl_geom
);
1413 gtk_window_set_default_size(GTK_WINDOW(hosttable
->win
), tl_geom
.width
* 8 / 10, HL_DLG_HEIGHT
);
1415 vbox
=ws_gtk_box_new(GTK_ORIENTATION_VERTICAL
, DLG_LABEL_SPACING
, FALSE
);
1416 gtk_container_add(GTK_CONTAINER(hosttable
->win
), vbox
);
1417 gtk_container_set_border_width(GTK_CONTAINER(vbox
), DLG_OUTER_MARGIN
);
1419 ret
= init_hostlist_table_page(hosttable
, vbox
, hide_ports
, table_name
, tap_name
, filter
, packet_func
);
1426 /* XXX - maybe we want to have a "Copy as CSV" stock button here? */
1427 /*copy_bt = gtk_button_new_with_label ("Copy content to clipboard as CSV");*/
1429 if( strstr(table_name
, "IPv4") || strstr(table_name
, "IPv6") ) {
1430 bbox
= dlg_button_row_new(GTK_STOCK_CLOSE
, GTK_STOCK_COPY
, WIRESHARK_STOCK_MAP
, GTK_STOCK_HELP
, NULL
);
1432 bbox
= dlg_button_row_new(GTK_STOCK_CLOSE
, GTK_STOCK_COPY
, GTK_STOCK_HELP
, NULL
);
1435 bbox
= dlg_button_row_new(GTK_STOCK_CLOSE
, GTK_STOCK_COPY
, GTK_STOCK_HELP
, NULL
);
1438 gtk_box_pack_end(GTK_BOX(vbox
), bbox
, FALSE
, FALSE
, 0);
1440 close_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_CLOSE
);
1441 window_set_cancel_button(hosttable
->win
, close_bt
, window_cancel_button_cb
);
1443 copy_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_COPY
);
1444 gtk_widget_set_tooltip_text(copy_bt
, "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.");
1445 g_object_set_data(G_OBJECT(copy_bt
), HOST_PTR_KEY
, hosttable
);
1446 g_signal_connect(copy_bt
, "clicked", G_CALLBACK(copy_as_csv_cb
), NULL
);
1449 map_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), WIRESHARK_STOCK_MAP
);
1450 if(map_bt
!= NULL
) {
1451 gtk_widget_set_tooltip_text(map_bt
, "Show a map of the IP addresses (internet connection required).");
1452 g_object_set_data(G_OBJECT(map_bt
), HOST_PTR_KEY
, hosttable
);
1453 g_signal_connect(map_bt
, "clicked", G_CALLBACK(open_as_map_cb
), NULL
);
1455 #endif /* HAVE_GEOIP */
1457 help_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_HELP
);
1458 g_signal_connect(help_bt
, "clicked", G_CALLBACK(topic_cb
), (gpointer
)HELP_STATS_ENDPOINTS_DIALOG
);
1460 g_signal_connect(hosttable
->win
, "delete_event", G_CALLBACK(window_delete_event_cb
), NULL
);
1461 g_signal_connect(hosttable
->win
, "destroy", G_CALLBACK(hostlist_win_destroy_cb
), hosttable
);
1463 gtk_widget_show_all(hosttable
->win
);
1464 window_present(hosttable
->win
);
1466 cf_retap_packets(&cfile
);
1467 gdk_window_raise(gtk_widget_get_window(hosttable
->win
));
1472 ct_nb_switch_page_cb(GtkNotebook
*nb
, gpointer
*pg _U_
, guint page
, gpointer data
)
1474 GtkWidget
*copy_bt
= (GtkWidget
*) data
;
1475 void ** pages
= (void **)g_object_get_data(G_OBJECT(nb
), NB_PAGES_KEY
);
1479 if (pages
&& page
> 0 && (int) page
<= GPOINTER_TO_INT(pages
[0]) && copy_bt
) {
1480 g_object_set_data(G_OBJECT(copy_bt
), HOST_PTR_KEY
, pages
[page
]);
1486 ct_nb_map_switch_page_cb(GtkNotebook
*nb
, gpointer
*pg _U_
, guint page
, gpointer data
)
1488 GtkWidget
*map_bt
= (GtkWidget
*) data
;
1489 void ** pages
= (void **)g_object_get_data(G_OBJECT(nb
), NB_PAGES_KEY
);
1493 if (pages
&& page
> 0 && (int) page
<= GPOINTER_TO_INT(pages
[0]) && map_bt
) {
1494 g_object_set_data(G_OBJECT(map_bt
), HOST_PTR_KEY
, pages
[page
]);
1495 if( strstr(((hostlist_table
*)pages
[page
])->name
, "IPv4") ||
1496 strstr(((hostlist_table
*)pages
[page
])->name
, "IPv6") ) {
1497 gtk_widget_set_sensitive(map_bt
, TRUE
);
1499 gtk_widget_set_sensitive(map_bt
, FALSE
);
1503 #endif /* HAVE_GEOIP */
1507 hostlist_win_destroy_notebook_cb(GtkWindow
*win _U_
, gpointer data
)
1509 void ** pages
= (void **)data
;
1512 /* first "page" contains the number of pages */
1513 for (page
=1; page
<=GPOINTER_TO_INT(pages
[0]); page
++) {
1514 hostlist_win_destroy_cb(NULL
, pages
[page
]);
1522 static hostlist_table
*
1523 init_hostlist_notebook_page_cb(gboolean hide_ports
, const char *table_name
, const char *tap_name
, const char *filter
,
1524 tap_packet_cb packet_func
)
1527 GtkWidget
*page_vbox
;
1528 hostlist_table
*hosttable
;
1530 hosttable
=g_new(hostlist_table
,1);
1531 hosttable
->name
=table_name
;
1532 hosttable
->filter
=filter
;
1533 hosttable
->use_dfilter
=FALSE
;
1535 page_vbox
=ws_gtk_box_new(GTK_ORIENTATION_VERTICAL
, 6, FALSE
);
1536 hosttable
->win
= page_vbox
;
1537 gtk_container_set_border_width(GTK_CONTAINER(page_vbox
), 6);
1539 ret
= init_hostlist_table_page(hosttable
, page_vbox
, hide_ports
, table_name
, tap_name
, filter
, packet_func
);
1550 gboolean hide_ports
; /* hide TCP / UDP port columns */
1551 const char *table_name
; /* GUI output name */
1552 const char *tap_name
; /* internal name */
1553 const char *filter
; /* display filter string (unused) */
1554 tap_packet_cb packet_func
; /* function to be called for new incoming packets */
1555 } register_hostlist_t
;
1558 static GSList
*registered_hostlist_tables
= NULL
;
1561 register_hostlist_table(gboolean hide_ports
, const char *table_name
, const char *tap_name
, const char *filter
, tap_packet_cb packet_func
)
1563 register_hostlist_t
*table
;
1565 table
= g_new(register_hostlist_t
,1);
1567 table
->hide_ports
= hide_ports
;
1568 table
->table_name
= table_name
;
1569 table
->tap_name
= tap_name
;
1570 table
->filter
= filter
;
1571 table
->packet_func
= packet_func
;
1573 registered_hostlist_tables
= g_slist_append(registered_hostlist_tables
, table
);
1578 hostlist_resolve_toggle_dest(GtkWidget
*widget
, gpointer data
)
1581 void ** pages
= (void **)data
;
1582 gboolean resolve_names
;
1583 hostlist_table
*hosttable
;
1586 resolve_names
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget
));
1588 for (page
=1; page
<=GPOINTER_TO_INT(pages
[0]); page
++) {
1589 hosttable
= (hostlist_table
*)pages
[page
];
1590 hosttable
->resolve_names
= resolve_names
;
1591 draw_hostlist_table_addresses(hosttable
);
1597 hostlist_filter_toggle_dest(GtkWidget
*widget
, gpointer data
)
1600 void ** pages
= (void **)data
;
1601 gboolean use_filter
;
1602 hostlist_table
*hosttable
= NULL
;
1604 use_filter
= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget
));
1606 for (page
=1; page
<=GPOINTER_TO_INT(pages
[0]); page
++) {
1607 hosttable
= (hostlist_table
*)pages
[page
];
1608 hosttable
->use_dfilter
= use_filter
;
1609 reset_hostlist_table_data(hosttable
);
1612 cf_retap_packets(&cfile
);
1614 gdk_window_raise(gtk_widget_get_window(hosttable
->win
));
1620 init_hostlist_notebook_cb(GtkWidget
*w _U_
, gpointer d _U_
)
1622 hostlist_table
*hosttable
;
1628 GtkWidget
*close_bt
, *help_bt
;
1630 GtkWidget
*resolv_cb
;
1631 GtkWidget
*filter_cb
;
1636 GSList
*current_table
;
1637 register_hostlist_t
*registered
;
1642 window_geometry_t tl_geom
;
1644 pages
= (void **)g_malloc(sizeof(void *) * (g_slist_length(registered_hostlist_tables
) + 1));
1646 win
= dlg_window_new("hostlist"); /* transient_for top_level */
1647 gtk_window_set_destroy_with_parent (GTK_WINDOW(win
), TRUE
);
1649 display_name
= cf_get_display_name(&cfile
);
1650 g_snprintf(title
, sizeof(title
), "Endpoints: %s", display_name
);
1651 g_free(display_name
);
1652 gtk_window_set_title(GTK_WINDOW(win
), title
);
1654 window_get_geometry(top_level
, &tl_geom
);
1655 gtk_window_set_default_size(GTK_WINDOW(win
), tl_geom
.width
* 8 / 10, HL_DLG_HEIGHT
);
1657 vbox
=ws_gtk_box_new(GTK_ORIENTATION_VERTICAL
, DLG_LABEL_SPACING
, FALSE
);
1658 gtk_container_add(GTK_CONTAINER(win
), vbox
);
1659 gtk_container_set_border_width(GTK_CONTAINER(vbox
), DLG_OUTER_MARGIN
);
1661 nb
= gtk_notebook_new();
1662 gtk_box_pack_start(GTK_BOX(vbox
), nb
, TRUE
, TRUE
, 0);
1663 g_object_set_data(G_OBJECT(nb
), NB_PAGES_KEY
, pages
);
1667 current_table
= registered_hostlist_tables
;
1668 while(current_table
) {
1669 registered
= (register_hostlist_t
*)current_table
->data
;
1670 page_lb
= gtk_label_new("");
1671 hosttable
= init_hostlist_notebook_page_cb(registered
->hide_ports
, registered
->table_name
, registered
->tap_name
,
1672 registered
->filter
, registered
->packet_func
);
1673 g_object_set_data(G_OBJECT(hosttable
->win
), HOST_PTR_KEY
, hosttable
);
1674 gtk_notebook_append_page(GTK_NOTEBOOK(nb
), hosttable
->win
, page_lb
);
1675 hosttable
->win
= win
;
1676 hosttable
->page_lb
= page_lb
;
1677 pages
[++page
] = hosttable
;
1679 current_table
= g_slist_next(current_table
);
1682 pages
[0] = GINT_TO_POINTER(page
);
1684 hbox
= ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL
, DLG_UNRELATED_SPACING
, FALSE
);
1685 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
1687 resolv_cb
= gtk_check_button_new_with_mnemonic("Name resolution");
1688 gtk_box_pack_start(GTK_BOX(hbox
), resolv_cb
, FALSE
, FALSE
, 0);
1689 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(resolv_cb
), TRUE
);
1690 gtk_widget_set_tooltip_text(resolv_cb
,
1691 "Show results of name resolutions rather than the \"raw\" values. Please note: The corresponding name resolution must be enabled.");
1693 g_signal_connect(resolv_cb
, "toggled", G_CALLBACK(hostlist_resolve_toggle_dest
), pages
);
1695 filter_cb
= gtk_check_button_new_with_mnemonic("Limit to display filter");
1696 gtk_box_pack_start(GTK_BOX(hbox
), filter_cb
, FALSE
, FALSE
, 0);
1697 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_cb
), FALSE
);
1698 gtk_widget_set_tooltip_text(filter_cb
, "Limit the list to endpoints matching the current display filter.");
1700 g_signal_connect(filter_cb
, "toggled", G_CALLBACK(hostlist_filter_toggle_dest
), pages
);
1704 bbox
= dlg_button_row_new(GTK_STOCK_CLOSE
, GTK_STOCK_COPY
, WIRESHARK_STOCK_MAP
, GTK_STOCK_HELP
, NULL
);
1706 bbox
= dlg_button_row_new(GTK_STOCK_CLOSE
, GTK_STOCK_COPY
, GTK_STOCK_HELP
, NULL
);
1708 gtk_box_pack_end(GTK_BOX(vbox
), bbox
, FALSE
, FALSE
, 0);
1710 close_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_CLOSE
);
1711 window_set_cancel_button(win
, close_bt
, window_cancel_button_cb
);
1713 copy_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_COPY
);
1714 gtk_widget_set_tooltip_text(copy_bt
, "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.");
1715 g_signal_connect(copy_bt
, "clicked", G_CALLBACK(copy_as_csv_cb
), NULL
);
1716 g_object_set_data(G_OBJECT(copy_bt
), HOST_PTR_KEY
, pages
[page
]);
1719 map_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), WIRESHARK_STOCK_MAP
);
1720 gtk_widget_set_tooltip_text(map_bt
, "Show a map of the IP addresses (internet connection required).");
1721 g_object_set_data(G_OBJECT(map_bt
), HOST_PTR_KEY
, pages
[page
]);
1722 g_signal_connect(map_bt
, "clicked", G_CALLBACK(open_as_map_cb
), NULL
);
1723 g_signal_connect(nb
, "switch-page", G_CALLBACK(ct_nb_map_switch_page_cb
), map_bt
);
1724 gtk_widget_set_sensitive(map_bt
, FALSE
);
1725 #endif /* HAVE_GEOIP */
1727 g_signal_connect(nb
, "switch-page", G_CALLBACK(ct_nb_switch_page_cb
), copy_bt
);
1729 help_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_HELP
);
1730 g_signal_connect(help_bt
, "clicked", G_CALLBACK(topic_cb
), (gpointer
)HELP_STATS_ENDPOINTS_DIALOG
);
1732 g_signal_connect(win
, "delete_event", G_CALLBACK(window_delete_event_cb
), NULL
);
1733 g_signal_connect(win
, "destroy", G_CALLBACK(hostlist_win_destroy_notebook_cb
), pages
);
1735 gtk_widget_show_all(win
);
1736 window_present(win
);
1738 cf_retap_packets(&cfile
);
1739 gdk_window_raise(gtk_widget_get_window(win
));
1743 * Compute the hash value for a given address/port pairs if the match
1752 host_hash(gconstpointer v
)
1754 const host_key_t
*key
= (const host_key_t
*)v
;
1758 ADD_ADDRESS_TO_HASH(hash_val
, &key
->myaddress
);
1759 hash_val
+= key
->port
;
1764 * Compare two host keys for an exact match.
1767 host_match(gconstpointer v
, gconstpointer w
)
1769 const host_key_t
*v1
= (const host_key_t
*)v
;
1770 const host_key_t
*v2
= (const host_key_t
*)w
;
1772 if (v1
->port
== v2
->port
&&
1773 ADDRESSES_EQUAL(&v1
->myaddress
, &v2
->myaddress
)) {
1777 * The addresses or the ports don't match.
1783 add_hostlist_table_data(hostlist_table
*hl
, const address
*addr
, guint32 port
, gboolean sender
, int num_frames
, int num_bytes
, SAT_E sat
, int port_type_val
)
1785 hostlist_talker_t
*talker
=NULL
;
1788 /* XXX should be optimized to allocate n extra entries at a time
1789 instead of just one */
1790 /* if we dont have any entries at all yet */
1791 if(hl
->hosts
==NULL
){
1792 hl
->hosts
=g_array_sized_new(FALSE
, FALSE
, sizeof(hostlist_talker_t
), 10000);
1793 hl
->hashtable
= g_hash_table_new_full(host_hash
,
1794 host_match
, /* key_equal_func */
1795 g_free
, /* key_destroy_func */
1796 NULL
); /* value_destroy_func */
1799 /* try to find it among the existing known conversations */
1800 host_key_t existing_key
;
1802 existing_key
.myaddress
= *addr
;
1803 existing_key
.port
= port
;
1804 talker_idx
= GPOINTER_TO_UINT(g_hash_table_lookup(hl
->hashtable
, &existing_key
));
1807 talker
=&g_array_index(hl
->hosts
, hostlist_talker_t
, talker_idx
);
1811 /* if we still dont know what talker this is it has to be a new one
1812 and we have to allocate it and append it to the end of the list */
1814 host_key_t
*new_key
;
1815 hostlist_talker_t host
;
1817 COPY_ADDRESS(&host
.myaddress
, addr
);
1819 host
.port_type
=port_type_val
;
1825 host
.iter_valid
= FALSE
;
1826 host
.modified
= TRUE
;
1828 g_array_append_val(hl
->hosts
, host
);
1829 talker_idx
= hl
->num_hosts
;
1830 talker
=&g_array_index(hl
->hosts
, hostlist_talker_t
, talker_idx
);
1832 /* hl->hosts address is not a constant but address.data is */
1833 new_key
= g_new(host_key_t
,1);
1834 SET_ADDRESS(&new_key
->myaddress
, talker
->myaddress
.type
, talker
->myaddress
.len
, talker
->myaddress
.data
);
1835 new_key
->port
= port
;
1836 g_hash_table_insert(hl
->hashtable
, new_key
, GUINT_TO_POINTER(talker_idx
+1));
1840 /* if this is a new talker we need to initialize the struct */
1841 talker
->modified
= TRUE
;
1843 /* update the talker struct */
1845 talker
->tx_frames
+=num_frames
;
1846 talker
->tx_bytes
+=num_bytes
;
1848 talker
->rx_frames
+=num_frames
;
1849 talker
->rx_bytes
+=num_bytes
;
1859 * indent-tabs-mode: nil
1862 * ex: set shiftwidth=4 tabstop=8 expandtab:
1863 * :indentSize=4:tabSize=8:noTabs=true: