every GUI action, which will erease a currently unsaved capture file,
[obnox/wireshark/wip.git] / gtk / capture_dlg.c
1 /* capture_dlg.c
2  * Routines for packet capture windows
3  *
4  * $Id: capture_dlg.c,v 1.98 2004/01/29 23:11:37 ulfl Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_LIBPCAP
30
31 #include <pcap.h>
32 #include <string.h>
33 #include <gtk/gtk.h>
34
35 #include <epan/packet.h>
36 #include "capture.h"
37 #include "globals.h"
38 #include <epan/resolv.h>
39 #include "main.h"
40 #include "ui_util.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"
47 #include "prefs.h"
48 #include "ringbuffer.h"
49 #include <epan/filesystem.h>
50 #include "compat_macros.h"
51 #include "file_dlg.h"
52
53 #ifdef _WIN32
54 #include "capture-wpcap.h"
55 #endif
56
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"
83
84 #define E_CAP_OM_LT_VALUE_KEY "cap_om_lt_value"
85
86 #define E_FS_CALLER_PTR_KEY       "fs_caller_ptr"
87 #define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr"
88
89 static void
90 capture_prep_file_cb(GtkWidget *w, gpointer te);
91
92 static void
93 select_link_type_cb(GtkWidget *w, gpointer data);
94
95 static void
96 cap_prep_fs_ok_cb(GtkWidget *w, gpointer data);
97
98 static void
99 cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data);
100
101 static void
102 cap_prep_fs_destroy_cb(GtkWidget *win, GtkWidget* file_te);
103
104 static void
105 capture_prep_adjust_sensitivity(GtkWidget *tb, gpointer parent_w);
106
107 static void
108 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
109
110 static void
111 capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w);
112
113 static void
114 capture_prep_destroy_cb(GtkWidget *win, gpointer user_data);
115
116 static void
117 capture_prep_interface_changed_cb(GtkWidget *entry, gpointer parent_w);
118
119 void
120 capture_stop_cb(GtkWidget *w _U_, gpointer d _U_)
121 {
122     capture_stop();
123 }
124
125 /*
126  * Given text that contains an interface name possibly prefixed by an
127  * interface description, extract the interface name.
128  */
129 static char *
130 get_if_name(char *if_text)
131 {
132   char *if_name;
133
134 #ifdef WIN32
135   /*
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.
141    */
142    if_name = if_text;
143    for (;;) {
144      if_name = strchr(if_name, '\\');
145      if (if_name == NULL)
146        return if_text;  /* give up */
147      if (strncmp(if_name + 1, "Device\\", 7) == 0)
148        return if_name;
149      if_name++;
150    }
151 #else
152   /*
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.
156    */
157   if_name = strrchr(if_text, ' ');
158   if (if_name == NULL) {
159     if_name = if_text;
160   } else {
161     if_name++;
162   }
163 #endif
164   return if_name;
165 }
166
167 /*
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.
172  */
173 static GtkWidget *cap_open_w;
174
175 static void
176 set_link_type_list(GtkWidget *linktype_om, GtkWidget *entry)
177 {
178   gchar *entry_text;
179   gchar *if_text;
180   gchar *if_name;
181   GList *if_list;
182   GList *if_entry;
183   if_info_t *if_info;
184   GList *lt_list;
185   int err;
186   char err_buf[PCAP_ERRBUF_SIZE];
187   GtkWidget *lt_menu, *lt_menu_item;
188   GList *lt_entry;
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);
193
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);
198
199   /*
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.
202    *
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.
210    */
211   lt_list = NULL;
212   if (*if_name != '\0') {
213     /*
214      * Try to get the list of known interfaces.
215      */
216     if_list = get_interface_list(&err, err_buf);
217     if (if_list != NULL) {
218       /*
219        * We have the list - check it.
220        */
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) {
225           /*
226            * It's in the list.
227            * Get the list of link-layer types for it.
228            */
229           lt_list = get_pcap_linktype_list(if_name, err_buf);
230         }
231       }
232       free_interface_list(if_list);
233     }
234   }
235   g_free(entry_text);
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++;
245     } else {
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);
252     }
253     gtk_menu_append(GTK_MENU(lt_menu), lt_menu_item);
254     gtk_widget_show(lt_menu_item);
255   }
256   if (lt_list != NULL)
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);
261 }
262
263 void
264 capture_prep(void)
265 {
266   GtkWidget     *main_vb,
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,
271                 *promisc_cb,
272                 *filter_hb, *filter_bt, *filter_te,
273                 *file_fr, *file_vb,
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, 
283                 *ring_duration_lb,
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;
289 #endif
290   GtkAdjustment *snap_adj, *ringbuffer_nbf_adj,
291                 *count_adj, *filesize_adj, *duration_adj, *ring_duration_adj;
292   GList         *if_list, *combo_list;
293   int           err;
294   char          err_str[PCAP_ERRBUF_SIZE];
295
296   if (cap_open_w != NULL) {
297     /* There's already a "Capture Options" dialog box; reactivate it. */
298     reactivate_window(cap_open_w);
299     return;
300   }
301
302 #ifdef _WIN32
303   /* Is WPcap loaded? */
304   if (!has_wpcap) {
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"
309                   "\n"
310                   "        http://winpcap.polito.it/\n"
311                   "\n"
312                   "or the mirror at\n"
313                   "\n"
314                   "        http://winpcap.mirror.ethereal.com/\n"
315                   "\n"
316                   "or the mirror at\n"
317                   "\n"
318                   "        http://www.mirrors.wiretapped.net/security/packet-capture/winpcap/\n"
319                   "\n"
320                   "for a downloadable version of WinPcap and for instructions\n"
321                   "on how to install WinPcap.");
322           return;
323   }
324 #endif
325
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",
329                         err_str);
330   }
331
332   cap_open_w = dlg_window_new("Ethereal: Capture Options");
333   SIGNAL_CONNECT(cap_open_w, "destroy", capture_prep_destroy_cb, NULL);
334
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);
341 #endif
342
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);
347
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);
352
353   capture_vb = gtk_vbox_new(FALSE, 0);
354   gtk_container_add(GTK_CONTAINER(capture_fr), capture_vb);
355   gtk_widget_show(capture_vb);
356
357   /* Interface row */
358   if_hb = gtk_hbox_new(FALSE, 3);
359   gtk_container_add(GTK_CONTAINER(capture_vb), if_hb);
360   gtk_widget_show(if_hb);
361
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);
365
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);
375   }
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);
381   }
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);
386
387   /* Linktype row */
388   linktype_hb = gtk_hbox_new(FALSE, 3);
389   gtk_container_add(GTK_CONTAINER(capture_vb), linktype_hb);
390   gtk_widget_show(linktype_hb);
391
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);
395
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);
405
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);
410
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);
417
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);
425
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);
430
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);
438
439   /* Filter row */
440   filter_hb = gtk_hbox_new(FALSE, 3);
441   gtk_container_add(GTK_CONTAINER(capture_vb), filter_hb);
442   gtk_widget_show(filter_hb);
443
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);
449
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);
455
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);
460
461   file_vb = gtk_vbox_new(FALSE, 3);
462   gtk_container_add(GTK_CONTAINER(file_fr), file_vb);
463   gtk_widget_show(file_vb);
464
465   /* File row */
466   file_hb = gtk_hbox_new(FALSE, 3);
467   gtk_container_add(GTK_CONTAINER(file_vb), file_hb);
468   gtk_widget_show(file_hb);
469
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);
473
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);
477
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);
481
482   SIGNAL_CONNECT(file_bt, "clicked", capture_prep_file_cb, file_te);
483
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);
488
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
492      a capture. */
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,
498                  cap_open_w);
499   gtk_box_pack_start(GTK_BOX(ringbuffer_hb), ringbuffer_on_tb, FALSE, FALSE, 0);
500   gtk_widget_show(ringbuffer_on_tb);
501
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);
506
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);
514
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);
519
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, 
526                      FALSE, FALSE, 0);
527   gtk_widget_show(ring_duration_cb);
528
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, 
535                       FALSE, FALSE, 0);
536   gtk_widget_show(ring_duration_sb);
537
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, 
541                      FALSE, FALSE, 0);
542   gtk_widget_show(ring_duration_lb);
543
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);
548
549   display_vb = gtk_vbox_new(FALSE, 0);
550   gtk_container_add(GTK_CONTAINER(display_fr), display_vb);
551   gtk_widget_show(display_vb);
552
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);
561
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);
568
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);
573
574   limit_vb = gtk_vbox_new(FALSE, 0);
575   gtk_container_add(GTK_CONTAINER(limit_fr), limit_vb);
576   gtk_widget_show(limit_vb);
577
578   /* Count row */
579   count_hb = gtk_hbox_new(FALSE, 3);
580   gtk_container_add(GTK_CONTAINER(limit_vb), count_hb);
581   gtk_widget_show(count_hb);
582
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);
589
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);
597
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);
602
603   /* Filesize row */
604   filesize_hb = gtk_hbox_new(FALSE, 3);
605   gtk_container_add(GTK_CONTAINER(limit_vb), filesize_hb);
606   gtk_widget_show(filesize_hb);
607
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);
614
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);
622
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);
627
628   /* Duration row */
629   duration_hb = gtk_hbox_new(FALSE, 3);
630   gtk_container_add(GTK_CONTAINER(limit_vb), duration_hb);
631   gtk_widget_show(duration_hb);
632
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);
639
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);
647
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);
652
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);
657
658   resolv_vb = gtk_vbox_new(FALSE, 0);
659   gtk_container_add(GTK_CONTAINER(resolv_fr), resolv_vb);
660   gtk_widget_show(resolv_vb);
661
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);
668
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);
675
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);
682
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);
687
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);
691
692   cancel_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
693   SIGNAL_CONNECT(cancel_bt, "clicked", capture_prep_close_cb, cap_open_w);
694
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);
720
721   /* Set the sensitivity of various widgets as per the settings of other
722      widgets. */
723   capture_prep_adjust_sensitivity(NULL, cap_open_w);
724
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);
731
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
734      been selected. */
735   dlg_set_cancel(cap_open_w, cancel_bt);
736
737   /* XXX - why does not
738
739      gtk_widget_grab_focus(if_cb);
740
741     give the initial focus to the "Interface" combo box?
742
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.... */
759
760   gtk_widget_show(cap_open_w);
761 }
762
763 static void 
764 capture_prep_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
765 {
766     switch(btn) {
767     case(ESD_BTN_YES):
768         /* save file first */
769         file_save_as_cmd(after_save_capture_dialog, data);
770         break;
771     case(ESD_BTN_NO):
772         capture_prep();
773         break;
774     case(ESD_BTN_CANCEL):
775         break;
776     default:
777         g_assert_not_reached();
778     }
779 }
780
781 void
782 capture_prep_cb(GtkWidget *w, gpointer d _U_)
783 {
784   gpointer  dialog;
785
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);
793   } else {
794     /* unchanged file, just capture a new one */
795     capture_prep();
796   }
797 }
798
799 static void
800 select_link_type_cb(GtkWidget *w, gpointer data)
801 {
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));
805
806   if (old_linktype != new_linktype)
807     OBJECT_SET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(new_linktype));
808 }
809
810 static void
811 capture_prep_file_cb(GtkWidget *w, gpointer file_te)
812 {
813   GtkWidget *caller = gtk_widget_get_toplevel(w);
814   GtkWidget *fs;
815
816   /* Has a file selection dialog box already been opened for that top-level
817      widget? */
818   fs = OBJECT_GET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY);
819
820   if (fs != NULL) {
821     /* Yes.  Just re-activate that dialog box. */
822     reactivate_window(fs);
823     return;
824   }
825
826   fs = file_selection_new ("Ethereal: Capture File");
827
828   /* If we've opened a file, start out by showing the files in the directory
829      in which that file resided. */
830   if (last_open_dir)
831     gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
832
833   OBJECT_SET_DATA(fs, E_CAP_FILE_TE_KEY, file_te);
834
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);
837
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);
840
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);
844
845   SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->ok_button, "clicked", cap_prep_fs_ok_cb, fs);
846
847   /* Connect the cancel_button to destroy the widget */
848   SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->cancel_button, "clicked", cap_prep_fs_cancel_cb,
849                  fs);
850
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
853      been selected. */
854   dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
855
856   gtk_widget_show(fs);
857 }
858
859 static void
860 cap_prep_fs_ok_cb(GtkWidget *w _U_, gpointer data)
861 {
862   gchar     *cf_name;
863
864   cf_name = g_strdup(gtk_file_selection_get_filename(
865     GTK_FILE_SELECTION (data)));
866
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);
872         g_free(cf_name);
873         gtk_file_selection_set_filename(GTK_FILE_SELECTION(data),
874           last_open_dir);
875         return;
876   }
877
878   gtk_entry_set_text(GTK_ENTRY(OBJECT_GET_DATA(data, E_CAP_FILE_TE_KEY)), cf_name);
879
880   gtk_widget_destroy(GTK_WIDGET(data));
881   g_free(cf_name);
882 }
883
884 static void
885 cap_prep_fs_cancel_cb(GtkWidget *w _U_, gpointer data)
886 {
887   gtk_widget_destroy(GTK_WIDGET(data));
888 }
889
890 static void
891 cap_prep_fs_destroy_cb(GtkWidget *win, GtkWidget* file_te)
892 {
893   GtkWidget *caller;
894
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);
899
900   /* Tell it we no longer exist. */
901   OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, NULL);
902
903   /* Now nuke this window. */
904   gtk_grab_remove(GTK_WIDGET(win));
905   gtk_widget_destroy(GTK_WIDGET(win));
906
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);
910 }
911
912 static void
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;
922   gchar *entry_text;
923   gchar *if_text;
924   gchar *if_name;
925   const gchar *filter_text;
926   gchar *save_file;
927   const gchar *g_save_file;
928   gchar *cf_name;
929   gchar *dirname;
930
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);
953
954   entry_text =
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.");
961     g_free(entry_text);
962     return;
963   }
964   if (cfile.iface)
965     g_free(cfile.iface);
966   cfile.iface = g_strdup(if_name);
967   g_free(entry_text);
968
969   capture_opts.linktype =
970       GPOINTER_TO_INT(OBJECT_GET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY));
971
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;
981   }
982
983   capture_opts.promisc_mode =
984     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(promisc_cb));
985
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));
995   if (cfile.cfilter)
996     g_free(cfile.cfilter);
997   g_assert(filter_text != NULL);
998   cfile.cfilter = g_strdup(filter_text);
999
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);
1008     g_free(cf_name);
1009   } else {
1010     /* User didn't specify a file; save to a temporary file. */
1011     save_file = NULL;
1012   }
1013
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));
1019
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));
1025
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));
1031
1032   capture_opts.sync_mode =
1033     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sync_cb));
1034
1035   auto_scroll_live =
1036       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(auto_scroll_cb));
1037
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;
1045
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.");
1053       return;
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.");
1058       g_free(save_file);
1059       return;
1060     }
1061   }
1062
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;
1070 #endif
1071
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));
1077
1078   gtk_widget_destroy(GTK_WIDGET(parent_w));
1079
1080   do_capture(save_file);
1081   if (save_file != NULL)
1082     g_free(save_file);
1083 }
1084
1085 static void
1086 capture_prep_close_cb(GtkWidget *close_bt _U_, gpointer parent_w)
1087 {
1088   gtk_grab_remove(GTK_WIDGET(parent_w));
1089   gtk_widget_destroy(GTK_WIDGET(parent_w));
1090 }
1091
1092 static void
1093 capture_prep_destroy_cb(GtkWidget *win, gpointer user_data _U_)
1094 {
1095   GtkWidget *fs;
1096
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);
1100
1101   if (fs != NULL) {
1102     /* Yes.  Destroy it. */
1103     gtk_widget_destroy(fs);
1104   }
1105
1106   /* Note that we no longer have a "Capture Options" dialog box. */
1107   cap_open_w = NULL;
1108 }
1109
1110 static void
1111 capture_prep_interface_changed_cb(GtkWidget *entry, gpointer argp)
1112 {
1113   GtkWidget *linktype_om = argp;
1114
1115   set_link_type_list(linktype_om, entry);
1116 }
1117
1118 /*
1119  * Adjust the sensitivity of various widgets as per the current setting
1120  * of other widgets.
1121  */
1122 static void
1123 capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
1124 {
1125   GtkWidget *if_cb,
1126             *snap_cb, *snap_sb,
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;
1133
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);
1151
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)));
1156
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);
1165     }
1166     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_on_tb), FALSE);
1167
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);
1171   } else {
1172     /* "Update list of packets in real time" captures disabled; that
1173        means ring buffer mode is OK, so make its toggle button
1174        sensitive. */
1175     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_on_tb), TRUE);
1176
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);
1180   }
1181
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);
1188
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);
1196   } else {
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);
1202
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");
1208   }
1209
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)));
1214
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)));
1219
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)));
1224
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)));
1229 }
1230
1231 #endif /* HAVE_LIBPCAP */