Handle the 2GiB boundary case of the max filesize autostop condition properly so that we avoid overflow conditions and so that we ensure we don't capture more than 2GiB. Also, document the max filesize autostop value of 2GIB as well as indicating that it's truly GiB and not GB.

This fixes the problem reported on ask: http://ask.wireshark.org/questions/23891/wireshark-wont-run-with-multiple-capture-files

#BACKPORT(1.10) ... not sure about 1.8?

svn path=/trunk/; revision=51576
This commit is contained in:
Chris Maynard 2013-08-29 18:15:13 +00:00
parent 894ca4e904
commit bc654875f0
9 changed files with 66 additions and 55 deletions

View File

@ -109,7 +109,7 @@ capture_opts_init(capture_options *capture_opts)
capture_opts->has_autostop_packets = FALSE;
capture_opts->autostop_packets = 0;
capture_opts->has_autostop_filesize = FALSE;
capture_opts->autostop_filesize = 1024; /* 1 MB */
capture_opts->autostop_filesize = 1024; /* 1 MiB */
capture_opts->has_autostop_duration = FALSE;
capture_opts->autostop_duration = 60; /* 1 min */
capture_opts->capture_comment = NULL;
@ -216,7 +216,7 @@ capture_opts_log(const char *log_domain, GLogLevelFlags log_level, capture_optio
g_log(log_domain, log_level, "AutostopFiles (%u) : %u", capture_opts->has_autostop_files, capture_opts->autostop_files);
g_log(log_domain, log_level, "AutostopPackets (%u) : %u", capture_opts->has_autostop_packets, capture_opts->autostop_packets);
g_log(log_domain, log_level, "AutostopFilesize(%u) : %u (KB)", capture_opts->has_autostop_filesize, capture_opts->autostop_filesize);
g_log(log_domain, log_level, "AutostopFilesize(%u) : %u (KiB)", capture_opts->has_autostop_filesize, capture_opts->autostop_filesize);
g_log(log_domain, log_level, "AutostopDuration(%u) : %u", capture_opts->has_autostop_duration, capture_opts->autostop_duration);
}

View File

