2 * Routines for packet capture windows
4 * $Id: capture_dlg.c,v 1.50 2001/12/04 08:25:58 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
44 #ifdef NEED_SNPRINTF_H
45 # include "snprintf.h"
53 #include "capture_dlg.h"
54 #include "filter_prefs.h"
55 #include "simple_dialog.h"
56 #include "dlg_utils.h"
57 #include "pcap-util.h"
59 #include "ringbuffer.h"
62 #include "capture-wpcap.h"
65 /* Capture callback data keys */
66 #define E_CAP_IFACE_KEY "cap_iface"
67 #define E_CAP_FILT_KEY "cap_filter_te"
68 #define E_CAP_FILE_TE_KEY "cap_file_te"
69 #define E_CAP_COUNT_KEY "cap_count"
70 #define E_CAP_SNAP_KEY "cap_snap"
71 #define E_CAP_PROMISC_KEY "cap_promisc"
72 #define E_CAP_SYNC_KEY "cap_sync"
73 #define E_CAP_AUTO_SCROLL_KEY "cap_auto_scroll"
74 #define E_CAP_M_RESOLVE_KEY "cap_m_resolve"
75 #define E_CAP_N_RESOLVE_KEY "cap_n_resolve"
76 #define E_CAP_T_RESOLVE_KEY "cap_t_resolve"
77 #define E_CAP_FILESIZE_KEY "cap_filesize"
78 #define E_CAP_DURATION_KEY "cap_duration"
79 #define E_CAP_RING_TB_KEY "cap_ringbuffer_tb"
80 #define E_CAP_RING_SB_KEY "cap_ringbuffer_sb"
82 #define E_FS_CALLER_PTR_KEY "fs_caller_ptr"
83 #define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr"
86 capture_prep_file_cb(GtkWidget *w, gpointer te);
89 cap_prep_fs_ok_cb(GtkWidget *w, gpointer data);
92 cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data);
95 cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data);
98 capture_prep_sync_toggle_cb(GtkWidget *sync_cb, gpointer parent_w);
101 capture_prep_ringbuffer_toggle_cb(GtkWidget *ringbuffer_tb, gpointer parent_w);
104 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
107 capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w);
110 capture_prep_destroy_cb(GtkWidget *win, gpointer user_data);
113 capture_stop_cb(GtkWidget *w, gpointer d)
119 * Keep a static pointer to the current "Capture Preferences" window, if
120 * any, so that if somebody tries to do "Capture:Start" while there's
121 * already a "Capture Preferences" window up, we just pop up the existing
122 * one, rather than creating a new one.
124 static GtkWidget *cap_open_w;
127 capture_prep_cb(GtkWidget *w, gpointer d)
129 GtkWidget *if_cb, *if_lb,
130 *count_lb, *count_cb, *main_vb,
131 *filter_bt, *filter_te,
133 *filesize_lb, *filesize_cb,
134 *duration_lb, *duration_cb,
136 *bbox, *ok_bt, *cancel_bt, *snap_lb,
137 *snap_sb, *promisc_cb, *sync_cb, *auto_scroll_cb,
138 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb,
139 *ringbuffer_hb, *ringbuffer_on_tb, *ringbuffer_nbf_lb, *ringbuffer_nbf_sb;
140 GtkAccelGroup *accel_group;
141 GtkAdjustment *snap_adj, *ringbuffer_nbf_adj;
142 GList *if_list, *count_list = NULL, *filesize_list = NULL, *duration_list = NULL;
143 gchar *count_item1 = "0 (Infinite)", count_item2[16],
144 *filesize_item1 = "0 (Infinite)", filesize_item2[16],
145 *duration_item1 = "0 (Infinite)", duration_item2[16];
147 char err_str[PCAP_ERRBUF_SIZE];
149 if (cap_open_w != NULL) {
150 /* There's already a "Capture Preferences" dialog box; reactivate it. */
151 reactivate_window(cap_open_w);
156 /* Is WPcap loaded? */
158 simple_dialog(ESD_TYPE_CRIT, NULL,
159 "Unable to load WinPcap (wpcap.dll); Ethereal will not be able\n"
160 "to capture packets.\n\n"
161 "In order to capture packets, WinPcap must be installed; see\n"
163 " http://netgroup-serv.polito.it/winpcap/\n"
167 " http://netgroup-mirror.ethereal.com/winpcap/\n"
171 " http://www.wiretapped.net/security/packet-capture/winpcap/default.htm\n"
173 "for a downloadable version of WinPcap and for instructions\n"
174 "on how to install WinPcap.");
179 if_list = get_interface_list(&err, err_str);
180 if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
181 simple_dialog(ESD_TYPE_WARN, NULL, "Can't get list of interfaces: %s",
185 cap_open_w = dlg_window_new("Ethereal: Capture Preferences");
186 gtk_signal_connect(GTK_OBJECT(cap_open_w), "destroy",
187 GTK_SIGNAL_FUNC(capture_prep_destroy_cb), NULL);
189 /* Accelerator group for the accelerators (or, as they're called in
190 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
191 Ctrl+<key> is an accelerator). */
192 accel_group = gtk_accel_group_new();
193 gtk_window_add_accel_group(GTK_WINDOW(cap_open_w), accel_group);
195 main_vb = gtk_vbox_new(FALSE, 3);
196 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
197 gtk_container_add(GTK_CONTAINER(cap_open_w), main_vb);
198 gtk_widget_show(main_vb);
200 /* Table : container of the first 6 rows */
201 table = gtk_table_new (6, 2, FALSE);
202 gtk_table_set_row_spacings(GTK_TABLE (table), 5);
203 gtk_table_set_col_spacings(GTK_TABLE (table), 5);
204 gtk_container_add(GTK_CONTAINER(main_vb), table);
205 gtk_widget_show(table);
209 if_lb = gtk_label_new("Interface:");
210 gtk_table_attach_defaults(GTK_TABLE(table), if_lb, 0, 1, 0, 1);
211 gtk_widget_show(if_lb);
213 if_cb = gtk_combo_new();
215 gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), if_list);
217 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cfile.iface);
219 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), if_list->data);
220 gtk_table_attach_defaults(GTK_TABLE(table), if_cb, 1, 2, 0, 1);
221 gtk_widget_show(if_cb);
223 free_interface_list(if_list);
227 count_lb = gtk_label_new("Count:");
228 gtk_table_attach_defaults(GTK_TABLE(table), count_lb, 0, 1, 1, 2);
229 gtk_widget_show(count_lb);
231 count_list = g_list_append(count_list, count_item1);
233 snprintf(count_item2, 15, "%d", cfile.count);
234 count_list = g_list_append(count_list, count_item2);
237 count_cb = gtk_combo_new();
238 gtk_combo_set_popdown_strings(GTK_COMBO(count_cb), count_list);
239 gtk_table_attach_defaults(GTK_TABLE(table), count_cb, 1, 2, 1, 2);
240 gtk_widget_show(count_cb);
243 count_list = g_list_remove_link(count_list, count_list);
247 filesize_lb = gtk_label_new("File size:");
248 gtk_table_attach_defaults(GTK_TABLE(table), filesize_lb, 0, 1, 2, 3);
249 gtk_widget_show(filesize_lb);
251 filesize_list = g_list_append(filesize_list, filesize_item1);
252 if (cfile.autostop_filesize) {
253 snprintf(filesize_item2, 15, "%d", cfile.autostop_filesize);
254 filesize_list = g_list_append(filesize_list, filesize_item2);
257 filesize_cb = gtk_combo_new();
258 gtk_combo_set_popdown_strings(GTK_COMBO(filesize_cb), filesize_list);
259 gtk_table_attach_defaults(GTK_TABLE(table), filesize_cb, 1, 2, 2, 3);
260 gtk_widget_show(filesize_cb);
262 while (filesize_list)
263 filesize_list = g_list_remove_link(filesize_list, filesize_list);
267 duration_lb = gtk_label_new("Duration:");
268 gtk_table_attach_defaults(GTK_TABLE(table), duration_lb, 0, 1, 3, 4);
269 gtk_widget_show(duration_lb);
271 duration_list = g_list_append(duration_list, duration_item1);
272 if (cfile.autostop_duration) {
273 snprintf(duration_item2, 15, "%d", cfile.autostop_duration);
274 duration_list = g_list_append(duration_list, duration_item2);
277 duration_cb = gtk_combo_new();
278 gtk_combo_set_popdown_strings(GTK_COMBO(duration_cb), duration_list);
279 gtk_table_attach_defaults(GTK_TABLE(table), duration_cb, 1, 2, 3, 4);
280 gtk_widget_show(duration_cb);
282 while (duration_list)
283 duration_list = g_list_remove_link(duration_list, duration_list);
287 filter_bt = gtk_button_new_with_label("Filter:");
288 gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
289 GTK_SIGNAL_FUNC(capture_filter_construct_cb), NULL);
290 gtk_table_attach_defaults(GTK_TABLE(table), filter_bt, 0, 1, 4, 5);
291 gtk_widget_show(filter_bt);
293 filter_te = gtk_entry_new();
294 if (cfile.cfilter) gtk_entry_set_text(GTK_ENTRY(filter_te), cfile.cfilter);
295 gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
296 gtk_table_attach_defaults(GTK_TABLE(table), filter_te, 1, 2, 4, 5);
297 gtk_widget_show(filter_te);
301 file_bt = gtk_button_new_with_label("File:");
302 gtk_table_attach_defaults(GTK_TABLE(table), file_bt, 0, 1, 5, 6);
303 gtk_widget_show(file_bt);
305 file_te = gtk_entry_new();
306 gtk_table_attach_defaults(GTK_TABLE(table), file_te, 1, 2, 5, 6);
307 gtk_widget_show(file_te);
309 gtk_signal_connect(GTK_OBJECT(file_bt), "clicked",
310 GTK_SIGNAL_FUNC(capture_prep_file_cb), GTK_OBJECT(file_te));
312 /* Misc row: Snap spinbutton */
313 caplen_hb = gtk_hbox_new(FALSE, 3);
314 gtk_container_add(GTK_CONTAINER(main_vb), caplen_hb);
315 gtk_widget_show(caplen_hb);
317 snap_lb = gtk_label_new("Capture length");
318 gtk_misc_set_alignment(GTK_MISC(snap_lb), 0, 0.5);
319 gtk_box_pack_start(GTK_BOX(caplen_hb), snap_lb, FALSE, FALSE, 6);
320 gtk_widget_show(snap_lb);
322 snap_adj = (GtkAdjustment *) gtk_adjustment_new((float) cfile.snap,
323 MIN_PACKET_SIZE, WTAP_MAX_PACKET_SIZE, 1.0, 10.0, 0.0);
324 snap_sb = gtk_spin_button_new (snap_adj, 0, 0);
325 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE);
326 gtk_widget_set_usize (snap_sb, 80, 0);
327 gtk_box_pack_start (GTK_BOX(caplen_hb), snap_sb, FALSE, FALSE, 3);
328 gtk_widget_show(snap_sb);
330 promisc_cb = dlg_check_button_new_with_label_with_mnemonic(
331 "Capture packets in _promiscuous mode", accel_group);
332 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(promisc_cb), prefs.capture_prom_mode);
333 gtk_container_add(GTK_CONTAINER(main_vb), promisc_cb);
334 gtk_widget_show(promisc_cb);
336 /* Misc row: Ringbuffer toggle button and Ringbuffer spinbutton */
337 ringbuffer_hb = gtk_hbox_new(FALSE, 3);
338 gtk_container_add(GTK_CONTAINER(main_vb), ringbuffer_hb);
339 gtk_widget_show(ringbuffer_hb);
341 ringbuffer_on_tb = dlg_check_button_new_with_label_with_mnemonic(
342 "Use _ringbuffer", accel_group);
343 if (prefs.capture_real_time == TRUE)
344 cfile.ringbuffer_on = FALSE;
345 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ringbuffer_on_tb),cfile.ringbuffer_on);
346 gtk_signal_connect(GTK_OBJECT(ringbuffer_on_tb), "toggled",
347 GTK_SIGNAL_FUNC(capture_prep_ringbuffer_toggle_cb), GTK_OBJECT(cap_open_w));
348 gtk_box_pack_start(GTK_BOX(ringbuffer_hb), ringbuffer_on_tb, FALSE, FALSE, 0);
349 gtk_widget_show(ringbuffer_on_tb);
351 ringbuffer_nbf_lb = gtk_label_new("Number of files");
352 gtk_misc_set_alignment(GTK_MISC(ringbuffer_nbf_lb), 1, 0.5);
353 gtk_box_pack_start(GTK_BOX(ringbuffer_hb), ringbuffer_nbf_lb, FALSE, FALSE, 6);
354 gtk_widget_show(ringbuffer_nbf_lb);
356 ringbuffer_nbf_adj = (GtkAdjustment *) gtk_adjustment_new((float) cfile.ringbuffer_num_files,
357 RINGBUFFER_MIN_NUM_FILES, RINGBUFFER_MAX_NUM_FILES, 1.0, 10.0, 0.0);
358 ringbuffer_nbf_sb = gtk_spin_button_new (ringbuffer_nbf_adj, 0, 0);
359 gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (ringbuffer_nbf_sb), TRUE);
360 gtk_widget_set_usize (ringbuffer_nbf_sb, 40, 0);
361 gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), cfile.ringbuffer_on);
362 gtk_box_pack_start (GTK_BOX(ringbuffer_hb), ringbuffer_nbf_sb, TRUE, TRUE, 0);
363 gtk_widget_show(ringbuffer_nbf_sb);
365 /* Misc row: Capture file checkboxes */
366 sync_cb = dlg_check_button_new_with_label_with_mnemonic(
367 "_Update list of packets in real time", accel_group);
368 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(sync_cb), prefs.capture_real_time);
369 gtk_signal_connect(GTK_OBJECT(sync_cb), "toggled",
370 GTK_SIGNAL_FUNC(capture_prep_sync_toggle_cb), GTK_OBJECT(cap_open_w));
371 gtk_container_add(GTK_CONTAINER(main_vb), sync_cb);
372 gtk_widget_show(sync_cb);
374 auto_scroll_cb = dlg_check_button_new_with_label_with_mnemonic(
375 "_Automatic scrolling in live capture", accel_group);
376 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(auto_scroll_cb), prefs.capture_auto_scroll);
377 gtk_container_add(GTK_CONTAINER(main_vb), auto_scroll_cb);
378 gtk_widget_show(auto_scroll_cb);
380 m_resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
381 "Enable _MAC name resolution", accel_group);
382 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(m_resolv_cb),
383 prefs.name_resolve & PREFS_RESOLV_MAC);
384 gtk_container_add(GTK_CONTAINER(main_vb), m_resolv_cb);
385 gtk_widget_show(m_resolv_cb);
387 n_resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
388 "Enable _network name resolution", accel_group);
389 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(n_resolv_cb),
390 prefs.name_resolve & PREFS_RESOLV_NETWORK);
391 gtk_container_add(GTK_CONTAINER(main_vb), n_resolv_cb);
392 gtk_widget_show(n_resolv_cb);
394 t_resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
395 "Enable _transport name resolution", accel_group);
396 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(t_resolv_cb),
397 prefs.name_resolve & PREFS_RESOLV_TRANSPORT);
398 gtk_container_add(GTK_CONTAINER(main_vb), t_resolv_cb);
399 gtk_widget_show(t_resolv_cb);
401 /* Button row: OK and cancel buttons */
402 bbox = gtk_hbutton_box_new();
403 gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
404 gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
405 gtk_container_add(GTK_CONTAINER(main_vb), bbox);
406 gtk_widget_show(bbox);
408 ok_bt = gtk_button_new_with_label ("OK");
409 gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
410 GTK_SIGNAL_FUNC(capture_prep_ok_cb), GTK_OBJECT(cap_open_w));
411 GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
412 gtk_box_pack_start (GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
413 gtk_widget_grab_default(ok_bt);
414 gtk_widget_show(ok_bt);
416 cancel_bt = gtk_button_new_with_label ("Cancel");
417 gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
418 GTK_SIGNAL_FUNC(capture_prep_close_cb), GTK_OBJECT(cap_open_w));
419 GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
420 gtk_box_pack_start (GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
421 gtk_widget_show(cancel_bt);
423 /* Attach pointers to needed widgets to the capture prefs window/object */
424 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_IFACE_KEY, if_cb);
425 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILT_KEY, filter_te);
426 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILE_TE_KEY, file_te);
427 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_COUNT_KEY, count_cb);
428 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SNAP_KEY, snap_sb);
429 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_PROMISC_KEY, promisc_cb);
430 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SYNC_KEY, sync_cb);
431 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_AUTO_SCROLL_KEY, auto_scroll_cb);
432 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_M_RESOLVE_KEY, m_resolv_cb);
433 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_N_RESOLVE_KEY, n_resolv_cb);
434 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_T_RESOLVE_KEY, t_resolv_cb);
435 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILESIZE_KEY, filesize_cb);
436 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_DURATION_KEY, duration_cb);
437 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_RING_TB_KEY, ringbuffer_on_tb);
438 gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_RING_SB_KEY, ringbuffer_nbf_sb);
440 /* Catch the "activate" signal on the frame number and file name text
441 entries, so that if the user types Return there, we act as if the
442 "OK" button had been selected, as happens if Return is typed if some
443 widget that *doesn't* handle the Return key has the input focus. */
444 dlg_set_activate(filter_te, ok_bt);
445 dlg_set_activate(file_te, ok_bt);
447 /* Catch the "key_press_event" signal in the window, so that we can catch
448 the ESC key being pressed and act as if the "Cancel" button had
450 dlg_set_cancel(cap_open_w, cancel_bt);
452 /* XXX - why does not
454 gtk_widget_grab_focus(if_cb);
456 give the initial focus to the "Interface" combo box?
458 Or should I phrase that as "why does GTK+ continually frustrate
459 attempts to make GUIs driveable from the keyboard?" We have to
460 go catch the activate signal on every single GtkEntry widget
461 (rather than having widgets whose activate signal is *not*
462 caught not catch the Return keystroke, so that it passes on,
463 ultimately, to the window, which can activate the default
464 widget, i.e. the "OK" button); we have to catch the "key_press_event"
465 signal and have the handler check for ESC, so that we can have ESC
466 activate the "Cancel" button; in order to support Alt+<key> mnemonics
467 for buttons and the like, we may have to construct an accelerator
468 group by hand and set up the accelerators by hand (if that even
469 works - I've not tried it yet); we have to do a "gtk_widget_grab_focus()"
470 to keep some container widget from getting the initial focus, so that
471 you don't have to tab into the first widget in order to start typing
472 in it; and it now appears that you simply *can't* make a combo box
473 get the initial focus, at least not in the obvious fashion. Sigh.... */
475 gtk_widget_show(cap_open_w);
479 capture_prep_file_cb(GtkWidget *w, gpointer file_te)
481 GtkWidget *caller = gtk_widget_get_toplevel(w);
484 /* Has a file selection dialog box already been opened for that top-level
486 fs = gtk_object_get_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY);
489 /* Yes. Just re-activate that dialog box. */
490 reactivate_window(fs);
494 fs = gtk_file_selection_new ("Ethereal: Capture File");
496 gtk_object_set_data(GTK_OBJECT(fs), E_CAP_FILE_TE_KEY, file_te);
498 /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
499 gtk_object_set_data(GTK_OBJECT(fs), E_FS_CALLER_PTR_KEY, caller);
501 /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
502 gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, fs);
504 /* Call a handler when the file selection box is destroyed, so we can inform
505 our caller, if any, that it's been destroyed. */
506 gtk_signal_connect(GTK_OBJECT(fs), "destroy",
507 GTK_SIGNAL_FUNC(cap_prep_fs_destroy_cb), NULL);
509 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
510 "clicked", (GtkSignalFunc) cap_prep_fs_ok_cb, fs);
512 /* Connect the cancel_button to destroy the widget */
513 gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button),
514 "clicked", (GtkSignalFunc) cap_prep_fs_cancel_cb, fs);
516 /* Catch the "key_press_event" signal in the window, so that we can catch
517 the ESC key being pressed and act as if the "Cancel" button had
519 dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
525 cap_prep_fs_ok_cb(GtkWidget *w, gpointer data)
527 gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(data),
529 gtk_file_selection_get_filename (GTK_FILE_SELECTION(data)));
530 gtk_widget_destroy(GTK_WIDGET(data));
534 cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data)
536 gtk_widget_destroy(GTK_WIDGET(data));
540 cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data)
544 /* Get the widget that requested that we be popped up.
545 (It should arrange to destroy us if it's destroyed, so
546 that we don't get a pointer to a non-existent window here.) */
547 caller = gtk_object_get_data(GTK_OBJECT(win), E_FS_CALLER_PTR_KEY);
549 /* Tell it we no longer exist. */
550 gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, NULL);
552 /* Now nuke this window. */
553 gtk_grab_remove(GTK_WIDGET(win));
554 gtk_widget_destroy(GTK_WIDGET(win));
558 get_positive_int(const char *string, const char *name)
563 number = strtol(string, &p, 10);
565 * XXX - we allow extra stuff after 0, so that we don't have
566 * problems with the "(Infinite)" value.
568 if (p == string || (*p != '\0' && number != 0)) {
569 simple_dialog(ESD_TYPE_CRIT, NULL,
570 "The specified %s is not a decimal number.", name);
574 simple_dialog(ESD_TYPE_CRIT, NULL,
575 "The specified %s is a negative number.", name);
578 if (number > INT_MAX) {
579 simple_dialog(ESD_TYPE_CRIT, NULL,
580 "The specified %s is too large (greater than %d).", name, INT_MAX);
587 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
588 GtkWidget *if_cb, *filter_te, *file_te, *count_cb, *snap_sb, *promisc_cb,
589 *sync_cb, *auto_scroll_cb, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb,
590 *filesize_cb, *duration_cb, *ringbuffer_on_tb, *ringbuffer_nbf_sb;
597 if_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_IFACE_KEY);
598 filter_te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILT_KEY);
599 file_te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILE_TE_KEY);
600 count_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_COUNT_KEY);
601 snap_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SNAP_KEY);
602 promisc_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_PROMISC_KEY);
603 sync_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SYNC_KEY);
604 auto_scroll_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_AUTO_SCROLL_KEY);
605 m_resolv_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_M_RESOLVE_KEY);
606 n_resolv_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_N_RESOLVE_KEY);
607 t_resolv_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_T_RESOLVE_KEY);
608 filesize_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILESIZE_KEY);
609 duration_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_DURATION_KEY);
610 ringbuffer_on_tb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_TB_KEY);
611 ringbuffer_nbf_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_SB_KEY);
614 g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
615 if_name = strtok(if_text, " \t");
616 if (if_name == NULL) {
617 simple_dialog(ESD_TYPE_CRIT, NULL,
618 "You didn't specify an interface on which to capture packets.");
624 cfile.iface = g_strdup(if_name);
627 /* XXX - don't try to get clever and set "cfile.filter" to NULL if the
628 filter string is empty, as an indication that we don't have a filter
629 and thus don't have to set a filter when capturing - the version of
630 libpcap in Red Hat Linux 6.1, and versions based on later patches
631 in that series, don't bind the AF_PACKET socket to an interface
632 until a filter is set, which means they aren't bound at all if
633 no filter is set, which means no packets arrive as input on that
634 socket, which means Ethereal never sees any packets. */
635 filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
637 g_free(cfile.cfilter);
638 g_assert(filter_text != NULL);
639 cfile.cfilter = g_strdup(filter_text);
641 save_file = gtk_entry_get_text(GTK_ENTRY(file_te));
642 if (save_file && save_file[0]) {
643 /* User specified a file to which the capture should be written. */
644 save_file = g_strdup(save_file);
646 /* User didn't specify a file; save to a temporary file. */
650 cfile.count = atoi(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry)));
652 value = get_positive_int(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(filesize_cb)->entry)),
653 "maximum capture file size");
656 cfile.autostop_filesize = value;
658 value = get_positive_int(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(duration_cb)->entry)),
662 cfile.autostop_duration = value;
664 cfile.snap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
666 cfile.snap = WTAP_MAX_PACKET_SIZE;
667 else if (cfile.snap < MIN_PACKET_SIZE)
668 cfile.snap = MIN_PACKET_SIZE;
670 prefs.capture_prom_mode = GTK_TOGGLE_BUTTON (promisc_cb)->active;
672 prefs.capture_real_time = GTK_TOGGLE_BUTTON (sync_cb)->active;
674 prefs.capture_auto_scroll = GTK_TOGGLE_BUTTON (auto_scroll_cb)->active;
676 prefs.name_resolve = PREFS_RESOLV_NONE;
677 prefs.name_resolve |= (GTK_TOGGLE_BUTTON (m_resolv_cb)->active ? PREFS_RESOLV_MAC : PREFS_RESOLV_NONE);
678 prefs.name_resolve |= (GTK_TOGGLE_BUTTON (n_resolv_cb)->active ? PREFS_RESOLV_NETWORK : PREFS_RESOLV_NONE);
679 prefs.name_resolve |= (GTK_TOGGLE_BUTTON (t_resolv_cb)->active ? PREFS_RESOLV_TRANSPORT : PREFS_RESOLV_NONE);
681 cfile.ringbuffer_on = GTK_TOGGLE_BUTTON (ringbuffer_on_tb)->active && !(prefs.capture_real_time);
682 if (cfile.ringbuffer_on == TRUE) {
683 if (save_file == NULL) {
684 simple_dialog(ESD_TYPE_CRIT, NULL,
685 "You must specify a save file if you want to use the ringbuffer.");
687 } else if (cfile.autostop_filesize == 0) {
688 simple_dialog(ESD_TYPE_CRIT, NULL,
689 "You must specify a maximum save file size other \nthan 0 (infinite) if you want to use the ringbuffer.");
694 cfile.ringbuffer_num_files = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ringbuffer_nbf_sb));
695 if (cfile.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
696 cfile.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
697 else if (cfile.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
698 cfile.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
700 gtk_widget_destroy(GTK_WIDGET(parent_w));
702 do_capture(save_file);
706 capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w)
708 gtk_grab_remove(GTK_WIDGET(parent_w));
709 gtk_widget_destroy(GTK_WIDGET(parent_w));
713 capture_prep_destroy_cb(GtkWidget *win, gpointer user_data)
715 GtkWidget *capture_prep_filter_w;
718 /* Is there a filter edit/selection dialog associated with this
719 Capture Preferences dialog? */
720 capture_prep_filter_w = gtk_object_get_data(GTK_OBJECT(win), E_FILT_DIALOG_PTR_KEY);
722 if (capture_prep_filter_w != NULL) {
723 /* Yes. Destroy it. */
724 gtk_widget_destroy(capture_prep_filter_w);
727 /* Is there a file selection dialog associated with this
728 Print File dialog? */
729 fs = gtk_object_get_data(GTK_OBJECT(win), E_FILE_SEL_DIALOG_PTR_KEY);
732 /* Yes. Destroy it. */
733 gtk_widget_destroy(fs);
736 /* Note that we no longer have a "Capture Preferences" dialog box. */
741 capture_prep_ringbuffer_toggle_cb(GtkWidget *ringbuffer_tb, gpointer parent_w)
743 GtkWidget *ringbuffer_nbf_sb, *sync_cb;
745 ringbuffer_nbf_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_SB_KEY);
746 sync_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SYNC_KEY);
748 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_tb)) == TRUE) {
749 gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), TRUE);
750 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sync_cb)) == TRUE) {
751 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sync_cb), FALSE);
754 gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), FALSE);
759 capture_prep_sync_toggle_cb(GtkWidget *sync_cb, gpointer parent_w)
761 GtkWidget *ringbuffer_on_tb;
763 ringbuffer_on_tb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_TB_KEY);
765 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sync_cb)) == TRUE) {
766 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb)) == TRUE) {
767 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb), FALSE);
772 #endif /* HAVE_LIBPCAP */