Don't do pcap heuristics on a pipe.

Instead, just:

  assume a file with the regular pcap magic number is a regular pcap
  file, not an unhelpfully-modified-without-changing-the-magic-number
  format such as one of the (fortunately, short-lived) memory-mapped
  capture formats or the Nokia format;

  reject a file with the memory-mapped-capture-finally-changed-the-
  magic-number magic number, as they then changed the *new* format
  without changing its magic number;

  and don't even leave a provision for multiple formats using the
  "nanosecond pcap" magic number - not even when reading from a file -
  so we can punish bad behavior (which is what changing the format
  without changing the magic number is).

This should get rid of the last place where, when reading a pcap file
from a pipe, the first packet isn't displayed as soon as it arrives.

Bug: 14345
Change-Id: I2fcb3354dc84cdd2d8ec749a0db883e56971c4b4
Reviewed-on: https://code.wireshark.org/review/25383
Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
Guy Harris 2018-01-18 23:06:24 -08:00
parent ecced16299
commit 5b9e9b3fe3
3 changed files with 87 additions and 49 deletions

View File

@ -720,6 +720,7 @@ wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_
{
int fd;
ws_statb64 statb;
gboolean ispipe = FALSE;
wtap *wth;
unsigned int i;
gboolean use_stdin = FALSE;
@ -761,6 +762,7 @@ wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_
*err = WTAP_ERR_RANDOM_OPEN_PIPE;
return NULL;
}
ispipe = TRUE;
} else if (S_ISDIR(statb.st_mode)) {
/*
* Return different errors for "this is a directory"
@ -836,6 +838,7 @@ wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_
wth->random_fh = NULL;
/* initialization */
wth->ispipe = ispipe;
wth->file_encap = WTAP_ENCAP_UNKNOWN;
wth->subtype_sequential_close = NULL;
wth->subtype_close = NULL;

View File

@ -88,12 +88,8 @@ wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA
};
#define N_SUBTYPES_STANDARD G_N_ELEMENTS(subtypes_standard)
static const int subtypes_nsec[] = {
WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC
};
#define N_SUBTYPES_NSEC G_N_ELEMENTS(subtypes_nsec)
#define MAX_FIGURES_OF_MERIT \
MAX(MAX(N_SUBTYPES_MODIFIED, N_SUBTYPES_STANDARD), N_SUBTYPES_NSEC)
MAX(N_SUBTYPES_MODIFIED, N_SUBTYPES_STANDARD)
int figures_of_merit[MAX_FIGURES_OF_MERIT];
const int *subtypes;
int n_subtypes;
@ -362,80 +358,118 @@ wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
* Oh, and if it has the standard magic number, it might, instead,
* be a Nokia libpcap file, so we may need to try that if
* neither normal nor ss990417 headers work.
*
* But don't do that if the input is a pipe; that would mean the
* open won't complete until two packets have been written to
* the pipe, unless the pipe is closed after one packet has
* been written, so a program reading from the file won't see
* the first packet until the second packet has been written.
*/
if (modified) {
/*
* Well, we have the magic number from Alexey's
* later two patches. Try the subtypes for that.
* later two patches. Try the subtypes for that,
* and fail if we're reading from a pipe.
*/
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;
subtypes = subtypes_modified;
n_subtypes = N_SUBTYPES_MODIFIED;
} else {
if (wth->file_tsprec == WTAP_TSPREC_NSEC) {
/*
* We have nanosecond-format libpcap's magic
* number. Try the subtypes for that.
* number. There's only one format with that
* magic number (if somebody comes up with
* another one, we'll just refuse to support
* it and tell them to ask The Tcpdump Group
* for another magic number).
*/
subtypes = subtypes_nsec;
n_subtypes = N_SUBTYPES_NSEC;
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC;
subtypes = NULL;
n_subtypes = 0;
} else {
/*
* We have the regular libpcap magic number.
* Try the subtypes for that.
* Try the subtypes for that, unless we're
* reading from a pipe, in which case we
* just assume it's a regular libpcap file.
*/
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP;
subtypes = subtypes_standard;
n_subtypes = N_SUBTYPES_STANDARD;
}
}
/*
* Try all the subtypes.
* Do we have any subtypes to try?
*/
first_packet_offset = file_tell(wth->fh);
for (i = 0; i < n_subtypes; i++) {
wth->file_type_subtype = subtypes[i];
figures_of_merit[i] = libpcap_try(wth, err, err_info);
if (figures_of_merit[i] == -1) {
/*
* Well, we couldn't even read it.
* Give up.
*/
if (n_subtypes == 0) {
/*
* No, so just use what we picked.
*/
goto done;
} else if (wth->ispipe) {
/*
* It's a pipe, so use what we picked, unless we picked
* WTAP_FILE_TYPE_SUBTYPE_UNKNOWN, in which case we fail.
*/
if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_UNKNOWN) {
*err = WTAP_ERR_UNSUPPORTED;
*err_info = g_strdup("pcap: that type of pcap file can't be read from a pipe");
return WTAP_OPEN_ERROR;
}
if (figures_of_merit[i] == 0) {
/*
* This format doesn't have any issues.
* Put the seek pointer back, and finish.
*/
if (file_seek(wth->fh, first_packet_offset, SEEK_SET, err) == -1) {
goto done;
} else {
first_packet_offset = file_tell(wth->fh);
for (i = 0; i < n_subtypes; i++) {
wth->file_type_subtype = subtypes[i];
figures_of_merit[i] = libpcap_try(wth, err, err_info);
if (figures_of_merit[i] == -1) {
/*
* Well, we couldn't even read it.
* Give up.
*/
return WTAP_OPEN_ERROR;
}
goto done;
}
if (figures_of_merit[i] == 0) {
/*
* This format doesn't have any issues.
* Put the seek pointer back, and finish,
* using that format as the subtype.
*/
if (file_seek(wth->fh, first_packet_offset,
SEEK_SET, err) == -1) {
return WTAP_OPEN_ERROR;
}
goto done;
}
/*
* OK, we've recorded the figure of merit for this one;
* go back to the first packet and try the next one.
*/
if (file_seek(wth->fh, first_packet_offset, SEEK_SET, err) == -1) {
return WTAP_OPEN_ERROR;
}
}
/*
* OK, none are perfect; let's see which one is least bad.
*/
best_subtype = INT_MAX;
for (i = 0; i < n_subtypes; i++) {
/*
* Is this subtype better than the last one we saw?
*/
if (figures_of_merit[i] < best_subtype) {
/*
* Yes. Choose it until we find a better one.
* OK, we've recorded the figure of merit for this
* one; go back to the first packet and try the
* next one.
*/
wth->file_type_subtype = subtypes[i];
best_subtype = figures_of_merit[i];
if (file_seek(wth->fh, first_packet_offset, SEEK_SET,
err) == -1) {
return WTAP_OPEN_ERROR;
}
}
/*
* OK, none are perfect; let's see which one is least bad.
*/
best_subtype = INT_MAX;
for (i = 0; i < n_subtypes; i++) {
/*
* Is this subtype better than the last one we saw?
*/
if (figures_of_merit[i] < best_subtype) {
/*
* Yes. Choose it until we find a better one.
*/
wth->file_type_subtype = subtypes[i];
best_subtype = figures_of_merit[i];
}
}
}

View File

@ -47,6 +47,7 @@ typedef gboolean (*subtype_seek_read_func)(struct wtap*, gint64,
struct wtap {
FILE_T fh;
FILE_T random_fh; /**< Secondary FILE_T for random access */
gboolean ispipe; /**< TRUE if the file is a pipe */
int file_type_subtype;
guint snapshot_length;
struct Buffer *frame_buffer;