@ -205,14 +205,14 @@ typedef struct capture_options_tag {
int autostop_packets; /**< Maximum packet count */
gboolean has_autostop_filesize; /**< TRUE if maximum capture file size
is specified */
gint32 autostop_filesize; /**< Maximum capture file size */
guint32 autostop_filesize; /**< Maximum capture file size */
gboolean has_autostop_duration; /**< TRUE if maximum capture duration
is specified */
gint32 autostop_duration; /**< Maximum capture duration */
gchar *capture_comment; /** capture comment to write to the
output file */
/* internally used (don't touch from outside) */
gboolean output_to_pipe; /**< save_file is a pipe (named or stdout) */
gboolean capture_child; /**< hidden option: Wireshark child mode */

View File

@ -145,7 +145,7 @@ const char* CND_CLASS_CAPTURESIZE = "cnd_class_capturesize";
/* structure that contains user supplied data for this condition */
typedef struct _cnd_capturesize_dat{
long max_capture_size;
guint64 max_capture_size;
}cnd_capturesize_dat;
/*
@ -164,7 +164,9 @@ static condition* _cnd_constr_capturesize(condition* cnd, va_list ap){
if((data = (cnd_capturesize_dat*)g_malloc(sizeof(cnd_capturesize_dat))) == NULL)
return NULL;
/* initialize user data */
data->max_capture_size = va_arg(ap, long);
data->max_capture_size = va_arg(ap, guint64);
if (data->max_capture_size > ((guint64)INT_MAX + 1))
data->max_capture_size = (guint64)INT_MAX + 1;
cnd_set_user_data(cnd, (void*)data);
return cnd;
} /* END _cnd_constr_capturesize() */
@ -194,7 +196,7 @@ static gboolean _cnd_eval_capturesize(condition* cnd, va_list ap){
cnd_capturesize_dat* data = (cnd_capturesize_dat*)cnd_get_user_data(cnd);
/* check capturesize here */
if(data->max_capture_size == 0) return FALSE; /* 0 == infinite */
if(va_arg(ap, long) >= data->max_capture_size){
if(va_arg(ap, guint64) >= data->max_capture_size){
return TRUE;
}
return FALSE;

View File

@ -245,7 +245,7 @@ win32strerror(DWORD error)
char *p;
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error, 0, errbuf, ERRBUF_SIZE, NULL);
NULL, error, 0, errbuf, ERRBUF_SIZE, NULL);
/*
* "FormatMessage()" "helpfully" sticks CR/LF at the end of the
@ -415,7 +415,7 @@ sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, voi
if (capture_opts->multi_files_on) {
if (capture_opts->has_autostop_filesize) {
argv = sync_pipe_add_arg(argv, &argc, "-b");
g_snprintf(sfilesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
g_snprintf(sfilesize, ARGV_NUMBER_LEN, "filesize:%u",capture_opts->autostop_filesize);
argv = sync_pipe_add_arg(argv, &argc, sfilesize);
}
@ -439,7 +439,7 @@ sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, voi
} else {
if (capture_opts->has_autostop_filesize) {
argv = sync_pipe_add_arg(argv, &argc, "-a");
g_snprintf(sautostop_filesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
g_snprintf(sautostop_filesize, ARGV_NUMBER_LEN, "filesize:%u",capture_opts->autostop_filesize);
argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
}
}
@ -1146,7 +1146,7 @@ sync_pipe_run_command_actual(char** argv, gchar **data, gchar **primary_msg,
return ret;
}
/* centralised logging and timing for sync_pipe_run_command_actual(),
/* centralised logging and timing for sync_pipe_run_command_actual(),
* redirects to sync_pipe_run_command_actual()
*/
static int
@ -1158,7 +1158,7 @@ sync_pipe_run_command(char** argv, gchar **data, gchar **primary_msg,
GTimeVal end_time;
float elapsed;
int logging_enabled;
/* check if logging is actually enabled, otherwise don't expend the CPU generating logging */
logging_enabled=( (G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO) & G_LOG_LEVEL_MASK & prefs.console_log_level);
if(logging_enabled){
@ -1653,10 +1653,10 @@ pipe_read_block(int pipe_fd, char *indicator, int len, char *msg,
/* we have a problem here, try to read some more bytes from the pipe to debug where the problem really is */
memcpy(msg, header, sizeof(header));
newly = read(pipe_fd, &msg[sizeof(header)], len-sizeof(header));
if (newly < 0) { /* error */
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
"read from pipe %d: error(%u): %s", pipe_fd, errno, g_strerror(errno));
}
if (newly < 0) { /* error */
g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
"read from pipe %d: error(%u): %s", pipe_fd, errno, g_strerror(errno));
}
*err_msg = g_strdup_printf("Unknown message from dumpcap, try to show it as a string: %s",
msg);
return -1;
@ -1760,13 +1760,13 @@ sync_pipe_input_cb(gint source, gpointer user_data)
/* The child has sent us a filename which we couldn't open.
This could mean that the child is creating files faster
than we can handle it. (XXX - why would that result in
a failure to open the file?)
than we can handle it. (XXX - why would that result in
a failure to open the file?)
That should only be the case for very fast file switches;
We can't do much more than telling the child to stop.
(This is the "emergency brake" if the user e.g. wants to
switch files every second).
switch files every second).
This can also happen if the user specified "-", meaning
"standard output", as the capture file. */
@ -2003,13 +2003,13 @@ sync_pipe_signame(int sig)
static void create_dummy_signal_pipe() {
gchar *dummy_signal_pipe_name;
if (dummy_signal_pipe != NULL) return;
if (!dummy_control_id) {
dummy_control_id = g_strdup_printf("%d.dummy", GetCurrentProcessId());
dummy_control_id = g_strdup_printf("%d.dummy", GetCurrentProcessId());
}
/* Create the signal pipe */
dummy_signal_pipe_name = g_strdup_printf(SIGNAL_PIPE_FORMAT, dummy_control_id);
dummy_signal_pipe = CreateNamedPipe(utf_8to16(dummy_signal_pipe_name),

View File

@ -68,9 +68,9 @@ B<duration>:I<value> Stop writing to a capture file after I<value> seconds have
elapsed.
B<filesize>:I<value> Stop writing to a capture file after it reaches a size of
I<value> kilobytes (where a kilobyte is 1024 bytes). If this option is used
together with the -b option, dumpcap will stop writing to the current capture
file and switch to the next one if filesize is reached.
I<value> KiB. If this option is used together with the -b option, dumpcap will
stop writing to the current capture file and switch to the next one if filesize
is reached. Note that the filesize is limited to a maximum value of 2 GiB.
B<files>:I<value> Stop writing to capture files after I<value> number of files
were written.
@ -99,7 +99,7 @@ B<duration>:I<value> switch to the next file after I<value> seconds have
elapsed, even if the current file is not completely filled up.
B<filesize>:I<value> switch to the next file after it reaches a size of
I<value> kilobytes (where a kilobyte is 1024 bytes).
I<value> KiB. Note that the filesize is limited to a maximum value of 2 GiB.
B<files>:I<value> begin again with the first file after I<value> number of
files were written (form a ring buffer). This value must be less than 100000.

View File

@ -165,12 +165,12 @@ B<duration>:I<value> Stop writing to a capture file after I<value> seconds
have elapsed.
B<filesize>:I<value> Stop writing to a capture file after it reaches a size of
I<value> kilobytes (where a kilobyte is 1024 bytes). If this option is used
together with the -b option, B<TShark> will stop writing to the current
capture file and switch to the next one if filesize is reached. When reading a
capture file, B<TShark> will stop reading the file after the number of bytes
read exceeds this number (the complete packet will be read, so more bytes than
this number may be read).
I<value> KiB. If this option is used together with the -b option, B<TShark>
will stop writing to the current capture file and switch to the next one if
filesize is reached. When reading a capture file, B<TShark> will stop reading
the file after the number of bytes read exceeds this number (the complete
packet will be read, so more bytes than this number may be read). Note that
the filesize is limited to a maximum value of 2 GiB.
B<files>:I<value> Stop writing to capture files after I<value> number of files
were written.
@ -199,7 +199,7 @@ B<duration>:I<value> switch to the next file after I<value> seconds have
elapsed, even if the current file is not completely filled up.
B<filesize>:I<value> switch to the next file after it reaches a size of
I<value> kilobytes (where a kilobyte is 1024 bytes).
I<value> KiB. Note that the filesize is limited to a maximum value of 2 GiB.
B<files>:I<value> begin again with the first file after I<value> number of
files were written (form a ring buffer). This value must be less than 100000.

View File

@ -232,9 +232,10 @@ B<duration>:I<value> Stop writing to a capture file after I<value> seconds have
elapsed.
B<filesize>:I<value> Stop writing to a capture file after it reaches a size of
I<value> kilobytes (where a kilobyte is 1024 bytes). If this option is used
together with the -b option, Wireshark will stop writing to the current
capture file and switch to the next one if filesize is reached.
I<value> KiB. If this option is used together with the -b option, Wireshark
will stop writing to the current capture file and switch to the next one if
filesize is reached. Note that the filesize is limited to a maximum value of
2 GiB.
B<files>:I<value> Stop writing to capture files after I<value> number of files
were written.
@ -263,7 +264,7 @@ B<duration>:I<value> switch to the next file after I<value> seconds have
elapsed, even if the current file is not completely filled up.
B<filesize>:I<value> switch to the next file after it reaches a size of
I<value> kilobytes (where a kilobyte is 1024 bytes).
I<value> KiB. Note that the filesize is limited to a maximum value of 2 GiB.
B<files>:I<value> begin again with the first file after I<value> number of
files were written (form a ring buffer). This value must be less than 100000.
@ -2361,7 +2362,7 @@ I<Update list of packets in real time> option is checked.
The I<Next file every ... megabyte(s)> check box and fields lets
you specify that a switch to a next file should be done
if the specified filesize is reached. You can also select the appropriate
unit, but beware that the filesize has a maximum of 2 GB.
unit, but beware that the filesize has a maximum of 2 GiB.
The check box is forced to be checked, as "multiple files" mode requires a
file size to be specified.

View File

@ -3575,9 +3575,13 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
/* initialize capture stop (and alike) conditions */
init_capture_stop_conditions();
/* create stop conditions */
if (capture_opts->has_autostop_filesize)
if (capture_opts->has_autostop_filesize) {
if (capture_opts->autostop_filesize > (((guint32)INT_MAX + 1) / 1024)) {
capture_opts->autostop_filesize = ((guint32)INT_MAX + 1) / 1024;
}
cnd_autostop_size =
cnd_new(CND_CLASS_CAPTURESIZE,(long)capture_opts->autostop_filesize * 1024);
cnd_new(CND_CLASS_CAPTURESIZE, (guint64)capture_opts->autostop_filesize * 1024);
}
if (capture_opts->has_autostop_duration)
cnd_autostop_duration =
cnd_new(CND_CLASS_TIMEOUT,(gint32)capture_opts->autostop_duration);
@ -3678,7 +3682,7 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
/* check capture size condition */
if (cnd_autostop_size != NULL &&
cnd_eval(cnd_autostop_size, (guint32)global_ld.bytes_written)) {
cnd_eval(cnd_autostop_size, global_ld.bytes_written)) {
/* Capture size limit reached, do we have another file? */
if (!do_file_switch_or_stop(capture_opts, cnd_autostop_files,
cnd_autostop_size, cnd_file_duration))

View File

@ -952,9 +952,9 @@ guint32 value)
#define SIZE_UNIT_GIGABYTES 2
#define MAX_SIZE_UNITS 3
static const char *size_unit_name[MAX_SIZE_UNITS] = {
"kilobyte(s)",
"megabyte(s)",
"gigabyte(s)",
"kibibyte(s)",
"mebibyte(s)",
"gibibyte(s)"
};
/* create one of the size options */
@ -1013,15 +1013,19 @@ guint32 value)
switch(unit) {
case(SIZE_UNIT_KILOBYTES):
return value;
if (value > (((guint32)G_MAXINT + 1) / 1024)) {
return 0;
} else {
return value;
}
case(SIZE_UNIT_MEGABYTES):
if (value > G_MAXINT / 1024) {
if (value > (((guint32)G_MAXINT + 1) / (1024 * 1024))) {
return 0;
} else {
return value * 1024;
}
case(SIZE_UNIT_GIGABYTES):
if (value > G_MAXINT / (1024 * 1024)) {
if (value > (((guint32)G_MAXINT + 1) / (1024 * 1024 * 1024))) {
return 0;
} else {
return value * 1024 * 1024;
@ -5308,7 +5312,7 @@ fprintf(stderr, "Adding the default filter \"%s\"???\n", global_capture_opts.def
window_get_geometry(top_level, &tl_geom);
gtk_window_set_default_size(GTK_WINDOW(cap_open_w), tl_geom.width * 8 / 10, -1);
gtk_widget_show_all(cap_open_w);
window_present(cap_open_w);
@ -5601,8 +5605,8 @@ capture_dlg_prep(gpointer parent_w) {
} else {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"%sMultiple files: Requested filesize too large!%s\n\n"
"The setting \"Next file every x byte(s)\" can't be greater than %u bytes (2GB).",
simple_dialog_primary_start(), simple_dialog_primary_end(), G_MAXINT);
"The setting \"Next file every x byte(s)\" can't be greater than %u bytes (2GiB).",
simple_dialog_primary_start(), simple_dialog_primary_end(), (guint32)G_MAXINT + 1);
return FALSE;
}
}
@ -5635,8 +5639,8 @@ capture_dlg_prep(gpointer parent_w) {
} else {
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
"%sStop Capture: Requested filesize too large!%s\n\n"
"The setting \"after x byte(s)\" can't be greater than %u bytes (2GB).",
simple_dialog_primary_start(), simple_dialog_primary_end(), G_MAXINT);
"The setting \"after x byte(s)\" can't be greater than %u bytes (2GiB).",
simple_dialog_primary_start(), simple_dialog_primary_end(), (guint32)G_MAXINT + 1);
return FALSE;
}
}
@ -5704,7 +5708,7 @@ create_and_fill_model(GtkTreeView *view)
device.snaplen = WTAP_MAX_PACKET_SIZE;
device.has_snaplen = FALSE;
}
if (device.has_snaplen) {
snaplen_string = g_strdup_printf("%d", device.snaplen);
} else {
@ -5717,7 +5721,7 @@ create_and_fill_model(GtkTreeView *view)
device.buffer = buffer;
} else {
device.buffer = DEFAULT_CAPTURE_BUFFER_SIZE;
}
}
#endif
global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, i);
g_array_insert_val(global_capture_opts.all_ifaces, i, device);