summaryrefslogtreecommitdiff
path: root/wiretap/ngsniffer.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2014-01-02 02:18:04 +0000
committerGuy Harris <guy@alum.mit.edu>2014-01-02 02:18:04 +0000
commitce4d667efe586f78ddab0708412cffe10bd9af01 (patch)
tree6d0a228e190b9d594f3e9d41174d12047103a7ad /wiretap/ngsniffer.c
parentabda7cd1af7500fa6f2ad0ddbe2be9addafccc9e (diff)
downloadwireshark-ce4d667efe586f78ddab0708412cffe10bd9af01.tar.gz
Process the packet header and data in common code, shared by the read
and seek-read routines. svn path=/trunk/; revision=54548
Diffstat (limited to 'wiretap/ngsniffer.c')
-rw-r--r--wiretap/ngsniffer.c543
1 files changed, 246 insertions, 297 deletions
diff --git a/wiretap/ngsniffer.c b/wiretap/ngsniffer.c
index c41da046f5..64ba7e3232 100644
--- a/wiretap/ngsniffer.c
+++ b/wiretap/ngsniffer.c
@@ -516,22 +516,15 @@ static gboolean ngsniffer_read(wtap *wth, int *err, gchar **err_info,
static gboolean ngsniffer_seek_read(wtap *wth, gint64 seek_off,
struct wtap_pkthdr *phdr, Buffer *buf, int packet_size,
int *err, gchar **err_info);
-static int ngsniffer_read_rec_header(wtap *wth, gboolean is_random,
- guint16 *typep, guint16 *lengthp, int *err, gchar **err_info);
-static gboolean ngsniffer_read_frame2(wtap *wth, gboolean is_random,
- struct frame2_rec *frame2, int *err, gchar **err_info);
+static int ngsniffer_process_record(wtap *wth, gboolean is_random,
+ guint *padding, struct wtap_pkthdr *phdr, Buffer *buf, int *err,
+ gchar **err_info);
static void set_pseudo_header_frame2(wtap *wth,
union wtap_pseudo_header *pseudo_header, struct frame2_rec *frame2);
-static gboolean ngsniffer_read_frame4(wtap *wth, gboolean is_random,
- struct frame4_rec *frame4, int *err, gchar **err_info);
static void set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
struct frame4_rec *frame4);
-static gboolean ngsniffer_read_frame6(wtap *wth, gboolean is_random,
- struct frame6_rec *frame6, int *err, gchar **err_info);
static void set_pseudo_header_frame6(wtap *wth,
union wtap_pseudo_header *pseudo_header, struct frame6_rec *frame6);
-static gboolean ngsniffer_read_rec_data(wtap *wth, gboolean is_random,
- Buffer *buf, unsigned int length, int *err, gchar **err_info);
static int infer_pkt_encap(const guint8 *pd, int len);
static int fix_pseudo_header(int encap, Buffer *buf, int len,
union wtap_pseudo_header *pseudo_header);
@@ -1068,13 +1061,7 @@ ngsniffer_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
{
ngsniffer_t *ngsniffer;
int ret;
- guint16 type, length;
- struct frame2_rec frame2;
- struct frame4_rec frame4;
- struct frame6_rec frame6;
- guint16 time_low, time_med, true_size, size;
- guint8 time_high, time_day;
- guint64 t, tsecs, tpsecs;
+ guint padding;
ngsniffer = (ngsniffer_t *)wth->priv;
for (;;) {
@@ -1085,107 +1072,33 @@ ngsniffer_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
*data_offset = ngsniffer->seq.uncomp_offset;
/*
- * Read the record header.
+ * Process the record.
*/
- ret = ngsniffer_read_rec_header(wth, FALSE, &type, &length,
- err, err_info);
- if (ret <= 0) {
- /* Read error or EOF */
+ ret = ngsniffer_process_record(wth, FALSE, &padding,
+ &wth->phdr, wth->frame_buffer, err, err_info);
+ if (ret < 0) {
+ /* Read error or short read */
return FALSE;
}
- switch (type) {
+ /*
+ * ret is the record type.
+ */
+ switch (ret) {
case REC_FRAME2:
- if (ngsniffer->network == NETWORK_ATM) {
- /*
- * We shouldn't get a frame2 record in
- * an ATM capture.
- */
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup("ngsniffer: REC_FRAME2 record in an ATM Sniffer file");
- return FALSE;
- }
-
- /* Read the f_frame2_struct */
- if (!ngsniffer_read_frame2(wth, FALSE, &frame2, err,
- err_info)) {
- /* Read error */
- return FALSE;
- }
- time_low = pletoh16(&frame2.time_low);
- time_med = pletoh16(&frame2.time_med);
- time_high = frame2.time_high;
- time_day = frame2.time_day;
- size = pletoh16(&frame2.size);
- true_size = pletoh16(&frame2.true_size);
-
- length -= sizeof frame2; /* we already read that much */
-
- set_pseudo_header_frame2(wth, &wth->phdr.pseudo_header,
- &frame2);
- goto found;
-
case REC_FRAME4:
- if (ngsniffer->network != NETWORK_ATM) {
- /*
- * We shouldn't get a frame2 record in
- * a non-ATM capture.
- */
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup("ngsniffer: REC_FRAME4 record in a non-ATM Sniffer file");
- return FALSE;
- }
-
- /* Read the f_frame4_struct */
- if (!ngsniffer_read_frame4(wth, FALSE, &frame4, err,
- err_info)) {
- /* Read error */
- return FALSE;
- }
- time_low = pletoh16(&frame4.time_low);
- time_med = pletoh16(&frame4.time_med);
- time_high = frame4.time_high;
- time_day = frame4.time_day;
- size = pletoh16(&frame4.size);
- true_size = pletoh16(&frame4.true_size);
-
+ case REC_FRAME6:
/*
- * XXX - it looks as if some version 4 captures have
- * a bogus record length, based on the assumption
- * that the record is a frame2 record.
+ * Packet record.
+ * Skip any extra data in the record.
*/
- if (ngsniffer->maj_vers >= 5)
- length -= sizeof frame4; /* we already read that much */
- else {
- if (ngsniffer->min_vers >= 95)
- length -= sizeof frame2;
- else
- length -= sizeof frame4;
+ if (padding != 0) {
+ if (!ng_file_skip_seq(wth, padding, err,
+ err_info))
+ return FALSE;
}
-
- set_pseudo_header_frame4(&wth->phdr.pseudo_header, &frame4);
- goto found;
-
- case REC_FRAME6:
- /* Read the f_frame6_struct */
- if (!ngsniffer_read_frame6(wth, FALSE, &frame6, err,
- err_info)) {
- /* Read error */
- return FALSE;
- }
- time_low = pletoh16(&frame6.time_low);
- time_med = pletoh16(&frame6.time_med);
- time_high = frame6.time_high;
- time_day = frame6.time_day;
- size = pletoh16(&frame6.size);
- true_size = pletoh16(&frame6.true_size);
-
- length -= sizeof frame6; /* we already read that much */
-
- set_pseudo_header_frame6(wth, &wth->phdr.pseudo_header,
- &frame6);
- goto found;
+ return TRUE;
case REC_EOF:
/*
@@ -1195,212 +1108,300 @@ ngsniffer_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
return FALSE;
default:
- break; /* unknown type, skip it */
+ /*
+ * 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.
+ */
+ if (padding != 0) {
+ if (!ng_file_skip_seq(wth, padding, err,
+ err_info))
+ return FALSE;
+ }
+ break;
}
-
- /*
- * Well, we don't know what it is, or we know what
- * it is but can't handle it. Skip past the data
- * portion, and keep looping.
- */
- if (!ng_file_skip_seq(wth, length, err, err_info))
- return FALSE;
- }
-
-found:
- /*
- * OK, is the frame data size greater than than what's left of the
- * record?
- */
- if (size > length) {
- /*
- * Yes - treat this as an error.
- */
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup("ngsniffer: Record length is less than packet size");
- return FALSE;
}
+}
- wth->phdr.presence_flags = true_size ? WTAP_HAS_TS|WTAP_HAS_CAP_LEN : WTAP_HAS_TS;
- wth->phdr.len = true_size ? true_size : size;
- wth->phdr.caplen = size;
-
- /*
- * Read the packet data.
- */
- if (!ngsniffer_read_rec_data(wth, FALSE, wth->frame_buffer, length,
- err, err_info))
- return FALSE; /* Read error */
-
- wth->phdr.pkt_encap = fix_pseudo_header(wth->file_encap, wth->frame_buffer, length,
- &wth->phdr.pseudo_header);
+static gboolean
+ngsniffer_seek_read(wtap *wth, gint64 seek_off,
+ struct wtap_pkthdr *phdr, Buffer *buf, int packet_size _U_,
+ int *err, gchar **err_info)
+{
+ int ret;
- /*
- * 40-bit time stamp, in units of timeunit picoseconds.
- */
- t = (((guint64)time_high)<<32) | (((guint64)time_med) << 16) | time_low;
+ if (!ng_file_seek_rand(wth, seek_off, err, err_info))
+ return FALSE;
- /*
- * timeunit is always < 2^(64-40), so t * timeunit fits in 64
- * bits. That gives a 64-bit time stamp, in units of
- * picoseconds.
- */
- t *= ngsniffer->timeunit;
+ ret = ngsniffer_process_record(wth, TRUE, NULL, phdr, buf, err, err_info);
+ if (ret < 0) {
+ /* Read error or short read */
+ return FALSE;
+ }
/*
- * Convert to seconds and picoseconds.
+ * ret is the record type.
*/
- tsecs = t/G_GUINT64_CONSTANT(1000000000000);
- tpsecs = t - tsecs*G_GUINT64_CONSTANT(1000000000000);
+ switch (ret) {
- /*
- * Add in the time_day value (86400 seconds/day).
- */
- tsecs += time_day*86400;
+ case REC_FRAME2:
+ case REC_FRAME4:
+ case REC_FRAME6:
+ /* Packet record */
+ break;
- /*
- * Add in the capture start time.
- */
- tsecs += ngsniffer->start;
+ default:
+ /*
+ * "Can't happen".
+ */
+ g_assert_not_reached();
+ return FALSE;
+ }
- wth->phdr.ts.secs = (time_t)tsecs;
- wth->phdr.ts.nsecs = (int)(tpsecs/1000); /* psecs to nsecs */
return TRUE;
}
-static gboolean
-ngsniffer_seek_read(wtap *wth, gint64 seek_off,
- struct wtap_pkthdr *phdr, Buffer *buf, int packet_size,
- int *err, gchar **err_info)
+/*
+ * Returns -1 on error, REC_EOF on end-of-file, record type on success.
+ * If padding is non-null, sets *padding to the amount of padding at
+ * the end of the record.
+ */
+static int
+ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
+ struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
{
- union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
- int ret;
+ ngsniffer_t *ngsniffer;
+ gint64 bytes_read;
+ char record_type[2];
+ char record_length[4]; /* only 1st 2 bytes are length */
guint16 type, length;
struct frame2_rec frame2;
struct frame4_rec frame4;
struct frame6_rec frame6;
+ guint16 time_low, time_med, true_size, size;
+ guint8 time_high, time_day;
+ guint64 t, tsecs, tpsecs;
- if (!ng_file_seek_rand(wth, seek_off, err, err_info))
- return FALSE;
-
- ret = ngsniffer_read_rec_header(wth, TRUE, &type, &length, err,
+ /*
+ * Read the record header.
+ */
+ bytes_read = ng_file_read(record_type, 2, wth, is_random, err,
err_info);
- if (ret <= 0) {
- /* Read error or EOF */
- if (ret == 0) {
- /* EOF means "short read" in random-access mode */
+ if (bytes_read != 2) {
+ if (*err != 0)
+ return -1;
+ if (bytes_read != 0) {
*err = WTAP_ERR_SHORT_READ;
+ return -1;
}
- return FALSE;
+ return REC_EOF;
+ }
+ bytes_read = ng_file_read(record_length, 4, wth, is_random, err,
+ err_info);
+ if (bytes_read != 4) {
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return -1;
}
+ type = pletoh16(record_type);
+ length = pletoh16(record_length);
+
+ ngsniffer = (ngsniffer_t *)wth->priv;
switch (type) {
case REC_FRAME2:
+ if (ngsniffer->network == NETWORK_ATM) {
+ /*
+ * We shouldn't get a frame2 record in
+ * an ATM capture.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup("ngsniffer: REC_FRAME2 record in an ATM Sniffer file");
+ return -1;
+ }
+
/* Read the f_frame2_struct */
- if (!ngsniffer_read_frame2(wth, TRUE, &frame2, err, err_info)) {
- /* Read error */
- return FALSE;
+ bytes_read = ng_file_read(&frame2, (unsigned int)sizeof frame2,
+ wth, is_random, err, err_info);
+ if (bytes_read != sizeof frame2) {
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return -1;
}
+ time_low = pletoh16(&frame2.time_low);
+ time_med = pletoh16(&frame2.time_med);
+ time_high = frame2.time_high;
+ time_day = frame2.time_day;
+ size = pletoh16(&frame2.size);
+ true_size = pletoh16(&frame2.true_size);
length -= sizeof frame2; /* we already read that much */
- set_pseudo_header_frame2(wth, pseudo_header, &frame2);
+ set_pseudo_header_frame2(wth, &phdr->pseudo_header, &frame2);
break;
case REC_FRAME4:
+ if (ngsniffer->network != NETWORK_ATM) {
+ /*
+ * We shouldn't get a frame2 record in
+ * a non-ATM capture.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup("ngsniffer: REC_FRAME4 record in a non-ATM Sniffer file");
+ return -1;
+ }
+
/* Read the f_frame4_struct */
- if (!ngsniffer_read_frame4(wth, TRUE, &frame4, err, err_info)) {
- /* Read error */
- return FALSE;
+ bytes_read = ng_file_read(&frame4, (unsigned int)sizeof frame4,
+ wth, is_random, err, err_info);
+ if (bytes_read != sizeof frame4) {
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return -1;
}
+ time_low = pletoh16(&frame4.time_low);
+ time_med = pletoh16(&frame4.time_med);
+ time_high = frame4.time_high;
+ time_day = frame4.time_day;
+ size = pletoh16(&frame4.size);
+ true_size = pletoh16(&frame4.true_size);
- length -= sizeof frame4; /* we already read that much */
+ /*
+ * XXX - it looks as if some version 4 captures have
+ * a bogus record length, based on the assumption
+ * that the record is a frame2 record.
+ */
+ if (ngsniffer->maj_vers >= 5)
+ length -= sizeof frame4; /* we already read that much */
+ else {
+ if (ngsniffer->min_vers >= 95)
+ length -= sizeof frame2;
+ else
+ length -= sizeof frame4;
+ }
- set_pseudo_header_frame4(pseudo_header, &frame4);
+ set_pseudo_header_frame4(&phdr->pseudo_header, &frame4);
break;
case REC_FRAME6:
/* Read the f_frame6_struct */
- if (!ngsniffer_read_frame6(wth, TRUE, &frame6, err, err_info)) {
- /* Read error */
- return FALSE;
+ bytes_read = ng_file_read(&frame6, (unsigned int)sizeof frame6,
+ wth, is_random, err, err_info);
+ if (bytes_read != sizeof frame6) {
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return -1;
}
+ time_low = pletoh16(&frame6.time_low);
+ time_med = pletoh16(&frame6.time_med);
+ time_high = frame6.time_high;
+ time_day = frame6.time_day;
+ size = pletoh16(&frame6.size);
+ true_size = pletoh16(&frame6.true_size);
length -= sizeof frame6; /* we already read that much */
- set_pseudo_header_frame6(wth, pseudo_header, &frame6);
+ set_pseudo_header_frame6(wth, &phdr->pseudo_header, &frame6);
break;
+ case REC_EOF:
+ /*
+ * End of file. Return an EOF indication.
+ */
+ *err = 0; /* EOF, not error */
+ return REC_EOF;
+
default:
/*
- * "Can't happen".
+ * Unknown record type, or type that's not an EOF or
+ * a packet record.
*/
- g_assert_not_reached();
- return FALSE;
+ if (padding != NULL) {
+ /*
+ * Treat the entire record as padding, so we
+ * skip it.
+ */
+ *padding = length;
+ }
+ return type; /* unknown type */
}
/*
- * Got the pseudo-header (if any), now get the data.
+ * This is a packet record.
+ *
+ * Is the frame data size greater than than what's left of the
+ * record?
*/
- if (!ngsniffer_read_rec_data(wth, TRUE, buf, packet_size, err, err_info))
- return FALSE;
-
- fix_pseudo_header(wth->file_encap, buf, packet_size, pseudo_header);
+ if (size > length) {
+ /*
+ * Yes - treat this as an error.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup("ngsniffer: Record length is less than packet size");
+ return -1;
+ }
- return TRUE;
-}
+ if (padding != NULL) {
+ /*
+ * Padding, if the frame data size is less than what's
+ * left of the record.
+ */
+ *padding = length - size;
+ }
-static int
-ngsniffer_read_rec_header(wtap *wth, gboolean is_random, guint16 *typep,
- guint16 *lengthp, int *err, gchar **err_info)
-{
- gint64 bytes_read;
- char record_type[2];
- char record_length[4]; /* only 1st 2 bytes are length */
+ phdr->presence_flags = true_size ? WTAP_HAS_TS|WTAP_HAS_CAP_LEN : WTAP_HAS_TS;
+ phdr->len = true_size ? true_size : size;
+ phdr->caplen = size;
/*
- * Read the record header.
+ * Read the packet data.
*/
- bytes_read = ng_file_read(record_type, 2, wth, is_random, err,
- err_info);
- if (bytes_read != 2) {
- if (*err != 0)
- return -1;
- if (bytes_read != 0) {
- *err = WTAP_ERR_SHORT_READ;
- return -1;
- }
- return 0;
- }
- bytes_read = ng_file_read(record_length, 4, wth, is_random, err,
- err_info);
- if (bytes_read != 4) {
+ buffer_assure_space(buf, size);
+ bytes_read = ng_file_read(buffer_start_ptr(buf), size, wth,
+ is_random, err, err_info);
+ if (bytes_read != (gint64) size) {
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return -1;
}
- *typep = pletoh16(record_type);
- *lengthp = pletoh16(record_length);
- return 1; /* success */
-}
+ phdr->pkt_encap = fix_pseudo_header(wth->file_encap,
+ buf, length, &phdr->pseudo_header);
-static gboolean
-ngsniffer_read_frame2(wtap *wth, gboolean is_random, struct frame2_rec *frame2,
- int *err, gchar **err_info)
-{
- gint64 bytes_read;
+ /*
+ * 40-bit time stamp, in units of timeunit picoseconds.
+ */
+ t = (((guint64)time_high)<<32) | (((guint64)time_med) << 16) | time_low;
- /* Read the f_frame2_struct */
- bytes_read = ng_file_read(frame2, (unsigned int)sizeof *frame2, wth,
- is_random, err, err_info);
- if (bytes_read != sizeof *frame2) {
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
- return TRUE;
+ /*
+ * timeunit is always < 2^(64-40), so t * timeunit fits in 64
+ * bits. That gives a 64-bit time stamp, in units of
+ * picoseconds.
+ */
+ t *= ngsniffer->timeunit;
+
+ /*
+ * Convert to seconds and picoseconds.
+ */
+ tsecs = t/G_GUINT64_CONSTANT(1000000000000);
+ tpsecs = t - tsecs*G_GUINT64_CONSTANT(1000000000000);
+
+ /*
+ * Add in the time_day value (86400 seconds/day).
+ */
+ tsecs += time_day*86400;
+
+ /*
+ * Add in the capture start time.
+ */
+ tsecs += ngsniffer->start;
+
+ phdr->ts.secs = (time_t)tsecs;
+ phdr->ts.nsecs = (int)(tpsecs/1000); /* psecs to nsecs */
+
+ return type; /* success */
}
static void
@@ -1496,23 +1497,6 @@ set_pseudo_header_frame2(wtap *wth, union wtap_pseudo_header *pseudo_header,
}
}
-static gboolean
-ngsniffer_read_frame4(wtap *wth, gboolean is_random, struct frame4_rec *frame4,
- int *err, gchar **err_info)
-{
- gint64 bytes_read;
-
- /* Read the f_frame4_struct */
- bytes_read = ng_file_read(frame4, (unsigned int)sizeof *frame4, wth,
- is_random, err, err_info);
- if (bytes_read != sizeof *frame4) {
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
- return TRUE;
-}
-
static void
set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
struct frame4_rec *frame4)
@@ -1767,23 +1751,6 @@ set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
pseudo_header->atm.aal5t_chksum = pntoh32(&frame4->atm_info.Trailer.aal5t_chksum);
}
-static gboolean
-ngsniffer_read_frame6(wtap *wth, gboolean is_random, struct frame6_rec *frame6,
- int *err, gchar **err_info)
-{
- gint64 bytes_read;
-
- /* Read the f_frame6_struct */
- bytes_read = ng_file_read(frame6, (unsigned int)sizeof *frame6, wth,
- is_random, err, err_info);
- if (bytes_read != sizeof *frame6) {
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
- return TRUE;
-}
-
static void
set_pseudo_header_frame6(wtap *wth, union wtap_pseudo_header *pseudo_header,
struct frame6_rec *frame6 _U_)
@@ -1799,24 +1766,6 @@ set_pseudo_header_frame6(wtap *wth, union wtap_pseudo_header *pseudo_header,
}
}
-static gboolean
-ngsniffer_read_rec_data(wtap *wth, gboolean is_random, Buffer *buf,
- unsigned int length, int *err, gchar **err_info)
-{
- gint64 bytes_read;
-
- buffer_assure_space(buf, length);
- bytes_read = ng_file_read(buffer_start_ptr(buf), length, wth,
- is_random, err, err_info);
-
- if (bytes_read != (gint64) length) {
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
- return TRUE;
-}
-
/*
* OK, this capture is from an "Internetwork analyzer", and we either
* didn't see a type 7 record or it had a network type such as NET_HDLC