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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 #include <epan/packet_info.h>
38 #include <epan/to_str.h>
39 #include <epan/addr_resolv.h>
41 #include <epan/strutil.h>
43 #include <epan/geoip_db.h>
44 #include <epan/pint.h>
45 #include <epan/filesystem.h>
48 #include <wsutil/file_util.h>
50 #include "../simple_dialog.h"
51 #include "../globals.h"
53 #include "../alert_box.h"
55 #include "gtk/hostlist_table.h"
56 #include "gtk/filter_utils.h"
57 #include "gtk/gtkglobals.h"
59 #include "gtk/gui_utils.h"
60 #include "gtk/dlg_utils.h"
61 #include "gtk/help_dlg.h"
64 #include "gtk/webbrowser.h"
65 #include "gtk/stock_icons.h"
68 #include "image/clist_ascend.xpm"
69 #include "image/clist_descend.xpm"
72 #define HOST_PTR_KEY "hostlist-pointer"
73 #define NB_PAGES_KEY "notebook-pages"
75 #define COL_STR_LEN 32
77 /* convert a port number into a string */
79 hostlist_port_to_str(int port_type, guint32 port)
82 static gchar str[4][12];
89 g_snprintf(str[i], sizeof(str[0]), "%d", port);
96 #define FN_ANY_ADDRESS 0
99 /* given an address (to distinguish between ipv4 and ipv6 for tcp/udp
100 a port_type and a name_type (FN_...)
101 return a string for the filter name
103 some addresses, like AT_ETHER may actually be any of multiple types
104 of protocols, either ethernet, tokenring, fddi etc so we must be more
105 specific there thats why we need specific_addr_type
108 hostlist_get_filter_name(address *addr, int specific_addr_type, int port_type, int name_type)
114 switch(specific_addr_type){
136 switch(specific_addr_type){
138 return "jxta.message.address";
160 g_assert_not_reached();
165 typedef struct column_arrows {
167 GtkWidget *ascend_pm;
168 GtkWidget *descend_pm;
173 reset_hostlist_table_data(hostlist_table *hosts)
177 GString *error_string;
180 if (hosts->use_dfilter) {
181 filter = gtk_entry_get_text(GTK_ENTRY(main_display_filter_widget));
183 filter = hosts->filter;
185 error_string = set_tap_dfilter (hosts, filter);
187 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
188 g_string_free(error_string, TRUE);
192 /* Allow clist to update */
193 gtk_clist_thaw(hosts->table);
196 g_snprintf(title, sizeof(title), "Endpoints: %s", cf_get_display_name(&cfile));
197 gtk_window_set_title(GTK_WINDOW(hosts->win), title);
198 g_snprintf(title, sizeof(title), "%s", hosts->name);
199 gtk_label_set_text(GTK_LABEL(hosts->page_lb), title);
200 gtk_widget_set_sensitive(hosts->page_lb, FALSE);
202 if (hosts->use_dfilter) {
203 if (filter && strlen(filter)) {
204 g_snprintf(title, sizeof(title), "%s Endpoints - Filter: %s", hosts->name, filter);
206 g_snprintf(title, sizeof(title), "%s Endpoints - No Filter", hosts->name);
209 g_snprintf(title, sizeof(title), "%s Endpoints", hosts->name);
211 gtk_label_set_text(GTK_LABEL(hosts->name_lb), title);
213 g_snprintf(title, sizeof(title), "%s Endpoints: %s", hosts->name, cf_get_display_name(&cfile));
214 gtk_window_set_title(GTK_WINDOW(hosts->win), title);
217 /* remove all entries from the clist */
218 gtk_clist_clear(hosts->table);
220 /* delete all hosts */
221 for(i=0;i<hosts->num_hosts;i++){
222 g_free((gpointer)hosts->hosts[i].address.data);
224 g_free(hosts->hosts);
230 reset_hostlist_table_data_cb(void *arg)
232 reset_hostlist_table_data(arg);
236 hostlist_win_destroy_cb(GtkWindow *win _U_, gpointer data)
238 hostlist_table *hosts=(hostlist_table *)data;
240 protect_thread_critical_region();
241 remove_tap_listener(hosts);
242 unprotect_thread_critical_region();
244 reset_hostlist_table_data(hosts);
249 hostlist_sort_column(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
255 const GtkCListRow *row1 = ptr1;
256 const GtkCListRow *row2 = ptr2;
258 text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
259 text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
261 if (clist->sort_column >= 2 && clist->sort_column <= 7) { /* Integers */
262 sscanf(text1, "%" G_GINT64_MODIFIER "u", &i1);
263 sscanf(text2, "%" G_GINT64_MODIFIER "u", &i2);
266 } else if (i1 < i2) {
271 } else { /* Strings */
272 return strcmp (text1, text2);
274 g_assert_not_reached();
276 /* Allow clist to redraw */
278 gtk_clist_thaw(clist);
279 gtk_clist_freeze(clist);
285 hostlist_click_column_cb(GtkCList *clist, gint column, gpointer data)
287 column_arrows *col_arrows = (column_arrows *) data;
290 for (i = 0; i < NUM_HOSTLIST_COLS; i++) {
291 gtk_widget_hide(col_arrows[i].ascend_pm);
292 gtk_widget_hide(col_arrows[i].descend_pm);
295 if (column == clist->sort_column) {
296 if (clist->sort_type == GTK_SORT_ASCENDING) {
297 clist->sort_type = GTK_SORT_DESCENDING;
298 gtk_widget_show(col_arrows[column].descend_pm);
300 clist->sort_type = GTK_SORT_ASCENDING;
301 gtk_widget_show(col_arrows[column].ascend_pm);
304 clist->sort_type = GTK_SORT_DESCENDING;
305 gtk_widget_show(col_arrows[column].descend_pm);
306 gtk_clist_set_sort_column(clist, column);
309 gtk_clist_sort(clist);
311 /* Allow update of clist */
312 gtk_clist_thaw(clist);
313 gtk_clist_freeze(clist);
317 hostlist_select_filter_cb(GtkWidget *widget _U_, gpointer callback_data, guint callback_action)
320 hostlist_table *hl=(hostlist_table *)callback_data;
324 selection=GPOINTER_TO_INT(g_list_nth_data(GTK_CLIST(hl->table)->selection, 0));
325 if(selection>=(int)hl->num_hosts){
326 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No hostlist selected");
329 /* translate it back from row index to index in hostlist array */
330 selection=GPOINTER_TO_INT(gtk_clist_get_row_data(hl->table, selection));
332 sport=hostlist_port_to_str(hl->hosts[selection].port_type, hl->hosts[selection].port);
334 str = g_strdup_printf("%s==%s%s%s%s%s",
335 hostlist_get_filter_name(&hl->hosts[selection].address,
336 hl->hosts[selection].sat, hl->hosts[selection].port_type, FN_ANY_ADDRESS),
337 address_to_str(&hl->hosts[selection].address),
339 sport?hostlist_get_filter_name(&hl->hosts[selection].address, hl->hosts[selection].sat, hl->hosts[selection].port_type, FN_ANY_PORT):"",
343 apply_selected_filter (callback_action, str);
348 hostlist_show_popup_menu_cb(void *widg _U_, GdkEvent *event, hostlist_table *et)
350 GdkEventButton *bevent = (GdkEventButton *)event;
354 /* To qoute the "Gdk Event Structures" doc:
355 * "Normally button 1 is the left mouse button, 2 is the middle button, and 3 is the right button" */
356 if(event->type==GDK_BUTTON_PRESS && bevent->button==3){
357 /* if this is a right click on one of our columns, select it and popup the context menu */
358 if(gtk_clist_get_selection_info(et->table,
359 (gint) (((GdkEventButton *)event)->x),
360 (gint) (((GdkEventButton *)event)->y),
362 gtk_clist_unselect_all(et->table);
363 gtk_clist_select_row(et->table, row, -1);
365 gtk_menu_popup(GTK_MENU(et->menu), NULL, NULL, NULL, NULL,
366 bevent->button, bevent->time);
373 static GtkItemFactoryEntry hostlist_list_menu_items[] =
376 {"/Apply as Filter", NULL, NULL, 0, "<Branch>", NULL,},
377 {"/Apply as Filter/Selected", NULL,
378 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_MATCH(ACTYPE_SELECTED, 0), NULL, NULL,},
379 {"/Apply as Filter/Not Selected", NULL,
380 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_MATCH(ACTYPE_NOT_SELECTED, 0), NULL, NULL,},
381 {"/Apply as Filter/... and Selected", NULL,
382 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_SELECTED, 0), NULL, NULL,},
383 {"/Apply as Filter/... or Selected", NULL,
384 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_SELECTED, 0), NULL, NULL,},
385 {"/Apply as Filter/... and not Selected", NULL,
386 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_MATCH(ACTYPE_AND_NOT_SELECTED, 0), NULL, NULL,},
387 {"/Apply as Filter/... or not Selected", NULL,
388 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_MATCH(ACTYPE_OR_NOT_SELECTED, 0), NULL, NULL,},
391 {"/Prepare a Filter", NULL, NULL, 0, "<Branch>", NULL,},
392 {"/Prepare a Filter/Selected", NULL,
393 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_PREPARE(ACTYPE_SELECTED, 0), NULL, NULL,},
394 {"/Prepare a Filter/Not Selected", NULL,
395 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_PREPARE(ACTYPE_NOT_SELECTED, 0), NULL, NULL,},
396 {"/Prepare a Filter/... and Selected", NULL,
397 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_SELECTED, 0), NULL, NULL,},
398 {"/Prepare a Filter/... or Selected", NULL,
399 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_SELECTED, 0), NULL, NULL,},
400 {"/Prepare a Filter/... and not Selected", NULL,
401 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_PREPARE(ACTYPE_AND_NOT_SELECTED, 0), NULL, NULL,},
402 {"/Prepare a Filter/... or not Selected", NULL,
403 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_PREPARE(ACTYPE_OR_NOT_SELECTED, 0), NULL, NULL,},
406 {"/Find Frame", NULL, NULL, 0, "<Branch>", NULL,},
407 {"/Find Frame/Find Frame", NULL,
408 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_FIND_FRAME(ACTYPE_SELECTED, 0), NULL, NULL,},
410 {"/Find Frame/Find Next", NULL,
411 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_FIND_NEXT(ACTYPE_SELECTED, 0), NULL, NULL,},
413 {"/Find Frame/Find Previous", NULL,
414 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_FIND_PREVIOUS(ACTYPE_SELECTED, 0), NULL, NULL,},
416 /* Colorize Host Traffic */
417 {"/Colorize Host Traffic", NULL,
418 GTK_MENU_FUNC(hostlist_select_filter_cb), CALLBACK_COLORIZE(ACTYPE_SELECTED, 0), NULL, NULL,}
423 hostlist_create_popup_menu(hostlist_table *hl)
425 GtkItemFactory *item_factory;
427 item_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
429 gtk_item_factory_create_items_ac(item_factory, sizeof(hostlist_list_menu_items)/sizeof(hostlist_list_menu_items[0]), hostlist_list_menu_items, hl, 2);
431 hl->menu = gtk_item_factory_get_widget(item_factory, "<main>");
432 g_signal_connect(hl->table, "button_press_event", G_CALLBACK(hostlist_show_popup_menu_cb), hl);
436 /* Draw/refresh the address field of a single entry at the specified index */
438 draw_hostlist_table_address(hostlist_table *hl, int hostlist_idx)
445 rownum=gtk_clist_find_row_from_data(hl->table, (gpointer)(long)hostlist_idx);
447 if (!hl->resolve_names)
448 entry=address_to_str(&hl->hosts[hostlist_idx].address);
450 entry=get_addr_name(&hl->hosts[hostlist_idx].address);
452 gtk_clist_set_text(hl->table, rownum, 0, entry);
454 pt = hl->hosts[hostlist_idx].port_type;
455 if(!hl->resolve_names) pt = PT_NONE;
458 entry=get_tcp_port(hl->hosts[hostlist_idx].port);
461 entry=get_udp_port(hl->hosts[hostlist_idx].port);
464 entry=get_sctp_port(hl->hosts[hostlist_idx].port);
467 port=hostlist_port_to_str(hl->hosts[hostlist_idx].port_type, hl->hosts[hostlist_idx].port);
470 gtk_clist_set_text(hl->table, rownum, 1, entry);
473 /* Refresh the address fields of all entries in the list */
475 draw_hostlist_table_addresses(hostlist_table *hl)
479 for(i=0;i<hl->num_hosts;i++){
480 draw_hostlist_table_address(hl, i);
486 draw_hostlist_table_data(hostlist_table *hl)
494 g_snprintf(title, sizeof(title), "%s: %u", hl->name, hl->num_hosts);
496 g_snprintf(title, sizeof(title), "%s", hl->name);
498 gtk_label_set_text(GTK_LABEL(hl->page_lb), title);
499 gtk_widget_set_sensitive(hl->page_lb, hl->num_hosts);
502 g_snprintf(title, sizeof(title), "%s Endpoints: %u", hl->name, hl->num_hosts);
504 g_snprintf(title, sizeof(title), "%s Endpoints", hl->name);
506 gtk_label_set_text(GTK_LABEL(hl->name_lb), title);
509 for(i=0;i<hl->num_hosts;i++){
510 char str[COL_STR_LEN];
512 j=gtk_clist_find_row_from_data(hl->table, (gpointer)(unsigned long)i);
514 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", hl->hosts[i].tx_frames+hl->hosts[i].rx_frames);
515 gtk_clist_set_text(hl->table, j, 2, str);
516 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", hl->hosts[i].tx_bytes+hl->hosts[i].rx_bytes);
517 gtk_clist_set_text(hl->table, j, 3, str);
520 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", hl->hosts[i].tx_frames);
521 gtk_clist_set_text(hl->table, j, 4, str);
522 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", hl->hosts[i].tx_bytes);
523 gtk_clist_set_text(hl->table, j, 5, str);
526 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", hl->hosts[i].rx_frames);
527 gtk_clist_set_text(hl->table, j, 6, str);
528 g_snprintf(str, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", hl->hosts[i].rx_bytes);
529 gtk_clist_set_text(hl->table, j, 7, str);
533 draw_hostlist_table_addresses(hl);
535 gtk_clist_sort(hl->table);
537 /* Allow table to redraw. */
538 gtk_clist_thaw(hl->table);
539 gtk_clist_freeze(hl->table);
543 draw_hostlist_table_data_cb(void *arg)
545 draw_hostlist_table_data(arg);
549 copy_as_csv_cb(GtkWindow *copy_bt, gpointer data _U_)
554 GString *CSV_str = g_string_new("");
556 hostlist_table *hosts=g_object_get_data(G_OBJECT(copy_bt), HOST_PTR_KEY);
560 /* Add the column headers to the CSV data */
561 for(i=0;i<hosts->num_columns;i++){ /* all columns */
562 if(i==1 && !hosts->has_ports) continue; /* Don't add the port column if it's empty */
563 g_string_append(CSV_str,hosts->default_titles[i]);/* add the column heading to the CSV string */
564 if(i!=hosts->num_columns-1)
565 g_string_append(CSV_str,",");
567 g_string_append(CSV_str,"\n"); /* new row */
569 /* Add the column values to the CSV data */
570 for(i=0;i<hosts->num_hosts;i++){ /* all rows */
571 for(j=0;j<hosts->num_columns;j++){ /* all columns */
572 if(j==1 && !hosts->has_ports) continue; /* Don't add the port column if it's empty */
573 gtk_clist_get_text(hosts->table,i,j,&table_entry);/* copy table item into string */
574 g_string_append(CSV_str,table_entry); /* add the table entry to the CSV string */
575 if(j!=hosts->num_columns-1)
576 g_string_append(CSV_str,",");
578 g_string_append(CSV_str,"\n"); /* new row */
581 /* Now that we have the CSV data, copy it into the default clipboard */
582 cb = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); /* Get the default clipboard */
583 gtk_clipboard_set_text(cb, CSV_str->str, -1); /* Copy the CSV data into the clipboard */
584 g_string_free(CSV_str, TRUE); /* Free the memory */
589 open_as_map_cb(GtkWindow *copy_bt, gpointer data _U_)
593 gint32 col_lat, col_lon, col_country, col_city, col_as_num, col_ip, col_packets, col_bytes;
599 hostlist_table *hosts=g_object_get_data(G_OBJECT(copy_bt), HOST_PTR_KEY);
603 col_lat = col_lon = col_country = col_city = col_as_num = col_ip = col_packets = col_bytes = -1;
605 /* Find the interesting columns */
606 for(i=0;i<hosts->num_columns;i++){
607 if(strcmp(hosts->default_titles[i], "Latitude") == 0) {
610 if(strcmp(hosts->default_titles[i], "Longitude") == 0) {
613 if(strcmp(hosts->default_titles[i], "Country") == 0) {
616 if(strcmp(hosts->default_titles[i], "City") == 0) {
619 if(strcmp(hosts->default_titles[i], "AS Number") == 0) {
622 if(strcmp(hosts->default_titles[i], "Address") == 0) {
625 if(strcmp(hosts->default_titles[i], "Packets") == 0) {
628 if(strcmp(hosts->default_titles[i], "Bytes") == 0) {
633 /* check for the minimum required data */
634 if(col_lat == -1 || col_lon == -1) {
635 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Latitude/Longitude data not available (GeoIP installed?)");
639 /* open the TSV output file */
640 /* XXX - add error handling */
641 file_path = get_tempfile_path("ipmap.txt");
642 out_file = ws_fopen(file_path, "w+b");
643 if(out_file == NULL) {
644 open_failure_alert_box(file_path, errno, TRUE);
650 fputs("lat\tlon\ttitle\tdescription\t\n", out_file);
652 /* Add the column values to the TSV data */
653 for(i=0;i<hosts->num_hosts;i++){ /* all rows */
654 /* check, if we have a geolocation available for this host */
655 gtk_clist_get_text(hosts->table,i,col_lat,&table_entry);
656 if(strcmp(table_entry, "-") == 0) {
659 gtk_clist_get_text(hosts->table,i,col_lon,&table_entry);
660 if(strcmp(table_entry, "-") == 0) {
665 gtk_clist_get_text(hosts->table,i,col_lat,&table_entry);
666 fputs(table_entry, out_file);
667 fputs("\t", out_file);
670 gtk_clist_get_text(hosts->table,i,col_lon,&table_entry);
671 fputs(table_entry, out_file);
672 fputs("\t", out_file);
675 gtk_clist_get_text(hosts->table,i,col_ip,&table_entry);
676 fputs(table_entry, out_file);
677 fputs("\t", out_file);
680 gtk_clist_get_text(hosts->table,i,col_as_num,&table_entry);
681 fputs("AS: ", out_file);
682 fputs(table_entry, out_file);
683 fputs("<br/>", out_file);
685 gtk_clist_get_text(hosts->table,i,col_country,&table_entry);
686 fputs("Country: ", out_file);
687 fputs(table_entry, out_file);
688 fputs("<br/>", out_file);
690 gtk_clist_get_text(hosts->table,i,col_city,&table_entry);
691 fputs("City: ", out_file);
692 fputs(table_entry, out_file);
693 fputs("<br/>", out_file);
695 gtk_clist_get_text(hosts->table,i,col_packets,&table_entry);
696 fputs("Packets: ", out_file);
697 fputs(table_entry, out_file);
698 fputs("<br/>", out_file);
700 gtk_clist_get_text(hosts->table,i,col_bytes,&table_entry);
701 fputs("Bytes: ", out_file);
702 fputs(table_entry, out_file);
703 fputs("\t", out_file);
705 /* XXX - we could add specific icons, e.g. depending on the amount of packets or bytes */
707 fputs("\n", out_file); /* new row */
712 /* copy ipmap.html to temp dir */
714 char * src_file_path;
715 char * dst_file_path;
717 src_file_path = get_datafile_path("ipmap.html");
718 dst_file_path = get_tempfile_path("ipmap.html");
720 if (!copy_file_binary_mode(src_file_path, dst_file_path)) {
721 g_free(src_file_path);
722 g_free(dst_file_path);
725 g_free(src_file_path);
726 g_free(dst_file_path);
729 /* open the webbrowser */
730 file_path = get_tempfile_path("ipmap.html");
731 file_uri = filename2uri(file_path);
733 uri_open = browser_open_url (file_uri);
735 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't open the file: \"%s\" in the webbrowser", file_uri);
742 #endif /* HAVE_GEOIP */
746 init_hostlist_table_page(hostlist_table *hosttable, GtkWidget *vbox, gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
749 column_arrows *col_arrows;
751 GtkWidget *column_lb;
752 GString *error_string;
755 hosttable->num_columns=NUM_HOSTLIST_COLS;
756 hosttable->default_titles[0] = "Address";
757 hosttable->default_titles[1] = "Port";
758 hosttable->default_titles[2] = "Packets";
759 hosttable->default_titles[3] = "Bytes";
760 hosttable->default_titles[4] = "Tx Packets";
761 hosttable->default_titles[5] = "Tx Bytes";
762 hosttable->default_titles[6] = "Rx Packets";
763 hosttable->default_titles[7] = "Rx Bytes";
766 for (i = 0; i < NUM_GEOIP_COLS; i++) {
767 if (i < geoip_db_num_dbs()) {
768 hosttable->default_titles[NUM_BUILTIN_COLS + i] = geoip_db_name(i);
770 hosttable->default_titles[NUM_BUILTIN_COLS + i] = "";
773 #endif /* HAVE_GEOIP */
775 if (strcmp(table_name, "NCP")==0) {
776 hosttable->default_titles[1] = "Connection";
779 hosttable->has_ports=!hide_ports;
780 hosttable->num_hosts = 0;
781 hosttable->resolve_names=TRUE;
782 hosttable->page_lb = NULL;
784 g_snprintf(title, sizeof(title), "%s Endpoints", table_name);
785 hosttable->name_lb = gtk_label_new(title);
786 gtk_box_pack_start(GTK_BOX(vbox), hosttable->name_lb, FALSE, FALSE, 0);
788 hosttable->scrolled_window=scrolled_window_new(NULL, NULL);
789 gtk_box_pack_start(GTK_BOX(vbox), hosttable->scrolled_window, TRUE, TRUE, 0);
791 hosttable->table=(GtkCList *)gtk_clist_new(NUM_HOSTLIST_COLS);
793 col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * NUM_HOSTLIST_COLS);
794 win_style = gtk_widget_get_style(hosttable->scrolled_window);
795 for (i = 0; i < NUM_HOSTLIST_COLS; i++) {
796 col_arrows[i].table = gtk_table_new(2, 2, FALSE);
797 gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
798 column_lb = gtk_label_new(hosttable->default_titles[i]);
799 gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
800 gtk_widget_show(column_lb);
802 col_arrows[i].ascend_pm = xpm_to_widget((const char **) clist_ascend_xpm);
803 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
804 col_arrows[i].descend_pm = xpm_to_widget((const char **) clist_descend_xpm);
805 gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
806 /* make total frames be the default sort order */
808 gtk_widget_show(col_arrows[i].descend_pm);
810 gtk_clist_set_column_widget(GTK_CLIST(hosttable->table), i, col_arrows[i].table);
811 gtk_widget_show(col_arrows[i].table);
813 gtk_clist_column_titles_show(GTK_CLIST(hosttable->table));
815 gtk_clist_set_compare_func(hosttable->table, hostlist_sort_column);
816 gtk_clist_set_sort_column(hosttable->table, 4);
817 gtk_clist_set_sort_type(hosttable->table, GTK_SORT_DESCENDING);
819 for (i = 0; i < NUM_HOSTLIST_COLS; i++) {
820 gtk_clist_set_column_auto_resize(hosttable->table, i, TRUE);
823 gtk_clist_set_shadow_type(hosttable->table, GTK_SHADOW_IN);
824 gtk_clist_column_titles_show(hosttable->table);
825 gtk_container_add(GTK_CONTAINER(hosttable->scrolled_window), (GtkWidget *)hosttable->table);
827 g_signal_connect(hosttable->table, "click-column", G_CALLBACK(hostlist_click_column_cb), col_arrows);
829 hosttable->num_hosts=0;
830 hosttable->hosts=NULL;
832 /* hide srcport and dstport if we don't use ports */
834 gtk_clist_set_column_visibility(hosttable->table, 1, FALSE);
838 /* Hide all of the GeoIP columns initially */
839 for (i = 0; i < NUM_GEOIP_COLS; i++) {
840 gtk_clist_set_column_visibility(hosttable->table, NUM_BUILTIN_COLS + i, FALSE);
842 #endif /* HAVE_GEOIP */
844 /* create popup menu for this table */
845 hostlist_create_popup_menu(hosttable);
847 /* register the tap and rerun the taps on the packet list */
848 error_string=register_tap_listener(tap_name, hosttable, filter, reset_hostlist_table_data_cb, packet_func, draw_hostlist_table_data_cb);
850 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", error_string->str);
851 g_string_free(error_string, TRUE);
861 init_hostlist_table(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
863 hostlist_table *hosttable;
867 GtkWidget *close_bt, *help_bt;
873 GtkTooltips *tooltips = gtk_tooltips_new();
876 hosttable=g_malloc(sizeof(hostlist_table));
878 hosttable->name=table_name;
879 hosttable->filter=filter;
880 hosttable->use_dfilter=FALSE;
881 g_snprintf(title, sizeof(title), "%s Endpoints: %s", table_name, cf_get_display_name(&cfile));
882 hosttable->win=window_new(GTK_WINDOW_TOPLEVEL, title);
884 gtk_window_set_default_size(GTK_WINDOW(hosttable->win), 750, 400);
886 vbox=gtk_vbox_new(FALSE, 3);
887 gtk_container_add(GTK_CONTAINER(hosttable->win), vbox);
888 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
890 ret = init_hostlist_table_page(hosttable, vbox, hide_ports, table_name, tap_name, filter, packet_func);
897 /* XXX - maybe we want to have a "Copy as CSV" stock button here? */
898 /*copy_bt = gtk_button_new_with_label ("Copy content to clipboard as CSV");*/
900 if( strstr(table_name, "IPv4") != NULL) {
901 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, WIRESHARK_STOCK_MAP, GTK_STOCK_HELP, NULL);
903 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, GTK_STOCK_HELP, NULL);
906 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, GTK_STOCK_HELP, NULL);
909 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
911 close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
912 window_set_cancel_button(hosttable->win, close_bt, window_cancel_button_cb);
914 copy_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_COPY);
915 gtk_tooltips_set_tip(tooltips, copy_bt,
916 "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.", NULL);
917 g_object_set_data(G_OBJECT(copy_bt), HOST_PTR_KEY, hosttable);
918 g_signal_connect(copy_bt, "clicked", G_CALLBACK(copy_as_csv_cb), NULL);
921 map_bt = g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_MAP);
923 gtk_tooltips_set_tip(tooltips, map_bt,
924 "Show a map of the IP addresses (internet connection required).", NULL);
925 g_object_set_data(G_OBJECT(map_bt), HOST_PTR_KEY, hosttable);
926 g_signal_connect(map_bt, "clicked", G_CALLBACK(open_as_map_cb), NULL);
928 #endif /* HAVE_GEOIP */
930 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
931 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_STATS_ENDPOINTS_DIALOG);
933 g_signal_connect(hosttable->win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
934 g_signal_connect(hosttable->win, "destroy", G_CALLBACK(hostlist_win_destroy_cb), hosttable);
936 gtk_widget_show_all(hosttable->win);
937 window_present(hosttable->win);
939 cf_retap_packets(&cfile, FALSE);
940 gdk_window_raise(hosttable->win->window);
942 /* Keep clist frozen to cause modifications to the clist (inserts, appends, others that are extremely slow
943 in GTK2) to not be drawn, allow refreshes to occur at strategic points for performance */
944 gtk_clist_freeze(hosttable->table);
947 /* after retapping, redraw table */
948 draw_hostlist_table_data(hosttable);
953 ct_nb_switch_page_cb(GtkNotebook *nb, GtkNotebookPage *pg _U_, guint page, gpointer data)
955 GtkWidget *copy_bt = (GtkWidget *) data;
956 void ** pages = g_object_get_data(G_OBJECT(nb), NB_PAGES_KEY);
960 if (pages && page > 0 && (int) page <= GPOINTER_TO_INT(pages[0]) && copy_bt) {
961 g_object_set_data(G_OBJECT(copy_bt), HOST_PTR_KEY, pages[page]);
967 ct_nb_map_switch_page_cb(GtkNotebook *nb, GtkNotebookPage *pg _U_, guint page, gpointer data)
969 GtkWidget *copy_bt = (GtkWidget *) data;
970 void ** pages = g_object_get_data(G_OBJECT(nb), NB_PAGES_KEY);
974 if (pages && page > 0 && (int) page <= GPOINTER_TO_INT(pages[0]) && copy_bt) {
975 g_object_set_data(G_OBJECT(copy_bt), HOST_PTR_KEY, pages[page]);
976 if(strstr( ((hostlist_table *)pages[page])->name, "IPv4") != NULL) {
977 gtk_widget_set_sensitive(copy_bt, TRUE);
979 gtk_widget_set_sensitive(copy_bt, FALSE);
983 #endif /* HAVE_GEOIP */
987 hostlist_win_destroy_notebook_cb(GtkWindow *win _U_, gpointer data)
989 void ** pages = data;
992 /* first "page" contains the number of pages */
993 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
994 hostlist_win_destroy_cb(NULL, pages[page]);
1002 static hostlist_table *
1003 init_hostlist_notebook_page_cb(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
1006 GtkWidget *page_vbox;
1007 hostlist_table *hosttable;
1009 hosttable=g_malloc(sizeof(hostlist_table));
1010 hosttable->name=table_name;
1011 hosttable->filter=filter;
1012 hosttable->resolve_names=TRUE;
1013 hosttable->use_dfilter=FALSE;
1015 page_vbox=gtk_vbox_new(FALSE, 6);
1016 hosttable->win = page_vbox;
1017 gtk_container_set_border_width(GTK_CONTAINER(page_vbox), 6);
1019 ret = init_hostlist_table_page(hosttable, page_vbox, hide_ports, table_name, tap_name, filter, packet_func);
1030 gboolean hide_ports; /* hide TCP / UDP port columns */
1031 const char *table_name; /* GUI output name */
1032 const char *tap_name; /* internal name */
1033 const char *filter; /* display filter string (unused) */
1034 tap_packet_cb packet_func; /* function to be called for new incoming packets */
1035 } register_hostlist_t;
1038 static GSList *registered_hostlist_tables = NULL;
1041 register_hostlist_table(gboolean hide_ports, const char *table_name, const char *tap_name, const char *filter, tap_packet_cb packet_func)
1043 register_hostlist_t *table;
1045 table = g_malloc(sizeof(register_hostlist_t));
1047 table->hide_ports = hide_ports;
1048 table->table_name = table_name;
1049 table->tap_name = tap_name;
1050 table->filter = filter;
1051 table->packet_func = packet_func;
1053 registered_hostlist_tables = g_slist_append(registered_hostlist_tables, table);
1058 hostlist_resolve_toggle_dest(GtkWidget *widget, gpointer data)
1061 void ** pages = data;
1062 gboolean resolve_names;
1063 hostlist_table *hosttable;
1066 resolve_names = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1068 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1069 hosttable = pages[page];
1070 hosttable->resolve_names = resolve_names;
1072 draw_hostlist_table_addresses(hosttable);
1074 gtk_clist_thaw(hosttable->table);
1075 gtk_clist_freeze(hosttable->table);
1081 hostlist_filter_toggle_dest(GtkWidget *widget, gpointer data)
1084 void ** pages = data;
1085 gboolean use_filter;
1086 hostlist_table *hosttable = NULL;
1088 use_filter = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1090 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1091 hosttable = pages[page];
1092 hosttable->use_dfilter = use_filter;
1093 reset_hostlist_table_data(hosttable);
1096 cf_retap_packets(&cfile, FALSE);
1098 gdk_window_raise(hosttable->win->window);
1101 /* after retapping, redraw table */
1102 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1103 draw_hostlist_table_data(pages[page]);
1109 init_hostlist_notebook_cb(GtkWidget *w _U_, gpointer d _U_)
1111 hostlist_table *hosttable;
1116 GtkWidget *close_bt, *help_bt;
1118 GtkWidget *resolv_cb;
1119 GtkWidget *filter_cb;
1124 GSList *current_table;
1125 register_hostlist_t *registered;
1126 GtkTooltips *tooltips = gtk_tooltips_new();
1133 pages = g_malloc(sizeof(void *) * (g_slist_length(registered_hostlist_tables) + 1));
1135 win=window_new(GTK_WINDOW_TOPLEVEL, "hostlist");
1136 g_snprintf(title, sizeof(title), "Endpoints: %s", cf_get_display_name(&cfile));
1137 gtk_window_set_title(GTK_WINDOW(win), title);
1138 gtk_window_set_default_size(GTK_WINDOW(win), 750, 400);
1140 vbox=gtk_vbox_new(FALSE, 6);
1141 gtk_container_add(GTK_CONTAINER(win), vbox);
1142 gtk_container_set_border_width(GTK_CONTAINER(vbox), 12);
1144 nb = gtk_notebook_new();
1145 gtk_container_add(GTK_CONTAINER(vbox), nb);
1146 g_object_set_data(G_OBJECT(nb), NB_PAGES_KEY, pages);
1150 current_table = registered_hostlist_tables;
1151 while(current_table) {
1152 registered = current_table->data;
1153 page_lb = gtk_label_new("");
1154 hosttable = init_hostlist_notebook_page_cb(registered->hide_ports,
1155 registered->table_name, registered->tap_name,
1156 registered->filter, registered->packet_func);
1157 g_object_set_data(G_OBJECT(hosttable->win), HOST_PTR_KEY, hosttable);
1158 gtk_notebook_append_page(GTK_NOTEBOOK(nb), hosttable->win, page_lb);
1159 hosttable->win = win;
1160 hosttable->page_lb = page_lb;
1161 pages[++page] = hosttable;
1163 current_table = g_slist_next(current_table);
1166 pages[0] = GINT_TO_POINTER(page);
1168 hbox = gtk_hbox_new(FALSE, 3);
1169 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
1171 resolv_cb = gtk_check_button_new_with_mnemonic("Name resolution");
1172 gtk_container_add(GTK_CONTAINER(hbox), resolv_cb);
1173 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(resolv_cb), TRUE);
1174 gtk_tooltips_set_tip(tooltips, resolv_cb, "Show results of name resolutions rather than the \"raw\" values. "
1175 "Please note: The corresponding name resolution must be enabled.", NULL);
1177 g_signal_connect(resolv_cb, "toggled", G_CALLBACK(hostlist_resolve_toggle_dest), pages);
1179 filter_cb = gtk_check_button_new_with_mnemonic("Limit to display filter");
1180 gtk_container_add(GTK_CONTAINER(hbox), filter_cb);
1181 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_cb), FALSE);
1182 gtk_tooltips_set_tip(tooltips, filter_cb, "Limit the list to endpoints matching the current display filter.", NULL);
1184 g_signal_connect(filter_cb, "toggled", G_CALLBACK(hostlist_filter_toggle_dest), pages);
1188 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, WIRESHARK_STOCK_MAP, GTK_STOCK_HELP, NULL);
1190 bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_COPY, GTK_STOCK_HELP, NULL);
1192 gtk_box_pack_end(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
1194 close_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CLOSE);
1195 window_set_cancel_button(win, close_bt, window_cancel_button_cb);
1197 copy_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_COPY);
1198 gtk_tooltips_set_tip(tooltips, copy_bt,
1199 "Copy all statistical values of this page to the clipboard in CSV (Comma Separated Values) format.", NULL);
1200 g_signal_connect(copy_bt, "clicked", G_CALLBACK(copy_as_csv_cb), NULL);
1201 g_object_set_data(G_OBJECT(copy_bt), HOST_PTR_KEY, pages[page]);
1204 map_bt = g_object_get_data(G_OBJECT(bbox), WIRESHARK_STOCK_MAP);
1205 gtk_tooltips_set_tip(tooltips, map_bt,
1206 "Show a map of the IP addresses (internet connection required).", NULL);
1207 g_object_set_data(G_OBJECT(map_bt), HOST_PTR_KEY, pages[page]);
1208 g_signal_connect(map_bt, "clicked", G_CALLBACK(open_as_map_cb), NULL);
1209 g_signal_connect(nb, "switch-page", G_CALLBACK(ct_nb_map_switch_page_cb), map_bt);
1210 gtk_widget_set_sensitive(map_bt, FALSE);
1211 #endif /* HAVE_GEOIP */
1213 g_signal_connect(nb, "switch-page", G_CALLBACK(ct_nb_switch_page_cb), copy_bt);
1215 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
1216 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_STATS_ENDPOINTS_DIALOG);
1218 g_signal_connect(win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
1219 g_signal_connect(win, "destroy", G_CALLBACK(hostlist_win_destroy_notebook_cb), pages);
1221 gtk_widget_show_all(win);
1222 window_present(win);
1224 cf_retap_packets(&cfile, FALSE);
1225 gdk_window_raise(win->window);
1227 /* after retapping, redraw table */
1228 for (page=1; page<=GPOINTER_TO_INT(pages[0]); page++) {
1229 draw_hostlist_table_data(pages[page]);
1236 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)
1238 hostlist_talker_t *talker=NULL;
1240 gboolean new_talker;
1243 /* XXX should be optimized to allocate n extra entries at a time
1244 instead of just one */
1245 /* if we dont have any entries at all yet */
1246 if(hl->hosts==NULL){
1247 hl->hosts=g_malloc(sizeof(hostlist_talker_t));
1249 talker=&hl->hosts[0];
1254 /* try to find it among the existing known hosts */
1257 for(i=0;i<hl->num_hosts;i++){
1258 if( (!CMP_ADDRESS(&hl->hosts[i].address, addr))&&(hl->hosts[i].port==port) ){
1259 talker=&hl->hosts[i];
1266 /* if we still dont know what talker this is it has to be a new one
1267 and we have to allocate it and append it to the end of the list */
1271 hl->hosts=g_realloc(hl->hosts, hl->num_hosts*sizeof(hostlist_talker_t));
1272 talker=&hl->hosts[hl->num_hosts-1];
1273 talker_idx=hl->num_hosts-1;
1276 /* if this is a new talker we need to initialize the struct */
1278 COPY_ADDRESS(&talker->address, addr);
1280 talker->port_type=port_type;
1282 talker->rx_frames=0;
1283 talker->tx_frames=0;
1288 /* update the talker struct */
1290 talker->tx_frames+=num_frames;
1291 talker->tx_bytes+=num_bytes;
1293 talker->rx_frames+=num_frames;
1294 talker->rx_bytes+=num_bytes;
1297 /* if this was a new talker we have to create a clist row for it */
1299 char *entries[NUM_HOSTLIST_COLS];
1300 char frames[COL_STR_LEN], bytes[COL_STR_LEN], txframes[COL_STR_LEN];
1301 char txbytes[COL_STR_LEN], rxframes[COL_STR_LEN], rxbytes[COL_STR_LEN];
1303 char geoip[NUM_GEOIP_COLS][COL_STR_LEN];
1305 #endif /* HAVE_GEOIP */
1307 /* these values will be filled by call to draw_hostlist_table_addresses() below */
1311 g_snprintf(frames, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", talker->tx_frames+talker->rx_frames);
1313 g_snprintf(bytes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", talker->tx_bytes+talker->rx_bytes);
1316 g_snprintf(txframes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", talker->tx_frames);
1317 entries[4]=txframes;
1318 g_snprintf(txbytes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", talker->tx_bytes);
1321 g_snprintf(rxframes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", talker->rx_frames);
1322 entries[6]=rxframes;
1323 g_snprintf(rxbytes, COL_STR_LEN, "%" G_GINT64_MODIFIER "u", talker->rx_bytes);
1327 /* Filled in from the GeoIP config, if any */
1328 for (i = 0; i < NUM_GEOIP_COLS; i++) {
1329 if (i < geoip_db_num_dbs() && talker->address.type == AT_IPv4) {
1330 const guchar *name = geoip_db_lookup_ipv4(i, pntohl(talker->address.data), "-");
1331 g_snprintf(geoip[i], COL_STR_LEN, "%s", format_text (name, strlen(name)));
1332 entries[NUM_BUILTIN_COLS + i] = geoip[i];
1333 gtk_clist_set_column_visibility(hl->table, NUM_BUILTIN_COLS + i, TRUE);
1335 entries[NUM_BUILTIN_COLS + i] = "";
1338 #endif /* HAVE_GEOIP */
1340 gtk_clist_insert(hl->table, talker_idx, entries);
1341 gtk_clist_set_row_data(hl->table, talker_idx, (gpointer)(long) talker_idx);
1343 draw_hostlist_table_address(hl, talker_idx);
1353 * indent-tabs-mode: nil
1356 * ex: set shiftwidth=4 tabstop=8 expandtab
1357 * :indentSize=4:tabSize=8:noTabs=true: