Ethereal-dev: [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: Joerg Mayer <jmayer@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 22 Apr 2000 03:43:44 +0200 (MET DST)
Hello Tim (+ ethereal-dev), I'm currently stuck with the seek code but I hope to get some implementation done for this during the next two days. I *think* I got the rest right but without seek I can't be sure (I don't get any output). I have attached a diff versus 0.8.7 that contains all the changes I have made. Feel free to comment/make suggenstions! Ciao Joerg PS: All testing done with *t*ethereal. PPS: I will probably copy ng_file_read to ng_file_skip and write the seek code around that function. On Thu, 20 Apr 2000, Farley, Tim (ISSAtlanta) wrote: > Did you get the C source code and doc files I sent you on the compressed > Sniffer format? Have you had any time to integrate it into Ethereal? > > If you need any help with it, feel free to ask. -- Joerg Mayer eMail: <jmayer@xxxxxxxxxxxxx> Give an engineer a problem and a curious form of time dilation occurs /AC
--- ethereal-0.8.7/wiretap/ngsniffer.c.distrib Mon Apr 17 09:35:54 2000 +++ ethereal-0.8.7/wiretap/ngsniffer.c Sat Apr 22 03:29:26 2000 @@ -85,6 +85,7 @@ /* * Sniffer version record format. * + * FIXME: The comment below is no longer valid * 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." @@ -246,6 +247,10 @@ #define NUM_NGSNIFF_TIMEUNITS 7 static double Usec[] = { 15.0, 0.838096, 15.0, 0.5, 2.0, 1.0, 0.1 }; +static int ng_file_read(void *buffer, size_t elementsize, size_t numelements, + wtap *wth); +static int SnifferDecompress( unsigned char * inbuf, size_t inlen, + unsigned char * outbuf, size_t outlen ); static int ngsniffer_read(wtap *wth, int *err); static void ngsniffer_close(wtap *wth); static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, @@ -330,13 +335,6 @@ } 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 @@ -368,8 +366,16 @@ } /* This is a ngsniffer file */ - wth->file_type = WTAP_FILE_NGSNIFFER; wth->capture.ngsniffer = g_malloc(sizeof(ngsniffer_t)); + /* compressed or uncompressed Sniffer file? */ + if (version.format != 1) { + wth->file_type = WTAP_FILE_NGSNIFFER_COMPRESSED; +fprintf( stderr, "open: compressed\n" ); + } else { + wth->file_type = WTAP_FILE_NGSNIFFER_UNCOMPRESSED; +fprintf( stderr, "open: uncompressed\n" ); + } + wth->subtype_read = ngsniffer_read; wth->subtype_close = ngsniffer_close; wth->snapshot_length = 16384; /* not available in header, only in frame */ @@ -431,7 +437,7 @@ * Read the record header. */ errno = WTAP_ERR_CANT_READ; - bytes_read = file_read(record_type, 1, 2, wth->fh); + bytes_read = ng_file_read(record_type, 1, 2, wth); if (bytes_read != 2) { *err = file_error(wth->fh); if (*err != 0) @@ -444,7 +450,7 @@ } wth->data_offset += 2; errno = WTAP_ERR_CANT_READ; - bytes_read = file_read(record_length, 1, 4, wth->fh); + bytes_read = ng_file_read(record_length, 1, 4, wth); if (bytes_read != 4) { *err = file_error(wth->fh); if (*err == 0) @@ -471,7 +477,7 @@ /* Read the f_frame2_struct */ errno = WTAP_ERR_CANT_READ; - bytes_read = file_read(&frame2, 1, sizeof frame2, wth->fh); + bytes_read = ng_file_read(&frame2, 1, sizeof frame2, wth); if (bytes_read != sizeof frame2) { *err = file_error(wth->fh); if (*err == 0) @@ -529,7 +535,7 @@ /* Read the f_frame4_struct */ errno = WTAP_ERR_CANT_READ; - bytes_read = file_read(&frame4, 1, sizeof frame4, wth->fh); + bytes_read = ng_file_read(&frame4, 1, sizeof frame4, wth); if (bytes_read != sizeof frame4) { *err = file_error(wth->fh); if (*err == 0) @@ -602,7 +608,7 @@ data_offset = wth->data_offset; errno = WTAP_ERR_CANT_READ; pd = buffer_start_ptr(wth->frame_buffer); - bytes_read = file_read(pd, 1, length, wth->fh); + bytes_read = ng_file_read(pd, 1, length, wth); if (bytes_read != length) { *err = file_error(wth->fh); @@ -834,4 +840,299 @@ 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 ) +{ + 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 */ + int truncated = 0; /* input appeared truncated */ + int overflow = 0; /* attempt to overflow output buffer */ + int bad_offset = 0; /* LZ string offset was bad */ + + 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 ) + { + truncated = 1; /* if we break here, data was oddly truncated */ + break; + } + } + + /* 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 ) + { + truncated = 1; /* if we break here, data was oddly truncated */ + break; + } + + /* 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 ) + { + overflow = 1; + break; + } + + /* 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 ) + { + truncated = 1; /* if we break here, data was oddly truncated */ + break; + } + /* If length would put us past end of output, avoid overflow */ + if ( pout + length > pout_end ) + { + overflow = 1; + break; + } + + /* 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 ) + { + truncated = 1; /* if we break here, data was oddly truncated */ + break; + } + /* Check if offset would put us back past begin of buffer */ + if ( pout - offset < outbuf ) + { + bad_offset = 1; + break; + } + + /* get length from next byte, make sure it won't overrun buf */ + length = (unsigned int)(*pin++) + 16; + if ( pout + length > pout_end ) + { + overflow = 1; + break; + } + + /* 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 ) + { + bad_offset = 1; + break; + } + + /* get length from code_type, make sure it won't overrun buf */ + length = code_type; + if ( pout + length > pout_end ) + { + overflow = 1; + break; + } + + /* Copy the string from previous text to output position, + advance output pointer */ + memcpy( pout, pout - offset, length ); + pout += length; + break; + } + + /* Propagate a break from inside switch to break the while() too */ + if ( truncated || overflow || bad_offset ) + break; + } + + /* If we've consumed all the input, we are done */ + if ( pin >= pin_end ) + break; + } + +/* FIXME: Use symbolic errors */ + if ( truncated ) + return ( -1 ); + + if ( overflow ) + return ( -2 ); + + if ( bad_offset ) + return ( -3 ); + + return ( pout - outbuf ); /* return length of expanded text */ +} + +static unsigned char file_inbuf[65536]; +static unsigned char file_outbuf[65536]; +static unsigned char* nextout; + +static int +ng_file_read(void *buffer, size_t elementsize, size_t numelements, wtap *wth) +{ + FILE* infile = wth->fh; + int copybytes = elementsize * numelements; /* bytes still to be copied */ + int copied_bytes = 0; /* bytes already copied */ + unsigned char* outbuffer = buffer; /* where to write next decompressed data */ + size_t out_len = 0; /* Number of bytes in outbuffer */ + unsigned short blob_len; + size_t in_len; + size_t read_len; + int uncompressed; + + if ( wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED ) { + if ( copybytes != (copied_bytes = + file_read( buffer, 1, copybytes, infile))) { + /* FIXME: Errorhandling */ +fprintf( stderr, "error copying plain data from file\n" ); + } + goto error; + } + +fprintf( stderr, "compressed\n" ); + while ( copybytes > out_len ) { + /* nothing happens on entry, we only fill outbuffer */ + memcpy( outbuffer, nextout, out_len ); + copybytes -= out_len; + outbuffer += out_len; + copied_bytes += out_len; + + /* Fill buffer */ + /* Read one 16-bit word which is length of next compressed blob */ + if ( 2 != (read_len = file_read( &blob_len, 1, 2, infile )) ) + { + /* FIXME: Errorhandling */ +fprintf( stderr, "error reading blob length from file (read %d bytes instead of 2\n", read_len ); + goto error; + break; + } + in_len = (size_t)pletohs(&blob_len); + + /* Uncompressed blob */ + uncompressed = 0; + if ( 49152 == in_len ) + { + in_len = 16384; + uncompressed = 1; + } + + /* Read the compressed blob */ + if ( in_len != ( read_len = file_read( file_inbuf, 1, in_len, infile ) ) ) + { + /* FIXME: Errorhandling */ +fprintf( stderr, "error reading blob of %d bytes (got %d bytes) from file\n", pletohs(&blob_len), read_len ); + break; + } + + if ( uncompressed ) { + memcpy( file_outbuf, file_inbuf, in_len ); + } else { + /* Decompress the blob */ + /* FIXME: Errorhandling */ + out_len = SnifferDecompress( file_inbuf, pletohs(&blob_len), + file_outbuf, sizeof(file_outbuf) ); + nextout = file_outbuf; + } + } + memcpy( outbuffer, nextout, copybytes); + nextout += copybytes; + out_len -= copybytes; + copied_bytes += copybytes; +error: + return( copied_bytes ); +} + +int ngsniffer_compressed_seek_read (FILE *fh, int seek_off, guint8 *pd, int len) +{ + return (-1); } --- ethereal-0.8.7/wiretap/wtap.h.distrib Mon Apr 17 09:35:54 2000 +++ ethereal-0.8.7/wiretap/wtap.h Sat Apr 22 02:53:47 2000 @@ -106,7 +106,7 @@ #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_NGSNIFFER_COMPRESSED 6 #define WTAP_FILE_SNOOP 7 #define WTAP_FILE_IPTRACE_1_0 8 #define WTAP_FILE_IPTRACE_2_0 9 @@ -120,9 +120,10 @@ #define WTAP_FILE_NETTL 17 #define WTAP_FILE_TOSHIBA 18 #define WTAP_FILE_I4BTRACE 19 +#define WTAP_FILE_NGSNIFFER_UNCOMPRESSED 20 /* last WTAP_FILE_ value + 1 */ -#define WTAP_NUM_FILE_TYPES 20 +#define WTAP_NUM_FILE_TYPES 21 /* * Maximum packet size we'll support. --- ethereal-0.8.7/wiretap/wtap.c.distrib Sat Apr 22 02:07:49 2000 +++ ethereal-0.8.7/wiretap/wtap.c Sat Apr 22 03:17:50 2000 @@ -31,6 +31,7 @@ #include "buffer.h" #include "ascend.h" #include "toshiba.h" +#include "ngsniffer.h" FILE* wtap_file(wtap *wth) { @@ -233,6 +234,9 @@ case WTAP_FILE_TOSHIBA: return toshiba_seek_read(fh, seek_off, pd, len); + + case WTAP_FILE_NGSNIFFER_COMPRESSED: + return ngsniffer_compressed_seek_read(fh, seek_off, pd, len); default: return wtap_def_seek_read(fh, seek_off, pd, len); --- ethereal-0.8.7/wiretap/ngsniffer.h.distrib Sat Apr 22 02:10:40 2000 +++ ethereal-0.8.7/wiretap/ngsniffer.h Sat Apr 22 02:51:57 2000 @@ -22,5 +22,6 @@ */ int ngsniffer_open(wtap *wth, int *err); +int ngsniffer_compressed_seek_read (FILE *fh, int seek_off, guint8 *pd, int len); gboolean ngsniffer_dump_open(wtap_dumper *wdh, int *err); int ngsniffer_dump_can_write_encap(int filetype, int encap); --- ethereal-0.8.7/tethereal.c.distrib Mon Apr 17 09:35:54 2000 +++ ethereal-0.8.7/tethereal.c Mon Apr 17 09:36:57 2000 @@ -130,14 +130,14 @@ fprintf(stderr, "This is GNU t%s %s, compiled with %s\n", PACKAGE, VERSION, comp_info_str); #ifdef HAVE_LIBPCAP - fprintf(stderr, "t%s [ -vVh ] [ -c count ] [ -D ] [ -f <filter expression> ]\n", PACKAGE); + fprintf(stderr, "t%s [ -vVh ] [ -c count ] [ -D ] [ -f <capture filter expression> ]\n", PACKAGE); fprintf(stderr, "\t[ -F <capture file type> ] [ -i iface ] [ -n ] [ -r infile ]\n"); - fprintf(stderr, "\t[ -R <filter expression> ] [ -s snaplen ] [ -t <time stamp format> ]\n"); - fprintf(stderr, "\t[ -w savefile ] [ -x ]\n"); + fprintf(stderr, "\t[ -R <read filter expression> ] [ -s snaplen ]\n"); + fprintf(stderr, "\t[ -t <time stamp format> ] [ -w savefile ] [ -x ]\n"); #else fprintf(stderr, "t%s [ -vVh ] [ -D ] [ -F <capture file type> ] [ -n ] [ -r infile ]\n", PACKAGE); - fprintf(stderr, "\t[ -R <filter expression> ] [ -t <time stamp format> ] [ -w savefile ]\n"); - fprintf(stderr, "\t[ -x ]\n"); + fprintf(stderr, "\t[ -R <read filter expression> ] [ -t <time stamp format> ]\n"); + fprintf(stderr, "\t[ -w savefile ] [ -x ]\n"); #endif fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n"); for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
- Prev by Date: Re: [ethereal-dev] LAT
- Next by Date: Re: [ethereal-dev] Targets dependent on proto.h
- Previous by thread: Re: [ethereal-dev] LAT
- Next by thread: Re: [ethereal-dev] Bug in Data-count and Hex-Dump from ethereal
- Index(es):