Ethereal-dev: Re: [ethereal-dev] RE: Correct sniffdecomp.c attached
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: Guy Harris <gharris@xxxxxxxxxxxx>
Date: Wed, 24 May 2000 00:40:03 -0700
Here's a new version of the patch (against the current CVS tree) that skips uncompressed records, and handles the blob length, as per your recommendations.
? errs
? tethereal.SAVE
? ethereal.SAVE
? wiretap/ngsniffer.c.SAVE
? wiretap/ngsniffer.c.SAVE2
Index: wiretap/file.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/wiretap/file.c,v
retrieving revision 1.52
diff -c -r1.52 file.c
*** file.c 2000/05/19 23:06:48 1.52
--- file.c 2000/05/24 07:32:31
***************
*** 169,174 ****
--- 169,175 ----
/* initialization */
wth->file_encap = WTAP_ENCAP_UNKNOWN;
wth->data_offset = 0;
+ wth->subtype_sequential_close = NULL;
wth->subtype_close = NULL;
/* Try all file types */
***************
*** 236,244 ****
{ "Novell LANalyzer", NULL,
NULL, NULL },
! /* WTAP_FILE_NGSNIFFER */
{ "Network Associates Sniffer (DOS-based)", "ngsniffer",
ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
/* WTAP_FILE_SNOOP */
{ "Sun snoop", "snoop",
--- 237,249 ----
{ "Novell LANalyzer", NULL,
NULL, NULL },
! /* WTAP_FILE_NGSNIFFER_UNCOMPRESSED */
{ "Network Associates Sniffer (DOS-based)", "ngsniffer",
ngsniffer_dump_can_write_encap, ngsniffer_dump_open },
+
+ /* WTAP_FILE_NGSNIFFER_COMPRESSED */
+ { "Network Associates Sniffer (DOS-based), compressed", "ngsniffer_comp",
+ NULL, NULL },
/* WTAP_FILE_SNOOP */
{ "Sun snoop", "snoop",
Index: wiretap/ngsniffer.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/wiretap/ngsniffer.c,v
retrieving revision 1.42
diff -c -r1.42 ngsniffer.c
*** ngsniffer.c 2000/05/19 23:06:59 1.42
--- ngsniffer.c 2000/05/24 07:32:35
***************
*** 84,93 ****
/*
* Sniffer version record format.
- *
- * XXX - the Sniffer documentation doesn't say what the compression stuff
- * means. The manual says "IMPORTANT: You must save the file uncompressed
- * to use this format specification."
*/
struct vers_rec {
gint16 maj_vers; /* major version number */
--- 84,89 ----
***************
*** 96,102 ****
gint16 date; /* DOS-format date */
gint8 type; /* what type of records follow */
guint8 network; /* network type */
! gint8 format; /* format version (we only support version 1!) */
guint8 timeunit; /* timestamp units */
gint8 cmprs_vers; /* compression version */
gint8 cmprs_level; /* compression level */
--- 92,98 ----
gint16 date; /* DOS-format date */
gint8 type; /* what type of records follow */
guint8 network; /* network type */
! gint8 format; /* format version */
guint8 timeunit; /* timestamp units */
gint8 cmprs_vers; /* compression version */
gint8 cmprs_level; /* compression level */
***************
*** 246,269 ****
#define NUM_NGSNIFF_TIMEUNITS 7
static double Usec[] = { 15.0, 0.838096, 15.0, 0.5, 2.0, 1.0, 0.1 };
static int ngsniffer_read(wtap *wth, int *err);
static int ngsniffer_seek_read(wtap *wth, int seek_off,
union wtap_pseudo_header *pseudo_header, u_char *pd, int packet_size);
! static int ngsniffer_read_rec_header(FILE_T fh, guint16 *typep,
! guint16 *lengthp, int *err);
! static int ngsniffer_read_frame2(FILE_T fh, struct frame2_rec *frame2,
int *err);
static void set_pseudo_header_frame2(union wtap_pseudo_header *pseudo_header,
struct frame2_rec *frame2);
! static int ngsniffer_read_frame4(FILE_T fh, struct frame4_rec *frame4,
! int *err);
static void set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
struct frame4_rec *frame4);
! static int ngsniffer_read_rec_data(FILE_T fh, char *pd, int length, int *err);
static void ngsniffer_close(wtap *wth);
static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
const union wtap_pseudo_header *pseudo_header, const u_char *pd, int *err);
static gboolean ngsniffer_dump_close(wtap_dumper *wdh, int *err);
int ngsniffer_open(wtap *wth, int *err)
{
--- 242,275 ----
#define NUM_NGSNIFF_TIMEUNITS 7
static double Usec[] = { 15.0, 0.838096, 15.0, 0.5, 2.0, 1.0, 0.1 };
+ static int skip_uncompressed_records(wtap *wth, int *err);
static int ngsniffer_read(wtap *wth, int *err);
static int ngsniffer_seek_read(wtap *wth, int seek_off,
union wtap_pseudo_header *pseudo_header, u_char *pd, int packet_size);
! static int ngsniffer_read_rec_header(wtap *wth, FILE_T fh,
! ngsniffer_comp_stream_t *comp_stream, guint16 *typep, guint16 *lengthp,
int *err);
+ static int ngsniffer_read_frame2(wtap *wth, FILE_T fh,
+ ngsniffer_comp_stream_t *comp_stream, struct frame2_rec *frame2, int *err);
static void set_pseudo_header_frame2(union wtap_pseudo_header *pseudo_header,
struct frame2_rec *frame2);
! static int ngsniffer_read_frame4(wtap *wth, FILE_T fh,
! ngsniffer_comp_stream_t *comp_stream, struct frame4_rec *frame4, int *err);
static void set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
struct frame4_rec *frame4);
! static int ngsniffer_read_rec_data(wtap *wth, FILE_T fh,
! ngsniffer_comp_stream_t *comp_stream, char *pd, int length, int *err);
! static void ngsniffer_sequential_close(wtap *wth);
static void ngsniffer_close(wtap *wth);
static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
const union wtap_pseudo_header *pseudo_header, const u_char *pd, int *err);
static gboolean ngsniffer_dump_close(wtap_dumper *wdh, int *err);
+ static int SnifferDecompress( unsigned char * inbuf, size_t inlen,
+ unsigned char * outbuf, size_t outlen, int *err );
+ static int ng_file_read(void *buffer, size_t elementsize, size_t numelements,
+ wtap *wth, FILE_T infile, ngsniffer_comp_stream_t *comp_stream, int *err);
+ static long ng_file_seek(wtap *wth, FILE_T infile,
+ ngsniffer_comp_stream_t *comp_stream, long offset, int whence);
int ngsniffer_open(wtap *wth, int *err)
{
***************
*** 271,278 ****
char magic[sizeof ngsniffer_magic];
char record_type[2];
char record_length[4]; /* only the first 2 bytes are length,
! the last 2 are "reserved" and are thrown away */
! guint16 type, length = 0;
struct vers_rec version;
guint16 start_date;
guint16 start_time;
--- 277,284 ----
char magic[sizeof ngsniffer_magic];
char record_type[2];
char record_length[4]; /* only the first 2 bytes are length,
! the last 2 are "reserved" and are thrown away */
! guint16 type, length;
struct vers_rec version;
guint16 start_date;
guint16 start_time;
***************
*** 343,355 ****
}
wth->data_offset += sizeof version;
- /* Make sure this is an uncompressed Sniffer file */
- if (version.format != 1) {
- g_message("ngsniffer: Compressed Sniffer files are not supported");
- *err = WTAP_ERR_UNSUPPORTED;
- return -1;
- }
-
/* Check the data link type.
If "version.network" is 7, that's "Internetwork analyzer";
Sniffers appear to write out both LAPB and PPP captures
--- 349,354 ----
***************
*** 380,390 ****
return -1;
}
/* This is a ngsniffer file */
- wth->file_type = WTAP_FILE_NGSNIFFER;
wth->capture.ngsniffer = g_malloc(sizeof(ngsniffer_t));
wth->subtype_read = ngsniffer_read;
wth->subtype_seek_read = ngsniffer_seek_read;
wth->subtype_close = ngsniffer_close;
wth->snapshot_length = 16384; /* not available in header, only in frame */
wth->capture.ngsniffer->timeunit = Usec[version.timeunit];
--- 379,439 ----
return -1;
}
+ /* compressed or uncompressed Sniffer file? */
+ if (version.format != 1) {
+ wth->file_type = WTAP_FILE_NGSNIFFER_COMPRESSED;
+
+ /*
+ * Compressed Sniffer files may have some uncompressed
+ * records at the beginning, containing various bits of
+ * header information.
+ *
+ * We skip over them, so we're positioned at the beginning
+ * of the compressed data; records for packet data are in
+ * the compressed part of the file, and the code to
+ * read sequentially through the packet data, and
+ * the code to seek to the beginning of a packet record
+ * and read it, work, in a compressed file, only in
+ * the compressed region of the file.
+ *
+ * We read and ignore all records with record types
+ * in the range 0-16; if we see a "record" with a
+ * type outside that range, we assume it's a compressed
+ * blob, with the the 2-byte field at the beginning
+ * being the blob size rather than being a record type.
+ */
+ if (skip_uncompressed_records(wth, err) < 0)
+ return -1;
+ } else {
+ wth->file_type = WTAP_FILE_NGSNIFFER_UNCOMPRESSED;
+ }
+
+ /*
+ * Now position the random stream to the same location, which
+ * should be the beginning of the real data, and should
+ * be the beginning of the compressed data.
+ *
+ * XXX - will we see any records other than REC_FRAME2, REC_FRAME4,
+ * or REC_EOF after this? If not, we can get rid of the loop in
+ * "ngsniffer_read()".
+ */
+ file_seek(wth->random_fh, wth->data_offset, SEEK_SET);
+
/* This is a ngsniffer file */
wth->capture.ngsniffer = g_malloc(sizeof(ngsniffer_t));
+
+ /* We haven't allocated any uncompression buffers yet. */
+ wth->capture.ngsniffer->seq.file_outbuf = NULL;
+ wth->capture.ngsniffer->rand.file_outbuf = NULL;
+
+ /* Set the current file offset. */
+ wth->capture.ngsniffer->data_offset = wth->data_offset;
+ wth->capture.ngsniffer->seq.offset = wth->data_offset;
+ wth->capture.ngsniffer->rand.offset = wth->data_offset;
+
wth->subtype_read = ngsniffer_read;
wth->subtype_seek_read = ngsniffer_seek_read;
+ wth->subtype_sequential_close = ngsniffer_sequential_close;
wth->subtype_close = ngsniffer_close;
wth->snapshot_length = 16384; /* not available in header, only in frame */
wth->capture.ngsniffer->timeunit = Usec[version.timeunit];
***************
*** 426,431 ****
--- 475,532 ----
return 1;
}
+ static int
+ skip_uncompressed_records(wtap *wth, int *err)
+ {
+ int bytes_read;
+ char record_type[2];
+ char record_length[4]; /* only the first 2 bytes are length,
+ the last 2 are "reserved" and are thrown away */
+ guint16 type, length;
+
+ for (;;) {
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(record_type, 1, 2, wth->fh);
+ if (bytes_read != 2) {
+ *err = file_error(wth->fh);
+ if (*err != 0)
+ return -1;
+ if (bytes_read != 0) {
+ *err = WTAP_ERR_SHORT_READ;
+ return -1;
+ }
+ return 0; /* EOF */
+ }
+
+ type = pletohs(record_type);
+ if (type > 16) {
+ /*
+ * Well, this is probably the length of a
+ * compressed blob. Seek backwards over the
+ * two bytes we read, and return.
+ */
+ file_seek(wth->fh, -2, SEEK_CUR);
+ return 0;
+ }
+
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(record_length, 1, 4, wth->fh);
+ if (bytes_read != 4) {
+ *err = file_error(wth->fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return -1;
+ }
+ wth->data_offset += 6;
+
+ length = pletohs(record_length);
+
+ /* OK, now skip over it the data. */
+ file_seek(wth->fh, length, SEEK_CUR);
+ wth->data_offset += length;
+ }
+ }
+
/* Read the next packet */
static int ngsniffer_read(wtap *wth, int *err)
{
***************
*** 443,449 ****
* Read the record header.
*/
record_offset = wth->data_offset;
! ret = ngsniffer_read_rec_header(wth->fh, &type, &length, err);
if (ret <= 0) {
/* Read error or EOF */
return ret;
--- 544,551 ----
* Read the record header.
*/
record_offset = wth->data_offset;
! ret = ngsniffer_read_rec_header(wth, wth->fh,
! &wth->capture.ngsniffer->seq, &type, &length, err);
if (ret <= 0) {
/* Read error or EOF */
return ret;
***************
*** 464,470 ****
}
/* Read the f_frame2_struct */
! ret = ngsniffer_read_frame2(wth->fh, &frame2, err);
if (ret < 0) {
/* Read error */
return ret;
--- 566,573 ----
}
/* Read the f_frame2_struct */
! ret = ngsniffer_read_frame2(wth, wth->fh,
! &wth->capture.ngsniffer->seq, &frame2, err);
if (ret < 0) {
/* Read error */
return ret;
***************
*** 496,502 ****
}
/* Read the f_frame4_struct */
! ret = ngsniffer_read_frame4(wth->fh, &frame4, err);
wth->data_offset += sizeof frame4;
time_low = pletohs(&frame4.time_low);
time_med = pletohs(&frame4.time_med);
--- 599,606 ----
}
/* Read the f_frame4_struct */
! ret = ngsniffer_read_frame4(wth, wth->fh,
! &wth->capture.ngsniffer->seq, &frame4, err);
wth->data_offset += sizeof frame4;
time_low = pletohs(&frame4.time_low);
time_med = pletohs(&frame4.time_med);
***************
*** 531,537 ****
* it is but can't handle it. Skip past the data
* portion, and keep looping.
*/
! file_seek(wth->fh, length, SEEK_CUR);
wth->data_offset += length;
}
--- 635,642 ----
* it is but can't handle it. Skip past the data
* portion, and keep looping.
*/
! ng_file_seek(wth, wth->fh, &wth->capture.ngsniffer->seq,
! length, SEEK_CUR);
wth->data_offset += length;
}
***************
*** 544,550 ****
*/
buffer_assure_space(wth->frame_buffer, length);
pd = buffer_start_ptr(wth->frame_buffer);
! if (ngsniffer_read_rec_data(wth->fh, pd, length, err) < 0)
return -1; /* Read error */
wth->data_offset += length;
--- 649,656 ----
*/
buffer_assure_space(wth->frame_buffer, length);
pd = buffer_start_ptr(wth->frame_buffer);
! if (ngsniffer_read_rec_data(wth, wth->fh,
! &wth->capture.ngsniffer->seq, pd, length, err) < 0)
return -1; /* Read error */
wth->data_offset += length;
***************
*** 585,593 ****
struct frame2_rec frame2;
struct frame4_rec frame4;
! file_seek(wth->random_fh, seek_off, SEEK_SET);
! ret = ngsniffer_read_rec_header(wth->random_fh, &type, &length, &err);
if (ret <= 0) {
/* Read error or EOF */
return ret;
--- 691,701 ----
struct frame2_rec frame2;
struct frame4_rec frame4;
! ng_file_seek(wth, wth->random_fh, &wth->capture.ngsniffer->rand,
! seek_off, SEEK_SET);
! ret = ngsniffer_read_rec_header(wth, wth->random_fh,
! &wth->capture.ngsniffer->rand, &type, &length, &err);
if (ret <= 0) {
/* Read error or EOF */
return ret;
***************
*** 597,603 ****
case REC_FRAME2:
/* Read the f_frame2_struct */
! ret = ngsniffer_read_frame2(wth->random_fh, &frame2, &err);
if (ret < 0) {
/* Read error */
return ret;
--- 705,712 ----
case REC_FRAME2:
/* Read the f_frame2_struct */
! ret = ngsniffer_read_frame2(wth, wth->random_fh,
! &wth->capture.ngsniffer->rand, &frame2, &err);
if (ret < 0) {
/* Read error */
return ret;
***************
*** 610,616 ****
case REC_FRAME4:
/* Read the f_frame4_struct */
! ret = ngsniffer_read_frame4(wth->random_fh, &frame4, &err);
length -= sizeof frame4; /* we already read that much */
--- 719,726 ----
case REC_FRAME4:
/* Read the f_frame4_struct */
! ret = ngsniffer_read_frame4(wth, wth->random_fh,
! &wth->capture.ngsniffer->rand, &frame4, &err);
length -= sizeof frame4; /* we already read that much */
***************
*** 628,638 ****
/*
* Got the pseudo-header (if any), now get the data.
*/
! return ngsniffer_read_rec_data(wth->random_fh, pd, packet_size, &err);
}
! static int ngsniffer_read_rec_header(FILE_T fh, guint16 *typep,
! guint16 *lengthp, int *err)
{
int bytes_read;
char record_type[2];
--- 738,750 ----
/*
* Got the pseudo-header (if any), now get the data.
*/
! return ngsniffer_read_rec_data(wth, wth->random_fh,
! &wth->capture.ngsniffer->rand, pd, packet_size, &err);
}
! static int ngsniffer_read_rec_header(wtap *wth, FILE_T fh,
! ngsniffer_comp_stream_t *comp_stream, guint16 *typep, guint16 *lengthp,
! int *err)
{
int bytes_read;
char record_type[2];
***************
*** 641,650 ****
/*
* Read the record header.
*/
! errno = WTAP_ERR_CANT_READ;
! bytes_read = file_read(record_type, 1, 2, fh);
if (bytes_read != 2) {
- *err = file_error(fh);
if (*err != 0)
return -1;
if (bytes_read != 0) {
--- 753,760 ----
/*
* Read the record header.
*/
! bytes_read = ng_file_read(record_type, 1, 2, wth, fh, comp_stream, err);
if (bytes_read != 2) {
if (*err != 0)
return -1;
if (bytes_read != 0) {
***************
*** 653,662 ****
}
return 0;
}
! errno = WTAP_ERR_CANT_READ;
! bytes_read = file_read(record_length, 1, 4, fh);
if (bytes_read != 4) {
- *err = file_error(fh);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return -1;
--- 763,771 ----
}
return 0;
}
! bytes_read = ng_file_read(record_length, 1, 4, wth, fh, comp_stream,
! err);
if (bytes_read != 4) {
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return -1;
***************
*** 667,682 ****
return 1; /* success */
}
! static int ngsniffer_read_frame2(FILE_T fh, struct frame2_rec *frame2,
! int *err)
{
int bytes_read;
/* Read the f_frame2_struct */
! errno = WTAP_ERR_CANT_READ;
! bytes_read = file_read(frame2, 1, sizeof *frame2, fh);
if (bytes_read != sizeof *frame2) {
- *err = file_error(fh);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return -1;
--- 776,790 ----
return 1; /* success */
}
! static int ngsniffer_read_frame2(wtap *wth, FILE_T fh,
! ngsniffer_comp_stream_t *comp_stream, struct frame2_rec *frame2, int *err)
{
int bytes_read;
/* Read the f_frame2_struct */
! bytes_read = ng_file_read(frame2, 1, sizeof *frame2, wth, fh,
! comp_stream, err);
if (bytes_read != sizeof *frame2) {
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return -1;
***************
*** 711,726 ****
pseudo_header->x25.flags = (frame2->fs & 0x80) ? 0x00 : 0x80;
}
! static int ngsniffer_read_frame4(FILE_T fh, struct frame4_rec *frame4,
! int *err)
{
int bytes_read;
/* Read the f_frame4_struct */
! errno = WTAP_ERR_CANT_READ;
! bytes_read = file_read(frame4, 1, sizeof *frame4, fh);
if (bytes_read != sizeof *frame4) {
- *err = file_error(fh);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return -1;
--- 819,833 ----
pseudo_header->x25.flags = (frame2->fs & 0x80) ? 0x00 : 0x80;
}
! static int ngsniffer_read_frame4(wtap *wth, FILE_T fh,
! ngsniffer_comp_stream_t *comp_stream, struct frame4_rec *frame4, int *err)
{
int bytes_read;
/* Read the f_frame4_struct */
! bytes_read = ng_file_read(frame4, 1, sizeof *frame4, wth, fh,
! comp_stream, err);
if (bytes_read != sizeof *frame4) {
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return -1;
***************
*** 742,756 ****
pseudo_header->ngsniffer_atm.aal5t_chksum = pletohl(&frame4->atm_info.Trailer.aal5t_chksum);
}
! static int ngsniffer_read_rec_data(FILE_T fh, char *pd, int length, int *err)
{
int bytes_read;
! errno = WTAP_ERR_CANT_READ;
! bytes_read = file_read(pd, 1, length, fh);
if (bytes_read != length) {
- *err = file_error(fh);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return -1;
--- 849,862 ----
pseudo_header->ngsniffer_atm.aal5t_chksum = pletohl(&frame4->atm_info.Trailer.aal5t_chksum);
}
! static int ngsniffer_read_rec_data(wtap *wth, FILE_T fh,
! ngsniffer_comp_stream_t *comp_stream, char *pd, int length, int *err)
{
int bytes_read;
! bytes_read = ng_file_read(pd, 1, length, wth, fh, comp_stream, err);
if (bytes_read != length) {
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return -1;
***************
*** 758,765 ****
--- 864,885 ----
return 0;
}
+ /* Throw away the buffers used by the sequential I/O stream, but not
+ those used by the random I/O stream. */
+ static void ngsniffer_sequential_close(wtap *wth)
+ {
+ if (wth->capture.ngsniffer->seq.file_outbuf != NULL) {
+ g_free(wth->capture.ngsniffer->seq.file_outbuf);
+ wth->capture.ngsniffer->seq.file_outbuf = NULL;
+ }
+ }
+
static void ngsniffer_close(wtap *wth)
{
+ if (wth->capture.ngsniffer->seq.file_outbuf != NULL)
+ g_free(wth->capture.ngsniffer->seq.file_outbuf);
+ if (wth->capture.ngsniffer->rand.file_outbuf != NULL)
+ g_free(wth->capture.ngsniffer->rand.file_outbuf);
g_free(wth->capture.ngsniffer);
}
***************
*** 951,954 ****
--- 1071,1457 ----
return FALSE;
}
return TRUE;
+ }
+
+ /*
+ SnifferDecompress() decompresses a blob of compressed data from a
+ Sniffer(R) capture file.
+
+ This function is Copyright (c) 1999-2999 Tim Farley
+
+ Parameters
+ inbuf - buffer of compressed bytes from file, not including
+ the preceding length word
+ inlen - length of inbuf in bytes
+ outbuf - decompressed contents, could contain a partial Sniffer
+ record at the end.
+ outlen - length of outbuf.
+
+ Return value is the number of bytes in outbuf on return.
+ */
+ static int
+ SnifferDecompress( unsigned char * inbuf, size_t inlen,
+ unsigned char * outbuf, size_t outlen, int *err )
+ {
+ unsigned char * pin = inbuf;
+ unsigned char * pout = outbuf;
+ unsigned char * pin_end = pin + inlen;
+ unsigned char * pout_end = pout + outlen;
+ unsigned int bit_mask; /* one bit is set in this, to mask with bit_value */
+ unsigned int bit_value = 0; /* cache the last 16 coding bits we retrieved */
+ unsigned int code_type; /* encoding type, from high 4 bits of byte */
+ unsigned int code_low; /* other 4 bits from encoding byte */
+ int length; /* length of RLE sequence or repeated string */
+ int offset; /* offset of string to repeat */
+
+ bit_mask = 0; /* don't have any bits yet */
+ while (1)
+ {
+ /* Shift down the bit mask we use to see whats encoded */
+ bit_mask = bit_mask >> 1;
+
+ /* If there are no bits left, time to get another 16 bits */
+ if ( 0 == bit_mask )
+ {
+ bit_mask = 0x8000; /* start with the high bit */
+ bit_value = pletohs(pin); /* get the next 16 bits */
+ pin += 2; /* skip over what we just grabbed */
+ if ( pin >= pin_end )
+ {
+ *err = WTAP_ERR_UNC_TRUNCATED; /* data was oddly truncated */
+ return ( -1 );
+ }
+ }
+
+ /* Use the bits in bit_value to see what's encoded and what is raw data */
+ if ( !(bit_mask & bit_value) )
+ {
+ /* bit not set - raw byte we just copy */
+ *(pout++) = *(pin++);
+ }
+ else
+ {
+ /* bit set - next item is encoded. Peel off high nybble
+ of next byte to see the encoding type. Set aside low
+ nybble while we are at it */
+ code_type = (unsigned int) ((*pin) >> 4 ) & 0xF;
+ code_low = (unsigned int) ((*pin) & 0xF );
+ pin++; /* increment over the code byte we just retrieved */
+ if ( pin >= pin_end )
+ {
+ *err = WTAP_ERR_UNC_TRUNCATED; /* data was oddly truncated */
+ return ( -1 );
+ }
+
+ /* Based on the code type, decode the compressed string */
+ switch ( code_type )
+ {
+ case 0 : /* RLE short runs */
+ /*
+ Run length is the low nybble of the first code byte.
+ Byte to repeat immediately follows.
+ Total code size: 2 bytes.
+ */
+ length = code_low + 3;
+ /* If length would put us past end of output, avoid overflow */
+ if ( pout + length > pout_end )
+ {
+ *err = WTAP_ERR_UNC_OVERFLOW;
+ return ( -1 );
+ }
+
+ /* generate the repeated series of bytes */
+ memset( pout, *pin++, length );
+ pout += length;
+ break;
+ case 1 : /* RLE long runs */
+ /*
+ Low 4 bits of run length is the low nybble of the
+ first code byte, upper 8 bits of run length is in
+ the next byte.
+ Byte to repeat immediately follows.
+ Total code size: 3 bytes.
+ */
+ length = code_low + ((unsigned int)(*pin++) << 4) + 19;
+ /* If we are already at end of input, there is no byte
+ to repeat */
+ if ( pin >= pin_end )
+ {
+ *err = WTAP_ERR_UNC_TRUNCATED; /* data was oddly truncated */
+ return ( -1 );
+ }
+ /* If length would put us past end of output, avoid overflow */
+ if ( pout + length > pout_end )
+ {
+ *err = WTAP_ERR_UNC_OVERFLOW;
+ return ( -1 );
+ }
+
+ /* generate the repeated series of bytes */
+ memset( pout, *pin++, length );
+ pout += length;
+ break;
+ case 2 : /* LZ77 long strings */
+ /*
+ Low 4 bits of offset to string is the low nybble of the
+ first code byte, upper 8 bits of offset is in
+ the next byte.
+ Length of string immediately follows.
+ Total code size: 3 bytes.
+ */
+ offset = code_low + ((unsigned int)(*pin++) << 4) + 3;
+ /* If we are already at end of input, there is no byte
+ to repeat */
+ if ( pin >= pin_end )
+ {
+ *err = WTAP_ERR_UNC_TRUNCATED; /* data was oddly truncated */
+ return ( -1 );
+ }
+ /* Check if offset would put us back past begin of buffer */
+ if ( pout - offset < outbuf )
+ {
+ *err = WTAP_ERR_UNC_BAD_OFFSET;
+ return ( -1 );
+ }
+
+ /* get length from next byte, make sure it won't overrun buf */
+ length = (unsigned int)(*pin++) + 16;
+ if ( pout + length > pout_end )
+ {
+ *err = WTAP_ERR_UNC_OVERFLOW;
+ return ( -1 );
+ }
+
+ /* Copy the string from previous text to output position,
+ advance output pointer */
+ memcpy( pout, pout - offset, length );
+ pout += length;
+ break;
+ default : /* (3 to 15): LZ77 short strings */
+ /*
+ Low 4 bits of offset to string is the low nybble of the
+ first code byte, upper 8 bits of offset is in
+ the next byte.
+ Length of string to repeat is overloaded into code_type.
+ Total code size: 2 bytes.
+ */
+ offset = code_low + ((unsigned int)(*pin++) << 4) + 3;
+ /* Check if offset would put us back past begin of buffer */
+ if ( pout - offset < outbuf )
+ {
+ *err = WTAP_ERR_UNC_BAD_OFFSET;
+ return ( -1 );
+ }
+
+ /* get length from code_type, make sure it won't overrun buf */
+ length = code_type;
+ if ( pout + length > pout_end )
+ {
+ *err = WTAP_ERR_UNC_OVERFLOW;
+ return ( -1 );
+ }
+
+ /* Copy the string from previous text to output position,
+ advance output pointer */
+ memcpy( pout, pout - offset, length );
+ pout += length;
+ break;
+ }
+ }
+
+ /* If we've consumed all the input, we are done */
+ if ( pin >= pin_end )
+ break;
+ }
+
+ return ( pout - outbuf ); /* return length of expanded text */
+ }
+
+ /*
+ * XXX - is there any guarantee that this is big enough to hold the
+ * uncompressed data from any blob?
+ */
+ #define OUTBUF_SIZE 65536
+
+ static int
+ ng_file_read(void *buffer, size_t elementsize, size_t numelements, wtap *wth,
+ FILE_T infile, ngsniffer_comp_stream_t *comp_stream, int *err)
+ {
+ unsigned char file_inbuf[65536];
+ unsigned char *file_outbuf;
+ int copybytes = elementsize * numelements; /* bytes left to be copied */
+ int copied_bytes = 0; /* bytes already copied */
+ unsigned char* outbuffer = buffer; /* where to write next decompressed data */
+ unsigned short blob_len;
+ gint16 blob_len_host;
+ size_t in_len;
+ size_t read_len;
+ gboolean uncompressed;
+ int out_len;
+ int bytes_to_copy;
+
+ if ( wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED ) {
+ errno = WTAP_ERR_CANT_READ;
+ copied_bytes = file_read( buffer, 1, copybytes, infile);
+ if (copied_bytes != copybytes)
+ *err = file_error(infile);
+ return copied_bytes;
+ }
+
+ /* Allocate the stream buffer if it hasn't already been allocated. */
+ if (comp_stream->file_outbuf == NULL) {
+ comp_stream->file_outbuf = g_malloc(OUTBUF_SIZE);
+ comp_stream->nextout = comp_stream->file_outbuf;
+ comp_stream->outbuf_nbytes = 0;
+ }
+ file_outbuf = comp_stream->file_outbuf;
+ while (copybytes > 0) {
+ if (comp_stream->outbuf_nbytes == 0) {
+ /* There's no decompressed stuff to copy; get some more. */
+
+ /* Read one 16-bit word which is length of next compressed blob */
+ errno = WTAP_ERR_CANT_READ;
+ read_len = file_read( &blob_len, 1, 2, infile );
+ if ( 2 != read_len ) {
+ *err = file_error(infile);
+ return( -1 );
+ }
+ blob_len_host = pletohs(&blob_len);
+
+ /* Compressed or uncompressed? */
+ if ( blob_len_host < 0 ) {
+ /* Uncompressed blob; blob length is absolute value
+ of the number. */
+ in_len = -blob_len_host;
+ uncompressed = TRUE;
+ } else {
+ in_len = blob_len_host;
+ uncompressed = FALSE;
+ }
+
+ /* Read the blob */
+ errno = WTAP_ERR_CANT_READ;
+ read_len = file_read( file_inbuf, 1, in_len, infile );
+ if ( in_len != read_len ) {
+ *err = file_error(infile);
+ return( -1 );
+ }
+
+ if ( uncompressed ) {
+ memcpy( file_outbuf, file_inbuf, in_len );
+ out_len = in_len;
+ } else {
+ /* Decompress the blob */
+ out_len = SnifferDecompress( file_inbuf, in_len,
+ file_outbuf, OUTBUF_SIZE, err );
+ if (out_len < 0)
+ return( -1 );
+ }
+ comp_stream->nextout = file_outbuf;
+ comp_stream->outbuf_nbytes = out_len;
+ }
+
+ bytes_to_copy = copybytes;
+ if (bytes_to_copy > comp_stream->outbuf_nbytes)
+ bytes_to_copy = comp_stream->outbuf_nbytes;
+ memcpy( outbuffer, comp_stream->nextout, bytes_to_copy );
+ copybytes -= bytes_to_copy;
+ copied_bytes += bytes_to_copy;
+ outbuffer += bytes_to_copy;
+ comp_stream->nextout += bytes_to_copy;
+ comp_stream->outbuf_nbytes -= bytes_to_copy;
+ comp_stream->offset += bytes_to_copy;
+ }
+ return( copied_bytes );
+ }
+
+ static long
+ ng_file_seek(wtap *wth, FILE_T infile, ngsniffer_comp_stream_t *comp_stream,
+ long offset, int whence)
+ {
+ long delta;
+ char buf[65536];
+ long amount_to_read;
+ int err;
+
+ if ( wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED )
+ return file_seek(infile, offset, whence);
+
+ /* OK, seeking in a compressed data stream is a pain - especially
+ given that the compressed Sniffer data stream we're reading
+ may actually be further compressed by gzip.
+
+ For now, we implement random access the same way zlib does:
+
+ compute the target position (we don't support relative-to-end);
+
+ if the target position is ahead of where we are, read and throw
+ away the number of bytes ahead it is;
+
+ if the target position is behind where we are, seek backward
+ to the beginning of the compressed part of the data (i.e.,
+ seek backward to the stuff after the header), and then recompute
+ the relative position based on the new position and seek forward
+ by reading and throwing away data. */
+
+ switch (whence) {
+
+ case SEEK_SET:
+ break; /* "offset" is the target offset */
+
+ case SEEK_CUR:
+ offset += comp_stream->offset;
+ break; /* "offset" is relative to the current offset */
+
+ case SEEK_END:
+ g_assert_not_reached(); /* "offset" is relative to the end of the file... */
+ break; /* ...but we don't know where that is. */
+ }
+
+ delta = offset - comp_stream->offset;
+ if (delta < 0) {
+ /* Oh, dear, we're going backwards. That's a pain.
+
+ Is the place to which we're seeking within the current buffer? */
+
+ if (comp_stream->nextout - comp_stream->file_outbuf >= -delta) {
+ /* Yes. Just adjust "comp_stream->nextout" to point to
+ the place to which we're seeking, adjust
+ "comp_stream->outbuf_nbytes" to add back the appropriate
+ number of bytes, and adjust "comp_stream->offset" to be
+ the destination offset. */
+ comp_stream->nextout += delta;
+ comp_stream->outbuf_nbytes -= delta;
+ comp_stream->offset += delta;
+ delta = 0; /* no skipping necessary */
+ } else {
+ /* No. Seek back to the beginning of the compressed data. */
+ if (file_seek(infile, wth->capture.ngsniffer->data_offset, SEEK_SET) == -1)
+ return -1;
+ comp_stream->offset = wth->capture.ngsniffer->data_offset;
+ delta = offset - comp_stream->offset;
+ if (delta < 0) {
+ /* "I'm sorry, Dave, I can't do that."
+ After doing a seek, we can only read stuff from the
+ possibly-compressed region, as we expect compressed
+ blob lengths. */
+ g_assert_not_reached();
+ }
+
+ /* Reset the output buffer. */
+ comp_stream->nextout = comp_stream->file_outbuf;
+ comp_stream->outbuf_nbytes = 0;
+ }
+ }
+
+ /* Ok, now read and discard "delta" bytes. */
+ while (delta != 0) {
+ amount_to_read = delta;
+ if (amount_to_read > sizeof buf)
+ amount_to_read = sizeof buf;
+ if (ng_file_read(buf, 1, amount_to_read, wth, infile, comp_stream, &err) < 0)
+ return -1; /* error */
+ delta -= amount_to_read;
+ }
+ return offset;
}
Index: wiretap/wtap-int.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/wiretap/wtap-int.h,v
retrieving revision 1.1
diff -c -r1.1 wtap-int.h
*** wtap-int.h 2000/05/19 23:07:04 1.1
--- wtap-int.h 2000/05/24 07:32:35
***************
*** 47,56 ****
--- 47,67 ----
#include "wtap.h"
+ /* Information for a compressed Sniffer data stream. */
typedef struct {
+ unsigned char *file_outbuf;
+ unsigned char *nextout;
+ size_t outbuf_nbytes;
+ long offset;
+ } ngsniffer_comp_stream_t;
+
+ typedef struct {
double timeunit;
time_t start;
int is_atm;
+ ngsniffer_comp_stream_t seq; /* sequential access */
+ ngsniffer_comp_stream_t rand; /* random access */
+ long data_offset; /* start of possibly-compressed stuff */
} ngsniffer_t;
typedef struct {
***************
*** 126,131 ****
--- 137,143 ----
subtype_read_func subtype_read;
subtype_seek_read_func subtype_seek_read;
+ void (*subtype_sequential_close)(struct wtap*);
void (*subtype_close)(struct wtap*);
int file_encap; /* per-file, for those
file formats that have
Index: wiretap/wtap.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/wiretap/wtap.c,v
retrieving revision 1.43
diff -c -r1.43 wtap.c
*** wtap.c 2000/05/19 23:07:04 1.43
--- wtap.c 2000/05/24 07:32:36
***************
*** 155,161 ****
NULL,
"Less data was read than was expected",
"File contains a record that's not valid",
! "Less data was written than was requested"
};
#define WTAP_ERRLIST_SIZE (sizeof wtap_errlist / sizeof wtap_errlist[0])
--- 155,164 ----
NULL,
"Less data was read than was expected",
"File contains a record that's not valid",
! "Less data was written than was requested",
! "Uncompression error: data oddly truncated",
! "Uncompression error: data would overflow buffer",
! "Uncompression error: bad LZ77 offset",
};
#define WTAP_ERRLIST_SIZE (sizeof wtap_errlist / sizeof wtap_errlist[0])
***************
*** 186,196 ****
}
/* Close only the sequential side, freeing up memory it uses.
Note that we do *not* want to call the subtype's close function,
as it would free any per-subtype data, and that data may be
! needed by the random-access side. */
void wtap_sequential_close(wtap *wth)
{
if (wth->fh != NULL) {
file_close(wth->fh);
wth->fh = NULL;
--- 189,206 ----
}
/* Close only the sequential side, freeing up memory it uses.
+
Note that we do *not* want to call the subtype's close function,
as it would free any per-subtype data, and that data may be
! needed by the random-access side.
!
! Instead, if the subtype has a "sequential close" function, we call it,
! to free up stuff used only by the sequential side. */
void wtap_sequential_close(wtap *wth)
{
+ if (wth->subtype_sequential_close != NULL)
+ (*wth->subtype_sequential_close)(wth);
+
if (wth->fh != NULL) {
file_close(wth->fh);
wth->fh = NULL;
Index: wiretap/wtap.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/wiretap/wtap.h,v
retrieving revision 1.71
diff -c -r1.71 wtap.h
*** wtap.h 2000/05/19 23:07:04 1.71
--- wtap.h 2000/05/24 07:32:36
***************
*** 106,128 ****
#define WTAP_FILE_PCAP_MODIFIED 3
#define WTAP_FILE_PCAP_RH_6_1 4
#define WTAP_FILE_LANALYZER 5
! #define WTAP_FILE_NGSNIFFER 6
! #define WTAP_FILE_SNOOP 7
! #define WTAP_FILE_IPTRACE_1_0 8
! #define WTAP_FILE_IPTRACE_2_0 9
! #define WTAP_FILE_NETMON_1_x 10
! #define WTAP_FILE_NETMON_2_x 11
! #define WTAP_FILE_NETXRAY_1_0 12
! #define WTAP_FILE_NETXRAY_1_1 13
! #define WTAP_FILE_NETXRAY_2_001 14
! #define WTAP_FILE_RADCOM 15
! #define WTAP_FILE_ASCEND 16
! #define WTAP_FILE_NETTL 17
! #define WTAP_FILE_TOSHIBA 18
! #define WTAP_FILE_I4BTRACE 19
/* last WTAP_FILE_ value + 1 */
! #define WTAP_NUM_FILE_TYPES 20
/*
* Maximum packet size we'll support.
--- 106,129 ----
#define WTAP_FILE_PCAP_MODIFIED 3
#define WTAP_FILE_PCAP_RH_6_1 4
#define WTAP_FILE_LANALYZER 5
! #define WTAP_FILE_NGSNIFFER_UNCOMPRESSED 6
! #define WTAP_FILE_NGSNIFFER_COMPRESSED 7
! #define WTAP_FILE_SNOOP 8
! #define WTAP_FILE_IPTRACE_1_0 9
! #define WTAP_FILE_IPTRACE_2_0 10
! #define WTAP_FILE_NETMON_1_x 11
! #define WTAP_FILE_NETMON_2_x 12
! #define WTAP_FILE_NETXRAY_1_0 13
! #define WTAP_FILE_NETXRAY_1_1 14
! #define WTAP_FILE_NETXRAY_2_001 15
! #define WTAP_FILE_RADCOM 16
! #define WTAP_FILE_ASCEND 17
! #define WTAP_FILE_NETTL 18
! #define WTAP_FILE_TOSHIBA 19
! #define WTAP_FILE_I4BTRACE 20
/* last WTAP_FILE_ value + 1 */
! #define WTAP_NUM_FILE_TYPES 21
/*
* Maximum packet size we'll support.
***************
*** 336,341 ****
--- 337,348 ----
/* We read an invalid record */
#define WTAP_ERR_SHORT_WRITE -12
/* An attempt to write wrote less data than it should have */
+ #define WTAP_ERR_UNC_TRUNCATED -13
+ /* Sniffer compressed data was oddly truncated */
+ #define WTAP_ERR_UNC_OVERFLOW -14
+ /* Uncompressing Sniffer data would overflow buffer */
+ #define WTAP_ERR_UNC_BAD_OFFSET -15
+ /* LZ77 compressed data has bad offset to string */
/* Errors from zlib; zlib error Z_xxx turns into Wiretap error
WTAP_ERR_ZLIB + Z_xxx.
- Follow-Ups:
- Re: [ethereal-dev] RE: Correct sniffdecomp.c attached
- From: Guy Harris
- Re: [ethereal-dev] RE: Correct sniffdecomp.c attached
- References:
- RE: [ethereal-dev] RE: Correct sniffdecomp.c attached
- From: Farley, Tim (ISSAtlanta)
- RE: [ethereal-dev] RE: Correct sniffdecomp.c attached
- Prev by Date: [ethereal-dev] Fragmentation reporting bug
- Next by Date: Re: [ethereal-dev] Fragmentation reporting bug
- Previous by thread: RE: [ethereal-dev] RE: Correct sniffdecomp.c attached
- Next by thread: Re: [ethereal-dev] RE: Correct sniffdecomp.c attached
- Index(es):





