Witness: enum witness_notifyResponse_type
[wireshark-wip.git] / ui / gtk / capture_if_dlg.c
blobba739de61db517db216d9c5803dc01d5767ed88a
1 /* capture_if_dlg.c
2 * Routines for the capture interface dialog
4 * $Id$
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.
25 #include "config.h"
27 #include <gtk/gtk.h>
29 #ifdef HAVE_LIBPCAP
31 #include <string.h>
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"
48 #ifdef _WIN32
49 #include "ui/gtk/capture_if_details_dlg_win32.h"
50 #include "../../capture-wpcap.h"
51 #endif
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"
69 #ifdef HAVE_AIRPCAP
70 #include "../../image/toolbar/capture_airpcap_16.xpm"
71 #endif
73 #if defined(HAVE_PCAP_REMOTE)
74 #include "ui/gtk/remote_icons.h"
75 #endif
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"*/
87 #ifdef HAVE_AIRPCAP
88 #include "airpcap.h"
89 #include "airpcap_loader.h"
90 #include "airpcap_gui_utils.h"
91 #include "airpcap_dlg.h"
92 #endif
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 {
123 gchar *device;
124 GtkWidget *device_lb;
125 GtkWidget *descr_lb;
126 GtkWidget *ip_lb;
127 GtkWidget *curr_lb;
128 GtkWidget *last_lb;
129 GtkWidget *choose_bt;
130 #ifdef _WIN32
131 GtkWidget *details_bt;
132 #endif
133 gboolean hidden;
134 } if_dlg_data_t;
136 static gboolean gbl_capture_in_progress = FALSE;
138 #if 0
139 void
140 add_interface(void)
142 if_dlg_data_t data;
144 data.device_lb = NULL;
145 data.descr_lb = NULL;
146 data.ip_lb = NULL;
147 data.curr_lb = NULL;
148 data.last_lb = NULL;
149 data.choose_bt = NULL;
150 #ifdef _WIN32
151 data.details_bt = NULL;
152 #endif
153 data.hidden = FALSE;
154 g_array_append_val(if_array, data);
155 refresh_if_window();
157 #endif
159 void
160 update_selected_interface(gchar *name)
162 guint i;
163 interface_t device;
164 if_dlg_data_t data;
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);
171 break;
176 static void
177 store_selected(GtkWidget *choose_bt, gpointer name)
179 interface_t device;
180 guint i;
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++;
189 } else {
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);
204 break;
207 if (cap_if_w) {
208 gtk_widget_set_sensitive(capture_bt, !gbl_capture_in_progress && (global_capture_opts.num_selected > 0));
212 /* start capture button was pressed */
213 static void
214 capture_do_cb(GtkWidget *capture_bt_arg _U_, gpointer if_data _U_)
216 if_dlg_data_t data;
217 guint ifs;
219 for (ifs = 0; ifs < if_array->len; ifs++) {
220 data = g_array_index(if_array, if_dlg_data_t, ifs);
221 if (data.hidden) {
222 continue;
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);
227 #ifdef HAVE_AIRPCAP
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;
230 #endif
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 */
250 static void
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);
262 #ifdef _WIN32
263 /* capture details button was pressed */
264 static void
265 capture_details_cb(GtkWidget *details_bt _U_, gpointer name)
267 capture_if_details_open(name);
269 #endif
271 /* update a single interface */
272 static void
273 update_if(gchar *name, if_stat_cache_t *sc_p)
275 struct pcap_stat stats;
276 gchar *str;
277 guint diff, ifs, data_ifs;
278 interface_t device;
279 if_dlg_data_t data;
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
286 * pcap_stats call.
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;
292 data.curr_lb = NULL;
293 data.last_lb = NULL;
294 if (sc_p) {
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) {
300 found = TRUE;
301 break;
305 if (found) {
306 if (capture_stats(sc_p, name, &stats)) {
307 if ((int)(stats.ps_recv - device.last_packets) < 0) {
308 diff = 0;
309 } else {
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);
316 g_free(str);
317 str = g_strdup_printf("%u", diff);
318 gtk_label_set_text(GTK_LABEL(data.last_lb), str);
319 g_free(str);
321 gtk_widget_set_sensitive(data.curr_lb, diff);
322 gtk_widget_set_sensitive(data.last_lb, diff);
323 } else {
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 */
336 static gboolean
337 update_all(gpointer data)
339 interface_t device;
340 guint ifs;
341 if_stat_cache_t *sc_p = (if_stat_cache_t *)data;
343 if (!cap_if_w) {
344 return FALSE;
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);
352 return TRUE;
355 /* a live capture has started or stopped */
356 void
357 set_capture_if_dialog_for_capture_in_progress(gboolean capture_in_progress)
359 gbl_capture_in_progress = capture_in_progress;
360 if (cap_if_w) {
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 */
367 void
368 set_capture_if_dialog_for_capture_stopping(void)
370 if (cap_if_w) {
371 gtk_widget_set_sensitive(stop_bt, FALSE);
376 /* the window was closed, cleanup things */
377 static void
378 capture_if_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
380 g_source_remove(timer_id);
382 if (sc) {
383 capture_stat_stop(sc);
384 sc = NULL;
386 window_destroy(GTK_WIDGET(cap_if_w));
387 /* Note that we no longer have a "Capture Options" dialog box. */
388 cap_if_w = NULL;
389 cap_if_top_vb = NULL;
390 cap_if_sw = NULL;
391 #ifdef HAVE_AIRPCAP
392 if (airpcap_if_active)
393 airpcap_set_toolbar_stop_capture(airpcap_if_active);
394 #endif
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);
407 #endif
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) {
412 case IF_DIALUP:
413 return xpm_to_widget(modem_16_xpm);
414 case IF_WIRELESS:
415 return pixbuf_to_widget(network_wireless_pb_data);
416 #ifdef HAVE_AIRPCAP
417 case IF_AIRPCAP:
418 return xpm_to_widget(capture_airpcap_16_xpm);
419 #endif
420 case IF_BLUETOOTH:
421 return pixbuf_to_widget(network_bluetooth_pb_data);
422 case IF_USB:
423 return pixbuf_to_widget(network_usb_pb_data);
424 case IF_VIRTUAL:
425 return xpm_to_widget(network_virtual_16_xpm);
426 case IF_WIRED:
427 return pixbuf_to_widget(network_wired_pb_data);
428 case IF_PIPE:
429 case IF_STDIN:
430 return pixbuf_to_widget(pipe_pb_data);
431 default:
432 printf("unknown device type\n");
434 return pixbuf_to_widget(network_wired_pb_data);
438 static int
439 get_ip_addr_count(GSList *addr_list)
441 GSList *curr_addr;
442 if_addr_t *addr;
443 int count;
445 count = 0;
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) {
451 case IF_AT_IPv4:
452 case IF_AT_IPv6:
453 count++;
454 break;
456 default:
457 /* In case we add non-IP addresses */
458 break;
461 return count;
464 static const gchar *
465 set_ip_addr_label(GSList *addr_list, GtkWidget *ip_lb, guint selected_ip_addr)
467 GSList *curr_addr;
468 if_addr_t *addr;
469 const gchar *addr_str = NULL;
471 curr_addr = g_slist_nth(addr_list, selected_ip_addr);
472 if (curr_addr) {
473 addr = (if_addr_t *)curr_addr->data;
474 switch (addr->ifat_type) {
476 case IF_AT_IPv4:
477 addr_str = ip_to_str((guint8 *)&addr->addr.ip4_addr);
478 break;
480 case IF_AT_IPv6:
481 addr_str = ip6_to_str((struct e_in6_addr *)&addr->addr.ip6_addr);
482 break;
484 default:
485 /* Ignore non-IP addresses, in case we ever support them */
486 break;
490 if (addr_str) {
491 gtk_label_set_text(GTK_LABEL(ip_lb), addr_str);
492 } else {
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));
497 return addr_str;
501 static gboolean
502 ip_label_enter_cb(GtkWidget *eb, GdkEventCrossing *event _U_, gpointer user_data _U_)
504 gtk_widget_set_state(eb, GTK_STATE_PRELIGHT);
506 return FALSE;
510 static gboolean
511 ip_label_leave_cb(GtkWidget *eb, GdkEvent *event _U_, gpointer user_data _U_)
513 gtk_widget_set_state(eb, GTK_STATE_NORMAL);
515 return FALSE;
519 static gboolean
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;
525 if_addr_t *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);
530 for (;;) {
531 selected_ip_addr++;
532 if (g_slist_length(addr_list) <= selected_ip_addr) {
533 /* Wrap around */
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 */
539 break;
542 addr = (if_addr_t *)curr_addr->data;
543 switch (addr->ifat_type) {
545 case IF_AT_IPv4:
546 case IF_AT_IPv6:
547 goto found;
549 default:
550 /* In case we add non-IP addresses */
551 break;
555 found:
556 set_ip_addr_label(addr_list, ip_lb, selected_ip_addr);
558 return FALSE;
561 static void
562 capture_if_stop_cb(GtkWidget *w _U_, gpointer d _U_)
564 guint ifs;
565 if_dlg_data_t data;
567 for (ifs = 0; ifs < if_array->len; ifs++) {
568 data = g_array_index(if_array, if_dlg_data_t, ifs);
569 if (data.hidden) {
570 continue;
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);
579 static void
580 make_if_array(void)
582 if_dlg_data_t data;
583 guint i;
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;
590 data.ip_lb = NULL;
591 data.curr_lb = NULL;
592 data.last_lb = NULL;
593 data.choose_bt = NULL;
594 #ifdef _WIN32
595 data.details_bt = NULL;
596 #endif
597 data.hidden = FALSE;
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.
612 static gboolean
613 can_capture(void)
615 #ifdef _WIN32
616 /* Is WPcap loaded? */
617 if (!has_wpcap) {
618 char *detailed_err;
620 detailed_err = cant_load_winpcap_err("Wireshark");
621 simple_error_message_box("%s", detailed_err);
622 g_free(detailed_err);
623 return FALSE;
625 #endif
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.");
629 return FALSE;
632 return TRUE;
635 static void
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;
641 guint ifs;
642 interface_t device;
643 const gchar *addr_str;
644 gchar *user_descr;
645 if_dlg_data_t data;
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. */
650 destroy_if_window();
651 return;
654 if (cap_if_sw) {
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
663 statistics on it. */
665 make_if_array();
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);
675 #else
676 gtk_container_add(GTK_CONTAINER(cap_if_sw), if_vb);
677 #endif
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);
706 row++;
708 height += 30;
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 */
717 if (device.hidden) {
718 data.hidden = TRUE;
719 if_array = g_array_remove_index(if_array, ifs);
720 g_array_insert_val(if_array, ifs, data);
721 continue;
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);
728 } else {
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);
738 /* device name */
739 #ifdef _WIN32
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);
746 #else
747 data.device_lb = gtk_label_new(device.name);
748 #endif
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);
756 /* description */
757 user_descr = capture_dev_user_descr_find(device.name);
758 if (user_descr) {
759 data.descr_lb = gtk_label_new(user_descr);
760 g_free (user_descr);
761 } else {
762 if (device.if_info.vendor_description)
763 data.descr_lb = gtk_label_new(device.if_info.vendor_description);
764 else
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);
774 /* IP address */
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);
778 if (addr_str) {
779 gtk_widget_set_sensitive(data.ip_lb, TRUE);
780 } else {
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);
796 /* packets */
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);
801 /* packets/s */
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);
806 /* details button */
807 #ifdef _WIN32
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);
813 } else {
814 gtk_widget_set_sensitive(data.details_bt, FALSE);
816 #endif
817 if_array = g_array_remove_index(if_array, ifs);
818 g_array_insert_val(if_array, ifs, data);
820 row++;
821 if (row <= 20) {
822 /* Add up to 20 rows of interfaces, otherwise the window may become too high */
823 #ifdef _WIN32
824 gtk_widget_get_preferred_size(GTK_WIDGET(data.details_bt), &requisition, NULL);
825 #else
826 gtk_widget_get_preferred_size(GTK_WIDGET(data.choose_bt), &requisition, NULL);
827 #endif
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 */
845 void
846 capture_if_cb(GtkWidget *w _U_, gpointer d _U_)
848 GtkWidget *bbox,
849 *help_bt;
850 #ifdef HAVE_AIRPCAP
851 GtkWidget *decryption_cb;
852 #endif
854 if (cap_if_w != NULL) {
855 /* There's already a "Capture Interfaces" dialog box; reactivate it. */
856 reactivate_window(cap_if_w);
857 return;
860 if (!can_capture()) {
861 /* No interfaces or, on Windows, no WinPcap; just give up. */
862 return;
865 #ifdef HAVE_AIRPCAP
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);
873 } else {
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);
888 #endif
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)
939 if (cap_if_w) {
940 capture_if_refresh_if_list();
944 void select_all_interfaces(gboolean enable _U_)
946 guint ifs;
947 interface_t device;
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)
957 if (cap_if_w) {
958 window_destroy(cap_if_w);
961 #else /* HAVE_LIBPCAP */
963 void
964 set_capture_if_dialog_for_capture_in_progress(gboolean capture_in_progress _U_)
968 #endif /* HAVE_LIBPCAP */
971 * Editor modelines
973 * Local Variables:
974 * c-basic-offset: 2
975 * tab-width: 8
976 * indent-tabs-mode: nil
977 * End:
979 * ex: set shiftwidth=2 tabstop=8 expandtab:
980 * :indentSize=2:tabSize=8:noTabs=true: