forked from osmocom/wireshark
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:
parent
ecced16299
commit
5b9e9b3fe3
|
@ -720,6 +720,7 @@ wtap_open_offline(const char *filename, unsigned int type, int *err, char **err_
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
ws_statb64 statb;
|
ws_statb64 statb;
|
||||||
|
gboolean ispipe = FALSE;
|
||||||
wtap *wth;
|
wtap *wth;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
gboolean use_stdin = FALSE;
|
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;
|
*err = WTAP_ERR_RANDOM_OPEN_PIPE;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
ispipe = TRUE;
|
||||||
} else if (S_ISDIR(statb.st_mode)) {
|
} else if (S_ISDIR(statb.st_mode)) {
|
||||||
/*
|
/*
|
||||||
* Return different errors for "this is a directory"
|
* 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;
|
wth->random_fh = NULL;
|
||||||
|
|
||||||
/* initialization */
|
/* initialization */
|
||||||
|
wth->ispipe = ispipe;
|
||||||
wth->file_encap = WTAP_ENCAP_UNKNOWN;
|
wth->file_encap = WTAP_ENCAP_UNKNOWN;
|
||||||
wth->subtype_sequential_close = NULL;
|
wth->subtype_sequential_close = NULL;
|
||||||
wth->subtype_close = NULL;
|
wth->subtype_close = NULL;
|
||||||
|
|
|
@ -88,12 +88,8 @@ wtap_open_return_val libpcap_open(wtap *wth, int *err, gchar **err_info)
|
||||||
WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA
|
WTAP_FILE_TYPE_SUBTYPE_PCAP_NOKIA
|
||||||
};
|
};
|
||||||
#define N_SUBTYPES_STANDARD G_N_ELEMENTS(subtypes_standard)
|
#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 \
|
#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];
|
int figures_of_merit[MAX_FIGURES_OF_MERIT];
|
||||||
const int *subtypes;
|
const int *subtypes;
|
||||||
int n_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,
|
* 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
|
* be a Nokia libpcap file, so we may need to try that if
|
||||||
* neither normal nor ss990417 headers work.
|
* 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) {
|
if (modified) {
|
||||||
/*
|
/*
|
||||||
* Well, we have the magic number from Alexey's
|
* 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;
|
subtypes = subtypes_modified;
|
||||||
n_subtypes = N_SUBTYPES_MODIFIED;
|
n_subtypes = N_SUBTYPES_MODIFIED;
|
||||||
} else {
|
} else {
|
||||||
if (wth->file_tsprec == WTAP_TSPREC_NSEC) {
|
if (wth->file_tsprec == WTAP_TSPREC_NSEC) {
|
||||||
/*
|
/*
|
||||||
* We have nanosecond-format libpcap's magic
|
* 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;
|
wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PCAP_NSEC;
|
||||||
n_subtypes = N_SUBTYPES_NSEC;
|
subtypes = NULL;
|
||||||
|
n_subtypes = 0;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* We have the regular libpcap magic number.
|
* 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;
|
subtypes = subtypes_standard;
|
||||||
n_subtypes = N_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);
|
if (n_subtypes == 0) {
|
||||||
for (i = 0; i < n_subtypes; i++) {
|
/*
|
||||||
wth->file_type_subtype = subtypes[i];
|
* No, so just use what we picked.
|
||||||
figures_of_merit[i] = libpcap_try(wth, err, err_info);
|
*/
|
||||||
if (figures_of_merit[i] == -1) {
|
goto done;
|
||||||
/*
|
} else if (wth->ispipe) {
|
||||||
* Well, we couldn't even read it.
|
/*
|
||||||
* Give up.
|
* 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;
|
return WTAP_OPEN_ERROR;
|
||||||
}
|
}
|
||||||
if (figures_of_merit[i] == 0) {
|
goto done;
|
||||||
/*
|
} else {
|
||||||
* This format doesn't have any issues.
|
first_packet_offset = file_tell(wth->fh);
|
||||||
* Put the seek pointer back, and finish.
|
for (i = 0; i < n_subtypes; i++) {
|
||||||
*/
|
wth->file_type_subtype = subtypes[i];
|
||||||
if (file_seek(wth->fh, first_packet_offset, SEEK_SET, err) == -1) {
|
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;
|
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];
|
if (file_seek(wth->fh, first_packet_offset, SEEK_SET,
|
||||||
best_subtype = figures_of_merit[i];
|
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];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ typedef gboolean (*subtype_seek_read_func)(struct wtap*, gint64,
|
||||||
struct wtap {
|
struct wtap {
|
||||||
FILE_T fh;
|
FILE_T fh;
|
||||||
FILE_T random_fh; /**< Secondary FILE_T for random access */
|
FILE_T random_fh; /**< Secondary FILE_T for random access */
|
||||||
|
gboolean ispipe; /**< TRUE if the file is a pipe */
|
||||||
int file_type_subtype;
|
int file_type_subtype;
|
||||||
guint snapshot_length;
|
guint snapshot_length;
|
||||||
struct Buffer *frame_buffer;
|
struct Buffer *frame_buffer;
|
||||||
|
|
Loading…
Reference in New Issue