aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorGuy Harris <gharris@sonic.net>2021-08-30 12:47:38 -0700
committerGuy Harris <gharris@sonic.net>2021-08-30 12:47:38 -0700
commitdcfa3ec8356b28d0cfd507978cf754d59cebb5b7 (patch)
tree1a24b67bb1b5d5753ae6caa572d65b6dbacc0cf4 /wiretap
parent2c543f999b8cf5521a20a225944433b4cfb6808f (diff)
ngsniffer: clean up the read process.
Have a routine to read the Sniffer record header, and call that in ngsniffer_read() and ngsniffer_seek_read(). Only call ngsniffer_process_record() for frame records that we understand, so that we only allocate a block for those rather than for records we don't understand or for EOF records, potentially leaking them.
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/ngsniffer.c184
1 files changed, 112 insertions, 72 deletions
diff --git a/wiretap/ngsniffer.c b/wiretap/ngsniffer.c
index 5340edeaa7..ef757bdb47 100644
--- a/wiretap/ngsniffer.c
+++ b/wiretap/ngsniffer.c
@@ -89,6 +89,13 @@ static const char ngsniffer_magic[] = {
#define REC_HEADER6 16 /* More broadcast/retransmission counts? */
#define REC_HEADER7 17 /* ? */
+/*
+ * Sniffer record header structure.
+ */
+struct rec_header {
+ guint16 type; /* record type */
+ guint16 length; /* record length */
+};
/*
* Sniffer version record format.
@@ -501,9 +508,11 @@ static gboolean ngsniffer_read(wtap *wth, wtap_rec *rec, Buffer *buf,
int *err, gchar **err_info, gint64 *data_offset);
static gboolean ngsniffer_seek_read(wtap *wth, gint64 seek_off,
wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
-static int ngsniffer_process_record(wtap *wth, gboolean is_random,
- guint *padding, wtap_rec *rec, Buffer *buf, int *err,
- gchar **err_info);
+static gboolean read_rec_header(wtap *wth, gboolean is_random,
+ struct rec_header *hdr, int *err, gchar **err_info);
+static gboolean ngsniffer_process_record(wtap *wth, gboolean is_random,
+ guint *padding, struct rec_header *hdr, wtap_rec *rec, Buffer *buf,
+ int *err, gchar **err_info);
static void set_metadata_frame2(wtap *wth, wtap_rec *rec,
struct frame2_rec *frame2);
static void set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
@@ -1022,7 +1031,7 @@ ngsniffer_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err,
gchar **err_info, gint64 *data_offset)
{
ngsniffer_t *ngsniffer;
- int ret;
+ struct rec_header hdr;
guint padding;
ngsniffer = (ngsniffer_t *)wth->priv;
@@ -1034,25 +1043,31 @@ ngsniffer_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err,
*data_offset = ngsniffer->seq.uncomp_offset;
/*
- * Process the record.
+ * Read the record header.
*/
- ret = ngsniffer_process_record(wth, FALSE, &padding,
- rec, buf, err, err_info);
- if (ret < 0) {
+ if (!read_rec_header(wth, FALSE, &hdr, err, err_info)) {
/* Read error or short read */
return FALSE;
}
/*
- * ret is the record type.
+ * Process the record.
*/
- switch (ret) {
+ switch (hdr.type) {
case REC_FRAME2:
case REC_FRAME4:
case REC_FRAME6:
/*
* Packet record.
+ */
+ if (!ngsniffer_process_record(wth, FALSE, &padding,
+ &hdr, rec, buf, err, err_info)) {
+ /* Read error, short read, or other error */
+ return FALSE;
+ }
+
+ /*
* Skip any extra data in the record.
*/
if (padding != 0) {
@@ -1064,8 +1079,15 @@ ngsniffer_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err,
case REC_EOF:
/*
- * End of file. Return an EOF indication.
+ * End of file. Skip past any data (if any),
+ * the length of which is in hdr.length, and
+ * return an EOF indication.
*/
+ if (hdr.length != 0) {
+ if (!ng_skip_bytes_seq(wth, hdr.length, err,
+ err_info))
+ return FALSE;
+ }
*err = 0; /* EOF, not error */
return FALSE;
@@ -1073,11 +1095,11 @@ ngsniffer_read(wtap *wth, wtap_rec *rec, Buffer *buf, int *err,
/*
* Well, we don't know what it is, or we know what
* it is but can't handle it. Skip past the data
- * portion, the length of which is in padding,
- * and keep looping.
+ * portion (if any), the length of which is in
+ * hdr.length, and keep looping.
*/
- if (padding != 0) {
- if (!ng_skip_bytes_seq(wth, padding, err,
+ if (hdr.length != 0) {
+ if (!ng_skip_bytes_seq(wth, hdr.length, err,
err_info))
return FALSE;
}
@@ -1090,31 +1112,36 @@ static gboolean
ngsniffer_seek_read(wtap *wth, gint64 seek_off,
wtap_rec *rec, Buffer *buf, int *err, gchar **err_info)
{
- int ret;
+ struct rec_header hdr;
if (!ng_file_seek_rand(wth, seek_off, err, err_info))
return FALSE;
- ret = ngsniffer_process_record(wth, TRUE, NULL, rec, buf, err, err_info);
- if (ret < 0) {
+ if (!read_rec_header(wth, TRUE, &hdr, err, err_info)) {
/* Read error or short read */
return FALSE;
}
/*
- * ret is the record type.
+ * hdr.type is the record type.
*/
- switch (ret) {
+ switch (hdr.type) {
case REC_FRAME2:
case REC_FRAME4:
case REC_FRAME6:
/* Packet record */
+ if (!ngsniffer_process_record(wth, TRUE, NULL, &hdr, rec, buf,
+ err, err_info)) {
+ /* Read error, short read, or other error */
+ return FALSE;
+ }
break;
default:
/*
- * "Can't happen".
+ * Other record type, or EOF.
+ * This "can't happen".
*/
ws_assert_not_reached();
return FALSE;
@@ -1124,18 +1151,57 @@ ngsniffer_seek_read(wtap *wth, gint64 seek_off,
}
/*
- * Returns -1 on error, REC_EOF on end-of-file, record type on success.
+ * Read the record header.
+ *
+ * Returns TRUE on success, FALSE on error.
+ */
+static gboolean
+read_rec_header(wtap *wth, gboolean is_random, struct rec_header *hdr,
+ int *err, gchar **err_info)
+{
+ char record_type[2];
+ char record_length[4]; /* only 1st 2 bytes are length */
+
+ /*
+ * Read the record type.
+ */
+ if (!ng_read_bytes_or_eof(wth, record_type, 2, is_random, err, err_info)) {
+ if (*err != 0)
+ return FALSE;
+ /*
+ * End-of-file; construct a fake EOF record.
+ * (A file might have an EOF record at the end, or
+ * it might just come to an end.)
+ * (XXX - is that true of all Sniffer files?)
+ */
+ hdr->type = REC_EOF;
+ hdr->length = 0;
+ return TRUE;
+ }
+
+ /*
+ * Read the record length.
+ */
+ if (!ng_read_bytes(wth, record_length, 4, is_random, err, err_info))
+ return FALSE;
+
+ hdr->type = pletoh16(record_type);
+ hdr->length = pletoh16(record_length);
+ return TRUE;
+}
+
+/*
+ * Returns TRUE on success, FALSE on error.
* If padding is non-null, sets *padding to the amount of padding at
* the end of the record.
*/
-static int
+static gboolean
ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
- wtap_rec *rec, Buffer *buf, int *err, gchar **err_info)
+ struct rec_header *hdr, wtap_rec *rec, Buffer *buf, int *err,
+ gchar **err_info)
{
ngsniffer_t *ngsniffer;
- char record_type[2];
- char record_length[4]; /* only 1st 2 bytes are length */
- guint rec_type, rec_length_remaining;
+ guint rec_length_remaining;
struct frame2_rec frame2;
struct frame4_rec frame4;
struct frame6_rec frame6;
@@ -1143,26 +1209,15 @@ ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
guint8 time_high, time_day;
guint64 t, tsecs, tpsecs;
- /*
- * Read the record header.
- */
- if (!ng_read_bytes_or_eof(wth, record_type, 2, is_random, err, err_info)) {
- if (*err != 0)
- return -1;
- return REC_EOF;
- }
- if (!ng_read_bytes(wth, record_length, 4, is_random, err, err_info))
- return -1;
-
- rec_type = pletoh16(record_type);
- rec_length_remaining = pletoh16(record_length);
+ rec_length_remaining = hdr->length;
/* Initialize - we'll be setting some presence flags below. */
- rec->presence_flags = 0;
+ rec->rec_type = REC_TYPE_PACKET;
rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
+ rec->presence_flags = 0;
ngsniffer = (ngsniffer_t *)wth->priv;
- switch (rec_type) {
+ switch (hdr->type) {
case REC_FRAME2:
if (ngsniffer->network == NETWORK_ATM) {
@@ -1172,20 +1227,20 @@ ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup("ngsniffer: REC_FRAME2 record in an ATM Sniffer file");
- return -1;
+ return FALSE;
}
/* Do we have an f_frame2_struct worth of data? */
if (rec_length_remaining < sizeof frame2) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup("ngsniffer: REC_FRAME2 record length is less than record header length");
- return -1;
+ return FALSE;
}
/* Read the f_frame2_struct */
if (!ng_read_bytes(wth, &frame2, (unsigned int)sizeof frame2,
is_random, err, err_info))
- return -1;
+ return FALSE;
time_low = pletoh16(&frame2.time_low);
time_med = pletoh16(&frame2.time_med);
time_high = frame2.time_high;
@@ -1206,7 +1261,7 @@ ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup("ngsniffer: REC_FRAME4 record in a non-ATM Sniffer file");
- return -1;
+ return FALSE;
}
/*
@@ -1223,13 +1278,13 @@ ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
if (rec_length_remaining < sizeof frame4) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup("ngsniffer: REC_FRAME4 record length is less than record header length");
- return -1;
+ return FALSE;
}
/* Read the f_frame4_struct */
if (!ng_read_bytes(wth, &frame4, (unsigned int)sizeof frame4,
is_random, err, err_info))
- return -1;
+ return FALSE;
time_low = pletoh16(&frame4.time_low);
time_med = pletoh16(&frame4.time_med);
time_high = frame4.time_high;
@@ -1247,13 +1302,13 @@ ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
if (rec_length_remaining < sizeof frame6) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup("ngsniffer: REC_FRAME6 record length is less than record header length");
- return -1;
+ return FALSE;
}
/* Read the f_frame6_struct */
if (!ng_read_bytes(wth, &frame6, (unsigned int)sizeof frame6,
is_random, err, err_info))
- return -1;
+ return FALSE;
time_low = pletoh16(&frame6.time_low);
time_med = pletoh16(&frame6.time_med);
time_high = frame6.time_high;
@@ -1266,26 +1321,12 @@ ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
set_pseudo_header_frame6(wth, &rec->rec_header.packet_header.pseudo_header, &frame6);
break;
- case REC_EOF:
- /*
- * End of file. Return an EOF indication.
- */
- *err = 0; /* EOF, not error */
- return REC_EOF;
-
default:
/*
- * Unknown record type, or type that's not an EOF or
- * a packet record.
+ * This should never happen.
*/
- if (padding != NULL) {
- /*
- * Treat the entire record as padding, so we
- * skip it.
- */
- *padding = rec_length_remaining;
- }
- return rec_type; /* unknown type */
+ ws_assert_not_reached();
+ return FALSE;
}
/*
@@ -1300,14 +1341,14 @@ ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup("ngsniffer: Record length is less than packet size");
- return -1;
+ return FALSE;
}
+
/*
* The maximum value of length is 65535, which is less than
* WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't need to check
* it.
*/
-
if (padding != NULL) {
/*
* Padding, if the frame data size is less than what's
@@ -1316,7 +1357,6 @@ ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
*padding = rec_length_remaining - size;
}
- rec->rec_type = REC_TYPE_PACKET;
rec->presence_flags |= true_size ? WTAP_HAS_TS|WTAP_HAS_CAP_LEN : WTAP_HAS_TS;
rec->rec_header.packet_header.len = true_size ? true_size : size;
rec->rec_header.packet_header.caplen = size;
@@ -1327,7 +1367,7 @@ ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
ws_buffer_assure_space(buf, size);
if (!ng_read_bytes(wth, ws_buffer_start_ptr(buf), size, is_random,
err, err_info))
- return -1;
+ return FALSE;
rec->rec_header.packet_header.pkt_encap = fix_pseudo_header(wth->file_encap,
buf, size, &rec->rec_header.packet_header.pseudo_header);
@@ -1363,7 +1403,7 @@ ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
rec->ts.secs = (time_t)tsecs;
rec->ts.nsecs = (int)(tpsecs/1000); /* psecs to nsecs */
- return rec_type; /* success */
+ return TRUE; /* success */
}
static void