/* capture.c
* Routines for packet capture windows
*
- * $Id: capture.c,v 1.243 2004/03/02 22:07:21 ulfl Exp $
+ * $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+/* With MSVC and a libethereal.dll this file needs to import some variables
+ in a special way. Therefore _NEED_VAR_IMPORT_ is defined. */
+#define _NEED_VAR_IMPORT_
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "pcap-util.h"
#include "alert_box.h"
#include "simple_dialog.h"
-#include "prefs.h"
+#include <epan/prefs.h>
#include "globals.h"
#include "conditions.h"
#include "capture_stop_conditions.h"
#include "wiretap/wtap.h"
#include "wiretap/wtap-capture.h"
-#include "packet-atalk.h"
-#include "packet-atm.h"
-#include "packet-clip.h"
-#include "packet-eth.h"
-#include "packet-fddi.h"
-#include "packet-null.h"
-#include "packet-ppp.h"
-#include "packet-raw.h"
-#include "packet-sll.h"
-#include "packet-tr.h"
-#include "packet-ieee80211.h"
-#include "packet-chdlc.h"
-#include "packet-prism.h"
-#include "packet-ipfc.h"
-#include "packet-arcnet.h"
+#include <epan/dissectors/packet-ap1394.h>
+#include <epan/dissectors/packet-atalk.h>
+#include <epan/dissectors/packet-atm.h>
+#include <epan/dissectors/packet-clip.h>
+#include <epan/dissectors/packet-eth.h>
+#include <epan/dissectors/packet-fddi.h>
+#include <epan/dissectors/packet-null.h>
+#include <epan/dissectors/packet-ppp.h>
+#include <epan/dissectors/packet-raw.h>
+#include <epan/dissectors/packet-sll.h>
+#include <epan/dissectors/packet-tr.h>
+#include <epan/dissectors/packet-ieee80211.h>
+#include <epan/dissectors/packet-chdlc.h>
+#include <epan/dissectors/packet-prism.h>
+#include <epan/dissectors/packet-ipfc.h>
+#include <epan/dissectors/packet-arcnet.h>
#ifdef _WIN32
#include "capture-wpcap.h"
#define O_BINARY 0
#endif
-
static gboolean sync_pipe_do_capture(gboolean is_tempfile);
static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
static void sync_pipe_wait_for_child(gboolean);
char tmpname[128+1];
gboolean is_tempfile;
gchar *capfile_name;
+ gboolean ret;
if (save_file != NULL) {
/* If the Sync option is set, we return to the caller while the capture
if (capture_opts.multi_files_on) {
/* ringbuffer is enabled */
cfile.save_file_fd = ringbuf_init(capfile_name,
- (capture_opts.has_ring_num_files) ? capture_opts.num_files : 0);
+ (capture_opts.has_ring_num_files) ? capture_opts.ring_num_files : 0);
} else {
/* Try to open/create the specified file for use as a capture buffer. */
cfile.save_file_fd = open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT,
cfile.save_file = capfile_name;
/* cfile.save_file is "g_free"ed below, which is equivalent to
"g_free(capfile_name)". */
+ fork_child = -1;
if (capture_opts.sync_mode) {
/* sync mode: do the capture in a child process */
- return sync_pipe_do_capture(is_tempfile);
+ ret = sync_pipe_do_capture(is_tempfile);
/* capture is still running */
+ set_main_window_name("(Live Capture in Progress) - Ethereal");
} else {
/* normal mode: do the capture synchronously */
- return normal_do_capture(is_tempfile);
+ set_main_window_name("(Live Capture in Progress) - Ethereal");
+ ret = normal_do_capture(is_tempfile);
/* capture is finished here */
}
+
+ return ret;
}
sprintf(save_file_fd,"%d",cfile.save_file_fd); /* in lieu of itoa */
argv = sync_pipe_add_arg(argv, &argc, save_file_fd);
- if (capture_opts.has_autostop_count) {
+ if (capture_opts.has_autostop_packets) {
argv = sync_pipe_add_arg(argv, &argc, "-c");
- sprintf(scount,"%d",capture_opts.autostop_count);
+ sprintf(scount,"%d",capture_opts.autostop_packets);
argv = sync_pipe_add_arg(argv, &argc, scount);
}
if (capture_opts.linktype != -1) {
argv = sync_pipe_add_arg(argv, &argc, "-y");
+#ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
+ sprintf(ssnap,"%s",pcap_datalink_val_to_name(capture_opts.linktype));
+#else
+ /* XXX - just treat it as a number */
sprintf(ssnap,"%d",capture_opts.linktype);
+#endif
argv = sync_pipe_add_arg(argv, &argc, ssnap);
}
argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
}
+ if (!capture_opts.show_info) {
+ argv = sync_pipe_add_arg(argv, &argc, "-H");
+ }
+
if (!capture_opts.promisc_mode)
argv = sync_pipe_add_arg(argv, &argc, "-p");
unlink(cfile.save_file);
g_free(cfile.save_file);
cfile.save_file = NULL;
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Capture child process sent us a bad message");
return FALSE;
}
what the problem was. */
if (byte_count == 0) {
/* Zero-length message? */
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Capture child process failed, but its error message was empty.");
} else {
msg = g_malloc(byte_count + 1);
if (msg == NULL) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Capture child process failed, but its error message was too big.");
} else {
i = read(sync_pipe[READ], msg, byte_count);
msg[byte_count] = '\0';
if (i < 0) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Capture child process failed: Error %s reading its error message.",
strerror(errno));
} else if (i == 0) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Capture child process failed: EOF reading its error message.");
sync_pipe_wait_for_child(FALSE);
} else
in the dialog box?
XXX - set "fork_child" to -1 if we find it exited? */
if (_cwait(&wstatus, fork_child, _WAIT_CHILD) == -1) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Child capture process stopped unexpectedly");
}
#else
/* The child exited; display its exit status, if it's not zero,
and even if it's zero if "always_report" is true. */
if (always_report || WEXITSTATUS(wstatus) != 0) {
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Child capture process exited: exit status %d",
WEXITSTATUS(wstatus));
}
} else if (WIFSTOPPED(wstatus)) {
/* It stopped, rather than exiting. "Should not happen." */
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Child capture process stopped: %s",
sync_pipe_signame(WSTOPSIG(wstatus)));
} else if (WIFSIGNALED(wstatus)) {
/* It died with a signal. */
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Child capture process died: %s%s",
sync_pipe_signame(WTERMSIG(wstatus)),
WCOREDUMP(wstatus) ? " - core dumped" : "");
} else {
/* What? It had to either have exited, or stopped, or died with
a signal; what happened here? */
- simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
+ simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"Child capture process died: wait status %#o", wstatus);
}
}
time_t upd_time, cur_time;
time_t start_time;
int err, inpkts;
- condition *cnd_stop_capturesize = NULL;
- condition *cnd_stop_timeout = NULL;
- condition *cnd_ring_timeout = NULL;
+ condition *cnd_file_duration = NULL;
+ condition *cnd_autostop_files = NULL;
+ condition *cnd_autostop_size = NULL;
+ condition *cnd_autostop_duration = NULL;
+ guint32 autostop_files = 0;
char errmsg[4096+1];
gboolean write_ok;
gboolean close_ok;
#ifdef MUST_DO_SELECT
int pcap_fd = 0;
#endif
- guint32 num_files = capture_opts.num_files;
+ gboolean show_info = capture_opts.show_info || !capture_opts.sync_mode;
/* Initialize Windows Socket if we are in a WIN32 OS
This needs to be done before querying the interface for network/netmask */
ld.go = TRUE;
ld.counts.total = 0;
- if (capture_opts.has_autostop_count)
- ld.max = capture_opts.autostop_count;
+ if (capture_opts.has_autostop_packets)
+ ld.max = capture_opts.autostop_packets;
else
ld.max = 0; /* no limit */
ld.err = 0; /* no error seen yet */
open_err_str);
if (pch != NULL) {
+#ifdef _WIN32
+ /* try to set the capture buffer size */
+ if (pcap_setbuff(pch, capture_opts.buffer_size * 1024 * 1024) != 0) {
+ simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
+ "%sCouldn't set the capture buffer size!%s\n"
+ "\n"
+ "The capture buffer size of %luMB seems to be too high for your machine,\n"
+ "the default of 1MB will be used.\n"
+ "\n"
+ "Nonetheless, the capture is started.\n",
+ simple_dialog_primary_start(), simple_dialog_primary_end(), capture_opts.buffer_size);
+ }
+#endif
+
/* setting the data link type only works on real interfaces */
if (capture_opts.linktype != -1) {
set_linktype_err_str = set_pcap_linktype(pch, cfile.iface,
}
/* start capture info dialog */
- capture_ui.callback_data = &ld;
- capture_ui.counts = &ld.counts;
- capture_info_create(&capture_ui);
+ if(show_info) {
+ capture_ui.callback_data = &ld;
+ capture_ui.counts = &ld.counts;
+ capture_info_create(&capture_ui, cfile.iface);
+ }
start_time = time(NULL);
upd_time = time(NULL);
if (capture_child)
signal(SIGUSR1, stop_capture_signal_handler);
#endif
+
/* initialize capture stop conditions */
init_capture_stop_conditions();
/* create stop conditions */
if (capture_opts.has_autostop_filesize)
- cnd_stop_capturesize =
- cnd_new(CND_CLASS_CAPTURESIZE,(long)capture_opts.autostop_filesize * 1000);
+ cnd_autostop_size =
+ cnd_new(CND_CLASS_CAPTURESIZE,(long)capture_opts.autostop_filesize);
if (capture_opts.has_autostop_duration)
- cnd_stop_timeout =
+ cnd_autostop_duration =
cnd_new(CND_CLASS_TIMEOUT,(gint32)capture_opts.autostop_duration);
- if (capture_opts.multi_files_on && capture_opts.has_ring_duration)
- cnd_ring_timeout =
- cnd_new(CND_CLASS_TIMEOUT, capture_opts.ringbuffer_duration);
+ if (capture_opts.multi_files_on) {
+ if (capture_opts.has_file_duration)
+ cnd_file_duration =
+ cnd_new(CND_CLASS_TIMEOUT, capture_opts.file_duration);
+ if (capture_opts.has_autostop_files)
+ cnd_autostop_files =
+ cnd_new(CND_CLASS_CAPTURESIZE, capture_opts.autostop_files);
+ }
/* WOW, everything is prepared! */
/* please fasten your seat belts, we will enter now the actual capture loop */
}
}
else
-#endif
+#endif /* _WIN32 */
{
#ifdef MUST_DO_SELECT
/*
ld.pcap_err = TRUE;
ld.go = FALSE;
}
-#endif
+#endif /* MUST_DO_SELECT */
}
if (inpkts > 0) {
ld.sync_packets += inpkts;
- /* check capture stop conditons */
- if (cnd_stop_capturesize != NULL && cnd_eval(cnd_stop_capturesize,
+
+ /* check capture size condition */
+ if (cnd_autostop_size != NULL && cnd_eval(cnd_autostop_size,
(guint32)wtap_get_bytes_dumped(ld.pdh))){
- /* Capture file reached its maximum size. */
- if (num_files > 1 || capture_opts.multi_files_on) {
+ /* Capture size limit reached, do we have another file? */
+ if (capture_opts.multi_files_on) {
+ if (cnd_autostop_files != NULL && cnd_eval(cnd_autostop_files, ++autostop_files)) {
+ /* no files left: stop here */
+ ld.go = FALSE;
+ continue;
+ }
+
/* Switch to the next ringbuffer file */
if (ringbuf_switch_file(&cfile, &ld.pdh, &ld.err)) {
- num_files--;
- /* File switch succeeded: reset the condition */
- cnd_reset(cnd_stop_capturesize);
- if (cnd_ring_timeout) {
- cnd_reset(cnd_ring_timeout);
+ /* File switch succeeded: reset the conditions */
+ cnd_reset(cnd_autostop_size);
+ if (cnd_file_duration) {
+ cnd_reset(cnd_file_duration);
}
} else {
/* File switch failed: stop here */
continue;
}
} else {
- /* no files left */
- if (!capture_opts.multi_files_on) {
- /* ... and no ringbuffer, stop now */
- ld.go = FALSE;
- }
+ /* single file, stop now */
+ ld.go = FALSE;
+ continue;
}
- }
+ } /* cnd_autostop_size */
}
/* Only update once a second so as not to overload slow displays */
/* Let the parent process know. */
/* calculate and display running time */
- cur_time -= start_time;
- capture_ui.running_time = cur_time;
- capture_ui.new_packets = ld.sync_packets;
- capture_info_update(&capture_ui);
+ if(show_info) {
+ cur_time -= start_time;
+ capture_ui.running_time = cur_time;
+ capture_ui.new_packets = ld.sync_packets;
+ capture_info_update(&capture_ui);
+ }
if (ld.sync_packets) {
/* do sync here */
ld.sync_packets = 0;
}
- if (cnd_stop_timeout != NULL && cnd_eval(cnd_stop_timeout)) {
- /* The specified capture time has elapsed; stop the capture. */
+ /* check capture duration condition */
+ if (cnd_autostop_duration != NULL && cnd_eval(cnd_autostop_duration)) {
+ /* The maximum capture time has elapsed; stop the capture. */
ld.go = FALSE;
- } else if (cnd_ring_timeout != NULL && cnd_eval(cnd_ring_timeout)) {
- if(num_files > 1 || capture_opts.multi_files_on) {
- /* time elasped for this ring file, switch to the next */
+ continue;
+ }
+
+ /* check capture file duration condition */
+ if (cnd_file_duration != NULL && cnd_eval(cnd_file_duration)) {
+ /* duration limit reached, do we have another file? */
+ if (capture_opts.multi_files_on) {
+ if (cnd_autostop_files != NULL && cnd_eval(cnd_autostop_files, ++autostop_files)) {
+ /* no files left: stop here */
+ ld.go = FALSE;
+ continue;
+ }
+
+ /* Switch to the next ringbuffer file */
if (ringbuf_switch_file(&cfile, &ld.pdh, &ld.err)) {
- /* File switch succeeded: reset the condition */
- cnd_reset(cnd_ring_timeout);
- num_files--;
+ /* file switch succeeded: reset the conditions */
+ cnd_reset(cnd_file_duration);
+ if(cnd_autostop_size)
+ cnd_reset(cnd_autostop_size);
} else {
/* File switch failed: stop here */
ld.go = FALSE;
+ continue;
}
} else {
- /* no files left */
- if (!capture_opts.multi_files_on) {
- /* ... and no ringbuffer, stop now */
- ld.go = FALSE;
- }
+ /* single file, stop now */
+ ld.go = FALSE;
+ continue;
}
- }
+ } /* cnd_file_duration */
}
} /* while (ld.go) */
/* delete stop conditions */
- if (cnd_stop_capturesize != NULL)
- cnd_delete(cnd_stop_capturesize);
- if (cnd_stop_timeout != NULL)
- cnd_delete(cnd_stop_timeout);
- if (cnd_ring_timeout != NULL)
- cnd_delete(cnd_ring_timeout);
+ if (cnd_file_duration != NULL)
+ cnd_delete(cnd_file_duration);
+ if (cnd_autostop_files != NULL)
+ cnd_delete(cnd_autostop_files);
+ if (cnd_autostop_size != NULL)
+ cnd_delete(cnd_autostop_size);
+ if (cnd_autostop_duration != NULL)
+ cnd_delete(cnd_autostop_duration);
if (ld.pcap_err) {
snprintf(errmsg, sizeof(errmsg), "Error while capturing packets: %s",
WSACleanup();
#endif
- capture_info_destroy(&capture_ui);
+ if(show_info) {
+ capture_info_destroy(&capture_ui);
+ }
return write_ok;
case WTAP_ENCAP_ARCNET_LINUX:
capture_arcnet(pd, whdr.caplen, &ld->counts, TRUE, FALSE);
break;
+ case WTAP_ENCAP_APPLE_IP_OVER_IEEE1394:
+ capture_ap1394(pd, 0, whdr.caplen, &ld->counts);
+ break;
/* XXX - some ATM drivers on FreeBSD might prepend a 4-byte ATM
pseudo-header to DLT_ATM_RFC1483, with LLC header following;
we might have to implement that at some point. */