2 * Routines for packet capture windows
4 * $Id: capture_dlg.c,v 1.98 2004/01/29 23:11:37 ulfl Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #include <epan/packet.h>
38 #include <epan/resolv.h>
41 #include "capture_dlg.h"
42 #include "filter_prefs.h"
43 #include "simple_dialog.h"
44 #include "dlg_utils.h"
45 #include "pcap-util.h"
46 #include "capture_combo_utils.h"
48 #include "ringbuffer.h"
49 #include <epan/filesystem.h>
50 #include "compat_macros.h"
54 #include "capture-wpcap.h"
57 /* Capture callback data keys */
58 #define E_CAP_IFACE_KEY "cap_iface"
59 #define E_CAP_SNAP_CB_KEY "cap_snap_cb"
60 #define E_CAP_LT_OM_KEY "cap_lt_om"
61 #define E_CAP_LT_OM_LABEL_KEY "cap_lt_om_label"
62 #define E_CAP_SNAP_SB_KEY "cap_snap_sb"
63 #define E_CAP_PROMISC_KEY "cap_promisc"
64 #define E_CAP_FILT_KEY "cap_filter_te"
65 #define E_CAP_FILE_TE_KEY "cap_file_te"
66 #define E_CAP_RING_ON_TB_KEY "cap_ringbuffer_on_tb"
67 #define E_CAP_RING_NBF_LB_KEY "cap_ringbuffer_nbf_lb"
68 #define E_CAP_RING_NBF_SB_KEY "cap_ringbuffer_nbf_sb"
69 #define E_CAP_RING_DURATION_CB_KEY "cap_ringbuffer_duration_cb"
70 #define E_CAP_RING_DURATION_SB_KEY "cap_ringbuffer_duration_sb"
71 #define E_CAP_SYNC_KEY "cap_sync"
72 #define E_CAP_AUTO_SCROLL_KEY "cap_auto_scroll"
73 #define E_CAP_COUNT_CB_KEY "cap_count_cb"
74 #define E_CAP_COUNT_SB_KEY "cap_count_sb"
75 #define E_CAP_FILESIZE_CB_KEY "cap_filesize_cb"
76 #define E_CAP_FILESIZE_SB_KEY "cap_filesize_sb"
77 #define E_CAP_FILESIZE_LB_KEY "cap_filesize_lb"
78 #define E_CAP_DURATION_CB_KEY "cap_duration_cb"
79 #define E_CAP_DURATION_SB_KEY "cap_duration_sb"
80 #define E_CAP_M_RESOLVE_KEY "cap_m_resolve"
81 #define E_CAP_N_RESOLVE_KEY "cap_n_resolve"
82 #define E_CAP_T_RESOLVE_KEY "cap_t_resolve"
84 #define E_CAP_OM_LT_VALUE_KEY "cap_om_lt_value"
86 #define E_FS_CALLER_PTR_KEY "fs_caller_ptr"
87 #define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr"
90 capture_prep_file_cb(GtkWidget *w, gpointer te);
93 select_link_type_cb(GtkWidget *w, gpointer data);
96 cap_prep_fs_ok_cb(GtkWidget *w, gpointer data);
99 cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data);
102 cap_prep_fs_destroy_cb(GtkWidget *win, GtkWidget* file_te);
105 capture_prep_adjust_sensitivity(GtkWidget *tb, gpointer parent_w);
108 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
111 capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w);
114 capture_prep_destroy_cb(GtkWidget *win, gpointer user_data);
117 capture_prep_interface_changed_cb(GtkWidget *entry, gpointer parent_w);
120 capture_stop_cb(GtkWidget *w _U_, gpointer d _U_)
126 * Given text that contains an interface name possibly prefixed by an
127 * interface description, extract the interface name.
130 get_if_name(char *if_text)
136 * We cannot assume that the interface name doesn't contain a space;
137 * however, we can assume it begins with "\Device\". Search forwards
138 * for a backslash; if it's followed by "Device\", stop there,
139 * otherwise keep scanning until we find "\Device\". If we don't find
140 * it, just return the entire string.
144 if_name = strchr(if_name, '\\');
146 return if_text; /* give up */
147 if (strncmp(if_name + 1, "Device\\", 7) == 0)
153 * There's a space between the interface description and name, and
154 * the interface name shouldn't have a space in it (it doesn't, on
155 * UNIX systems); look backwards in the string for a space.
157 if_name = strrchr(if_text, ' ');
158 if (if_name == NULL) {
168 * Keep a static pointer to the current "Capture Options" window, if
169 * any, so that if somebody tries to do "Capture:Start" while there's
170 * already a "Capture Options" window up, we just pop up the existing
171 * one, rather than creating a new one.
173 static GtkWidget *cap_open_w;
176 set_link_type_list(GtkWidget *linktype_om, GtkWidget *entry)
186 char err_buf[PCAP_ERRBUF_SIZE];
187 GtkWidget *lt_menu, *lt_menu_item;
189 data_link_info_t *data_link_info;
190 gchar *linktype_menu_label;
191 guint num_supported_link_types;
192 GtkWidget *linktype_lb = OBJECT_GET_DATA(linktype_om, E_CAP_LT_OM_LABEL_KEY);
194 lt_menu = gtk_menu_new();
195 entry_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
196 if_text = g_strstrip(entry_text);
197 if_name = get_if_name(if_text);
200 * If the interface name is in the list of known interfaces, get
201 * its list of link-layer types and set the option menu to display it.
203 * If it's not, don't bother - the user might be in the middle of
204 * editing the list, or it might be a remote device in which case
205 * getting the list could take an arbitrarily-long period of time.
206 * The list currently won't contain any remote devices (as
207 * "pcap_findalldevs()" doesn't know about remote devices, and neither
208 * does the code we use if "pcap_findalldevs()" isn't available), but
209 * should contain all the local devices on which you can capture.
212 if (*if_name != '\0') {
214 * Try to get the list of known interfaces.
216 if_list = get_interface_list(&err, err_buf);
217 if (if_list != NULL) {
219 * We have the list - check it.
221 for (if_entry = if_list; if_entry != NULL;
222 if_entry = g_list_next(if_entry)) {
223 if_info = if_entry->data;
224 if (strcmp(if_info->name, if_name) == 0) {
227 * Get the list of link-layer types for it.
229 lt_list = get_pcap_linktype_list(if_name, err_buf);
232 free_interface_list(if_list);
236 num_supported_link_types = 0;
237 for (lt_entry = lt_list; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
238 data_link_info = lt_entry->data;
239 if (data_link_info->description != NULL) {
240 lt_menu_item = gtk_menu_item_new_with_label(data_link_info->description);
241 OBJECT_SET_DATA(lt_menu_item, E_CAP_LT_OM_KEY, linktype_om);
242 SIGNAL_CONNECT(lt_menu_item, "activate", select_link_type_cb,
243 GINT_TO_POINTER(data_link_info->dlt));
244 num_supported_link_types++;
246 /* Not supported - tell them about it but don't let them select it. */
247 linktype_menu_label = g_strdup_printf("%s (not supported)",
248 data_link_info->name);
249 lt_menu_item = gtk_menu_item_new_with_label(linktype_menu_label);
250 g_free(linktype_menu_label);
251 gtk_widget_set_sensitive(lt_menu_item, FALSE);
253 gtk_menu_append(GTK_MENU(lt_menu), lt_menu_item);
254 gtk_widget_show(lt_menu_item);
257 free_pcap_linktype_list(lt_list);
258 gtk_option_menu_set_menu(GTK_OPTION_MENU(linktype_om), lt_menu);
259 gtk_widget_set_sensitive(linktype_lb, num_supported_link_types >= 2);
260 gtk_widget_set_sensitive(linktype_om, num_supported_link_types >= 2);
267 *capture_fr, *capture_vb,
268 *if_hb, *if_cb, *if_lb,
269 *linktype_hb, *linktype_lb, *linktype_om,
270 *snap_hb, *snap_cb, *snap_sb, *snap_lb,
272 *filter_hb, *filter_bt, *filter_te,
274 *file_hb, *file_bt, *file_lb, *file_te,
275 *ringbuffer_hb, *ringbuffer_on_tb, *ringbuffer_nbf_lb, *ringbuffer_nbf_sb,
276 *display_fr, *display_vb,
277 *sync_cb, *auto_scroll_cb,
278 *limit_fr, *limit_vb,
279 *count_hb, *count_cb, *count_sb, *count_lb,
280 *filesize_hb, *filesize_cb, *filesize_sb, *filesize_lb,
281 *duration_hb, *duration_cb, *duration_sb, *duration_lb,
282 *ring_duration_hb, *ring_duration_cb, *ring_duration_sb,
284 *resolv_fr, *resolv_vb,
285 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb,
286 *bbox, *ok_bt, *cancel_bt;
287 #if GTK_MAJOR_VERSION < 2
288 GtkAccelGroup *accel_group;
290 GtkAdjustment *snap_adj, *ringbuffer_nbf_adj,
291 *count_adj, *filesize_adj, *duration_adj, *ring_duration_adj;
292 GList *if_list, *combo_list;
294 char err_str[PCAP_ERRBUF_SIZE];
296 if (cap_open_w != NULL) {
297 /* There's already a "Capture Options" dialog box; reactivate it. */
298 reactivate_window(cap_open_w);
303 /* Is WPcap loaded? */
305 simple_dialog(ESD_TYPE_CRIT, NULL,
306 "Unable to load WinPcap (wpcap.dll); Ethereal will not be able\n"
307 "to capture packets.\n\n"
308 "In order to capture packets, WinPcap must be installed; see\n"
310 " http://winpcap.polito.it/\n"
314 " http://winpcap.mirror.ethereal.com/\n"
318 " http://www.mirrors.wiretapped.net/security/packet-capture/winpcap/\n"
320 "for a downloadable version of WinPcap and for instructions\n"
321 "on how to install WinPcap.");
326 if_list = get_interface_list(&err, err_str);
327 if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
328 simple_dialog(ESD_TYPE_WARN, NULL, "Can't get list of interfaces: %s",
332 cap_open_w = dlg_window_new("Ethereal: Capture Options");
333 SIGNAL_CONNECT(cap_open_w, "destroy", capture_prep_destroy_cb, NULL);
335 #if GTK_MAJOR_VERSION < 2
336 /* Accelerator group for the accelerators (or, as they're called in
337 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
338 Ctrl+<key> is an accelerator). */
339 accel_group = gtk_accel_group_new();
340 gtk_window_add_accel_group(GTK_WINDOW(cap_open_w), accel_group);
343 main_vb = gtk_vbox_new(FALSE, 0);
344 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
345 gtk_container_add(GTK_CONTAINER(cap_open_w), main_vb);
346 gtk_widget_show(main_vb);
348 /* Capture-related options frame */
349 capture_fr = gtk_frame_new("Capture");
350 gtk_container_add(GTK_CONTAINER(main_vb), capture_fr);
351 gtk_widget_show(capture_fr);
353 capture_vb = gtk_vbox_new(FALSE, 0);
354 gtk_container_add(GTK_CONTAINER(capture_fr), capture_vb);
355 gtk_widget_show(capture_vb);
358 if_hb = gtk_hbox_new(FALSE, 3);
359 gtk_container_add(GTK_CONTAINER(capture_vb), if_hb);
360 gtk_widget_show(if_hb);
362 if_lb = gtk_label_new("Interface:");
363 gtk_box_pack_start(GTK_BOX(if_hb), if_lb, FALSE, FALSE, 6);
364 gtk_widget_show(if_lb);
366 if_cb = gtk_combo_new();
367 combo_list = build_capture_combo_list(if_list, TRUE);
368 if (combo_list != NULL)
369 gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), combo_list);
370 if (cfile.iface == NULL && prefs.capture_device != NULL) {
371 /* No interface was specified on the command line or in a previous
372 capture, but there is one specified in the preferences file;
373 make the one from the preferences file the default */
374 cfile.iface = g_strdup(prefs.capture_device);
376 if (cfile.iface != NULL)
377 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cfile.iface);
378 else if (combo_list != NULL) {
379 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry),
380 (char *)combo_list->data);
382 free_capture_combo_list(combo_list);
383 free_interface_list(if_list);
384 gtk_box_pack_start(GTK_BOX(if_hb), if_cb, TRUE, TRUE, 6);
385 gtk_widget_show(if_cb);
388 linktype_hb = gtk_hbox_new(FALSE, 3);
389 gtk_container_add(GTK_CONTAINER(capture_vb), linktype_hb);
390 gtk_widget_show(linktype_hb);
392 linktype_lb = gtk_label_new("Link-layer header type:");
393 gtk_box_pack_start(GTK_BOX(linktype_hb), linktype_lb, FALSE, FALSE, 6);
394 gtk_widget_show(linktype_lb);
396 linktype_om = gtk_option_menu_new();
397 OBJECT_SET_DATA(linktype_om, E_CAP_LT_OM_LABEL_KEY, linktype_lb);
398 /* Default to "use the default" */
399 OBJECT_SET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(-1));
400 set_link_type_list(linktype_om, GTK_COMBO(if_cb)->entry);
401 gtk_box_pack_start (GTK_BOX(linktype_hb), linktype_om, FALSE, FALSE, 0);
402 gtk_widget_show(linktype_om);
403 SIGNAL_CONNECT(GTK_ENTRY(GTK_COMBO(if_cb)->entry), "changed",
404 capture_prep_interface_changed_cb, linktype_om);
406 /* Capture length row */
407 snap_hb = gtk_hbox_new(FALSE, 3);
408 gtk_container_add(GTK_CONTAINER(capture_vb), snap_hb);
409 gtk_widget_show(snap_hb);
411 snap_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("_Limit each packet to", accel_group);
412 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(snap_cb),
413 capture_opts.has_snaplen);
414 SIGNAL_CONNECT(snap_cb, "toggled", capture_prep_adjust_sensitivity, cap_open_w);
415 gtk_box_pack_start(GTK_BOX(snap_hb), snap_cb, FALSE, FALSE, 0);
416 gtk_widget_show(snap_cb);
418 snap_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat) capture_opts.snaplen,
419 MIN_PACKET_SIZE, WTAP_MAX_PACKET_SIZE, 1.0, 10.0, 0.0);
420 snap_sb = gtk_spin_button_new (snap_adj, 0, 0);
421 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE);
422 WIDGET_SET_SIZE(snap_sb, 80, -1);
423 gtk_box_pack_start (GTK_BOX(snap_hb), snap_sb, FALSE, FALSE, 0);
424 gtk_widget_show(snap_sb);
426 snap_lb = gtk_label_new("bytes");
427 gtk_misc_set_alignment(GTK_MISC(snap_lb), 0, 0.5);
428 gtk_box_pack_start(GTK_BOX(snap_hb), snap_lb, FALSE, FALSE, 0);
429 gtk_widget_show(snap_lb);
431 /* Promiscuous mode row */
432 promisc_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC(
433 "Capture packets in _promiscuous mode", accel_group);
434 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(promisc_cb),
435 capture_opts.promisc_mode);
436 gtk_container_add(GTK_CONTAINER(capture_vb), promisc_cb);
437 gtk_widget_show(promisc_cb);
440 filter_hb = gtk_hbox_new(FALSE, 3);
441 gtk_container_add(GTK_CONTAINER(capture_vb), filter_hb);
442 gtk_widget_show(filter_hb);
444 filter_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_CAPTURE_FILTER_ENTRY);
445 SIGNAL_CONNECT(filter_bt, "clicked", capture_filter_construct_cb, NULL);
446 SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
447 gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, FALSE, 3);
448 gtk_widget_show(filter_bt);
450 filter_te = gtk_entry_new();
451 if (cfile.cfilter) gtk_entry_set_text(GTK_ENTRY(filter_te), cfile.cfilter);
452 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
453 gtk_box_pack_start(GTK_BOX(filter_hb), filter_te, TRUE, TRUE, 3);
454 gtk_widget_show(filter_te);
456 /* Capture file-related options frame */
457 file_fr = gtk_frame_new("Capture file(s)");
458 gtk_container_add(GTK_CONTAINER(main_vb), file_fr);
459 gtk_widget_show(file_fr);
461 file_vb = gtk_vbox_new(FALSE, 3);
462 gtk_container_add(GTK_CONTAINER(file_fr), file_vb);
463 gtk_widget_show(file_vb);
466 file_hb = gtk_hbox_new(FALSE, 3);
467 gtk_container_add(GTK_CONTAINER(file_vb), file_hb);
468 gtk_widget_show(file_hb);
470 file_lb = gtk_label_new("File:");
471 gtk_box_pack_start(GTK_BOX(file_hb), file_lb, FALSE, FALSE, 3);
472 gtk_widget_show(file_lb);
474 file_te = gtk_entry_new();
475 gtk_box_pack_start(GTK_BOX(file_hb), file_te, TRUE, TRUE, 3);
476 gtk_widget_show(file_te);
478 file_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_BROWSE);
479 gtk_box_pack_start(GTK_BOX(file_hb), file_bt, FALSE, FALSE, 3);
480 gtk_widget_show(file_bt);
482 SIGNAL_CONNECT(file_bt, "clicked", capture_prep_file_cb, file_te);
484 /* Ring buffer row */
485 ringbuffer_hb = gtk_hbox_new(FALSE, 3);
486 gtk_container_add(GTK_CONTAINER(file_vb), ringbuffer_hb);
487 gtk_widget_show(ringbuffer_hb);
489 ringbuffer_on_tb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Use _ring buffer", accel_group);
490 /* Ring buffer mode is allowed only if we're not doing an "Update list of
491 packets in real time" capture, so force it off if we're doing such
493 if (capture_opts.sync_mode)
494 capture_opts.ringbuffer_on = FALSE;
495 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ringbuffer_on_tb),
496 capture_opts.ringbuffer_on);
497 SIGNAL_CONNECT(ringbuffer_on_tb, "toggled", capture_prep_adjust_sensitivity,
499 gtk_box_pack_start(GTK_BOX(ringbuffer_hb), ringbuffer_on_tb, FALSE, FALSE, 0);
500 gtk_widget_show(ringbuffer_on_tb);
502 ringbuffer_nbf_lb = gtk_label_new("Number of files");
503 gtk_misc_set_alignment(GTK_MISC(ringbuffer_nbf_lb), 1, 0.5);
504 gtk_box_pack_start(GTK_BOX(ringbuffer_hb), ringbuffer_nbf_lb, FALSE, FALSE, 6);
505 gtk_widget_show(ringbuffer_nbf_lb);
507 ringbuffer_nbf_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat) capture_opts.ringbuffer_num_files,
508 RINGBUFFER_MIN_NUM_FILES, RINGBUFFER_MAX_NUM_FILES, 1.0, 10.0, 0.0);
509 ringbuffer_nbf_sb = gtk_spin_button_new (ringbuffer_nbf_adj, 0, 0);
510 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (ringbuffer_nbf_sb), TRUE);
511 WIDGET_SET_SIZE(ringbuffer_nbf_sb, 40, -1);
512 gtk_box_pack_start (GTK_BOX(ringbuffer_hb), ringbuffer_nbf_sb, TRUE, TRUE, 0);
513 gtk_widget_show(ringbuffer_nbf_sb);
515 /* Ring buffer duration row */
516 ring_duration_hb = gtk_hbox_new(FALSE, 3);
517 gtk_container_add(GTK_CONTAINER(file_vb), ring_duration_hb);
518 gtk_widget_show(ring_duration_hb);
520 ring_duration_cb = gtk_check_button_new_with_label("Rotate capture file every");
521 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ring_duration_cb),
522 capture_opts.has_ring_duration);
523 SIGNAL_CONNECT(ring_duration_cb, "toggled",
524 capture_prep_adjust_sensitivity, cap_open_w);
525 gtk_box_pack_start(GTK_BOX(ring_duration_hb), ring_duration_cb,
527 gtk_widget_show(ring_duration_cb);
529 ring_duration_adj = (GtkAdjustment *)gtk_adjustment_new((gfloat)capture_opts.ringbuffer_duration,
530 1, (gfloat)INT_MAX, 1.0, 10.0, 0.0);
531 ring_duration_sb = gtk_spin_button_new (ring_duration_adj, 0, 0);
532 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (ring_duration_sb), TRUE);
533 WIDGET_SET_SIZE(ring_duration_sb, 80, -1);
534 gtk_box_pack_start (GTK_BOX(ring_duration_hb), ring_duration_sb,
536 gtk_widget_show(ring_duration_sb);
538 ring_duration_lb = gtk_label_new("second(s)");
539 gtk_misc_set_alignment(GTK_MISC(ring_duration_lb), 0, 0.5);
540 gtk_box_pack_start(GTK_BOX(ring_duration_hb), ring_duration_lb,
542 gtk_widget_show(ring_duration_lb);
544 /* Display-related options frame */
545 display_fr = gtk_frame_new("Display options");
546 gtk_container_add(GTK_CONTAINER(main_vb), display_fr);
547 gtk_widget_show(display_fr);
549 display_vb = gtk_vbox_new(FALSE, 0);
550 gtk_container_add(GTK_CONTAINER(display_fr), display_vb);
551 gtk_widget_show(display_vb);
553 /* "Update display in real time" row */
554 sync_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC(
555 "_Update list of packets in real time", accel_group);
556 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(sync_cb),
557 capture_opts.sync_mode);
558 SIGNAL_CONNECT(sync_cb, "toggled", capture_prep_adjust_sensitivity, cap_open_w);
559 gtk_container_add(GTK_CONTAINER(display_vb), sync_cb);
560 gtk_widget_show(sync_cb);
562 /* "Auto-scroll live update" row */
563 auto_scroll_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC(
564 "_Automatic scrolling in live capture", accel_group);
565 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(auto_scroll_cb), auto_scroll_live);
566 gtk_container_add(GTK_CONTAINER(display_vb), auto_scroll_cb);
567 gtk_widget_show(auto_scroll_cb);
569 /* Capture limits frame */
570 limit_fr = gtk_frame_new("Capture limits");
571 gtk_container_add(GTK_CONTAINER(main_vb), limit_fr);
572 gtk_widget_show(limit_fr);
574 limit_vb = gtk_vbox_new(FALSE, 0);
575 gtk_container_add(GTK_CONTAINER(limit_fr), limit_vb);
576 gtk_widget_show(limit_vb);
579 count_hb = gtk_hbox_new(FALSE, 3);
580 gtk_container_add(GTK_CONTAINER(limit_vb), count_hb);
581 gtk_widget_show(count_hb);
583 count_cb = gtk_check_button_new_with_label("Stop capture after");
584 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(count_cb),
585 capture_opts.has_autostop_count);
586 SIGNAL_CONNECT(count_cb, "toggled", capture_prep_adjust_sensitivity, cap_open_w);
587 gtk_box_pack_start(GTK_BOX(count_hb), count_cb, FALSE, FALSE, 0);
588 gtk_widget_show(count_cb);
590 count_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat)capture_opts.autostop_count,
591 1, (gfloat)INT_MAX, 1.0, 10.0, 0.0);
592 count_sb = gtk_spin_button_new (count_adj, 0, 0);
593 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (count_sb), TRUE);
594 WIDGET_SET_SIZE(count_sb, 80, -1);
595 gtk_box_pack_start (GTK_BOX(count_hb), count_sb, FALSE, FALSE, 0);
596 gtk_widget_show(count_sb);
598 count_lb = gtk_label_new("packet(s) captured");
599 gtk_misc_set_alignment(GTK_MISC(count_lb), 0, 0.5);
600 gtk_box_pack_start(GTK_BOX(count_hb), count_lb, FALSE, FALSE, 0);
601 gtk_widget_show(count_lb);
604 filesize_hb = gtk_hbox_new(FALSE, 3);
605 gtk_container_add(GTK_CONTAINER(limit_vb), filesize_hb);
606 gtk_widget_show(filesize_hb);
608 filesize_cb = gtk_check_button_new_with_label("");
609 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filesize_cb),
610 capture_opts.has_autostop_filesize);
611 SIGNAL_CONNECT(filesize_cb, "toggled", capture_prep_adjust_sensitivity, cap_open_w);
612 gtk_box_pack_start(GTK_BOX(filesize_hb), filesize_cb, FALSE, FALSE, 0);
613 gtk_widget_show(filesize_cb);
615 filesize_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat)capture_opts.autostop_filesize,
616 1, (gfloat)INT_MAX, 1.0, 10.0, 0.0);
617 filesize_sb = gtk_spin_button_new (filesize_adj, 0, 0);
618 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (filesize_sb), TRUE);
619 WIDGET_SET_SIZE(filesize_sb, 80, -1);
620 gtk_box_pack_start (GTK_BOX(filesize_hb), filesize_sb, FALSE, FALSE, 0);
621 gtk_widget_show(filesize_sb);
623 filesize_lb = gtk_label_new("");
624 gtk_misc_set_alignment(GTK_MISC(filesize_lb), 0, 0.5);
625 gtk_box_pack_start(GTK_BOX(filesize_hb), filesize_lb, FALSE, FALSE, 0);
626 gtk_widget_show(filesize_lb);
629 duration_hb = gtk_hbox_new(FALSE, 3);
630 gtk_container_add(GTK_CONTAINER(limit_vb), duration_hb);
631 gtk_widget_show(duration_hb);
633 duration_cb = gtk_check_button_new_with_label("Stop capture after");
634 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(duration_cb),
635 capture_opts.has_autostop_duration);
636 SIGNAL_CONNECT(duration_cb, "toggled", capture_prep_adjust_sensitivity, cap_open_w);
637 gtk_box_pack_start(GTK_BOX(duration_hb), duration_cb, FALSE, FALSE, 0);
638 gtk_widget_show(duration_cb);
640 duration_adj = (GtkAdjustment *) gtk_adjustment_new((gfloat)capture_opts.autostop_duration,
641 1, (gfloat)INT_MAX, 1.0, 10.0, 0.0);
642 duration_sb = gtk_spin_button_new (duration_adj, 0, 0);
643 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (duration_sb), TRUE);
644 WIDGET_SET_SIZE(duration_sb, 80, -1);
645 gtk_box_pack_start (GTK_BOX(duration_hb), duration_sb, FALSE, FALSE, 0);
646 gtk_widget_show(duration_sb);
648 duration_lb = gtk_label_new("second(s)");
649 gtk_misc_set_alignment(GTK_MISC(duration_lb), 0, 0.5);
650 gtk_box_pack_start(GTK_BOX(duration_hb), duration_lb, FALSE, FALSE, 0);
651 gtk_widget_show(duration_lb);
653 /* Resolution options frame */
654 resolv_fr = gtk_frame_new("Name resolution");
655 gtk_container_add(GTK_CONTAINER(main_vb), resolv_fr);
656 gtk_widget_show(resolv_fr);
658 resolv_vb = gtk_vbox_new(FALSE, 0);
659 gtk_container_add(GTK_CONTAINER(resolv_fr), resolv_vb);
660 gtk_widget_show(resolv_vb);
662 m_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC(
663 "Enable _MAC name resolution", accel_group);
664 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(m_resolv_cb),
665 g_resolv_flags & RESOLV_MAC);
666 gtk_container_add(GTK_CONTAINER(resolv_vb), m_resolv_cb);
667 gtk_widget_show(m_resolv_cb);
669 n_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC(
670 "Enable _network name resolution", accel_group);
671 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(n_resolv_cb),
672 g_resolv_flags & RESOLV_NETWORK);
673 gtk_container_add(GTK_CONTAINER(resolv_vb), n_resolv_cb);
674 gtk_widget_show(n_resolv_cb);
676 t_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC(
677 "Enable _transport name resolution", accel_group);
678 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(t_resolv_cb),
679 g_resolv_flags & RESOLV_TRANSPORT);
680 gtk_container_add(GTK_CONTAINER(resolv_vb), t_resolv_cb);
681 gtk_widget_show(t_resolv_cb);
683 /* Button row: OK and cancel buttons */
684 bbox = dlg_button_row_new(GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL);
685 gtk_container_add(GTK_CONTAINER(main_vb), bbox);
686 gtk_widget_show(bbox);
688 ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_OK);
689 SIGNAL_CONNECT(ok_bt, "clicked", capture_prep_ok_cb, cap_open_w);
690 gtk_widget_grab_default(ok_bt);
692 cancel_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
693 SIGNAL_CONNECT(cancel_bt, "clicked", capture_prep_close_cb, cap_open_w);
695 /* Attach pointers to needed widgets to the capture prefs window/object */
696 OBJECT_SET_DATA(cap_open_w, E_CAP_IFACE_KEY, if_cb);
697 OBJECT_SET_DATA(cap_open_w, E_CAP_SNAP_CB_KEY, snap_cb);
698 OBJECT_SET_DATA(cap_open_w, E_CAP_SNAP_SB_KEY, snap_sb);
699 OBJECT_SET_DATA(cap_open_w, E_CAP_LT_OM_KEY, linktype_om);
700 OBJECT_SET_DATA(cap_open_w, E_CAP_PROMISC_KEY, promisc_cb);
701 OBJECT_SET_DATA(cap_open_w, E_CAP_FILT_KEY, filter_te);
702 OBJECT_SET_DATA(cap_open_w, E_CAP_FILE_TE_KEY, file_te);
703 OBJECT_SET_DATA(cap_open_w, E_CAP_RING_ON_TB_KEY, ringbuffer_on_tb);
704 OBJECT_SET_DATA(cap_open_w, E_CAP_RING_NBF_LB_KEY, ringbuffer_nbf_lb);
705 OBJECT_SET_DATA(cap_open_w, E_CAP_RING_NBF_SB_KEY, ringbuffer_nbf_sb);
706 OBJECT_SET_DATA(cap_open_w, E_CAP_RING_DURATION_CB_KEY, ring_duration_cb);
707 OBJECT_SET_DATA(cap_open_w, E_CAP_RING_DURATION_SB_KEY, ring_duration_sb);
708 OBJECT_SET_DATA(cap_open_w, E_CAP_SYNC_KEY, sync_cb);
709 OBJECT_SET_DATA(cap_open_w, E_CAP_AUTO_SCROLL_KEY, auto_scroll_cb);
710 OBJECT_SET_DATA(cap_open_w, E_CAP_COUNT_CB_KEY, count_cb);
711 OBJECT_SET_DATA(cap_open_w, E_CAP_COUNT_SB_KEY, count_sb);
712 OBJECT_SET_DATA(cap_open_w, E_CAP_FILESIZE_CB_KEY, filesize_cb);
713 OBJECT_SET_DATA(cap_open_w, E_CAP_FILESIZE_SB_KEY, filesize_sb);
714 OBJECT_SET_DATA(cap_open_w, E_CAP_FILESIZE_LB_KEY, filesize_lb);
715 OBJECT_SET_DATA(cap_open_w, E_CAP_DURATION_CB_KEY, duration_cb);
716 OBJECT_SET_DATA(cap_open_w, E_CAP_DURATION_SB_KEY, duration_sb);
717 OBJECT_SET_DATA(cap_open_w, E_CAP_M_RESOLVE_KEY, m_resolv_cb);
718 OBJECT_SET_DATA(cap_open_w, E_CAP_N_RESOLVE_KEY, n_resolv_cb);
719 OBJECT_SET_DATA(cap_open_w, E_CAP_T_RESOLVE_KEY, t_resolv_cb);
721 /* Set the sensitivity of various widgets as per the settings of other
723 capture_prep_adjust_sensitivity(NULL, cap_open_w);
725 /* Catch the "activate" signal on the filter and file name text
726 entries, so that if the user types Return there, we act as if the
727 "OK" button had been selected, as happens if Return is typed if some
728 widget that *doesn't* handle the Return key has the input focus. */
729 dlg_set_activate(filter_te, ok_bt);
730 dlg_set_activate(file_te, ok_bt);
732 /* Catch the "key_press_event" signal in the window, so that we can catch
733 the ESC key being pressed and act as if the "Cancel" button had
735 dlg_set_cancel(cap_open_w, cancel_bt);
737 /* XXX - why does not
739 gtk_widget_grab_focus(if_cb);
741 give the initial focus to the "Interface" combo box?
743 Or should I phrase that as "why does GTK+ continually frustrate
744 attempts to make GUIs driveable from the keyboard?" We have to
745 go catch the activate signal on every single GtkEntry widget
746 (rather than having widgets whose activate signal is *not*
747 caught not catch the Return keystroke, so that it passes on,
748 ultimately, to the window, which can activate the default
749 widget, i.e. the "OK" button); we have to catch the "key_press_event"
750 signal and have the handler check for ESC, so that we can have ESC
751 activate the "Cancel" button; in order to support Alt+<key> mnemonics
752 for buttons and the like, we may have to construct an accelerator
753 group by hand and set up the accelerators by hand (if that even
754 works - I've not tried it yet); we have to do a "gtk_widget_grab_focus()"
755 to keep some container widget from getting the initial focus, so that
756 you don't have to tab into the first widget in order to start typing
757 in it; and it now appears that you simply *can't* make a combo box
758 get the initial focus, at least not in the obvious fashion. Sigh.... */
760 gtk_widget_show(cap_open_w);
764 capture_prep_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
768 /* save file first */
769 file_save_as_cmd(after_save_capture_dialog, data);
774 case(ESD_BTN_CANCEL):
777 g_assert_not_reached();
782 capture_prep_cb(GtkWidget *w, gpointer d _U_)
786 if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
787 /* user didn't saved his current file, ask him */
788 dialog = simple_dialog(ESD_TYPE_QUEST | ESD_TYPE_MODAL,
789 ESD_BTN_YES | ESD_BTN_NO | ESD_BTN_CANCEL,
790 "Save packets to \"%s\" before capturing?",
791 cf_get_display_name(&cfile));
792 simple_dialog_set_cb(dialog, capture_prep_answered_cb, NULL);
794 /* unchanged file, just capture a new one */
800 select_link_type_cb(GtkWidget *w, gpointer data)
802 int new_linktype = GPOINTER_TO_INT(data);
803 GtkWidget *linktype_om = OBJECT_GET_DATA(w, E_CAP_LT_OM_KEY);
804 int old_linktype = GPOINTER_TO_INT(OBJECT_GET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY));
806 if (old_linktype != new_linktype)
807 OBJECT_SET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(new_linktype));
811 capture_prep_file_cb(GtkWidget *w, gpointer file_te)
813 GtkWidget *caller = gtk_widget_get_toplevel(w);
816 /* Has a file selection dialog box already been opened for that top-level
818 fs = OBJECT_GET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY);
821 /* Yes. Just re-activate that dialog box. */
822 reactivate_window(fs);
826 fs = file_selection_new ("Ethereal: Capture File");
828 /* If we've opened a file, start out by showing the files in the directory
829 in which that file resided. */
831 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
833 OBJECT_SET_DATA(fs, E_CAP_FILE_TE_KEY, file_te);
835 /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
836 OBJECT_SET_DATA(fs, E_FS_CALLER_PTR_KEY, caller);
838 /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
839 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, fs);
841 /* Call a handler when the file selection box is destroyed, so we can inform
842 our caller, if any, that it's been destroyed. */
843 SIGNAL_CONNECT(fs, "destroy", cap_prep_fs_destroy_cb, file_te);
845 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->ok_button, "clicked", cap_prep_fs_ok_cb, fs);
847 /* Connect the cancel_button to destroy the widget */
848 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->cancel_button, "clicked", cap_prep_fs_cancel_cb,
851 /* Catch the "key_press_event" signal in the window, so that we can catch
852 the ESC key being pressed and act as if the "Cancel" button had
854 dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
860 cap_prep_fs_ok_cb(GtkWidget *w _U_, gpointer data)
864 cf_name = g_strdup(gtk_file_selection_get_filename(
865 GTK_FILE_SELECTION (data)));
867 /* Perhaps the user specified a directory instead of a file.
868 Check whether they did. */
869 if (test_for_directory(cf_name) == EISDIR) {
870 /* It's a directory - set the file selection box to display it. */
871 set_last_open_dir(cf_name);
873 gtk_file_selection_set_filename(GTK_FILE_SELECTION(data),
878 gtk_entry_set_text(GTK_ENTRY(OBJECT_GET_DATA(data, E_CAP_FILE_TE_KEY)), cf_name);
880 gtk_widget_destroy(GTK_WIDGET(data));
885 cap_prep_fs_cancel_cb(GtkWidget *w _U_, gpointer data)
887 gtk_widget_destroy(GTK_WIDGET(data));
891 cap_prep_fs_destroy_cb(GtkWidget *win, GtkWidget* file_te)
895 /* Get the widget that requested that we be popped up.
896 (It should arrange to destroy us if it's destroyed, so
897 that we don't get a pointer to a non-existent window here.) */
898 caller = OBJECT_GET_DATA(win, E_FS_CALLER_PTR_KEY);
900 /* Tell it we no longer exist. */
901 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, NULL);
903 /* Now nuke this window. */
904 gtk_grab_remove(GTK_WIDGET(win));
905 gtk_widget_destroy(GTK_WIDGET(win));
907 /* Give the focus to the file text entry widget so the user can just press
908 Return to start the capture. */
909 gtk_widget_grab_focus(file_te);
913 capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) {
914 GtkWidget *if_cb, *snap_cb, *snap_sb, *promisc_cb, *filter_te,
915 *file_te, *ringbuffer_on_tb, *ringbuffer_nbf_sb,
916 *linktype_om, *sync_cb, *auto_scroll_cb,
917 *count_cb, *count_sb,
918 *filesize_cb, *filesize_sb,
919 *duration_cb, *duration_sb,
920 *ring_duration_cb, *ring_duration_sb,
921 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
925 const gchar *filter_text;
927 const gchar *g_save_file;
931 if_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_IFACE_KEY);
932 snap_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_CB_KEY);
933 snap_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_SB_KEY);
934 linktype_om = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_LT_OM_KEY);
935 promisc_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_PROMISC_KEY);
936 filter_te = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILT_KEY);
937 file_te = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILE_TE_KEY);
938 ringbuffer_on_tb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_ON_TB_KEY);
939 ringbuffer_nbf_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_SB_KEY);
940 ring_duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_CB_KEY);
941 ring_duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_SB_KEY);
942 sync_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SYNC_KEY);
943 auto_scroll_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_AUTO_SCROLL_KEY);
944 count_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_CB_KEY);
945 count_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_SB_KEY);
946 filesize_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILESIZE_CB_KEY);
947 filesize_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILESIZE_SB_KEY);
948 duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_DURATION_CB_KEY);
949 duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_DURATION_SB_KEY);
950 m_resolv_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_M_RESOLVE_KEY);
951 n_resolv_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_N_RESOLVE_KEY);
952 t_resolv_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_T_RESOLVE_KEY);
955 g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
956 if_text = g_strstrip(entry_text);
957 if_name = get_if_name(if_text);
958 if (*if_name == '\0') {
959 simple_dialog(ESD_TYPE_CRIT, NULL,
960 "You didn't specify an interface on which to capture packets.");
966 cfile.iface = g_strdup(if_name);
969 capture_opts.linktype =
970 GPOINTER_TO_INT(OBJECT_GET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY));
972 capture_opts.has_snaplen =
973 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb));
974 if (capture_opts.has_snaplen) {
975 capture_opts.snaplen =
976 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
977 if (capture_opts.snaplen < 1)
978 capture_opts.snaplen = WTAP_MAX_PACKET_SIZE;
979 else if (capture_opts.snaplen < MIN_PACKET_SIZE)
980 capture_opts.snaplen = MIN_PACKET_SIZE;
983 capture_opts.promisc_mode =
984 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(promisc_cb));
986 /* XXX - don't try to get clever and set "cfile.filter" to NULL if the
987 filter string is empty, as an indication that we don't have a filter
988 and thus don't have to set a filter when capturing - the version of
989 libpcap in Red Hat Linux 6.1, and versions based on later patches
990 in that series, don't bind the AF_PACKET socket to an interface
991 until a filter is set, which means they aren't bound at all if
992 no filter is set, which means no packets arrive as input on that
993 socket, which means Ethereal never sees any packets. */
994 filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
996 g_free(cfile.cfilter);
997 g_assert(filter_text != NULL);
998 cfile.cfilter = g_strdup(filter_text);
1000 g_save_file = gtk_entry_get_text(GTK_ENTRY(file_te));
1001 if (g_save_file && g_save_file[0]) {
1002 /* User specified a file to which the capture should be written. */
1003 save_file = g_strdup(g_save_file);
1004 /* Save the directory name for future file dialogs. */
1005 cf_name = g_strdup(g_save_file);
1006 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1007 set_last_open_dir(dirname);
1010 /* User didn't specify a file; save to a temporary file. */
1014 capture_opts.has_autostop_count =
1015 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(count_cb));
1016 if (capture_opts.has_autostop_count)
1017 capture_opts.autostop_count =
1018 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(count_sb));
1020 capture_opts.has_autostop_filesize =
1021 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filesize_cb));
1022 if (capture_opts.has_autostop_filesize)
1023 capture_opts.autostop_filesize =
1024 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(filesize_sb));
1026 capture_opts.has_autostop_duration =
1027 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(duration_cb));
1028 if (capture_opts.has_autostop_duration)
1029 capture_opts.autostop_duration =
1030 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(duration_sb));
1032 capture_opts.sync_mode =
1033 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sync_cb));
1036 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(auto_scroll_cb));
1038 g_resolv_flags = RESOLV_NONE;
1039 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(m_resolv_cb)))
1040 g_resolv_flags |= RESOLV_MAC;
1041 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(n_resolv_cb)))
1042 g_resolv_flags |= RESOLV_NETWORK;
1043 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t_resolv_cb)))
1044 g_resolv_flags |= RESOLV_TRANSPORT;
1046 capture_opts.ringbuffer_on =
1047 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb)) &&
1048 !(capture_opts.sync_mode);
1049 if (capture_opts.ringbuffer_on) {
1050 if (save_file == NULL) {
1051 simple_dialog(ESD_TYPE_CRIT, NULL,
1052 "You must specify a save file if you want to use the ring buffer.");
1054 } else if (!capture_opts.has_autostop_filesize) {
1055 simple_dialog(ESD_TYPE_CRIT, NULL,
1056 "You must specify a file size at which to rotate the capture files\n"
1057 "if you want to use the ring buffer.");
1063 capture_opts.ringbuffer_num_files =
1064 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ringbuffer_nbf_sb));
1065 if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
1066 capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
1067 #if RINGBUFFER_MIN_NUM_FILES > 0
1068 else if (capture_opts.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
1069 capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
1072 capture_opts.has_ring_duration =
1073 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ring_duration_cb));
1074 if (capture_opts.has_ring_duration)
1075 capture_opts.ringbuffer_duration =
1076 gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ring_duration_sb));
1078 gtk_widget_destroy(GTK_WIDGET(parent_w));
1080 do_capture(save_file);
1081 if (save_file != NULL)
1086 capture_prep_close_cb(GtkWidget *close_bt _U_, gpointer parent_w)
1088 gtk_grab_remove(GTK_WIDGET(parent_w));
1089 gtk_widget_destroy(GTK_WIDGET(parent_w));
1093 capture_prep_destroy_cb(GtkWidget *win, gpointer user_data _U_)
1097 /* Is there a file selection dialog associated with this
1098 Capture Options dialog? */
1099 fs = OBJECT_GET_DATA(win, E_FILE_SEL_DIALOG_PTR_KEY);
1102 /* Yes. Destroy it. */
1103 gtk_widget_destroy(fs);
1106 /* Note that we no longer have a "Capture Options" dialog box. */
1111 capture_prep_interface_changed_cb(GtkWidget *entry, gpointer argp)
1113 GtkWidget *linktype_om = argp;
1115 set_link_type_list(linktype_om, entry);
1119 * Adjust the sensitivity of various widgets as per the current setting
1123 capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
1127 *ringbuffer_on_tb, *ringbuffer_nbf_lb, *ringbuffer_nbf_sb,
1128 *sync_cb, *auto_scroll_cb,
1129 *count_cb, *count_sb,
1130 *filesize_cb, *filesize_sb, *filesize_lb,
1131 *duration_cb, *duration_sb,
1132 *ring_duration_cb, *ring_duration_sb;
1134 if_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_IFACE_KEY);
1135 snap_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_CB_KEY);
1136 snap_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_SB_KEY);
1137 ringbuffer_on_tb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_ON_TB_KEY);
1138 ringbuffer_nbf_lb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_LB_KEY);
1139 ringbuffer_nbf_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_SB_KEY);
1140 ring_duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_CB_KEY);
1141 ring_duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_SB_KEY);
1142 sync_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SYNC_KEY);
1143 auto_scroll_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_AUTO_SCROLL_KEY);
1144 count_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_CB_KEY);
1145 count_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_SB_KEY);
1146 filesize_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILESIZE_CB_KEY);
1147 filesize_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILESIZE_SB_KEY);
1148 filesize_lb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILESIZE_LB_KEY);
1149 duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_DURATION_CB_KEY);
1150 duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_DURATION_SB_KEY);
1152 /* The snapshot length spinbox is sensitive iff the "Limit each packet
1153 to" checkbox is on. */
1154 gtk_widget_set_sensitive(GTK_WIDGET(snap_sb),
1155 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb)));
1157 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sync_cb))) {
1158 /* "Update list of packets in real time" captures enabled; we don't
1159 support ring buffer mode for those captures, so turn ring buffer
1160 mode off if it's on, and make its toggle button, and the spin
1161 button for the number of ring buffer files (and the spin button's
1162 label), insensitive. */
1163 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb))) {
1164 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb), FALSE);
1166 gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_on_tb), FALSE);
1168 /* Auto-scroll mode is meaningful only in "Update list of packets
1169 in real time" captures, so make its toggle button sensitive. */
1170 gtk_widget_set_sensitive(GTK_WIDGET(auto_scroll_cb), TRUE);
1172 /* "Update list of packets in real time" captures disabled; that
1173 means ring buffer mode is OK, so make its toggle button
1175 gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_on_tb), TRUE);
1177 /* Auto-scroll mode is meaningful only in "Update list of packets
1178 in real time" captures, so make its toggle button insensitive. */
1179 gtk_widget_set_sensitive(GTK_WIDGET(auto_scroll_cb), FALSE);
1182 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb))) {
1183 /* Ring buffer mode enabled. Make the spin button for the number
1184 of ring buffer files, and its label, sensitive. */
1185 gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_lb), TRUE);
1186 gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), TRUE);
1187 gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_cb), TRUE);
1189 /* Also, indicate that the file size is a size at which to switch
1190 ring buffer files, not a size at which to stop the capture,
1191 turn its button on. */
1192 gtk_label_set_text(GTK_LABEL(GTK_BIN(filesize_cb)->child),
1193 "Rotate capture file every");
1194 gtk_label_set_text(GTK_LABEL(filesize_lb), "kilobyte(s)");
1195 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filesize_cb), TRUE);
1197 /* Ring buffer mode disabled. Make the spin button for the number
1198 of ring buffer files, and its label insensitive. */
1199 gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_lb), FALSE);
1200 gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), FALSE);
1201 gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_cb), FALSE);
1203 /* Also, indicate that the file size is a size at which to stop the
1204 capture, not a size at which to switch ring buffer files. */
1205 gtk_label_set_text(GTK_LABEL(GTK_BIN(filesize_cb)->child),
1206 "Stop capture after");
1207 gtk_label_set_text(GTK_LABEL(filesize_lb), "kilobyte(s) captured");
1210 /* The maximum packet count spinbox is sensitive if the "Stop capture
1211 after N packets captured" checkbox is on. */
1212 gtk_widget_set_sensitive(GTK_WIDGET(count_sb),
1213 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(count_cb)));
1215 /* The maximum file size spinbox is sensitive if the "Stop capture
1216 after N kilobytes captured" checkbox is on. */
1217 gtk_widget_set_sensitive(GTK_WIDGET(filesize_sb),
1218 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filesize_cb)));
1220 /* The capture duration spinbox is sensitive if the "Stop capture
1221 after N seconds" checkbox is on. */
1222 gtk_widget_set_sensitive(GTK_WIDGET(duration_sb),
1223 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(duration_cb)));
1225 /* The ring duration spinbox is sensitive if the "Rotate capture file
1226 after N seconds" checkbox is on. */
1227 gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_sb),
1228 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ring_duration_cb)));
1231 #endif /* HAVE_LIBPCAP */