diff options
author | Guy Harris <gharris@sonic.net> | 2021-08-30 12:47:38 -0700 |
---|---|---|
committer | Guy Harris <gharris@sonic.net> | 2021-08-30 12:47:38 -0700 |
commit | dcfa3ec8356b28d0cfd507978cf754d59cebb5b7 (patch) | |
tree | 1a24b67bb1b5d5753ae6caa572d65b6dbacc0cf4 /wiretap | |
parent | 2c543f999b8cf5521a20a225944433b4cfb6808f (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.c | 184 |
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 |