2 * Routines for the capture interface dialog
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
33 #include <epan/prefs.h>
35 #include "../capture_opts.h"
36 #include "../capture_session.h"
37 #include "../capture_ifinfo.h"
38 #include "../capture.h"
39 #include "../capture-pcap-util.h"
40 #include "../capture_ui_utils.h"
41 #include "wsutil/file_util.h"
42 #include <wiretap/wtap.h>
44 #include "ui/capture_globals.h"
45 #include "ui/recent.h"
46 #include "ui/simple_dialog.h"
49 #include "ui/gtk/capture_if_details_dlg_win32.h"
50 #include "../../capture-wpcap.h"
53 #include "ui/gtk/stock_icons.h"
54 #include "ui/gtk/capture_dlg.h"
55 #include "ui/gtk/capture_if_dlg.h"
56 #include "ui/gtk/gui_utils.h"
57 #include "ui/gtk/dlg_utils.h"
58 #include "ui/gtk/main.h"
59 #include "ui/gtk/main_toolbar.h"
60 #include "ui/gtk/help_dlg.h"
61 #include "ui/gtk/keys.h"
62 #include "ui/gtk/webbrowser.h"
63 #include "ui/gtk/network_icons.h"
64 #include "ui/gtk/pipe_icon.h"
65 #include "ui/gtk/main_welcome.h"
67 #include "ui/gtk/old-gtk-compat.h"
70 #include "../../image/toolbar/capture_airpcap_16.xpm"
73 #if defined(HAVE_PCAP_REMOTE)
74 #include "ui/gtk/remote_icons.h"
77 #include "../../image/toolbar/modem_16.xpm"
79 #include "../../image/toolbar/network_virtual_16.xpm"
81 /* new buttons to be used instead of labels for 'Capture','Prepare',' */
82 /*#include "../../image/toolbar/capture_capture_16.xpm"*/
83 /*#include "../../image/toolbar/capture_prepare_16.xpm"*/
84 /*#include "../../image/toolbar/capture_details_16.xpm"*/
89 #include "airpcap_loader.h"
90 #include "airpcap_gui_utils.h"
91 #include "airpcap_dlg.h"
94 #define CAPTURE_IF_IP_ADDR_LABEL "capture_if_ip_addr_label"
95 #define CAPTURE_IF_SELECTED_IP_ADDR "capture_if_selected_ip_addr"
96 #define SOFT_LABEL_LEN 50
99 * Keep a static pointer to the current "Capture Interfaces" window, if
100 * any, so that if somebody tries to do "Capture:Start" while there's
101 * already a "Capture Interfaces" window up, we just pop up the existing
102 * one, rather than creating a new one.
104 static GtkWidget
*cap_if_w
;
106 static guint timer_id
;
108 static GtkWidget
*close_bt
, *stop_bt
, *capture_bt
, *options_bt
;
110 static GArray
*if_array
;
112 static if_stat_cache_t
*sc
;
113 static GtkWidget
*cap_if_top_vb
, *cap_if_sw
;
116 * Timeout, in milliseconds, for reads from the stream of captured packets.
118 #define CAP_READ_TIMEOUT 250
121 /* the "runtime" data of one interface */
122 typedef struct if_dlg_data_s
{
124 GtkWidget
*device_lb
;
129 GtkWidget
*choose_bt
;
131 GtkWidget
*details_bt
;
136 static gboolean gbl_capture_in_progress
= FALSE
;
144 data
.device_lb
= NULL
;
145 data
.descr_lb
= NULL
;
149 data
.choose_bt
= NULL
;
151 data
.details_bt
= NULL
;
154 g_array_append_val(if_array
, data
);
160 update_selected_interface(gchar
*name
)
166 for (i
= 0; i
< global_capture_opts
.all_ifaces
->len
; i
++) {
167 device
= g_array_index(global_capture_opts
.all_ifaces
, interface_t
, i
);
168 data
= g_array_index(if_array
, if_dlg_data_t
, i
);
169 if (strcmp(name
, device
.name
) == 0) {
170 gtk_toggle_button_set_active((GtkToggleButton
*)data
.choose_bt
, device
.selected
);
177 store_selected(GtkWidget
*choose_bt
, gpointer name
)
182 for (i
= 0; i
< global_capture_opts
.all_ifaces
->len
; i
++) {
183 device
= g_array_index(global_capture_opts
.all_ifaces
, interface_t
, i
);
184 if (strcmp((char *)name
, device
.if_info
.name
) == 0) {
185 if (!device
.locked
) {
186 device
.selected
^= 1;
187 if (device
.selected
) {
188 global_capture_opts
.num_selected
++;
190 global_capture_opts
.num_selected
--;
192 global_capture_opts
.all_ifaces
= g_array_remove_index(global_capture_opts
.all_ifaces
, i
);
193 g_array_insert_val(global_capture_opts
.all_ifaces
, i
, device
);
194 if (gtk_widget_is_focus(choose_bt
) && get_welcome_window()) {
195 change_interface_selection(device
.name
, device
.selected
);
197 if (gtk_widget_is_focus(choose_bt
) && capture_dlg_window_present()) {
198 enable_selected_interface(device
.name
, device
.selected
);
200 device
.locked
= FALSE
;
201 global_capture_opts
.all_ifaces
= g_array_remove_index(global_capture_opts
.all_ifaces
, i
);
202 g_array_insert_val(global_capture_opts
.all_ifaces
, i
, device
);
208 gtk_widget_set_sensitive(capture_bt
, !gbl_capture_in_progress
&& (global_capture_opts
.num_selected
> 0));
212 /* start capture button was pressed */
214 capture_do_cb(GtkWidget
*capture_bt_arg _U_
, gpointer if_data _U_
)
219 for (ifs
= 0; ifs
< if_array
->len
; ifs
++) {
220 data
= g_array_index(if_array
, if_dlg_data_t
, ifs
);
224 gtk_widget_set_sensitive(data
.choose_bt
, FALSE
);
225 if_array
= g_array_remove_index(if_array
, ifs
);
226 g_array_insert_val(if_array
, ifs
, data
);
228 airpcap_if_active
= get_airpcap_if_from_name(airpcap_if_list
, gtk_label_get_text(GTK_LABEL(data
.device_lb
)));
229 airpcap_if_selected
= airpcap_if_active
;
233 /* XXX - remove this? */
234 if (global_capture_opts
.save_file
) {
235 g_free(global_capture_opts
.save_file
);
236 global_capture_opts
.save_file
= NULL
;
239 if (global_capture_opts
.ifaces
->len
> 1) {
240 global_capture_opts
.use_pcapng
= TRUE
;
242 /* stop capturing from all interfaces, we are going to do real work now ... */
243 window_destroy(cap_if_w
);
245 capture_start_cb(NULL
, NULL
);
249 /* prepare capture button was pressed */
251 capture_prepare_cb(GtkWidget
*prepare_bt _U_
, gpointer if_data _U_
)
253 /* stop capturing from all interfaces, we are going to do real work now ... */
254 window_destroy(cap_if_w
);
255 if (global_capture_opts
.ifaces
->len
> 1) {
256 global_capture_opts
.use_pcapng
= TRUE
;
258 capture_prep_cb(NULL
, NULL
);
263 /* capture details button was pressed */
265 capture_details_cb(GtkWidget
*details_bt _U_
, gpointer name
)
267 capture_if_details_open(name
);
271 /* update a single interface */
273 update_if(gchar
*name
, if_stat_cache_t
*sc_p
)
275 struct pcap_stat stats
;
277 guint diff
, ifs
, data_ifs
;
280 gboolean found
= FALSE
;
284 * Note that some versions of libpcap, on some versions of UN*X,
285 * pcap_stats() returns the number of packets since the last
288 * That's a bug, and should be fixed; "pcap_stats()" is supposed
289 * to work the same way on all platforms.
291 device
.last_packets
= 0;
295 for (ifs
= 0, data_ifs
= 0; ifs
< global_capture_opts
.all_ifaces
->len
; ifs
++) {
296 device
= g_array_index(global_capture_opts
.all_ifaces
, interface_t
, ifs
);
297 if (device
.type
!= IF_PIPE
) {
298 data
= g_array_index(if_array
, if_dlg_data_t
, data_ifs
++);
299 if (!device
.hidden
&& strcmp(name
, device
.name
) == 0) {
306 if (capture_stats(sc_p
, name
, &stats
)) {
307 if ((int)(stats
.ps_recv
- device
.last_packets
) < 0) {
310 diff
= stats
.ps_recv
- device
.last_packets
;
312 device
.last_packets
= stats
.ps_recv
;
314 str
= g_strdup_printf("%u", device
.last_packets
);
315 gtk_label_set_text(GTK_LABEL(data
.curr_lb
), str
);
317 str
= g_strdup_printf("%u", diff
);
318 gtk_label_set_text(GTK_LABEL(data
.last_lb
), str
);
321 gtk_widget_set_sensitive(data
.curr_lb
, diff
);
322 gtk_widget_set_sensitive(data
.last_lb
, diff
);
324 gtk_label_set_text(GTK_LABEL(data
.curr_lb
), "error");
325 gtk_label_set_text(GTK_LABEL(data
.last_lb
), "error");
327 global_capture_opts
.all_ifaces
= g_array_remove_index(global_capture_opts
.all_ifaces
, ifs
);
328 g_array_insert_val(global_capture_opts
.all_ifaces
, ifs
, device
);
329 if_array
= g_array_remove_index(if_array
, ifs
);
330 g_array_insert_val(if_array
, ifs
, data
);
335 /* update all interfaces */
337 update_all(gpointer data
)
341 if_stat_cache_t
*sc_p
= (if_stat_cache_t
*)data
;
347 for (ifs
= 0; ifs
< global_capture_opts
.all_ifaces
->len
; ifs
++) {
348 device
= g_array_index(global_capture_opts
.all_ifaces
, interface_t
, ifs
);
349 update_if(device
.name
, sc_p
);
355 /* a live capture has started or stopped */
357 set_capture_if_dialog_for_capture_in_progress(gboolean capture_in_progress
)
359 gbl_capture_in_progress
= capture_in_progress
;
361 gtk_widget_set_sensitive(stop_bt
, capture_in_progress
);
362 gtk_widget_set_sensitive(capture_bt
, !capture_in_progress
&& (global_capture_opts
.num_selected
> 0));
366 /* a live capture is being stopped */
368 set_capture_if_dialog_for_capture_stopping(void)
371 gtk_widget_set_sensitive(stop_bt
, FALSE
);
376 /* the window was closed, cleanup things */
378 capture_if_destroy_cb(GtkWidget
*win _U_
, gpointer user_data _U_
)
380 g_source_remove(timer_id
);
383 capture_stat_stop(sc
);
386 window_destroy(GTK_WIDGET(cap_if_w
));
387 /* Note that we no longer have a "Capture Options" dialog box. */
389 cap_if_top_vb
= NULL
;
392 if (airpcap_if_active
)
393 airpcap_set_toolbar_stop_capture(airpcap_if_active
);
399 * Used to retrieve the interface icon.
401 GtkWidget
* capture_get_if_icon(interface_t
*device
)
403 #ifdef HAVE_PCAP_REMOTE
404 if (!device
->local
) {
405 return pixbuf_to_widget(remote_sat_pb_data
);
408 if (device
->display_name
&& strstr(device
->display_name
,"Wi-Fi") != NULL
) {
409 return pixbuf_to_widget(network_wireless_pb_data
);
411 switch (device
->type
) {
413 return xpm_to_widget(modem_16_xpm
);
415 return pixbuf_to_widget(network_wireless_pb_data
);
418 return xpm_to_widget(capture_airpcap_16_xpm
);
421 return pixbuf_to_widget(network_bluetooth_pb_data
);
423 return pixbuf_to_widget(network_usb_pb_data
);
425 return xpm_to_widget(network_virtual_16_xpm
);
427 return pixbuf_to_widget(network_wired_pb_data
);
430 return pixbuf_to_widget(pipe_pb_data
);
432 printf("unknown device type\n");
434 return pixbuf_to_widget(network_wired_pb_data
);
439 get_ip_addr_count(GSList
*addr_list
)
446 for (curr_addr
= addr_list
; curr_addr
!= NULL
;
447 curr_addr
= g_slist_next(curr_addr
)) {
448 addr
= (if_addr_t
*)curr_addr
->data
;
449 switch (addr
->ifat_type
) {
457 /* In case we add non-IP addresses */
465 set_ip_addr_label(GSList
*addr_list
, GtkWidget
*ip_lb
, guint selected_ip_addr
)
469 const gchar
*addr_str
= NULL
;
471 curr_addr
= g_slist_nth(addr_list
, selected_ip_addr
);
473 addr
= (if_addr_t
*)curr_addr
->data
;
474 switch (addr
->ifat_type
) {
477 addr_str
= ip_to_str((guint8
*)&addr
->addr
.ip4_addr
);
481 addr_str
= ip6_to_str((struct e_in6_addr
*)&addr
->addr
.ip6_addr
);
485 /* Ignore non-IP addresses, in case we ever support them */
491 gtk_label_set_text(GTK_LABEL(ip_lb
), addr_str
);
493 gtk_label_set_text(GTK_LABEL(ip_lb
), "none");
495 g_object_set_data(G_OBJECT(ip_lb
), CAPTURE_IF_SELECTED_IP_ADDR
, GINT_TO_POINTER(selected_ip_addr
));
502 ip_label_enter_cb(GtkWidget
*eb
, GdkEventCrossing
*event _U_
, gpointer user_data _U_
)
504 gtk_widget_set_state(eb
, GTK_STATE_PRELIGHT
);
511 ip_label_leave_cb(GtkWidget
*eb
, GdkEvent
*event _U_
, gpointer user_data _U_
)
513 gtk_widget_set_state(eb
, GTK_STATE_NORMAL
);
520 ip_label_press_cb(GtkWidget
*widget
, GdkEvent
*event _U_
, gpointer data
)
522 GtkWidget
*ip_lb
= (GtkWidget
*)g_object_get_data(G_OBJECT(widget
), CAPTURE_IF_IP_ADDR_LABEL
);
523 GSList
*addr_list
= (GSList
*)data
;
524 GSList
*curr_addr
, *start_addr
;
526 guint selected_ip_addr
= GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(ip_lb
), CAPTURE_IF_SELECTED_IP_ADDR
));
528 /* Select next IP address */
529 start_addr
= g_slist_nth(addr_list
, selected_ip_addr
);
532 if (g_slist_length(addr_list
) <= selected_ip_addr
) {
534 selected_ip_addr
= 0;
536 curr_addr
= g_slist_nth(addr_list
, selected_ip_addr
);
537 if (curr_addr
== start_addr
) {
538 /* We wrapped all the way around */
542 addr
= (if_addr_t
*)curr_addr
->data
;
543 switch (addr
->ifat_type
) {
550 /* In case we add non-IP addresses */
556 set_ip_addr_label(addr_list
, ip_lb
, selected_ip_addr
);
562 capture_if_stop_cb(GtkWidget
*w _U_
, gpointer d _U_
)
567 for (ifs
= 0; ifs
< if_array
->len
; ifs
++) {
568 data
= g_array_index(if_array
, if_dlg_data_t
, ifs
);
572 gtk_widget_set_sensitive(data
.choose_bt
, TRUE
);
573 if_array
= g_array_remove_index(if_array
, ifs
);
574 g_array_insert_val(if_array
, ifs
, data
);
576 capture_stop_cb(NULL
, NULL
);
585 if_array
= g_array_new(FALSE
, FALSE
, sizeof(if_dlg_data_t
));
587 for (i
= 0; i
< global_capture_opts
.all_ifaces
->len
; i
++) {
588 data
.device_lb
= NULL
;
589 data
.descr_lb
= NULL
;
593 data
.choose_bt
= NULL
;
595 data
.details_bt
= NULL
;
598 g_array_append_val(if_array
, data
);
603 * If this is Windows, is WinPcap loaded? If not, pop up a dialog noting
604 * that fact and return FALSE, as we can't capture traffic.
606 * Otherwise (not Windows or WinPcap loaded), are there any interfaces?
607 * If not, pop up a dialog noting that fact and return FALSE, as there
608 * are no interfaces on which to capture traffic.
610 * Otherwise, return TRUE, as we can capture.
616 /* Is WPcap loaded? */
620 detailed_err
= cant_load_winpcap_err("Wireshark");
621 simple_error_message_box("%s", detailed_err
);
622 g_free(detailed_err
);
627 if (global_capture_opts
.all_ifaces
->len
== 0) {
628 simple_error_message_box("There are no interfaces on which a capture can be done.");
636 capture_if_refresh_if_list(void)
638 GtkWidget
*if_vb
, *if_grid
, *icon
, *if_lb
, *eb
;
639 GtkRequisition requisition
;
640 int row
= 0, height
= 0;
643 const gchar
*addr_str
;
647 if (!can_capture()) {
648 /* No interfaces or, on Windows, no WinPcap; we've already popped
649 up a message, so just get rid of the interface dialog. */
655 /* First, get rid of the old interface list, and stop updating
656 the statistics on it. */
657 gtk_container_remove(GTK_CONTAINER(cap_if_top_vb
), cap_if_sw
);
658 capture_stat_stop(sc
);
659 g_source_remove(timer_id
);
662 /* Now construct the new interface list, and start updating the
667 cap_if_sw
= gtk_scrolled_window_new(NULL
, NULL
);
668 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(cap_if_sw
), GTK_POLICY_NEVER
, GTK_POLICY_AUTOMATIC
);
669 gtk_box_pack_start(GTK_BOX(cap_if_top_vb
), cap_if_sw
, TRUE
, TRUE
, 0);
671 if_vb
= gtk_alignment_new(0.0F
, 0.0F
, 1.0F
, 0.0F
);
672 gtk_container_set_border_width(GTK_CONTAINER(if_vb
), 5);
673 #if ! GTK_CHECK_VERSION(3,8,0)
674 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(cap_if_sw
), if_vb
);
676 gtk_container_add(GTK_CONTAINER(cap_if_sw
), if_vb
);
679 if_grid
= ws_gtk_grid_new();
680 ws_gtk_grid_set_row_spacing(GTK_GRID(if_grid
), 3);
681 ws_gtk_grid_set_column_spacing(GTK_GRID(if_grid
), 3);
682 gtk_container_add(GTK_CONTAINER(if_vb
), if_grid
);
684 /* This is the icon column, used to display which kind of interface we have */
685 if_lb
= gtk_label_new("");
686 ws_gtk_grid_attach_extended(GTK_GRID(if_grid
), if_lb
, 0, row
, 1, 1,
687 (GtkAttachOptions
)0, (GtkAttachOptions
)0, 0, 0);
689 if_lb
= gtk_label_new("Device");
690 ws_gtk_grid_attach_defaults(GTK_GRID(if_grid
), if_lb
, 1, row
, 3, 1);
692 if_lb
= gtk_label_new("Description");
693 ws_gtk_grid_attach_defaults(GTK_GRID(if_grid
), if_lb
, 4, row
, 1, 1);
695 if_lb
= gtk_label_new(" IP ");
696 ws_gtk_grid_attach_extended(GTK_GRID(if_grid
), if_lb
, 5, row
, 1, 1,
697 (GtkAttachOptions
)0, (GtkAttachOptions
)0, 0, 0);
699 if_lb
= gtk_label_new("Packets");
700 ws_gtk_grid_attach_extended(GTK_GRID(if_grid
), if_lb
, 6, row
, 1, 1,
701 (GtkAttachOptions
)0, (GtkAttachOptions
)0, 0, 0);
703 if_lb
= gtk_label_new(" Packets/s ");
704 ws_gtk_grid_attach_extended(GTK_GRID(if_grid
), if_lb
, 7, row
, 1, 1,
705 (GtkAttachOptions
)0, (GtkAttachOptions
)0, 0, 0);
709 /* Start gathering statistics (using dumpcap) */
710 sc
= capture_stat_start(&global_capture_opts
);
712 /* List the interfaces */
713 for (ifs
= 0; ifs
< global_capture_opts
.all_ifaces
->len
; ifs
++) {
714 device
= g_array_index(global_capture_opts
.all_ifaces
, interface_t
, ifs
);
715 data
= g_array_index(if_array
, if_dlg_data_t
, ifs
);
716 /* Continue if capture device is hidden */
719 if_array
= g_array_remove_index(if_array
, ifs
);
720 g_array_insert_val(if_array
, ifs
, data
);
723 data
.choose_bt
= gtk_check_button_new();
724 ws_gtk_grid_attach_extended(GTK_GRID(if_grid
), data
.choose_bt
, 0, row
, 1, 1,
725 (GtkAttachOptions
)0, (GtkAttachOptions
)0, 0, 0);
726 if (gbl_capture_in_progress
) {
727 gtk_widget_set_sensitive(data
.choose_bt
, FALSE
);
729 gtk_widget_set_sensitive(data
.choose_bt
, TRUE
);
731 gtk_toggle_button_set_active((GtkToggleButton
*)data
.choose_bt
, device
.selected
);
732 g_signal_connect(data
.choose_bt
, "toggled", G_CALLBACK(store_selected
), device
.name
);
733 /* Kind of adaptor (icon) */
734 icon
= capture_get_if_icon(&(device
));
735 ws_gtk_grid_attach_extended(GTK_GRID(if_grid
), icon
, 1, row
, 1, 1,
736 (GtkAttachOptions
)0, (GtkAttachOptions
)0, 0, 0);
741 * On Windows, device names are generally not meaningful - NT 5
742 * uses long blobs with GUIDs in them, for example - so instead we use
743 * the display name which should match that shown in ncpa.cpl
745 data
.device_lb
= gtk_label_new(device
.display_name
);
747 data
.device_lb
= gtk_label_new(device
.name
);
749 gtk_misc_set_alignment(GTK_MISC(data
.device_lb
), 0.0f
, 0.5f
);
750 if (strlen(gtk_label_get_text(GTK_LABEL(data
.device_lb
))) > SOFT_LABEL_LEN
) {
751 gtk_label_set_ellipsize(GTK_LABEL(data
.device_lb
), PANGO_ELLIPSIZE_MIDDLE
);
752 gtk_label_set_width_chars(GTK_LABEL(data
.device_lb
), SOFT_LABEL_LEN
);
754 ws_gtk_grid_attach_defaults(GTK_GRID(if_grid
), data
.device_lb
, 2, row
, 2, 1);
757 user_descr
= capture_dev_user_descr_find(device
.name
);
759 data
.descr_lb
= gtk_label_new(user_descr
);
762 if (device
.if_info
.vendor_description
)
763 data
.descr_lb
= gtk_label_new(device
.if_info
.vendor_description
);
765 data
.descr_lb
= gtk_label_new("");
767 gtk_misc_set_alignment(GTK_MISC(data
.descr_lb
), 0.0f
, 0.5f
);
768 if (strlen(gtk_label_get_text(GTK_LABEL(data
.descr_lb
))) > SOFT_LABEL_LEN
) {
769 gtk_label_set_ellipsize(GTK_LABEL(data
.descr_lb
), PANGO_ELLIPSIZE_MIDDLE
);
770 gtk_label_set_width_chars(GTK_LABEL(data
.descr_lb
), SOFT_LABEL_LEN
);
772 ws_gtk_grid_attach_defaults(GTK_GRID(if_grid
), data
.descr_lb
, 4, row
, 1, 1);
775 /* Only one IP address will be shown, start with the first */
776 data
.ip_lb
= gtk_label_new("");
777 addr_str
= set_ip_addr_label (device
.if_info
.addrs
, data
.ip_lb
, 0);
779 gtk_widget_set_sensitive(data
.ip_lb
, TRUE
);
781 gtk_widget_set_sensitive(data
.ip_lb
, FALSE
);
783 eb
= gtk_event_box_new ();
784 gtk_container_add(GTK_CONTAINER(eb
), data
.ip_lb
);
785 ws_gtk_grid_attach_extended(GTK_GRID(if_grid
), eb
, 5, row
, 1, 1,
786 (GtkAttachOptions
)0, (GtkAttachOptions
)0, 0, 0);
787 if (get_ip_addr_count(device
.if_info
.addrs
) > 1) {
788 /* More than one IP address, make it possible to toggle */
789 g_object_set_data(G_OBJECT(eb
), CAPTURE_IF_IP_ADDR_LABEL
, data
.ip_lb
);
790 gtk_widget_set_tooltip_text(eb
, "Click to see additional IP addresses");
791 g_signal_connect(eb
, "enter-notify-event", G_CALLBACK(ip_label_enter_cb
), NULL
);
792 g_signal_connect(eb
, "leave-notify-event", G_CALLBACK(ip_label_leave_cb
), NULL
);
793 g_signal_connect(eb
, "button-press-event", G_CALLBACK(ip_label_press_cb
), device
.if_info
.addrs
);
797 data
.curr_lb
= gtk_label_new("-");
798 ws_gtk_grid_attach_extended(GTK_GRID(if_grid
), data
.curr_lb
, 6, row
, 1, 1,
799 (GtkAttachOptions
)0, (GtkAttachOptions
)0, 0, 0);
802 data
.last_lb
= gtk_label_new("-");
803 ws_gtk_grid_attach_extended(GTK_GRID(if_grid
), data
.last_lb
, 7, row
, 1, 1,
804 (GtkAttachOptions
)0, (GtkAttachOptions
)0, 0, 0);
808 data
.details_bt
= gtk_button_new_from_stock(WIRESHARK_STOCK_CAPTURE_DETAILS
);
809 gtk_widget_set_tooltip_text(data
.details_bt
, "Open the capture details dialog of this interface.");
810 ws_gtk_grid_attach_extended(GTK_GRID(if_grid
), data
.details_bt
, 8, row
, 1, 1, 0, 0, 0, 0);
811 if (capture_if_has_details(device
.name
)) {
812 g_signal_connect(data
.details_bt
, "clicked", G_CALLBACK(capture_details_cb
), device
.name
);
814 gtk_widget_set_sensitive(data
.details_bt
, FALSE
);
817 if_array
= g_array_remove_index(if_array
, ifs
);
818 g_array_insert_val(if_array
, ifs
, data
);
822 /* Add up to 20 rows of interfaces, otherwise the window may become too high */
824 gtk_widget_get_preferred_size(GTK_WIDGET(data
.details_bt
), &requisition
, NULL
);
826 gtk_widget_get_preferred_size(GTK_WIDGET(data
.choose_bt
), &requisition
, NULL
);
828 height
+= requisition
.height
;
832 gtk_widget_get_preferred_size(GTK_WIDGET(close_bt
), &requisition
, NULL
);
833 /* height + static offset + grid spacing */
834 height
+= requisition
.height
+ 40 + (row
* 3);
836 gtk_window_set_default_size(GTK_WINDOW(cap_if_w
), -1, height
);
838 gtk_widget_show_all(cap_if_w
);
840 /* update the interface list every 1000ms */
841 timer_id
= g_timeout_add(1000, update_all
, sc
);
844 /* start getting capture stats from all interfaces */
846 capture_if_cb(GtkWidget
*w _U_
, gpointer d _U_
)
851 GtkWidget
*decryption_cb
;
854 if (cap_if_w
!= NULL
) {
855 /* There's already a "Capture Interfaces" dialog box; reactivate it. */
856 reactivate_window(cap_if_w
);
860 if (!can_capture()) {
861 /* No interfaces or, on Windows, no WinPcap; just give up. */
866 /* LOAD AIRPCAP INTERFACES */
868 /* If no airpcap interface is present, gray everything */
869 if (airpcap_if_active
== NULL
) {
870 if (airpcap_if_list
== NULL
) {
871 /*No airpcap device found */
872 airpcap_enable_toolbar_widgets(wireless_tb
,FALSE
);
874 /* default adapter is not airpcap... or is airpcap but is not found*/
875 if (airpcap_if_active
){
876 /* XXX can never happen? */
877 airpcap_set_toolbar_stop_capture(airpcap_if_active
);
879 airpcap_enable_toolbar_widgets(wireless_tb
,FALSE
);
882 if (airpcap_if_active
){
883 decryption_cb
= (GtkWidget
*)g_object_get_data(G_OBJECT(wireless_tb
),AIRPCAP_TOOLBAR_DECRYPTION_KEY
);
884 /* XXXX update_decryption_mode_list() trigers a rescan, should only be done if the mode is changed */
885 update_decryption_mode_list(decryption_cb
);
886 airpcap_set_toolbar_start_capture(airpcap_if_active
);
890 cap_if_w
= dlg_window_new("Wireshark: Capture Interfaces"); /* transient_for top_level */
891 /* XXX: Note that on Windows the following is effectively a no-op; See dlg_window_new(). */
892 /* This means, on Windows, if the top_level Wireshark window is destroyed when */
893 /* the capture_interfaces dialog window is open, that the dumpcap process will not */
894 /* be stopped since the destroy callback for the capture_interfaces dialog window */
895 /* will not be called. */
896 /* ToDo: Fix this ! */
897 gtk_window_set_destroy_with_parent (GTK_WINDOW(cap_if_w
), TRUE
);
899 cap_if_top_vb
= ws_gtk_box_new(GTK_ORIENTATION_VERTICAL
, DLG_UNRELATED_SPACING
, FALSE
);
900 gtk_container_add(GTK_CONTAINER(cap_if_w
), cap_if_top_vb
);
901 gtk_container_set_border_width(GTK_CONTAINER(cap_if_top_vb
), DLG_OUTER_MARGIN
);
903 /* Button row: close, help, stop, start, and options button */
904 bbox
= dlg_button_row_new(GTK_STOCK_HELP
, WIRESHARK_STOCK_CAPTURE_START
, WIRESHARK_STOCK_CAPTURE_OPTIONS
, WIRESHARK_STOCK_CAPTURE_STOP
, GTK_STOCK_CLOSE
, NULL
);
906 gtk_box_pack_end(GTK_BOX(cap_if_top_vb
), bbox
, FALSE
, FALSE
, 0);
907 help_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_HELP
);
908 g_signal_connect(help_bt
, "clicked", G_CALLBACK(topic_cb
), (gpointer
)(HELP_CAPTURE_INTERFACES_DIALOG
));
910 stop_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), WIRESHARK_STOCK_CAPTURE_STOP
);
911 g_signal_connect(stop_bt
, "clicked", G_CALLBACK(capture_if_stop_cb
), NULL
);
912 close_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), GTK_STOCK_CLOSE
);
913 window_set_cancel_button(cap_if_w
, close_bt
, window_cancel_button_cb
);
914 gtk_widget_set_tooltip_text(close_bt
, "Close this window.");
915 options_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), WIRESHARK_STOCK_CAPTURE_OPTIONS
);
916 g_signal_connect(options_bt
, "clicked", G_CALLBACK(capture_prepare_cb
), NULL
);
917 capture_bt
= (GtkWidget
*)g_object_get_data(G_OBJECT(bbox
), WIRESHARK_STOCK_CAPTURE_START
);
918 g_signal_connect(capture_bt
, "clicked", G_CALLBACK(capture_do_cb
), NULL
);
920 gtk_widget_grab_default(close_bt
);
922 g_signal_connect(cap_if_w
, "delete_event", G_CALLBACK(window_delete_event_cb
), NULL
);
923 g_signal_connect(cap_if_w
, "destroy", G_CALLBACK(capture_if_destroy_cb
), sc
);
925 capture_if_refresh_if_list();
927 window_present(cap_if_w
);
929 set_capture_if_dialog_for_capture_in_progress(gbl_capture_in_progress
);
932 gboolean
interfaces_dialog_window_present(void)
934 return (cap_if_w
?TRUE
:FALSE
);
937 void refresh_if_window(void)
940 capture_if_refresh_if_list();
944 void select_all_interfaces(gboolean enable _U_
)
949 for (ifs
= 0; ifs
< global_capture_opts
.all_ifaces
->len
; ifs
++) {
950 device
= g_array_index(global_capture_opts
.all_ifaces
, interface_t
, ifs
);
951 update_selected_interface(device
.if_info
.name
);
955 void destroy_if_window(void)
958 window_destroy(cap_if_w
);
961 #else /* HAVE_LIBPCAP */
964 set_capture_if_dialog_for_capture_in_progress(gboolean capture_in_progress _U_
)
968 #endif /* HAVE_LIBPCAP */
976 * indent-tabs-mode: nil
979 * ex: set shiftwidth=2 tabstop=8 expandtab:
980 * :indentSize=2:tabSize=8:noTabs=true: