1998-09-16 02:39:15 +00:00
|
|
|
/* capture.c
|
|
|
|
* Routines for packet capture windows
|
|
|
|
*
|
2004-07-18 00:24:25 +00:00
|
|
|
* $Id$
|
1998-09-16 03:22:19 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* Ethereal - Network traffic analyzer
|
2001-10-25 06:41:48 +00:00
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
1998-09-16 02:39:15 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
1998-09-16 02:39:15 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2004-05-09 10:03:41 +00:00
|
|
|
/* 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_
|
|
|
|
|
1998-09-16 02:39:15 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
1999-07-09 04:18:36 +00:00
|
|
|
#ifdef HAVE_LIBPCAP
|
|
|
|
|
1998-12-17 05:42:33 +00:00
|
|
|
#include <stdlib.h>
|
1998-09-16 02:39:15 +00:00
|
|
|
#include <string.h>
|
2000-08-11 13:37:21 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_FCNTL_H
|
1999-10-02 06:26:53 +00:00
|
|
|
#include <fcntl.h>
|
2000-08-11 13:37:21 +00:00
|
|
|
#endif
|
1999-08-03 20:51:41 +00:00
|
|
|
|
2004-10-30 23:26:47 +00:00
|
|
|
#ifdef HAVE_IO_H
|
|
|
|
# include <io.h>
|
1999-08-03 20:51:41 +00:00
|
|
|
#endif
|
|
|
|
|
1999-05-11 18:51:10 +00:00
|
|
|
#include <signal.h>
|
|
|
|
#include <errno.h>
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2004-10-30 23:26:47 +00:00
|
|
|
#include <pcap.h>
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/packet.h>
|
2003-10-11 21:49:56 +00:00
|
|
|
#include <epan/dfilter/dfilter.h>
|
1998-09-16 02:39:15 +00:00
|
|
|
#include "file.h"
|
|
|
|
#include "capture.h"
|
2004-10-30 11:44:06 +00:00
|
|
|
#include "capture_sync.h"
|
1998-09-16 02:39:15 +00:00
|
|
|
#include "util.h"
|
2001-11-09 07:44:51 +00:00
|
|
|
#include "pcap-util.h"
|
2004-02-11 01:23:25 +00:00
|
|
|
#include "alert_box.h"
|
2000-01-03 06:59:25 +00:00
|
|
|
#include "simple_dialog.h"
|
2004-09-27 22:55:15 +00:00
|
|
|
#include <epan/prefs.h>
|
1999-09-09 03:32:03 +00:00
|
|
|
#include "globals.h"
|
2001-12-04 07:32:05 +00:00
|
|
|
#include "conditions.h"
|
2001-12-04 08:26:00 +00:00
|
|
|
#include "ringbuffer.h"
|
1998-09-16 02:39:15 +00:00
|
|
|
|
2002-12-31 21:12:55 +00:00
|
|
|
#ifdef _WIN32
|
2001-11-09 07:44:51 +00:00
|
|
|
#include "capture-wpcap.h"
|
|
|
|
#endif
|
2004-01-22 18:13:57 +00:00
|
|
|
#include "ui_util.h"
|
2001-11-09 07:44:51 +00:00
|
|
|
|
"autostop_filesize" and "autostop_duration" don't need to be in the
"capture_file" structure - they're a property of an in-progress capture,
not a property of an open capture file. Make them just variables.
The maximum number of packets to be captured should be a variable
separate from the "count" field in the "capture_file" structure - the
latter is a count of the packets in the capture file in question.
Have Boolean variables indicating whether a maximum packet count,
maximum capture file size, and maximum capture duration were specified.
If an option isn't set, and we're doing an "update list of packets in
real time" capture, don't pass the option to the child process with a
command-line argument.
Don't create "stop when the capture file reaches this size" or "stop
when the capture's run for this long" conditions if a maximum capture
file size or a maximum capture duration, respectively, haven't been
specified. Don't test or free a condition if it wasn't created.
Don't allow a 0 argument to the "-c" flag - the absence of a "-c" flag
is the way you specify "no limit on the number of packets".
Initialize the check boxes and spin buttons for the "maximum packets to
capture", "maximum capture size", and "maximum capture duration" options
to the values they had in the last capture. If an option wasn't
specified, don't read its value from the dialog box and set the
variable.
svn path=/trunk/; revision=4795
2002-02-24 03:33:05 +00:00
|
|
|
/*
|
|
|
|
* Capture options.
|
|
|
|
*/
|
2002-02-24 09:25:36 +00:00
|
|
|
capture_options capture_opts;
|
2004-02-21 13:40:06 +00:00
|
|
|
gboolean capture_child; /* if this is the child for "-S" */
|
"autostop_filesize" and "autostop_duration" don't need to be in the
"capture_file" structure - they're a property of an in-progress capture,
not a property of an open capture file. Make them just variables.
The maximum number of packets to be captured should be a variable
separate from the "count" field in the "capture_file" structure - the
latter is a count of the packets in the capture file in question.
Have Boolean variables indicating whether a maximum packet count,
maximum capture file size, and maximum capture duration were specified.
If an option isn't set, and we're doing an "update list of packets in
real time" capture, don't pass the option to the child process with a
command-line argument.
Don't create "stop when the capture file reaches this size" or "stop
when the capture's run for this long" conditions if a maximum capture
file size or a maximum capture duration, respectively, haven't been
specified. Don't test or free a condition if it wasn't created.
Don't allow a 0 argument to the "-c" flag - the absence of a "-c" flag
is the way you specify "no limit on the number of packets".
Initialize the check boxes and spin buttons for the "maximum packets to
capture", "maximum capture size", and "maximum capture duration" options
to the values they had in the last capture. If an option wasn't
specified, don't read its value from the dialog box and set the
variable.
svn path=/trunk/; revision=4795
2002-02-24 03:33:05 +00:00
|
|
|
|
2000-06-15 08:02:43 +00:00
|
|
|
|
2004-06-30 06:58:59 +00:00
|
|
|
/* Win32 needs the O_BINARY flag for open() */
|
|
|
|
#ifndef O_BINARY
|
|
|
|
#define O_BINARY 0
|
|
|
|
#endif
|
2000-09-15 05:32:49 +00:00
|
|
|
|
2004-02-21 14:04:17 +00:00
|
|
|
static gboolean normal_do_capture(gboolean is_tempfile);
|
|
|
|
static void stop_capture_signal_handler(int signo);
|
|
|
|
|
1999-10-02 06:26:53 +00:00
|
|
|
/* Open a specified file, or create a temporary file, and start a capture
|
2003-09-15 23:15:32 +00:00
|
|
|
to the file in question. Returns TRUE if the capture starts
|
|
|
|
successfully, FALSE otherwise. */
|
|
|
|
gboolean
|
2002-09-09 20:39:01 +00:00
|
|
|
do_capture(const char *save_file)
|
Move the toolkit-independent code to create a temporary capture file,
and to fork off and run a separate copy of "ethereal" for "-S" and "-F"
captures or just call "capture()" otherwise, out of "gtk/capture_dlg.c"
and into a routine in "capture.c".
If the attempt to create said temporary capture file fails, pop up a
dialog box and don't do the capture.
Have the child capture process send a message upstream after it either
successfully starts the capture and syncs out the header of the capture
file, or fails to start the capture; the message indicates whether it
succeeded or failed, and, if it failed, includes a failure message.
This:
avoids the use of a signal, and thus means we don't have to
worry about whether to capture the signal, or whether to start
or stop capturing depending on whether this particular capture
is in sync mode or not;
lets us pop up the message box for the error in the parent
process if we're in sync mode, rather than doing it in the
child, which didn't work well.
Add a check button to the Capture/Start dialog box, so that we can
control, for each capture, whether it's to be done in sync mode or not.
svn path=/trunk/; revision=708
1999-09-23 06:27:27 +00:00
|
|
|
{
|
|
|
|
char tmpname[128+1];
|
Allow the user to save either all of the current capture, or only the
packets that are currently being displayed from that capture.
Centralize the code to control whether "File:Save" and "File:Save As"
are enabled (and *always* have "File:Save As" enabled if you have a
capture; "File:Save" is enabled only if you have a live capture you've
not yet saved, although it does the same thing as "File:Save As").
Have the "save_file" member of a "capture_file" structure represent
*only* the file currently being *written* to by a capture, and, if there
is no capture currently in progress, have it be NULL; the name of the
file currently being *displayed" is in the "filename" member, and an
"is_tempfile" member indicates whether it's a temporary file for a live
capture or not.
Have "close_cap_file()" delete the current capture file if it's a
temporary capture file that hasn't been saved (in its entirety - saving
selected frames doesn't count). Do the same (if there *is* a current
capture file) when exiting.
The "Ready to load or capture" message is the only statusbar message in
the "main" context; "close_cap_file()" should never pop it, it should
only pop whatever message exists in the "file" context, and thus has no
need to take, as an argument, the context for the message it should pop.
Update the man page to reflect the new behavior of "File:Save" and
"File:Save As", and to reflect recent changes to "Display:Match Selected".
svn path=/trunk/; revision=1170
1999-11-30 20:50:15 +00:00
|
|
|
gboolean is_tempfile;
|
2002-09-09 20:39:01 +00:00
|
|
|
gchar *capfile_name;
|
2004-06-20 13:39:44 +00:00
|
|
|
gboolean ret;
|
2002-09-09 20:39:01 +00:00
|
|
|
|
|
|
|
if (save_file != NULL) {
|
|
|
|
/* If the Sync option is set, we return to the caller while the capture
|
|
|
|
* is in progress. Therefore we need to take a copy of save_file in
|
|
|
|
* case the caller destroys it after we return.
|
|
|
|
*/
|
|
|
|
capfile_name = g_strdup(save_file);
|
2004-03-02 22:07:23 +00:00
|
|
|
if (capture_opts.multi_files_on) {
|
2001-12-04 08:26:00 +00:00
|
|
|
/* ringbuffer is enabled */
|
2002-02-24 09:25:36 +00:00
|
|
|
cfile.save_file_fd = ringbuf_init(capfile_name,
|
2004-03-04 19:31:21 +00:00
|
|
|
(capture_opts.has_ring_num_files) ? capture_opts.ring_num_files : 0);
|
2001-12-04 08:26:00 +00:00
|
|
|
} else {
|
|
|
|
/* Try to open/create the specified file for use as a capture buffer. */
|
2002-02-24 09:25:36 +00:00
|
|
|
cfile.save_file_fd = open(capfile_name, O_RDWR|O_BINARY|O_TRUNC|O_CREAT,
|
|
|
|
0600);
|
2001-12-04 08:26:00 +00:00
|
|
|
}
|
Allow the user to save either all of the current capture, or only the
packets that are currently being displayed from that capture.
Centralize the code to control whether "File:Save" and "File:Save As"
are enabled (and *always* have "File:Save As" enabled if you have a
capture; "File:Save" is enabled only if you have a live capture you've
not yet saved, although it does the same thing as "File:Save As").
Have the "save_file" member of a "capture_file" structure represent
*only* the file currently being *written* to by a capture, and, if there
is no capture currently in progress, have it be NULL; the name of the
file currently being *displayed" is in the "filename" member, and an
"is_tempfile" member indicates whether it's a temporary file for a live
capture or not.
Have "close_cap_file()" delete the current capture file if it's a
temporary capture file that hasn't been saved (in its entirety - saving
selected frames doesn't count). Do the same (if there *is* a current
capture file) when exiting.
The "Ready to load or capture" message is the only statusbar message in
the "main" context; "close_cap_file()" should never pop it, it should
only pop whatever message exists in the "file" context, and thus has no
need to take, as an argument, the context for the message it should pop.
Update the man page to reflect the new behavior of "File:Save" and
"File:Save As", and to reflect recent changes to "Display:Match Selected".
svn path=/trunk/; revision=1170
1999-11-30 20:50:15 +00:00
|
|
|
is_tempfile = FALSE;
|
1999-10-02 06:26:53 +00:00
|
|
|
} else {
|
|
|
|
/* Choose a random name for the capture buffer */
|
2000-06-27 04:36:03 +00:00
|
|
|
cfile.save_file_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
|
1999-10-02 06:26:53 +00:00
|
|
|
capfile_name = g_strdup(tmpname);
|
Allow the user to save either all of the current capture, or only the
packets that are currently being displayed from that capture.
Centralize the code to control whether "File:Save" and "File:Save As"
are enabled (and *always* have "File:Save As" enabled if you have a
capture; "File:Save" is enabled only if you have a live capture you've
not yet saved, although it does the same thing as "File:Save As").
Have the "save_file" member of a "capture_file" structure represent
*only* the file currently being *written* to by a capture, and, if there
is no capture currently in progress, have it be NULL; the name of the
file currently being *displayed" is in the "filename" member, and an
"is_tempfile" member indicates whether it's a temporary file for a live
capture or not.
Have "close_cap_file()" delete the current capture file if it's a
temporary capture file that hasn't been saved (in its entirety - saving
selected frames doesn't count). Do the same (if there *is* a current
capture file) when exiting.
The "Ready to load or capture" message is the only statusbar message in
the "main" context; "close_cap_file()" should never pop it, it should
only pop whatever message exists in the "file" context, and thus has no
need to take, as an argument, the context for the message it should pop.
Update the man page to reflect the new behavior of "File:Save" and
"File:Save As", and to reflect recent changes to "Display:Match Selected".
svn path=/trunk/; revision=1170
1999-11-30 20:50:15 +00:00
|
|
|
is_tempfile = TRUE;
|
1999-10-02 06:26:53 +00:00
|
|
|
}
|
2000-06-27 04:36:03 +00:00
|
|
|
if (cfile.save_file_fd == -1) {
|
2000-07-20 05:10:02 +00:00
|
|
|
if (is_tempfile) {
|
2004-01-31 03:22:42 +00:00
|
|
|
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
|
2000-07-20 05:10:02 +00:00
|
|
|
"The temporary file to which the capture would be saved (\"%s\")"
|
1999-11-28 09:44:53 +00:00
|
|
|
"could not be opened: %s.", capfile_name, strerror(errno));
|
2000-07-20 05:10:02 +00:00
|
|
|
} else {
|
2004-03-02 22:07:23 +00:00
|
|
|
if (capture_opts.multi_files_on) {
|
2001-12-04 08:26:00 +00:00
|
|
|
ringbuf_error_cleanup();
|
|
|
|
}
|
2004-02-11 01:23:25 +00:00
|
|
|
open_failure_alert_box(capfile_name, errno, TRUE);
|
2000-07-20 05:10:02 +00:00
|
|
|
}
|
2002-09-09 20:39:01 +00:00
|
|
|
g_free(capfile_name);
|
2003-09-15 23:15:32 +00:00
|
|
|
return FALSE;
|
Move the toolkit-independent code to create a temporary capture file,
and to fork off and run a separate copy of "ethereal" for "-S" and "-F"
captures or just call "capture()" otherwise, out of "gtk/capture_dlg.c"
and into a routine in "capture.c".
If the attempt to create said temporary capture file fails, pop up a
dialog box and don't do the capture.
Have the child capture process send a message upstream after it either
successfully starts the capture and syncs out the header of the capture
file, or fails to start the capture; the message indicates whether it
succeeded or failed, and, if it failed, includes a failure message.
This:
avoids the use of a signal, and thus means we don't have to
worry about whether to capture the signal, or whether to start
or stop capturing depending on whether this particular capture
is in sync mode or not;
lets us pop up the message box for the error in the parent
process if we're in sync mode, rather than doing it in the
child, which didn't work well.
Add a check button to the Capture/Start dialog box, so that we can
control, for each capture, whether it's to be done in sync mode or not.
svn path=/trunk/; revision=708
1999-09-23 06:27:27 +00:00
|
|
|
}
|
2003-09-15 22:48:42 +00:00
|
|
|
cf_close(&cfile);
|
2000-06-27 04:36:03 +00:00
|
|
|
g_assert(cfile.save_file == NULL);
|
|
|
|
cfile.save_file = capfile_name;
|
2002-09-09 20:39:01 +00:00
|
|
|
/* cfile.save_file is "g_free"ed below, which is equivalent to
|
|
|
|
"g_free(capfile_name)". */
|
Add a new global flag "capture_child", which is TRUE if we're a child
process for a sync mode or fork mode capture.
Have that flag control whether we do things that *only* the parent or
*only* the child should do, rather than basing it solely on the setting
of "sync_mode" or "fork_mode" (or, in the case of stuff done in the
child process either in sync mode or fork mode, rather than basing it on
the setting of those flags at all).
Split "do_capture()" into a "run_capture()" routine that starts a
capture (possibly by forking off and execing a child process, if we're
supposed to do sync mode or fork mode captures), and that assumes the
file to which the capture is to write has already been opened and that
"cf.save_file_fd" is the file descriptor for that file, and a
"do_capture()" routine that creates a temporary file, getting an FD for
it, and calls "run_capture()".
Use "run_capture()", rather than "capture()", for "-k" captures, so that
it'll do the capture in a child process if "-S" or "-F" was specified
("do_capture()" won't do because "-k" captures should write to the file
specified by the "-w" flag, not some random temporary file).
For child process captures, however, just use "capture()" - the child
process shouldn't itself fork off a child if we're in sync or fork mode,
and should just write to the file whose file descriptor was specified by
the "-W" flag on the command line.
All this allows you to do "ethereal -S -w <file> -i <interface> -k" to
start a sync mode capture from the command line.
svn path=/trunk/; revision=740
1999-09-30 06:50:01 +00:00
|
|
|
|
2004-02-21 12:58:42 +00:00
|
|
|
if (capture_opts.sync_mode) {
|
|
|
|
/* sync mode: do the capture in a child process */
|
2004-06-20 13:39:44 +00:00
|
|
|
ret = sync_pipe_do_capture(is_tempfile);
|
2004-02-21 12:58:42 +00:00
|
|
|
/* capture is still running */
|
2004-06-20 13:39:44 +00:00
|
|
|
set_main_window_name("(Live Capture in Progress) - Ethereal");
|
2004-02-21 12:58:42 +00:00
|
|
|
} else {
|
|
|
|
/* normal mode: do the capture synchronously */
|
2004-06-20 13:39:44 +00:00
|
|
|
set_main_window_name("(Live Capture in Progress) - Ethereal");
|
|
|
|
ret = normal_do_capture(is_tempfile);
|
2004-02-21 12:58:42 +00:00
|
|
|
/* capture is finished here */
|
|
|
|
}
|
2004-06-20 13:39:44 +00:00
|
|
|
|
|
|
|
return ret;
|
2004-02-21 12:58:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-30 11:44:06 +00:00
|
|
|
/* start a normal capture session */
|
2004-02-21 12:58:42 +00:00
|
|
|
static gboolean
|
|
|
|
normal_do_capture(gboolean is_tempfile)
|
|
|
|
{
|
|
|
|
int capture_succeeded;
|
|
|
|
gboolean stats_known;
|
|
|
|
struct pcap_stat stats;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
/* Not sync mode. */
|
2004-10-30 17:50:51 +00:00
|
|
|
capture_succeeded = capture_start(&stats_known, &stats);
|
2004-10-30 14:30:52 +00:00
|
|
|
if (capture_opts.quit_after_cap) {
|
2004-02-21 12:58:42 +00:00
|
|
|
/* DON'T unlink the save file. Presumably someone wants it. */
|
|
|
|
main_window_exit();
|
|
|
|
}
|
|
|
|
if (!capture_succeeded) {
|
|
|
|
/* We didn't succeed in doing the capture, so we don't have a save
|
|
|
|
file. */
|
2004-03-02 22:07:23 +00:00
|
|
|
if (capture_opts.multi_files_on) {
|
2004-02-21 12:58:42 +00:00
|
|
|
ringbuf_free();
|
|
|
|
} else {
|
|
|
|
g_free(cfile.save_file);
|
|
|
|
}
|
|
|
|
cfile.save_file = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/* Capture succeeded; attempt to read in the capture file. */
|
|
|
|
if ((err = cf_open(cfile.save_file, is_tempfile, &cfile)) != 0) {
|
|
|
|
/* We're not doing a capture any more, so we don't have a save
|
|
|
|
file. */
|
2004-03-02 22:07:23 +00:00
|
|
|
if (capture_opts.multi_files_on) {
|
2004-02-21 12:58:42 +00:00
|
|
|
ringbuf_free();
|
|
|
|
} else {
|
|
|
|
g_free(cfile.save_file);
|
|
|
|
}
|
|
|
|
cfile.save_file = NULL;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the read filter to NULL. */
|
|
|
|
cfile.rfcode = NULL;
|
|
|
|
|
|
|
|
/* Get the packet-drop statistics.
|
|
|
|
|
|
|
|
XXX - there are currently no packet-drop statistics stored
|
|
|
|
in libpcap captures, and that's what we're reading.
|
|
|
|
|
|
|
|
At some point, we will add support in Wiretap to return
|
|
|
|
packet-drop statistics for capture file formats that store it,
|
|
|
|
and will make "cf_read()" get those statistics from Wiretap.
|
|
|
|
We clear the statistics (marking them as "not known") in
|
|
|
|
"cf_open()", and "cf_read()" will only fetch them and mark
|
|
|
|
them as known if Wiretap supplies them, so if we get the
|
|
|
|
statistics now, after calling "cf_open()" but before calling
|
|
|
|
"cf_read()", the values we store will be used by "cf_read()".
|
|
|
|
|
|
|
|
If a future libpcap capture file format stores the statistics,
|
|
|
|
we'll put them into the capture file that we write, and will
|
|
|
|
thus not have to set them here - "cf_read()" will get them from
|
|
|
|
the file and use them. */
|
|
|
|
if (stats_known) {
|
|
|
|
cfile.drops_known = TRUE;
|
|
|
|
|
|
|
|
/* XXX - on some systems, libpcap doesn't bother filling in
|
|
|
|
"ps_ifdrop" - it doesn't even set it to zero - so we don't
|
|
|
|
bother looking at it.
|
|
|
|
|
|
|
|
Ideally, libpcap would have an interface that gave us
|
|
|
|
several statistics - perhaps including various interface
|
|
|
|
error statistics - and would tell us which of them it
|
|
|
|
supplies, allowing us to display only the ones it does. */
|
|
|
|
cfile.drops = stats.ps_drop;
|
|
|
|
}
|
|
|
|
switch (cf_read(&cfile)) {
|
|
|
|
|
|
|
|
case READ_SUCCESS:
|
|
|
|
case READ_ERROR:
|
|
|
|
/* Just because we got an error, that doesn't mean we were unable
|
|
|
|
to read any of the file; we handle what we could get from the
|
|
|
|
file. */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case READ_ABORTED:
|
|
|
|
/* Exit by leaving the main loop, so that any quit functions
|
|
|
|
we registered get called. */
|
|
|
|
main_window_nested_quit();
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We're not doing a capture any more, so we don't have a save
|
|
|
|
file. */
|
2004-03-02 22:07:23 +00:00
|
|
|
if (capture_opts.multi_files_on) {
|
2004-02-21 12:58:42 +00:00
|
|
|
ringbuf_free();
|
|
|
|
} else {
|
|
|
|
g_free(cfile.save_file);
|
|
|
|
}
|
|
|
|
cfile.save_file = NULL;
|
|
|
|
|
|
|
|
/* if we didn't captured even a single packet, close the file again */
|
|
|
|
if(cfile.count == 0) {
|
|
|
|
simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK,
|
|
|
|
"%sNo packets captured!%s\n\n"
|
|
|
|
"As no data was captured, closing the %scapture file!",
|
|
|
|
simple_dialog_primary_start(), simple_dialog_primary_end(),
|
|
|
|
(cfile.is_tempfile) ? "temporary " : "");
|
|
|
|
cf_close(&cfile);
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
Enough is enough. Requiring anybody who uses Ethereal on Linux to
update their libpcap probably isn't going to scale - the increasing
frequency with which "Ethereal hangs when I try to capture packets"
shows up on "ethereal-dev" suggests that, unless and until a libpcap
with the "select()" in it becomes ubiquitous on Linux, that'll be the
source of a constant support burden - so we'll just put the "select()"
in Ethereal if it's being built for Linux.
(Putting it in for platforms where the read timeout argument to
"pcap_open_live()" works adds an extra useless system call at best and,
at worst, could make Ethereal not work - "select()" doesn't work on
"/dev/bpf" devices on FreeBSD 3.3, at least, unless you're in "immediate
mode", and, whilst "immediate mode" would make Ethereal respond more
quickly when packets arrive, it might cause Ethereal to respond too
quickly, doing reads for every new packet rather than waiting for
multiple packets to arrive and reading them all with one "read()", which
appears to be at least part of the intent of the read timeout on
"/dev/bpf" devices in BSD.)
svn path=/trunk/; revision=1451
2000-01-12 06:56:32 +00:00
|
|
|
|
2000-07-30 16:54:12 +00:00
|
|
|
static void
|
2004-10-30 17:50:51 +00:00
|
|
|
stop_capture_signal_handler(int signo _U_)
|
2000-07-30 16:54:12 +00:00
|
|
|
{
|
2004-10-30 17:50:51 +00:00
|
|
|
capture_loop_stop();
|
2000-07-30 16:54:12 +00:00
|
|
|
}
|
|
|
|
|
2000-10-11 06:01:16 +00:00
|
|
|
|
2004-10-30 17:50:51 +00:00
|
|
|
int
|
|
|
|
capture_start(gboolean *stats_known, struct pcap_stat *stats)
|
Move the toolkit-independent code to create a temporary capture file,
and to fork off and run a separate copy of "ethereal" for "-S" and "-F"
captures or just call "capture()" otherwise, out of "gtk/capture_dlg.c"
and into a routine in "capture.c".
If the attempt to create said temporary capture file fails, pop up a
dialog box and don't do the capture.
Have the child capture process send a message upstream after it either
successfully starts the capture and syncs out the header of the capture
file, or fails to start the capture; the message indicates whether it
succeeded or failed, and, if it failed, includes a failure message.
This:
avoids the use of a signal, and thus means we don't have to
worry about whether to capture the signal, or whether to start
or stop capturing depending on whether this particular capture
is in sync mode or not;
lets us pop up the message box for the error in the parent
process if we're in sync mode, rather than doing it in the
child, which didn't work well.
Add a check button to the Capture/Start dialog box, so that we can
control, for each capture, whether it's to be done in sync mode or not.
svn path=/trunk/; revision=708
1999-09-23 06:27:27 +00:00
|
|
|
{
|
2000-10-11 06:01:16 +00:00
|
|
|
#ifndef _WIN32
|
|
|
|
/*
|
|
|
|
* Catch SIGUSR1, so that we exit cleanly if the parent process
|
|
|
|
* kills us with it due to the user selecting "Capture->Stop".
|
|
|
|
*/
|
2002-06-13 21:23:02 +00:00
|
|
|
if (capture_child)
|
2004-02-21 12:58:42 +00:00
|
|
|
signal(SIGUSR1, stop_capture_signal_handler);
|
2000-10-11 06:01:16 +00:00
|
|
|
#endif
|
2004-03-04 19:31:21 +00:00
|
|
|
|
2004-10-30 17:50:51 +00:00
|
|
|
return capture_loop_start(stats_known, stats);
|
2002-06-04 11:19:59 +00:00
|
|
|
}
|
|
|
|
|
2000-10-11 06:01:16 +00:00
|
|
|
void
|
|
|
|
capture_stop(void)
|
|
|
|
{
|
2004-10-30 11:44:06 +00:00
|
|
|
|
|
|
|
if (capture_opts.sync_mode) {
|
2004-10-30 17:50:51 +00:00
|
|
|
sync_pipe_stop();
|
2004-02-03 17:59:01 +00:00
|
|
|
}
|
2004-11-10 17:58:16 +00:00
|
|
|
|
|
|
|
capture_loop_stop();
|
2000-10-11 06:01:16 +00:00
|
|
|
}
|
|
|
|
|
Add a routine to kill a capture child if it exists, so that if we exit
(by deleting the main window or selecting File->Quit or typing ^Q) while
an "Update list of packets in real time" capture is in progress, we can
abort the capture.
Arrange that "fork_child" is -1 when there is no capture child, so said
routine knows when it can kill the child.
When we exit, kill off any capture child, using that routine, and, if
we're exiting due to a request to delete the main window and, if a read
is in progress (from an "Update list of packets in real time" capture),
don't delete the main window - just set the "Read aborted" flag, so that
the code doing the read will see that flag (it will be called because
the pipe to the capture child is closed due to the child exiting) will
see that and clean up and exit itself.
svn path=/trunk/; revision=4498
2002-01-08 09:32:15 +00:00
|
|
|
void
|
|
|
|
kill_capture_child(void)
|
|
|
|
{
|
2004-10-30 11:44:06 +00:00
|
|
|
if (capture_opts.sync_mode) {
|
|
|
|
sync_pipe_kill();
|
|
|
|
}
|
Add a routine to kill a capture child if it exists, so that if we exit
(by deleting the main window or selecting File->Quit or typing ^Q) while
an "Update list of packets in real time" capture is in progress, we can
abort the capture.
Arrange that "fork_child" is -1 when there is no capture child, so said
routine knows when it can kill the child.
When we exit, kill off any capture child, using that routine, and, if
we're exiting due to a request to delete the main window and, if a read
is in progress (from an "Update list of packets in real time" capture),
don't delete the main window - just set the "Read aborted" flag, so that
the code doing the read will see that flag (it will be called because
the pipe to the capture child is closed due to the child exiting) will
see that and clean up and exit itself.
svn path=/trunk/; revision=4498
2002-01-08 09:32:15 +00:00
|
|
|
}
|
|
|
|
|
1999-07-09 04:18:36 +00:00
|
|
|
|
|
|
|
#endif /* HAVE_LIBPCAP */
|