removed some MSVC warnings (moved pcap.h before glib.h)
[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.90 2003/12/21 12:17:58 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
52 #ifdef _WIN32
53 #include "capture-wpcap.h"
54 #endif
55
56 /* Capture callback data keys */
57 #define E_CAP_IFACE_KEY       "cap_iface"
58 #define E_CAP_SNAP_CB_KEY     "cap_snap_cb"
59 #define E_CAP_LT_OM_KEY       "cap_lt_om"
60 #define E_CAP_LT_OM_LABEL_KEY "cap_lt_om_label"
61 #define E_CAP_SNAP_SB_KEY     "cap_snap_sb"
62 #define E_CAP_PROMISC_KEY     "cap_promisc"
63 #define E_CAP_FILT_KEY        "cap_filter_te"
64 #define E_CAP_FILE_TE_KEY     "cap_file_te"
65 #define E_CAP_RING_ON_TB_KEY  "cap_ringbuffer_on_tb"
66 #define E_CAP_RING_NBF_LB_KEY "cap_ringbuffer_nbf_lb"
67 #define E_CAP_RING_NBF_SB_KEY "cap_ringbuffer_nbf_sb"
68 #define E_CAP_RING_DURATION_CB_KEY "cap_ringbuffer_duration_cb"
69 #define E_CAP_RING_DURATION_SB_KEY "cap_ringbuffer_duration_sb"
70 #define E_CAP_SYNC_KEY        "cap_sync"
71 #define E_CAP_AUTO_SCROLL_KEY "cap_auto_scroll"
72 #define E_CAP_COUNT_CB_KEY    "cap_count_cb"
73 #define E_CAP_COUNT_SB_KEY    "cap_count_sb"
74 #define E_CAP_FILESIZE_CB_KEY "cap_filesize_cb"
75 #define E_CAP_FILESIZE_SB_KEY "cap_filesize_sb"
76 #define E_CAP_FILESIZE_LB_KEY "cap_filesize_lb"
77 #define E_CAP_DURATION_CB_KEY "cap_duration_cb"
78 #define E_CAP_DURATION_SB_KEY "cap_duration_sb"
79 #define E_CAP_M_RESOLVE_KEY   "cap_m_resolve"
80 #define E_CAP_N_RESOLVE_KEY   "cap_n_resolve"
81 #define E_CAP_T_RESOLVE_KEY   "cap_t_resolve"
82
83 #define E_CAP_OM_LT_VALUE_KEY "cap_om_lt_value"
84
85 #define E_FS_CALLER_PTR_KEY       "fs_caller_ptr"
86 #define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr"
87
88 static void
89 capture_prep_file_cb(GtkWidget *w, gpointer te);
90
91 static void
92 select_link_type_cb(GtkWidget *w, gpointer data);
93
94 static void
95 cap_prep_fs_ok_cb(GtkWidget *w, gpointer data);
96
97 static void
98 cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data);
99
100 static void
101 cap_prep_fs_destroy_cb(GtkWidget *win, GtkWidget* file_te);
102
103 static void
104 capture_prep_adjust_sensitivity(GtkWidget *tb, gpointer parent_w);
105
106 static void
107 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
108
109 static void
110 capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w);
111
112 static void
113 capture_prep_destroy_cb(GtkWidget *win, gpointer user_data);
114
115 static void
116 capture_prep_interface_changed_cb(GtkWidget *entry, gpointer parent_w);
117
118 void
119 capture_stop_cb(GtkWidget *w _U_, gpointer d _U_)
120 {
121     capture_stop();
122 }
123
124 /*
125  * Keep a static pointer to the current "Capture Options" window, if
126  * any, so that if somebody tries to do "Capture:Start" while there's
127  * already a "Capture Options" window up, we just pop up the existing
128  * one, rather than creating a new one.
129  */
130 static GtkWidget *cap_open_w;
131
132 static void
133 set_link_type_list(GtkWidget *linktype_om, GtkWidget *entry)
134 {
135   gchar *entry_text;
136   gchar *if_text;
137   gchar *if_name;
138   GList *if_list;
139   GList *if_entry;
140   if_info_t *if_info;
141   GList *lt_list;
142   int err;
143   char err_buf[PCAP_ERRBUF_SIZE];
144   GtkWidget *lt_menu, *lt_menu_item;
145   GList *lt_entry;
146   data_link_info_t *data_link_info;
147   gchar *linktype_menu_label;
148   guint num_supported_link_types;
149   GtkWidget *linktype_lb = OBJECT_GET_DATA(linktype_om, E_CAP_LT_OM_LABEL_KEY);
150
151   lt_menu = gtk_menu_new();
152   entry_text = g_strdup(gtk_entry_get_text(GTK_ENTRY(entry)));
153   if_text = g_strstrip(entry_text);
154   if_name = strrchr(if_text, ' ');
155   if (if_name == NULL) {
156     if_name = if_text;
157   } else {
158     if_name++;
159   }
160
161   /*
162    * If the interface name is in the list of known interfaces, get
163    * its list of link-layer types and set the option menu to display it.
164    *
165    * If it's not, don't bother - the user might be in the middle of
166    * editing the list, or it might be a remote device in which case
167    * getting the list could take an arbitrarily-long period of time.
168    * The list currently won't contain any remote devices (as
169    * "pcap_findalldevs()" doesn't know about remote devices, and neither
170    * does the code we use if "pcap_findalldevs()" isn't available), but
171    * should contain all the local devices on which you can capture.
172    */
173   lt_list = NULL;
174   if (*if_name != '\0') {
175     /*
176      * Try to get the list of known interfaces.
177      */
178     if_list = get_interface_list(&err, err_buf);
179     if (if_list != NULL) {
180       /*
181        * We have the list - check it.
182        */
183       for (if_entry = if_list; if_entry != NULL;
184            if_entry = g_list_next(if_entry)) {
185         if_info = if_entry->data;
186         if (strcmp(if_info->name, if_name) == 0) {
187           /*
188            * It's in the list.
189            * Get the list of link-layer types for it.
190            */
191           lt_list = get_pcap_linktype_list(if_name, err_buf);
192         }
193       }
194       free_interface_list(if_list);
195     }
196   }
197   g_free(entry_text);
198   num_supported_link_types = 0;
199   for (lt_entry = lt_list; lt_entry != NULL; lt_entry = g_list_next(lt_entry)) {
200     data_link_info = lt_entry->data;
201     if (data_link_info->description != NULL) {
202       lt_menu_item = gtk_menu_item_new_with_label(data_link_info->description);
203       OBJECT_SET_DATA(lt_menu_item, E_CAP_LT_OM_KEY, linktype_om);
204       SIGNAL_CONNECT(lt_menu_item, "activate", select_link_type_cb,
205                      GINT_TO_POINTER(data_link_info->dlt));
206       num_supported_link_types++;
207     } else {
208       /* Not supported - tell them about it but don't let them select it. */
209       linktype_menu_label = g_strdup_printf("%s (not supported)",
210                                             data_link_info->name);
211       lt_menu_item = gtk_menu_item_new_with_label(linktype_menu_label);
212       g_free(linktype_menu_label);
213       gtk_widget_set_sensitive(lt_menu_item, FALSE);
214     }
215     gtk_menu_append(GTK_MENU(lt_menu), lt_menu_item);
216     gtk_widget_show(lt_menu_item);
217   }
218   if (lt_list != NULL)
219     free_pcap_linktype_list(lt_list);
220   gtk_option_menu_set_menu(GTK_OPTION_MENU(linktype_om), lt_menu);
221   gtk_widget_set_sensitive(linktype_lb, num_supported_link_types >= 2);
222   gtk_widget_set_sensitive(linktype_om, num_supported_link_types >= 2);
223 }
224
225 void
226 capture_prep_cb(GtkWidget *w _U_, gpointer d _U_)
227 {
228   GtkWidget     *main_vb,
229                 *capture_fr, *capture_vb,
230                 *if_hb, *if_cb, *if_lb,
231                 *linktype_hb, *linktype_lb, *linktype_om,
232                 *snap_hb, *snap_cb, *snap_sb, *snap_lb,
233                 *promisc_cb,
234                 *filter_hb, *filter_bt, *filter_te,
235                 *file_fr, *file_vb,
236                 *file_hb, *file_bt, *file_te,
237                 *ringbuffer_hb, *ringbuffer_on_tb, *ringbuffer_nbf_lb, *ringbuffer_nbf_sb,
238                 *display_fr, *display_vb,
239                 *sync_cb, *auto_scroll_cb,
240                 *limit_fr, *limit_vb,
241                 *count_hb, *count_cb, *count_sb, *count_lb,
242                 *filesize_hb, *filesize_cb, *filesize_sb, *filesize_lb,
243                 *duration_hb, *duration_cb, *duration_sb, *duration_lb,
244                 *ring_duration_hb, *ring_duration_cb, *ring_duration_sb, 
245                 *ring_duration_lb,
246                 *resolv_fr, *resolv_vb,
247                 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb,
248                 *bbox, *ok_bt, *cancel_bt;
249 #if GTK_MAJOR_VERSION < 2
250   GtkAccelGroup *accel_group;
251 #endif
252   GtkAdjustment *snap_adj, *ringbuffer_nbf_adj,
253                 *count_adj, *filesize_adj, *duration_adj, *ring_duration_adj;
254   GList         *if_list, *combo_list;
255   int           err;
256   char          err_str[PCAP_ERRBUF_SIZE];
257
258   if (cap_open_w != NULL) {
259     /* There's already a "Capture Options" dialog box; reactivate it. */
260     reactivate_window(cap_open_w);
261     return;
262   }
263
264 #ifdef _WIN32
265   /* Is WPcap loaded? */
266   if (!has_wpcap) {
267           simple_dialog(ESD_TYPE_CRIT, NULL,
268                   "Unable to load WinPcap (wpcap.dll); Ethereal will not be able\n"
269                   "to capture packets.\n\n"
270                   "In order to capture packets, WinPcap must be installed; see\n"
271                   "\n"
272                   "        http://winpcap.polito.it/\n"
273                   "\n"
274                   "or the mirror at\n"
275                   "\n"
276                   "        http://winpcap.mirror.ethereal.com/\n"
277                   "\n"
278                   "or the mirror at\n"
279                   "\n"
280                   "        http://www.mirrors.wiretapped.net/security/packet-capture/winpcap/\n"
281                   "\n"
282                   "for a downloadable version of WinPcap and for instructions\n"
283                   "on how to install WinPcap.");
284           return;
285   }
286 #endif
287
288   if_list = get_interface_list(&err, err_str);
289   if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
290     simple_dialog(ESD_TYPE_WARN, NULL, "Can't get list of interfaces: %s",
291                         err_str);
292   }
293
294   cap_open_w = dlg_window_new("Ethereal: Capture Options");
295   SIGNAL_CONNECT(cap_open_w, "destroy", capture_prep_destroy_cb, NULL);
296
297 #if GTK_MAJOR_VERSION < 2
298   /* Accelerator group for the accelerators (or, as they're called in
299      Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
300      Ctrl+<key> is an accelerator). */
301   accel_group = gtk_accel_group_new();
302   gtk_window_add_accel_group(GTK_WINDOW(cap_open_w), accel_group);
303 #endif
304
305   main_vb = gtk_vbox_new(FALSE, 0);
306   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
307   gtk_container_add(GTK_CONTAINER(cap_open_w), main_vb);
308   gtk_widget_show(main_vb);
309
310   /* Capture-related options frame */
311   capture_fr = gtk_frame_new("Capture");
312   gtk_container_add(GTK_CONTAINER(main_vb), capture_fr);
313   gtk_widget_show(capture_fr);
314
315   capture_vb = gtk_vbox_new(FALSE, 0);
316   gtk_container_add(GTK_CONTAINER(capture_fr), capture_vb);
317   gtk_widget_show(capture_vb);
318
319   /* Interface row */
320   if_hb = gtk_hbox_new(FALSE, 3);
321   gtk_container_add(GTK_CONTAINER(capture_vb), if_hb);
322   gtk_widget_show(if_hb);
323
324   if_lb = gtk_label_new("Interface:");
325   gtk_box_pack_start(GTK_BOX(if_hb), if_lb, FALSE, FALSE, 6);
326   gtk_widget_show(if_lb);
327
328   if_cb = gtk_combo_new();
329   combo_list = build_capture_combo_list(if_list, TRUE);
330   if (combo_list != NULL)
331     gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), combo_list);
332   if (cfile.iface == NULL && prefs.capture_device != NULL) {
333     /* No interface was specified on the command line or in a previous
334        capture, but there is one specified in the preferences file;
335        make the one from the preferences file the default */
336     cfile.iface = g_strdup(prefs.capture_device);
337   }
338   if (cfile.iface != NULL)
339     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cfile.iface);
340   else if (combo_list != NULL) {
341     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry),
342                        (char *)combo_list->data);
343   }
344   free_capture_combo_list(combo_list);
345   free_interface_list(if_list);
346   gtk_box_pack_start(GTK_BOX(if_hb), if_cb, TRUE, TRUE, 6);
347   gtk_widget_show(if_cb);
348
349   /* Linktype row */
350   linktype_hb = gtk_hbox_new(FALSE, 3);
351   gtk_container_add(GTK_CONTAINER(capture_vb), linktype_hb);
352   gtk_widget_show(linktype_hb);
353
354   linktype_lb = gtk_label_new("Link-layer header type:");
355   gtk_box_pack_start(GTK_BOX(linktype_hb), linktype_lb, FALSE, FALSE, 6);
356   gtk_widget_show(linktype_lb);
357
358   linktype_om = gtk_option_menu_new();
359   OBJECT_SET_DATA(linktype_om, E_CAP_LT_OM_LABEL_KEY, linktype_lb);
360   /* Default to "use the default" */
361   OBJECT_SET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(-1));
362   set_link_type_list(linktype_om, GTK_COMBO(if_cb)->entry);
363   gtk_box_pack_start (GTK_BOX(linktype_hb), linktype_om, FALSE, FALSE, 0);
364   gtk_widget_show(linktype_om);
365   SIGNAL_CONNECT(GTK_ENTRY(GTK_COMBO(if_cb)->entry), "changed",
366                  capture_prep_interface_changed_cb, linktype_om);
367
368   /* Capture length row */
369   snap_hb = gtk_hbox_new(FALSE, 3);
370   gtk_container_add(GTK_CONTAINER(capture_vb), snap_hb);
371   gtk_widget_show(snap_hb);
372
373 #if GTK_MAJOR_VERSION < 2
374   snap_cb = dlg_check_button_new_with_label_with_mnemonic(
375                 "_Limit each packet to", accel_group);
376 #else
377   snap_cb = gtk_check_button_new_with_mnemonic("_Limit each packet to");
378 #endif
379   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(snap_cb),
380                 capture_opts.has_snaplen);
381   SIGNAL_CONNECT(snap_cb, "toggled", capture_prep_adjust_sensitivity, cap_open_w);
382   gtk_box_pack_start(GTK_BOX(snap_hb), snap_cb, FALSE, FALSE, 0);
383   gtk_widget_show(snap_cb);
384
385   snap_adj = (GtkAdjustment *) gtk_adjustment_new((float) capture_opts.snaplen,
386     MIN_PACKET_SIZE, WTAP_MAX_PACKET_SIZE, 1.0, 10.0, 0.0);
387   snap_sb = gtk_spin_button_new (snap_adj, 0, 0);
388   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE);
389   WIDGET_SET_SIZE(snap_sb, 80, -1);
390   gtk_box_pack_start (GTK_BOX(snap_hb), snap_sb, FALSE, FALSE, 0);
391   gtk_widget_show(snap_sb);
392
393   snap_lb = gtk_label_new("bytes");
394   gtk_misc_set_alignment(GTK_MISC(snap_lb), 0, 0.5);
395   gtk_box_pack_start(GTK_BOX(snap_hb), snap_lb, FALSE, FALSE, 0);
396   gtk_widget_show(snap_lb);
397
398   /* Promiscuous mode row */
399 #if GTK_MAJOR_VERSION < 2
400   promisc_cb = dlg_check_button_new_with_label_with_mnemonic(
401                 "Capture packets in _promiscuous mode", accel_group);
402 #else
403   promisc_cb = gtk_check_button_new_with_mnemonic(
404                 "Capture packets in _promiscuous mode");
405 #endif
406   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(promisc_cb),
407                 capture_opts.promisc_mode);
408   gtk_container_add(GTK_CONTAINER(capture_vb), promisc_cb);
409   gtk_widget_show(promisc_cb);
410
411   /* Filter row */
412   filter_hb = gtk_hbox_new(FALSE, 3);
413   gtk_container_add(GTK_CONTAINER(capture_vb), filter_hb);
414   gtk_widget_show(filter_hb);
415
416   filter_bt = gtk_button_new_with_label("Filter:");
417   SIGNAL_CONNECT(filter_bt, "clicked", capture_filter_construct_cb, NULL);
418   SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
419   gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, FALSE, 3);
420   gtk_widget_show(filter_bt);
421
422   filter_te = gtk_entry_new();
423   if (cfile.cfilter) gtk_entry_set_text(GTK_ENTRY(filter_te), cfile.cfilter);
424   OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
425   gtk_box_pack_start(GTK_BOX(filter_hb), filter_te, TRUE, TRUE, 3);
426   gtk_widget_show(filter_te);
427
428   /* Capture file-related options frame */
429   file_fr = gtk_frame_new("Capture file(s)");
430   gtk_container_add(GTK_CONTAINER(main_vb), file_fr);
431   gtk_widget_show(file_fr);
432
433   file_vb = gtk_vbox_new(FALSE, 3);
434   gtk_container_add(GTK_CONTAINER(file_fr), file_vb);
435   gtk_widget_show(file_vb);
436
437   /* File row */
438   file_hb = gtk_hbox_new(FALSE, 3);
439   gtk_container_add(GTK_CONTAINER(file_vb), file_hb);
440   gtk_widget_show(file_hb);
441
442   file_bt = gtk_button_new_with_label("File:");
443   gtk_box_pack_start(GTK_BOX(file_hb), file_bt, FALSE, FALSE, 3);
444   gtk_widget_show(file_bt);
445
446   file_te = gtk_entry_new();
447   gtk_box_pack_start(GTK_BOX(file_hb), file_te, TRUE, TRUE, 3);
448   gtk_widget_show(file_te);
449
450   SIGNAL_CONNECT(file_bt, "clicked", capture_prep_file_cb, file_te);
451
452   /* Ring buffer row */
453   ringbuffer_hb = gtk_hbox_new(FALSE, 3);
454   gtk_container_add(GTK_CONTAINER(file_vb), ringbuffer_hb);
455   gtk_widget_show(ringbuffer_hb);
456
457 #if GTK_MAJOR_VERSION < 2
458   ringbuffer_on_tb = dlg_check_button_new_with_label_with_mnemonic(
459     "Use _ring buffer", accel_group);
460 #else
461   ringbuffer_on_tb = gtk_check_button_new_with_mnemonic("Use _ring buffer");
462 #endif
463   /* Ring buffer mode is allowed only if we're not doing an "Update list of
464      packets in real time" capture, so force it off if we're doing such
465      a capture. */
466   if (capture_opts.sync_mode)
467     capture_opts.ringbuffer_on = FALSE;
468   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ringbuffer_on_tb),
469                 capture_opts.ringbuffer_on);
470   SIGNAL_CONNECT(ringbuffer_on_tb, "toggled", capture_prep_adjust_sensitivity,
471                  cap_open_w);
472   gtk_box_pack_start(GTK_BOX(ringbuffer_hb), ringbuffer_on_tb, FALSE, FALSE, 0);
473   gtk_widget_show(ringbuffer_on_tb);
474
475   ringbuffer_nbf_lb = gtk_label_new("Number of files");
476   gtk_misc_set_alignment(GTK_MISC(ringbuffer_nbf_lb), 1, 0.5);
477   gtk_box_pack_start(GTK_BOX(ringbuffer_hb), ringbuffer_nbf_lb, FALSE, FALSE, 6);
478   gtk_widget_show(ringbuffer_nbf_lb);
479
480   ringbuffer_nbf_adj = (GtkAdjustment *) gtk_adjustment_new((float) capture_opts.ringbuffer_num_files,
481     RINGBUFFER_MIN_NUM_FILES, RINGBUFFER_MAX_NUM_FILES, 1.0, 10.0, 0.0);
482   ringbuffer_nbf_sb = gtk_spin_button_new (ringbuffer_nbf_adj, 0, 0);
483   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (ringbuffer_nbf_sb), TRUE);
484   WIDGET_SET_SIZE(ringbuffer_nbf_sb, 40, -1);
485   gtk_box_pack_start (GTK_BOX(ringbuffer_hb), ringbuffer_nbf_sb, TRUE, TRUE, 0);
486   gtk_widget_show(ringbuffer_nbf_sb);
487
488   /* Ring buffer duration row */
489   ring_duration_hb = gtk_hbox_new(FALSE, 3);
490   gtk_container_add(GTK_CONTAINER(file_vb), ring_duration_hb);
491   gtk_widget_show(ring_duration_hb);
492
493   ring_duration_cb = gtk_check_button_new_with_label("Rotate capture file every");
494   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ring_duration_cb),
495                               capture_opts.has_ring_duration);
496   SIGNAL_CONNECT(ring_duration_cb, "toggled", 
497                  capture_prep_adjust_sensitivity, cap_open_w);
498   gtk_box_pack_start(GTK_BOX(ring_duration_hb), ring_duration_cb, 
499                      FALSE, FALSE, 0);
500   gtk_widget_show(ring_duration_cb);
501
502   ring_duration_adj = (GtkAdjustment *)gtk_adjustment_new(capture_opts.ringbuffer_duration,
503     1, INT_MAX, 1.0, 10.0, 0.0);
504   ring_duration_sb = gtk_spin_button_new (ring_duration_adj, 0, 0);
505   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (ring_duration_sb), TRUE);
506   WIDGET_SET_SIZE(ring_duration_sb, 80, -1);
507   gtk_box_pack_start (GTK_BOX(ring_duration_hb), ring_duration_sb, 
508                       FALSE, FALSE, 0);
509   gtk_widget_show(ring_duration_sb);
510
511   ring_duration_lb = gtk_label_new("second(s)");
512   gtk_misc_set_alignment(GTK_MISC(ring_duration_lb), 0, 0.5);
513   gtk_box_pack_start(GTK_BOX(ring_duration_hb), ring_duration_lb, 
514                      FALSE, FALSE, 0);
515   gtk_widget_show(ring_duration_lb);
516
517   /* Display-related options frame */
518   display_fr = gtk_frame_new("Display options");
519   gtk_container_add(GTK_CONTAINER(main_vb), display_fr);
520   gtk_widget_show(display_fr);
521
522   display_vb = gtk_vbox_new(FALSE, 0);
523   gtk_container_add(GTK_CONTAINER(display_fr), display_vb);
524   gtk_widget_show(display_vb);
525
526   /* "Update display in real time" row */
527 #if GTK_MAJOR_VERSION < 2
528   sync_cb = dlg_check_button_new_with_label_with_mnemonic(
529                 "_Update list of packets in real time", accel_group);
530 #else
531   sync_cb = gtk_check_button_new_with_mnemonic(
532                 "_Update list of packets in real time");
533 #endif
534   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(sync_cb),
535                 capture_opts.sync_mode);
536   SIGNAL_CONNECT(sync_cb, "toggled", capture_prep_adjust_sensitivity, cap_open_w);
537   gtk_container_add(GTK_CONTAINER(display_vb), sync_cb);
538   gtk_widget_show(sync_cb);
539
540   /* "Auto-scroll live update" row */
541 #if GTK_MAJOR_VERSION < 2
542   auto_scroll_cb = dlg_check_button_new_with_label_with_mnemonic(
543                 "_Automatic scrolling in live capture", accel_group);
544 #else
545   auto_scroll_cb = gtk_check_button_new_with_mnemonic(
546                 "_Automatic scrolling in live capture");
547 #endif
548   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(auto_scroll_cb), auto_scroll_live);
549   gtk_container_add(GTK_CONTAINER(display_vb), auto_scroll_cb);
550   gtk_widget_show(auto_scroll_cb);
551
552   /* Capture limits frame */
553   limit_fr = gtk_frame_new("Capture limits");
554   gtk_container_add(GTK_CONTAINER(main_vb), limit_fr);
555   gtk_widget_show(limit_fr);
556
557   limit_vb = gtk_vbox_new(FALSE, 0);
558   gtk_container_add(GTK_CONTAINER(limit_fr), limit_vb);
559   gtk_widget_show(limit_vb);
560
561   /* Count row */
562   count_hb = gtk_hbox_new(FALSE, 3);
563   gtk_container_add(GTK_CONTAINER(limit_vb), count_hb);
564   gtk_widget_show(count_hb);
565
566   count_cb = gtk_check_button_new_with_label("Stop capture after");
567   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(count_cb),
568                 capture_opts.has_autostop_count);
569   SIGNAL_CONNECT(count_cb, "toggled", capture_prep_adjust_sensitivity, cap_open_w);
570   gtk_box_pack_start(GTK_BOX(count_hb), count_cb, FALSE, FALSE, 0);
571   gtk_widget_show(count_cb);
572
573   count_adj = (GtkAdjustment *) gtk_adjustment_new(capture_opts.autostop_count,
574     1, INT_MAX, 1.0, 10.0, 0.0);
575   count_sb = gtk_spin_button_new (count_adj, 0, 0);
576   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (count_sb), TRUE);
577   WIDGET_SET_SIZE(count_sb, 80, -1);
578   gtk_box_pack_start (GTK_BOX(count_hb), count_sb, FALSE, FALSE, 0);
579   gtk_widget_show(count_sb);
580
581   count_lb = gtk_label_new("packet(s) captured");
582   gtk_misc_set_alignment(GTK_MISC(count_lb), 0, 0.5);
583   gtk_box_pack_start(GTK_BOX(count_hb), count_lb, FALSE, FALSE, 0);
584   gtk_widget_show(count_lb);
585
586   /* Filesize row */
587   filesize_hb = gtk_hbox_new(FALSE, 3);
588   gtk_container_add(GTK_CONTAINER(limit_vb), filesize_hb);
589   gtk_widget_show(filesize_hb);
590
591   filesize_cb = gtk_check_button_new_with_label("");
592   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filesize_cb),
593                 capture_opts.has_autostop_filesize);
594   SIGNAL_CONNECT(filesize_cb, "toggled", capture_prep_adjust_sensitivity, cap_open_w);
595   gtk_box_pack_start(GTK_BOX(filesize_hb), filesize_cb, FALSE, FALSE, 0);
596   gtk_widget_show(filesize_cb);
597
598   filesize_adj = (GtkAdjustment *) gtk_adjustment_new(capture_opts.autostop_filesize,
599     1, INT_MAX, 1.0, 10.0, 0.0);
600   filesize_sb = gtk_spin_button_new (filesize_adj, 0, 0);
601   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (filesize_sb), TRUE);
602   WIDGET_SET_SIZE(filesize_sb, 80, -1);
603   gtk_box_pack_start (GTK_BOX(filesize_hb), filesize_sb, FALSE, FALSE, 0);
604   gtk_widget_show(filesize_sb);
605
606   filesize_lb = gtk_label_new("");
607   gtk_misc_set_alignment(GTK_MISC(filesize_lb), 0, 0.5);
608   gtk_box_pack_start(GTK_BOX(filesize_hb), filesize_lb, FALSE, FALSE, 0);
609   gtk_widget_show(filesize_lb);
610
611   /* Duration row */
612   duration_hb = gtk_hbox_new(FALSE, 3);
613   gtk_container_add(GTK_CONTAINER(limit_vb), duration_hb);
614   gtk_widget_show(duration_hb);
615
616   duration_cb = gtk_check_button_new_with_label("Stop capture after");
617   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(duration_cb),
618                 capture_opts.has_autostop_duration);
619   SIGNAL_CONNECT(duration_cb, "toggled", capture_prep_adjust_sensitivity, cap_open_w);
620   gtk_box_pack_start(GTK_BOX(duration_hb), duration_cb, FALSE, FALSE, 0);
621   gtk_widget_show(duration_cb);
622
623   duration_adj = (GtkAdjustment *) gtk_adjustment_new(capture_opts.autostop_duration,
624     1, INT_MAX, 1.0, 10.0, 0.0);
625   duration_sb = gtk_spin_button_new (duration_adj, 0, 0);
626   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (duration_sb), TRUE);
627   WIDGET_SET_SIZE(duration_sb, 80, -1);
628   gtk_box_pack_start (GTK_BOX(duration_hb), duration_sb, FALSE, FALSE, 0);
629   gtk_widget_show(duration_sb);
630
631   duration_lb = gtk_label_new("second(s)");
632   gtk_misc_set_alignment(GTK_MISC(duration_lb), 0, 0.5);
633   gtk_box_pack_start(GTK_BOX(duration_hb), duration_lb, FALSE, FALSE, 0);
634   gtk_widget_show(duration_lb);
635
636   /* Resolution options frame */
637   resolv_fr = gtk_frame_new("Name resolution");
638   gtk_container_add(GTK_CONTAINER(main_vb), resolv_fr);
639   gtk_widget_show(resolv_fr);
640
641   resolv_vb = gtk_vbox_new(FALSE, 0);
642   gtk_container_add(GTK_CONTAINER(resolv_fr), resolv_vb);
643   gtk_widget_show(resolv_vb);
644
645 #if GTK_MAJOR_VERSION < 2
646   m_resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
647                 "Enable _MAC name resolution", accel_group);
648 #else
649   m_resolv_cb = gtk_check_button_new_with_mnemonic(
650                 "Enable _MAC name resolution");
651 #endif
652   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(m_resolv_cb),
653                 g_resolv_flags & RESOLV_MAC);
654   gtk_container_add(GTK_CONTAINER(resolv_vb), m_resolv_cb);
655   gtk_widget_show(m_resolv_cb);
656
657 #if GTK_MAJOR_VERSION < 2
658   n_resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
659                 "Enable _network name resolution", accel_group);
660 #else
661   n_resolv_cb = gtk_check_button_new_with_mnemonic(
662                 "Enable _network name resolution");
663 #endif
664   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(n_resolv_cb),
665                 g_resolv_flags & RESOLV_NETWORK);
666   gtk_container_add(GTK_CONTAINER(resolv_vb), n_resolv_cb);
667   gtk_widget_show(n_resolv_cb);
668
669 #if GTK_MAJOR_VERSION < 2
670   t_resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
671                 "Enable _transport name resolution", accel_group);
672 #else
673   t_resolv_cb = gtk_check_button_new_with_mnemonic(
674                 "Enable _transport name resolution");
675 #endif
676   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(t_resolv_cb),
677                 g_resolv_flags & RESOLV_TRANSPORT);
678   gtk_container_add(GTK_CONTAINER(resolv_vb), t_resolv_cb);
679   gtk_widget_show(t_resolv_cb);
680
681   /* Button row: OK and cancel buttons */
682   bbox = gtk_hbutton_box_new();
683   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
684   gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
685   gtk_container_add(GTK_CONTAINER(main_vb), bbox);
686   gtk_widget_show(bbox);
687
688 #if GTK_MAJOR_VERSION < 2
689   ok_bt = gtk_button_new_with_label ("OK");
690 #else
691   ok_bt = gtk_button_new_from_stock(GTK_STOCK_OK);
692 #endif
693   SIGNAL_CONNECT(ok_bt, "clicked", capture_prep_ok_cb, cap_open_w);
694   GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
695   gtk_box_pack_start (GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
696   gtk_widget_grab_default(ok_bt);
697   gtk_widget_show(ok_bt);
698
699 #if GTK_MAJOR_VERSION < 2
700   cancel_bt = gtk_button_new_with_label ("Cancel");
701 #else
702   cancel_bt = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
703 #endif
704   SIGNAL_CONNECT(cancel_bt, "clicked", capture_prep_close_cb, cap_open_w);
705   GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
706   gtk_box_pack_start (GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
707   gtk_widget_show(cancel_bt);
708
709   /* Attach pointers to needed widgets to the capture prefs window/object */
710   OBJECT_SET_DATA(cap_open_w, E_CAP_IFACE_KEY, if_cb);
711   OBJECT_SET_DATA(cap_open_w, E_CAP_SNAP_CB_KEY, snap_cb);
712   OBJECT_SET_DATA(cap_open_w, E_CAP_SNAP_SB_KEY, snap_sb);
713   OBJECT_SET_DATA(cap_open_w, E_CAP_LT_OM_KEY, linktype_om);
714   OBJECT_SET_DATA(cap_open_w, E_CAP_PROMISC_KEY, promisc_cb);
715   OBJECT_SET_DATA(cap_open_w, E_CAP_FILT_KEY,  filter_te);
716   OBJECT_SET_DATA(cap_open_w, E_CAP_FILE_TE_KEY,  file_te);
717   OBJECT_SET_DATA(cap_open_w, E_CAP_RING_ON_TB_KEY,  ringbuffer_on_tb);
718   OBJECT_SET_DATA(cap_open_w, E_CAP_RING_NBF_LB_KEY,  ringbuffer_nbf_lb);
719   OBJECT_SET_DATA(cap_open_w, E_CAP_RING_NBF_SB_KEY,  ringbuffer_nbf_sb);
720   OBJECT_SET_DATA(cap_open_w, E_CAP_RING_DURATION_CB_KEY,  ring_duration_cb);
721   OBJECT_SET_DATA(cap_open_w, E_CAP_RING_DURATION_SB_KEY,  ring_duration_sb);
722   OBJECT_SET_DATA(cap_open_w, E_CAP_SYNC_KEY,  sync_cb);
723   OBJECT_SET_DATA(cap_open_w, E_CAP_AUTO_SCROLL_KEY, auto_scroll_cb);
724   OBJECT_SET_DATA(cap_open_w, E_CAP_COUNT_CB_KEY, count_cb);
725   OBJECT_SET_DATA(cap_open_w, E_CAP_COUNT_SB_KEY, count_sb);
726   OBJECT_SET_DATA(cap_open_w, E_CAP_FILESIZE_CB_KEY, filesize_cb);
727   OBJECT_SET_DATA(cap_open_w, E_CAP_FILESIZE_SB_KEY, filesize_sb);
728   OBJECT_SET_DATA(cap_open_w, E_CAP_FILESIZE_LB_KEY, filesize_lb);
729   OBJECT_SET_DATA(cap_open_w, E_CAP_DURATION_CB_KEY,  duration_cb);
730   OBJECT_SET_DATA(cap_open_w, E_CAP_DURATION_SB_KEY,  duration_sb);
731   OBJECT_SET_DATA(cap_open_w, E_CAP_M_RESOLVE_KEY,  m_resolv_cb);
732   OBJECT_SET_DATA(cap_open_w, E_CAP_N_RESOLVE_KEY,  n_resolv_cb);
733   OBJECT_SET_DATA(cap_open_w, E_CAP_T_RESOLVE_KEY,  t_resolv_cb);
734
735   /* Set the sensitivity of various widgets as per the settings of other
736      widgets. */
737   capture_prep_adjust_sensitivity(NULL, cap_open_w);
738
739   /* Catch the "activate" signal on the filter and file name text
740      entries, so that if the user types Return there, we act as if the
741      "OK" button had been selected, as happens if Return is typed if some
742      widget that *doesn't* handle the Return key has the input focus. */
743   dlg_set_activate(filter_te, ok_bt);
744   dlg_set_activate(file_te, ok_bt);
745
746   /* Catch the "key_press_event" signal in the window, so that we can catch
747      the ESC key being pressed and act as if the "Cancel" button had
748      been selected. */
749   dlg_set_cancel(cap_open_w, cancel_bt);
750
751   /* XXX - why does not
752
753      gtk_widget_grab_focus(if_cb);
754
755     give the initial focus to the "Interface" combo box?
756
757     Or should I phrase that as "why does GTK+ continually frustrate
758     attempts to make GUIs driveable from the keyboard?"  We have to
759     go catch the activate signal on every single GtkEntry widget
760     (rather than having widgets whose activate signal is *not*
761     caught not catch the Return keystroke, so that it passes on,
762     ultimately, to the window, which can activate the default
763     widget, i.e. the "OK" button); we have to catch the "key_press_event"
764     signal and have the handler check for ESC, so that we can have ESC
765     activate the "Cancel" button; in order to support Alt+<key> mnemonics
766     for buttons and the like, we may have to construct an accelerator
767     group by hand and set up the accelerators by hand (if that even
768     works - I've not tried it yet); we have to do a "gtk_widget_grab_focus()"
769     to keep some container widget from getting the initial focus, so that
770     you don't have to tab into the first widget in order to start typing
771     in it; and it now appears that you simply *can't* make a combo box
772     get the initial focus, at least not in the obvious fashion. Sigh.... */
773
774   gtk_widget_show(cap_open_w);
775 }
776
777 static void
778 select_link_type_cb(GtkWidget *w, gpointer data)
779 {
780   int new_linktype = GPOINTER_TO_INT(data);
781   GtkWidget *linktype_om = OBJECT_GET_DATA(w, E_CAP_LT_OM_KEY);
782   int old_linktype = GPOINTER_TO_INT(OBJECT_GET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY));
783
784   if (old_linktype != new_linktype)
785     OBJECT_SET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY, GINT_TO_POINTER(new_linktype));
786 }
787
788 static void
789 capture_prep_file_cb(GtkWidget *w, gpointer file_te)
790 {
791   GtkWidget *caller = gtk_widget_get_toplevel(w);
792   GtkWidget *fs;
793
794   /* Has a file selection dialog box already been opened for that top-level
795      widget? */
796   fs = OBJECT_GET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY);
797
798   if (fs != NULL) {
799     /* Yes.  Just re-activate that dialog box. */
800     reactivate_window(fs);
801     return;
802   }
803
804   fs = file_selection_new ("Ethereal: Capture File");
805
806   /* If we've opened a file, start out by showing the files in the directory
807      in which that file resided. */
808   if (last_open_dir)
809     gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
810
811   OBJECT_SET_DATA(fs, E_CAP_FILE_TE_KEY, file_te);
812
813   /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
814   OBJECT_SET_DATA(fs, E_FS_CALLER_PTR_KEY, caller);
815
816   /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
817   OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, fs);
818
819   /* Call a handler when the file selection box is destroyed, so we can inform
820      our caller, if any, that it's been destroyed. */
821   SIGNAL_CONNECT(fs, "destroy", cap_prep_fs_destroy_cb, file_te);
822
823   SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->ok_button, "clicked", cap_prep_fs_ok_cb, fs);
824
825   /* Connect the cancel_button to destroy the widget */
826   SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->cancel_button, "clicked", cap_prep_fs_cancel_cb,
827                  fs);
828
829   /* Catch the "key_press_event" signal in the window, so that we can catch
830      the ESC key being pressed and act as if the "Cancel" button had
831      been selected. */
832   dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
833
834   gtk_widget_show(fs);
835 }
836
837 static void
838 cap_prep_fs_ok_cb(GtkWidget *w _U_, gpointer data)
839 {
840   gchar     *cf_name;
841
842   cf_name = g_strdup(gtk_file_selection_get_filename(
843     GTK_FILE_SELECTION (data)));
844
845   /* Perhaps the user specified a directory instead of a file.
846      Check whether they did. */
847   if (test_for_directory(cf_name) == EISDIR) {
848         /* It's a directory - set the file selection box to display it. */
849         set_last_open_dir(cf_name);
850         g_free(cf_name);
851         gtk_file_selection_set_filename(GTK_FILE_SELECTION(data),
852           last_open_dir);
853         return;
854   }
855
856   gtk_entry_set_text(GTK_ENTRY(OBJECT_GET_DATA(data, E_CAP_FILE_TE_KEY)), cf_name);
857
858   gtk_widget_destroy(GTK_WIDGET(data));
859   g_free(cf_name);
860 }
861
862 static void
863 cap_prep_fs_cancel_cb(GtkWidget *w _U_, gpointer data)
864 {
865   gtk_widget_destroy(GTK_WIDGET(data));
866 }
867
868 static void
869 cap_prep_fs_destroy_cb(GtkWidget *win, GtkWidget* file_te)
870 {
871   GtkWidget *caller;
872
873   /* Get the widget that requested that we be popped up.
874      (It should arrange to destroy us if it's destroyed, so
875      that we don't get a pointer to a non-existent window here.) */
876   caller = OBJECT_GET_DATA(win, E_FS_CALLER_PTR_KEY);
877
878   /* Tell it we no longer exist. */
879   OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, NULL);
880
881   /* Now nuke this window. */
882   gtk_grab_remove(GTK_WIDGET(win));
883   gtk_widget_destroy(GTK_WIDGET(win));
884
885   /* Give the focus to the file text entry widget so the user can just press
886      Return to start the capture. */
887   gtk_widget_grab_focus(file_te);
888 }
889
890 static void
891 capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) {
892   GtkWidget *if_cb, *snap_cb, *snap_sb, *promisc_cb, *filter_te,
893             *file_te, *ringbuffer_on_tb, *ringbuffer_nbf_sb,
894             *linktype_om, *sync_cb, *auto_scroll_cb,
895             *count_cb, *count_sb,
896             *filesize_cb, *filesize_sb,
897             *duration_cb, *duration_sb,
898             *ring_duration_cb, *ring_duration_sb,
899             *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
900   gchar *entry_text;
901   gchar *if_text;
902   gchar *if_name;
903   const gchar *filter_text;
904   gchar *save_file;
905   const gchar *g_save_file;
906   gchar *cf_name;
907   gchar *dirname;
908
909   if_cb     = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_IFACE_KEY);
910   snap_cb   = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_CB_KEY);
911   snap_sb   = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_SB_KEY);
912   linktype_om = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_LT_OM_KEY);
913   promisc_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_PROMISC_KEY);
914   filter_te = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILT_KEY);
915   file_te   = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILE_TE_KEY);
916   ringbuffer_on_tb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_ON_TB_KEY);
917   ringbuffer_nbf_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_SB_KEY);
918   ring_duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_CB_KEY);
919   ring_duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_SB_KEY);
920   sync_cb   = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SYNC_KEY);
921   auto_scroll_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_AUTO_SCROLL_KEY);
922   count_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_CB_KEY);
923   count_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_SB_KEY);
924   filesize_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILESIZE_CB_KEY);
925   filesize_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILESIZE_SB_KEY);
926   duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_DURATION_CB_KEY);
927   duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_DURATION_SB_KEY);
928   m_resolv_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_M_RESOLVE_KEY);
929   n_resolv_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_N_RESOLVE_KEY);
930   t_resolv_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_T_RESOLVE_KEY);
931
932   entry_text =
933     g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
934   if_text = g_strstrip(entry_text);
935   /* Remove interface description; if it's present, it comes before
936      the interface name, and there's a space between them, and the
937      interface name is assumed to contain no space, so we look backwards
938      in the string for a space. */
939   if_name = strrchr(if_text, ' ');
940   if (if_name == NULL) {
941     if_name = if_text;
942   } else {
943     if_name++;
944   }
945   if (*if_name == '\0') {
946     simple_dialog(ESD_TYPE_CRIT, NULL,
947       "You didn't specify an interface on which to capture packets.");
948     g_free(entry_text);
949     return;
950   }
951   if (cfile.iface)
952     g_free(cfile.iface);
953   cfile.iface = g_strdup(if_name);
954   g_free(entry_text);
955
956   capture_opts.linktype =
957       GPOINTER_TO_INT(OBJECT_GET_DATA(linktype_om, E_CAP_OM_LT_VALUE_KEY));
958
959   capture_opts.has_snaplen =
960     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb));
961   if (capture_opts.has_snaplen) {
962     capture_opts.snaplen =
963       gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
964     if (capture_opts.snaplen < 1)
965       capture_opts.snaplen = WTAP_MAX_PACKET_SIZE;
966     else if (capture_opts.snaplen < MIN_PACKET_SIZE)
967       capture_opts.snaplen = MIN_PACKET_SIZE;
968   }
969
970   capture_opts.promisc_mode =
971     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(promisc_cb));
972
973   /* XXX - don't try to get clever and set "cfile.filter" to NULL if the
974      filter string is empty, as an indication that we don't have a filter
975      and thus don't have to set a filter when capturing - the version of
976      libpcap in Red Hat Linux 6.1, and versions based on later patches
977      in that series, don't bind the AF_PACKET socket to an interface
978      until a filter is set, which means they aren't bound at all if
979      no filter is set, which means no packets arrive as input on that
980      socket, which means Ethereal never sees any packets. */
981   filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
982   if (cfile.cfilter)
983     g_free(cfile.cfilter);
984   g_assert(filter_text != NULL);
985   cfile.cfilter = g_strdup(filter_text);
986
987   g_save_file = gtk_entry_get_text(GTK_ENTRY(file_te));
988   if (g_save_file && g_save_file[0]) {
989     /* User specified a file to which the capture should be written. */
990     save_file = g_strdup(g_save_file);
991     /* Save the directory name for future file dialogs. */
992     cf_name = g_strdup(g_save_file);
993     dirname = get_dirname(cf_name);  /* Overwrites cf_name */
994     set_last_open_dir(dirname);
995     g_free(cf_name);
996   } else {
997     /* User didn't specify a file; save to a temporary file. */
998     save_file = NULL;
999   }
1000
1001   capture_opts.has_autostop_count =
1002     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(count_cb));
1003   if (capture_opts.has_autostop_count)
1004     capture_opts.autostop_count =
1005       gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(count_sb));
1006
1007   capture_opts.has_autostop_filesize =
1008     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filesize_cb));
1009   if (capture_opts.has_autostop_filesize)
1010     capture_opts.autostop_filesize =
1011       gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(filesize_sb));
1012
1013   capture_opts.has_autostop_duration =
1014     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(duration_cb));
1015   if (capture_opts.has_autostop_duration)
1016     capture_opts.autostop_duration =
1017       gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(duration_sb));
1018
1019   capture_opts.sync_mode =
1020     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sync_cb));
1021
1022   auto_scroll_live =
1023       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(auto_scroll_cb));
1024
1025   g_resolv_flags = RESOLV_NONE;
1026   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(m_resolv_cb)))
1027     g_resolv_flags |= RESOLV_MAC;
1028   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(n_resolv_cb)))
1029     g_resolv_flags |= RESOLV_NETWORK;
1030   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t_resolv_cb)))
1031     g_resolv_flags |= RESOLV_TRANSPORT;
1032
1033   capture_opts.ringbuffer_on =
1034     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb)) &&
1035         !(capture_opts.sync_mode);
1036   if (capture_opts.ringbuffer_on) {
1037     if (save_file == NULL) {
1038       simple_dialog(ESD_TYPE_CRIT, NULL,
1039         "You must specify a save file if you want to use the ring buffer.");
1040       return;
1041     } else if (!capture_opts.has_autostop_filesize) {
1042       simple_dialog(ESD_TYPE_CRIT, NULL,
1043         "You must specify a file size at which to rotate the capture files\n"
1044         "if you want to use the ring buffer.");
1045       g_free(save_file);
1046       return;
1047     }
1048   }
1049
1050   capture_opts.ringbuffer_num_files =
1051     gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ringbuffer_nbf_sb));
1052   if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
1053     capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
1054 #if RINGBUFFER_MIN_NUM_FILES > 0
1055   else if (capture_opts.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
1056     capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
1057 #endif
1058
1059   capture_opts.has_ring_duration =
1060     gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ring_duration_cb));
1061   if (capture_opts.has_ring_duration)
1062     capture_opts.ringbuffer_duration =
1063       gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ring_duration_sb));
1064
1065   gtk_widget_destroy(GTK_WIDGET(parent_w));
1066
1067   do_capture(save_file);
1068   if (save_file != NULL)
1069     g_free(save_file);
1070 }
1071
1072 static void
1073 capture_prep_close_cb(GtkWidget *close_bt _U_, gpointer parent_w)
1074 {
1075   gtk_grab_remove(GTK_WIDGET(parent_w));
1076   gtk_widget_destroy(GTK_WIDGET(parent_w));
1077 }
1078
1079 static void
1080 capture_prep_destroy_cb(GtkWidget *win, gpointer user_data _U_)
1081 {
1082   GtkWidget *fs;
1083
1084   /* Is there a file selection dialog associated with this
1085      Capture Options dialog? */
1086   fs = OBJECT_GET_DATA(win, E_FILE_SEL_DIALOG_PTR_KEY);
1087
1088   if (fs != NULL) {
1089     /* Yes.  Destroy it. */
1090     gtk_widget_destroy(fs);
1091   }
1092
1093   /* Note that we no longer have a "Capture Options" dialog box. */
1094   cap_open_w = NULL;
1095 }
1096
1097 static void
1098 capture_prep_interface_changed_cb(GtkWidget *entry, gpointer argp)
1099 {
1100   GtkWidget *linktype_om = argp;
1101
1102   set_link_type_list(linktype_om, entry);
1103 }
1104
1105 /*
1106  * Adjust the sensitivity of various widgets as per the current setting
1107  * of other widgets.
1108  */
1109 static void
1110 capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w)
1111 {
1112   GtkWidget *if_cb,
1113             *snap_cb, *snap_sb,
1114             *ringbuffer_on_tb, *ringbuffer_nbf_lb, *ringbuffer_nbf_sb,
1115             *sync_cb, *auto_scroll_cb,
1116             *count_cb, *count_sb,
1117             *filesize_cb, *filesize_sb, *filesize_lb,
1118             *duration_cb, *duration_sb,
1119             *ring_duration_cb, *ring_duration_sb;
1120
1121   if_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_IFACE_KEY);
1122   snap_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_CB_KEY);
1123   snap_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SNAP_SB_KEY);
1124   ringbuffer_on_tb  = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_ON_TB_KEY);
1125   ringbuffer_nbf_lb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_LB_KEY);
1126   ringbuffer_nbf_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_NBF_SB_KEY);
1127   ring_duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_CB_KEY);
1128   ring_duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_RING_DURATION_SB_KEY);
1129   sync_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_SYNC_KEY);
1130   auto_scroll_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_AUTO_SCROLL_KEY);
1131   count_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_CB_KEY);
1132   count_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_COUNT_SB_KEY);
1133   filesize_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILESIZE_CB_KEY);
1134   filesize_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILESIZE_SB_KEY);
1135   filesize_lb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_FILESIZE_LB_KEY);
1136   duration_cb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_DURATION_CB_KEY);
1137   duration_sb = (GtkWidget *) OBJECT_GET_DATA(parent_w, E_CAP_DURATION_SB_KEY);
1138
1139   /* The snapshot length spinbox is sensitive iff the "Limit each packet
1140      to" checkbox is on. */
1141   gtk_widget_set_sensitive(GTK_WIDGET(snap_sb),
1142       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb)));
1143
1144   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sync_cb))) {
1145     /* "Update list of packets in real time" captures enabled; we don't
1146        support ring buffer mode for those captures, so turn ring buffer
1147        mode off if it's on, and make its toggle button, and the spin
1148        button for the number of ring buffer files (and the spin button's
1149        label), insensitive. */
1150     if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb))) {
1151       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb), FALSE);
1152     }
1153     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_on_tb), FALSE);
1154
1155     /* Auto-scroll mode is meaningful only in "Update list of packets
1156        in real time" captures, so make its toggle button sensitive. */
1157     gtk_widget_set_sensitive(GTK_WIDGET(auto_scroll_cb), TRUE);
1158   } else {
1159     /* "Update list of packets in real time" captures disabled; that
1160        means ring buffer mode is OK, so make its toggle button
1161        sensitive. */
1162     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_on_tb), TRUE);
1163
1164     /* Auto-scroll mode is meaningful only in "Update list of packets
1165        in real time" captures, so make its toggle button insensitive. */
1166     gtk_widget_set_sensitive(GTK_WIDGET(auto_scroll_cb), FALSE);
1167   }
1168
1169   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb))) {
1170     /* Ring buffer mode enabled.  Make the spin button for the number
1171        of ring buffer files, and its label, sensitive. */
1172     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_lb), TRUE);
1173     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), TRUE);
1174     gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_cb), TRUE);
1175
1176     /* Also, indicate that the file size is a size at which to switch
1177        ring buffer files, not a size at which to stop the capture,
1178        turn its button on. */
1179     gtk_label_set_text(GTK_LABEL(GTK_BIN(filesize_cb)->child),
1180         "Rotate capture file every");
1181     gtk_label_set_text(GTK_LABEL(filesize_lb), "kilobyte(s)");
1182     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filesize_cb), TRUE);
1183   } else {
1184     /* Ring buffer mode disabled.  Make the spin button for the number
1185        of ring buffer files, and its label insensitive. */
1186     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_lb), FALSE);
1187     gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), FALSE);
1188     gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_cb), FALSE);
1189
1190     /* Also, indicate that the file size is a size at which to stop the
1191        capture, not a size at which to switch ring buffer files. */
1192     gtk_label_set_text(GTK_LABEL(GTK_BIN(filesize_cb)->child),
1193         "Stop capture after");
1194     gtk_label_set_text(GTK_LABEL(filesize_lb), "kilobyte(s) captured");
1195   }
1196
1197   /* The maximum packet count spinbox is sensitive iff the "Stop capture
1198      after N packets captured" checkbox is on. */
1199   gtk_widget_set_sensitive(GTK_WIDGET(count_sb),
1200       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(count_cb)));
1201
1202   /* The maximum file size spinbox is sensitive iff the "Stop capture
1203      after N kilobytes captured" checkbox is on. */
1204   gtk_widget_set_sensitive(GTK_WIDGET(filesize_sb),
1205       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filesize_cb)));
1206
1207   /* The capture duration spinbox is sensitive iff the "Stop capture
1208      after N seconds" checkbox is on. */
1209   gtk_widget_set_sensitive(GTK_WIDGET(duration_sb),
1210       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(duration_cb)));
1211
1212   /* The ring duration spinbox is sensitive if the "Rotate capture file
1213      after N seconds" checkbox is on. */
1214   gtk_widget_set_sensitive(GTK_WIDGET(ring_duration_sb),
1215       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ring_duration_cb)));
1216 }
1217
1218 #endif /* HAVE_LIBPCAP */