/* ngsniffer.c
*
- * $Id: ngsniffer.c,v 1.58 2001/01/16 09:17:34 guy Exp $
+ * $Id: ngsniffer.c,v 1.85 2002/08/28 20:30:45 jmayer Exp $
*
* Wiretap Library
- * Copyright (c) 1998 by Gilbert Ramirez <gram@xiexie.org>
- *
+ * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
*/
/* The code in ngsniffer.c that decodes the time fields for each packet in the
static double Usec[] = { 15.0, 0.838096, 15.0, 0.5, 2.0, 1.0, 0.1 };
static int skip_header_records(wtap *wth, int *err, gint16 version);
-static gboolean ngsniffer_read(wtap *wth, int *err, int *data_offset);
-static int ngsniffer_seek_read(wtap *wth, int seek_off,
- union wtap_pseudo_header *pseudo_header, u_char *pd, int packet_size);
+static gboolean ngsniffer_read(wtap *wth, int *err, long *data_offset);
+static gboolean ngsniffer_seek_read(wtap *wth, long seek_off,
+ union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size,
+ int *err);
static int ngsniffer_read_rec_header(wtap *wth, gboolean is_random,
guint16 *typep, guint16 *lengthp, int *err);
-static int ngsniffer_read_frame2(wtap *wth, gboolean is_random,
+static gboolean ngsniffer_read_frame2(wtap *wth, gboolean is_random,
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, gboolean is_random,
+static gboolean ngsniffer_read_frame4(wtap *wth, gboolean is_random,
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_frame6(wtap *wth, gboolean is_random,
+static gboolean ngsniffer_read_frame6(wtap *wth, gboolean is_random,
struct frame6_rec *frame6, int *err);
static void set_pseudo_header_frame6(union wtap_pseudo_header *pseudo_header,
struct frame6_rec *frame6);
-static int ngsniffer_read_rec_data(wtap *wth, gboolean is_random, u_char *pd,
- int length, int *err);
+static gboolean ngsniffer_read_rec_data(wtap *wth, gboolean is_random,
+ guchar *pd, int length, int *err);
static void fix_pseudo_header(wtap *wth,
union wtap_pseudo_header *pseudo_header);
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);
+ const union wtap_pseudo_header *pseudo_header, const guchar *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 );
wtap *wth, gboolean is_random, int *err);
static int read_blob(FILE_T infile, ngsniffer_comp_stream_t *comp_stream,
int *err);
-static long ng_file_seek_seq(wtap *wth, long offset, int whence);
-static long ng_file_seek_rand(wtap *wth, long offset, int whence);
+static long ng_file_seek_seq(wtap *wth, long offset, int whence, int *err);
+static long ng_file_seek_rand(wtap *wth, long offset, int whence, int *err);
int ngsniffer_open(wtap *wth, int *err)
{
struct tm tm;
/* Read in the string that should be at the start of a Sniffer file */
- file_seek(wth->fh, 0, SEEK_SET);
- wth->data_offset = 0;
errno = WTAP_ERR_CANT_READ;
bytes_read = file_read(magic, 1, sizeof magic, wth->fh);
if (bytes_read != sizeof magic) {
wth->file_type = WTAP_FILE_NGSNIFFER_UNCOMPRESSED;
}
+ /* Set encap type before reading header records because the
+ * header record may change encap type.
+ */
+ wth->file_encap = sniffer_encap[version.network];
+
/*
* We don't know how to handle the remaining header record types,
- * so we just skip them
+ * so we just skip them - except for REC_HEADER2 records, which
+ * we look at, for "Internetwork analyzer" captures, to attempt to
+ * determine what the link-layer encapsulation is.
*/
if (skip_header_records(wth, err, version.maj_vers) < 0)
return -1;
* or REC_EOF after this? If not, we can get rid of the loop in
* "ngsniffer_read()".
*/
- if (wth->random_fh != NULL)
- file_seek(wth->random_fh, wth->data_offset, SEEK_SET);
+ if (wth->random_fh != NULL) {
+ if (file_seek(wth->random_fh, wth->data_offset, SEEK_SET, err) == -1)
+ return -1;
+ }
/* This is a ngsniffer file */
wth->capture.ngsniffer = g_malloc(sizeof(ngsniffer_t));
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->snapshot_length = 0; /* not available in header, only in frame */
wth->capture.ngsniffer->timeunit = Usec[version.timeunit];
- wth->file_encap = sniffer_encap[version.network];
wth->capture.ngsniffer->is_atm =
(wth->file_encap == WTAP_ENCAP_ATM_SNIFFER);
type = pletohs(record_type);
if ((type != REC_HEADER1) && (type != REC_HEADER2)
+ && (type != REC_HEADER3) && (type != REC_HEADER4)
+ && (type != REC_HEADER5) && (type != REC_HEADER6)
+ && (type != REC_HEADER7)
&& ((type != REC_V2DESC) || (version > 2)) ) {
/*
* Well, this is either some unknown header type
* which implies data. Seek backwards over the
* two bytes we read, and return.
*/
- file_seek(wth->fh, -2, SEEK_CUR);
+ if (file_seek(wth->fh, -2, SEEK_CUR, err) == -1)
+ return -1;
return 0;
}
* Yes, get the first 32 bytes of the record
* data.
*/
- bytes_to_read = length;
- if (length > sizeof buffer)
- length = sizeof buffer;
+ bytes_to_read = MIN(length, sizeof buffer);
bytes_read = file_read(buffer, 1, bytes_to_read,
- wth->fh);
+ wth->fh);
if (bytes_read != bytes_to_read) {
*err = file_error(wth->fh);
if (*err == 0) {
return -1;
}
}
+ /*
+ * Skip the rest of the record.
+ */
+ if (length > sizeof buffer) {
+ if (file_seek(wth->fh, length - sizeof buffer,
+ SEEK_CUR, err) == -1)
+ return -1;
+ }
/*
* XXX - what about LAPB and LAPD? At least one
- * X.25 capture has a type of NET_HDLC, but one
+ * X.25 capture has a type of NET_HDLC, but one
* might also consider LAPD to be an HDLC
* variant; if it also has a type of NET_HDLC,
* we'd have to look at some other data to
break;
}
- /*
- * Skip the rest of the record.
- */
- if (length > sizeof buffer) {
- file_seek(wth->fh, length - sizeof buffer,
- SEEK_CUR);
- }
} else {
/* Nope, just skip over the data. */
- file_seek(wth->fh, length, SEEK_CUR);
+ if (file_seek(wth->fh, length, SEEK_CUR, err) == -1)
+ return -1;
}
wth->data_offset += length;
}
}
/* Read the next packet */
-static gboolean ngsniffer_read(wtap *wth, int *err, int *data_offset)
+static gboolean ngsniffer_read(wtap *wth, int *err, long *data_offset)
{
int ret;
guint16 type, length;
struct frame6_rec frame6;
double t;
guint16 time_low, time_med, time_high, true_size, size;
- u_char *pd;
+ guchar *pd;
for (;;) {
/*
}
/* Read the f_frame2_struct */
- ret = ngsniffer_read_frame2(wth, FALSE, &frame2, err);
- if (ret < 0) {
+ if (!ngsniffer_read_frame2(wth, FALSE, &frame2, err)) {
/* Read error */
return FALSE;
}
}
/* Read the f_frame4_struct */
- ret = ngsniffer_read_frame4(wth, FALSE, &frame4, err);
+ if (!ngsniffer_read_frame4(wth, FALSE, &frame4, err)) {
+ /* Read error */
+ return FALSE;
+ }
wth->data_offset += sizeof frame4;
time_low = pletohs(&frame4.time_low);
time_med = pletohs(&frame4.time_med);
}
/* Read the f_frame6_struct */
- ret = ngsniffer_read_frame6(wth, FALSE, &frame6, err);
+ if (!ngsniffer_read_frame6(wth, FALSE, &frame6, err)) {
+ /* Read error */
+ return FALSE;
+ }
wth->data_offset += sizeof frame6;
time_low = pletohs(&frame6.time_low);
time_med = pletohs(&frame6.time_med);
* it is but can't handle it. Skip past the data
* portion, and keep looping.
*/
- ng_file_seek_seq(wth, length, SEEK_CUR);
+ if (ng_file_seek_seq(wth, length, SEEK_CUR, err) == -1)
+ return FALSE;
wth->data_offset += length;
}
*/
buffer_assure_space(wth->frame_buffer, length);
pd = buffer_start_ptr(wth->frame_buffer);
- if (ngsniffer_read_rec_data(wth, FALSE, pd, length, err) < 0)
+ if (!ngsniffer_read_rec_data(wth, FALSE, pd, length, err))
return FALSE; /* Read error */
wth->data_offset += length;
return TRUE;
}
-static int ngsniffer_seek_read(wtap *wth, int seek_off,
- union wtap_pseudo_header *pseudo_header, u_char *pd, int packet_size)
+static gboolean ngsniffer_seek_read(wtap *wth, long seek_off,
+ union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size,
+ int *err)
{
int ret;
- int err; /* XXX - return this */
guint16 type, length;
struct frame2_rec frame2;
struct frame4_rec frame4;
struct frame6_rec frame6;
- ng_file_seek_rand(wth, seek_off, SEEK_SET);
+ if (ng_file_seek_rand(wth, seek_off, SEEK_SET, err) == -1)
+ return FALSE;
- ret = ngsniffer_read_rec_header(wth, TRUE, &type, &length, &err);
+ ret = ngsniffer_read_rec_header(wth, TRUE, &type, &length, err);
if (ret <= 0) {
/* Read error or EOF */
- return ret;
+ if (ret == 0) {
+ /* EOF means "short read" in random-access mode */
+ *err = WTAP_ERR_SHORT_READ;
+ }
+ return FALSE;
}
switch (type) {
case REC_FRAME2:
/* Read the f_frame2_struct */
- ret = ngsniffer_read_frame2(wth, TRUE, &frame2, &err);
- if (ret < 0) {
+ if (!ngsniffer_read_frame2(wth, TRUE, &frame2, err)) {
/* Read error */
- return ret;
+ return FALSE;
}
length -= sizeof frame2; /* we already read that much */
case REC_FRAME4:
/* Read the f_frame4_struct */
- ret = ngsniffer_read_frame4(wth, TRUE, &frame4, &err);
+ if (!ngsniffer_read_frame4(wth, TRUE, &frame4, err)) {
+ /* Read error */
+ return FALSE;
+ }
length -= sizeof frame4; /* we already read that much */
case REC_FRAME6:
/* Read the f_frame6_struct */
- ret = ngsniffer_read_frame6(wth, TRUE, &frame6, &err);
+ if (!ngsniffer_read_frame6(wth, TRUE, &frame6, err)) {
+ /* Read error */
+ return FALSE;
+ }
length -= sizeof frame6; /* we already read that much */
* "Can't happen".
*/
g_assert_not_reached();
- return -1;
+ return FALSE;
}
/*
/*
* Got the pseudo-header (if any), now get the data.
*/
- return ngsniffer_read_rec_data(wth, TRUE, pd, packet_size, &err);
+ return ngsniffer_read_rec_data(wth, TRUE, pd, packet_size, err);
}
static int ngsniffer_read_rec_header(wtap *wth, gboolean is_random,
return 1; /* success */
}
-static int ngsniffer_read_frame2(wtap *wth, gboolean is_random,
+static gboolean ngsniffer_read_frame2(wtap *wth, gboolean is_random,
struct frame2_rec *frame2, int *err)
{
int bytes_read;
if (bytes_read != sizeof *frame2) {
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
- return -1;
+ return FALSE;
}
- return 0;
+ return TRUE;
}
static void set_pseudo_header_frame2(union wtap_pseudo_header *pseudo_header,
* or 0xcc, and "flags" was either 0 or 0x18,
* with no obvious correlation with anything.
*/
- pseudo_header->x25.flags = (frame2->fs & 0x80) ? 0x00 : 0x80;
+ pseudo_header->x25.flags = (frame2->fs & 0x80) ? 0x00 : FROM_DCE;
}
-static int ngsniffer_read_frame4(wtap *wth, gboolean is_random,
+static gboolean ngsniffer_read_frame4(wtap *wth, gboolean is_random,
struct frame4_rec *frame4, int *err)
{
int bytes_read;
if (bytes_read != sizeof *frame4) {
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
- return -1;
+ return FALSE;
}
- return 0;
+ return TRUE;
}
static void set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
struct frame4_rec *frame4)
{
- pseudo_header->ngsniffer_atm.AppTrafType = frame4->atm_info.AppTrafType;
- pseudo_header->ngsniffer_atm.AppHLType = frame4->atm_info.AppHLType;
- pseudo_header->ngsniffer_atm.Vpi = pletohs(&frame4->atm_info.Vpi);
- pseudo_header->ngsniffer_atm.Vci = pletohs(&frame4->atm_info.Vci);
- pseudo_header->ngsniffer_atm.channel = pletohs(&frame4->atm_info.channel);
- pseudo_header->ngsniffer_atm.cells = pletohs(&frame4->atm_info.cells);
- pseudo_header->ngsniffer_atm.aal5t_u2u = pletohs(&frame4->atm_info.Trailer.aal5t_u2u);
- pseudo_header->ngsniffer_atm.aal5t_len = pletohs(&frame4->atm_info.Trailer.aal5t_len);
- pseudo_header->ngsniffer_atm.aal5t_chksum = pletohl(&frame4->atm_info.Trailer.aal5t_chksum);
+ guint8 aal_type, hl_type;
+ guint16 vpi, vci;
+
+ aal_type = frame4->atm_info.AppTrafType & ATT_AALTYPE;
+ hl_type = frame4->atm_info.AppTrafType & ATT_HLTYPE;
+ vpi = pletohs(&frame4->atm_info.Vpi);
+ vci = pletohs(&frame4->atm_info.Vci);
+
+ switch (aal_type) {
+
+ case ATT_AAL_UNKNOWN:
+ /*
+ * Map ATT_AAL_UNKNOWN on VPI 0, VCI 5 to ATT_AAL_SIGNALLING,
+ * as that's the VPCI used for signalling.
+ *
+ * XXX - is this necessary, or will frames to 0/5 always
+ * have ATT_AAL_SIGNALLING?
+ */
+ if (vpi == 0 && vci == 5)
+ pseudo_header->atm.aal = AAL_SIGNALLING;
+ else
+ pseudo_header->atm.aal = AAL_UNKNOWN;
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case ATT_AAL1:
+ pseudo_header->atm.aal = AAL_1;
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case ATT_AAL3_4:
+ pseudo_header->atm.aal = AAL_3_4;
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case ATT_AAL5:
+ pseudo_header->atm.aal = AAL_5;
+ switch (hl_type) {
+
+ case ATT_HL_UNKNOWN:
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case ATT_HL_LLCMX:
+ pseudo_header->atm.type = TRAF_LLCMX;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case ATT_HL_VCMX:
+ pseudo_header->atm.type = TRAF_VCMX;
+ switch (frame4->atm_info.AppHLType) {
+
+ case AHLT_UNKNOWN:
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case AHLT_VCMX_802_3_FCS:
+ pseudo_header->atm.subtype =
+ TRAF_ST_VCMX_802_3_FCS;
+ break;
+
+ case AHLT_VCMX_802_4_FCS:
+ pseudo_header->atm.subtype =
+ TRAF_ST_VCMX_802_4_FCS;
+ break;
+
+ case AHLT_VCMX_802_5_FCS:
+ pseudo_header->atm.subtype =
+ TRAF_ST_VCMX_802_5_FCS;
+ break;
+
+ case AHLT_VCMX_FDDI_FCS:
+ pseudo_header->atm.subtype =
+ TRAF_ST_VCMX_FDDI_FCS;
+ break;
+
+ case AHLT_VCMX_802_6_FCS:
+ pseudo_header->atm.subtype =
+ TRAF_ST_VCMX_802_6_FCS;
+ break;
+
+ case AHLT_VCMX_802_3:
+ pseudo_header->atm.subtype = TRAF_ST_VCMX_802_3;
+ break;
+
+ case AHLT_VCMX_802_4:
+ pseudo_header->atm.subtype = TRAF_ST_VCMX_802_4;
+ break;
+
+ case AHLT_VCMX_802_5:
+ pseudo_header->atm.subtype = TRAF_ST_VCMX_802_5;
+ break;
+
+ case AHLT_VCMX_FDDI:
+ pseudo_header->atm.subtype = TRAF_ST_VCMX_FDDI;
+ break;
+
+ case AHLT_VCMX_802_6:
+ pseudo_header->atm.subtype = TRAF_ST_VCMX_802_6;
+ break;
+
+ case AHLT_VCMX_FRAGMENTS:
+ pseudo_header->atm.subtype =
+ TRAF_ST_VCMX_FRAGMENTS;
+ break;
+
+ case AHLT_VCMX_BPDU:
+ pseudo_header->atm.subtype = TRAF_ST_VCMX_BPDU;
+ break;
+
+ default:
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+ }
+ break;
+
+ case ATT_HL_LANE:
+ pseudo_header->atm.type = TRAF_LANE;
+ switch (frame4->atm_info.AppHLType) {
+
+ case AHLT_UNKNOWN:
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case AHLT_LANE_LE_CTRL:
+ pseudo_header->atm.subtype =
+ TRAF_ST_LANE_LE_CTRL;
+ break;
+
+ case AHLT_LANE_802_3:
+ pseudo_header->atm.subtype = TRAF_ST_LANE_802_3;
+ break;
+
+ case AHLT_LANE_802_5:
+ pseudo_header->atm.subtype = TRAF_ST_LANE_802_5;
+ break;
+
+ case AHLT_LANE_802_3_MC:
+ pseudo_header->atm.subtype =
+ TRAF_ST_LANE_802_3_MC;
+ break;
+
+ case AHLT_LANE_802_5_MC:
+ pseudo_header->atm.subtype =
+ TRAF_ST_LANE_802_5_MC;
+ break;
+
+ default:
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+ }
+ break;
+
+ case ATT_HL_ILMI:
+ pseudo_header->atm.type = TRAF_ILMI;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case ATT_HL_FRMR:
+ pseudo_header->atm.type = TRAF_FR;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case ATT_HL_SPANS:
+ pseudo_header->atm.type = TRAF_SPANS;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case ATT_HL_IPSILON:
+ pseudo_header->atm.type = TRAF_IPSILON;
+ switch (frame4->atm_info.AppHLType) {
+
+ case AHLT_UNKNOWN:
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case AHLT_IPSILON_FT0:
+ pseudo_header->atm.subtype =
+ TRAF_ST_IPSILON_FT0;
+ break;
+
+ case AHLT_IPSILON_FT1:
+ pseudo_header->atm.subtype =
+ TRAF_ST_IPSILON_FT1;
+ break;
+
+ case AHLT_IPSILON_FT2:
+ pseudo_header->atm.subtype =
+ TRAF_ST_IPSILON_FT2;
+ break;
+
+ default:
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+ }
+ break;
+
+ default:
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+ }
+ break;
+
+ case ATT_AAL_USER:
+ pseudo_header->atm.aal = AAL_USER;
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case ATT_AAL_SIGNALLING:
+ pseudo_header->atm.aal = AAL_SIGNALLING;
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ case ATT_OAMCELL:
+ pseudo_header->atm.aal = AAL_OAMCELL;
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+
+ default:
+ pseudo_header->atm.aal = AAL_UNKNOWN;
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+ break;
+ }
+ pseudo_header->atm.vpi = vpi;
+ pseudo_header->atm.vci = vci;
+ pseudo_header->atm.channel = pletohs(&frame4->atm_info.channel);
+ pseudo_header->atm.cells = pletohs(&frame4->atm_info.cells);
+ pseudo_header->atm.aal5t_u2u = pletohs(&frame4->atm_info.Trailer.aal5t_u2u);
+ pseudo_header->atm.aal5t_len = pletohs(&frame4->atm_info.Trailer.aal5t_len);
+ pseudo_header->atm.aal5t_chksum = pletohl(&frame4->atm_info.Trailer.aal5t_chksum);
}
-static int ngsniffer_read_frame6(wtap *wth, gboolean is_random,
+static gboolean ngsniffer_read_frame6(wtap *wth, gboolean is_random,
struct frame6_rec *frame6, int *err)
{
int bytes_read;
if (bytes_read != sizeof *frame6) {
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
- return -1;
+ return FALSE;
}
- return 0;
+ return TRUE;
}
-static void set_pseudo_header_frame6(union wtap_pseudo_header *pseudo_header,
- struct frame6_rec *frame6)
+static void set_pseudo_header_frame6(
+ union wtap_pseudo_header *pseudo_header _U_,
+ struct frame6_rec *frame6 _U_)
{
/* XXX - Once the frame format is divined, something will most likely go here */
}
-static int ngsniffer_read_rec_data(wtap *wth, gboolean is_random, u_char *pd,
- int length, int *err)
+static gboolean ngsniffer_read_rec_data(wtap *wth, gboolean is_random,
+ guchar *pd, int length, int *err)
{
int bytes_read;
if (bytes_read != length) {
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
- return -1;
+ return FALSE;
}
- return 0;
+ return TRUE;
}
static void fix_pseudo_header(wtap *wth,
}
}
-static void free_blob(gpointer data, gpointer user_data)
+static void free_blob(gpointer data, gpointer user_data _U_)
{
g_free(data);
}
+/* Close stuff used by the random I/O stream, if any, and free up any
+ private data structures. (If there's a "sequential_close" routine
+ for a capture file type, it'll be called before the "close" routine
+ is called, so we don't have to free the sequential buffer here.) */
static void ngsniffer_close(wtap *wth)
{
- if (wth->capture.ngsniffer->seq.buf != NULL)
- g_free(wth->capture.ngsniffer->seq.buf);
if (wth->capture.ngsniffer->rand.buf != NULL)
g_free(wth->capture.ngsniffer->rand.buf);
if (wth->capture.ngsniffer->first_blob != NULL) {
0, /* WTAP_ENCAP_TOKEN_RING */
-1, /* WTAP_ENCAP_SLIP -> unsupported */
7, /* WTAP_ENCAP_PPP -> Internetwork analyzer (synchronous) FIXME ! */
- -1, /* WTAP_ENCAP_FDDI -> unsupported */
+ 9, /* WTAP_ENCAP_FDDI */
9, /* WTAP_ENCAP_FDDI_BITSWAPPED */
-1, /* WTAP_ENCAP_RAW_IP -> unsupported */
2, /* WTAP_ENCAP_ARCNET */
/* Returns 0 if we could write the specified encapsulation type,
an error indication otherwise. */
-int ngsniffer_dump_can_write_encap(int filetype, int encap)
+int ngsniffer_dump_can_write_encap(int encap)
{
/* Per-packet encapsulations aren't supported. */
if (encap == WTAP_ENCAP_PER_PACKET)
return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
- if (encap < 0 || encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
+ if (encap < 0 || (unsigned)encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
return WTAP_ERR_UNSUPPORTED_ENCAP;
return 0;
/* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
failure */
-gboolean ngsniffer_dump_open(wtap_dumper *wdh, int *err)
+gboolean ngsniffer_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err)
{
- int nwritten;
+ size_t nwritten;
char buf[6] = {REC_VERS, 0x00, 0x12, 0x00, 0x00, 0x00}; /* version record */
/* This is a sniffer file */
/* Write the file header. */
nwritten = fwrite(ngsniffer_magic, 1, sizeof ngsniffer_magic, wdh->fh);
if (nwritten != sizeof ngsniffer_magic) {
- if (nwritten < 0)
+ if (nwritten == 0 && ferror(wdh->fh))
*err = errno;
else
*err = WTAP_ERR_SHORT_WRITE;
}
nwritten = fwrite(buf, 1, 6, wdh->fh);
if (nwritten != 6) {
- if (nwritten < 0)
+ if (nwritten == 0 && ferror(wdh->fh))
*err = errno;
else
*err = WTAP_ERR_SHORT_WRITE;
/* Write a record for a packet to a dump file.
Returns TRUE on success, FALSE on failure. */
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)
+ const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
{
ngsniffer_dump_t *priv = wdh->dump.ngsniffer;
struct frame2_rec rec_hdr;
- int nwritten;
+ size_t nwritten;
char buf[6];
double t;
guint16 t_low, t_med, t_high;
if (priv->first_frame) {
priv->first_frame=FALSE;
tm = localtime(&phdr->ts.tv_sec);
- start_date = (tm->tm_year - (1980 - 1900)) << 9;
- start_date |= (tm->tm_mon + 1) << 5;
- start_date |= tm->tm_mday;
- /* record the start date, not the start time */
- priv->start = phdr->ts.tv_sec - (3600*tm->tm_hour + 60*tm->tm_min + tm->tm_sec);
+ if (tm != NULL) {
+ start_date = (tm->tm_year - (1980 - 1900)) << 9;
+ start_date |= (tm->tm_mon + 1) << 5;
+ start_date |= tm->tm_mday;
+ /* record the start date, not the start time */
+ priv->start = phdr->ts.tv_sec - (3600*tm->tm_hour + 60*tm->tm_min + tm->tm_sec);
+ } else {
+ start_date = 0;
+ priv->start = 0;
+ }
/* "sniffer" version ? */
maj_vers = 4;
version.rsvd[1] = 0;
nwritten = fwrite(&version, 1, sizeof version, wdh->fh);
if (nwritten != sizeof version) {
- if (nwritten < 0)
+ if (nwritten == 0 && ferror(wdh->fh))
*err = errno;
else
*err = WTAP_ERR_SHORT_WRITE;
buf[5] = 0x00;
nwritten = fwrite(buf, 1, 6, wdh->fh);
if (nwritten != 6) {
- if (nwritten < 0)
+ if (nwritten == 0 && ferror(wdh->fh))
*err = errno;
else
*err = WTAP_ERR_SHORT_WRITE;
rec_hdr.time_high = htoles(t_high);
rec_hdr.size = htoles(phdr->caplen);
if (wdh->encap == WTAP_ENCAP_LAPB || wdh->encap == WTAP_ENCAP_PPP)
- rec_hdr.fs = (pseudo_header->x25.flags & 0x80) ? 0x00 : 0x80;
+ rec_hdr.fs = (pseudo_header->x25.flags & FROM_DCE) ? 0x00 : 0x80;
else
rec_hdr.fs = 0;
rec_hdr.flags = 0;
rec_hdr.rsvd = 0;
nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, wdh->fh);
if (nwritten != sizeof rec_hdr) {
- if (nwritten < 0)
+ if (nwritten == 0 && ferror(wdh->fh))
*err = errno;
else
*err = WTAP_ERR_SHORT_WRITE;
}
nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
if (nwritten != phdr->caplen) {
- if (nwritten < 0)
+ if (nwritten == 0 && ferror(wdh->fh))
*err = errno;
else
*err = WTAP_ERR_SHORT_WRITE;
{
/* EOF record */
char buf[6] = {REC_EOF, 0x00, 0x00, 0x00, 0x00, 0x00};
- int nwritten;
+ size_t nwritten;
nwritten = fwrite(buf, 1, 6, wdh->fh);
if (nwritten != 6) {
- if (nwritten < 0)
- *err = errno;
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ if (err != NULL) {
+ if (nwritten == 0 && ferror(wdh->fh))
+ *err = errno;
+ else
+ *err = WTAP_ERR_SHORT_WRITE;
+ }
return FALSE;
}
return TRUE;
Return value is the number of bytes in outbuf on return.
*/
static int
-SnifferDecompress( unsigned char * inbuf, size_t inlen,
+SnifferDecompress( unsigned char * inbuf, size_t inlen,
unsigned char * outbuf, size_t outlen, int *err )
{
unsigned char * pin = inbuf;
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 )
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
+ 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 */
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
+ 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 */
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
+ 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 )
return -1;
bytes_left = comp_stream->nbytes - comp_stream->nextout;
}
-
+
bytes_to_copy = copybytes;
if (bytes_to_copy > bytes_left)
bytes_to_copy = bytes_left;
/* Seek in the sequential data stream; we can only seek forward, and we
do it on compressed files by skipping forward. */
static long
-ng_file_seek_seq(wtap *wth, long offset, int whence)
+ng_file_seek_seq(wtap *wth, long offset, int whence, int *err)
{
- long delta;
- char buf[65536];
- long amount_to_read;
- int err;
+ long delta;
+ char buf[65536];
+ long amount_to_read;
- if (wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED)
- return file_seek(wth->fh, offset, whence);
+ if (wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED)
+ return file_seek(wth->fh, offset, whence, err);
switch (whence) {
/* Ok, now read and discard "delta" bytes. */
while (delta != 0) {
amount_to_read = delta;
- if (amount_to_read > sizeof buf)
+ if ((unsigned long)amount_to_read > sizeof buf)
amount_to_read = sizeof buf;
- if (ng_file_read(buf, 1, amount_to_read, wth, FALSE, &err) < 0)
+ if (ng_file_read(buf, 1, amount_to_read, wth, FALSE, err) < 0)
return -1; /* error */
delta -= amount_to_read;
}
position within the blob we have in memory (whether it's the blob we
already had in memory or, if necessary, the one we read in). */
static long
-ng_file_seek_rand(wtap *wth, long offset, int whence)
+ng_file_seek_rand(wtap *wth, long offset, int whence, int *err)
{
- ngsniffer_t *ngsniffer;
- long delta;
- int err;
- GList *new, *next;
- blob_info_t *next_blob, *new_blob;
-
- if (wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED)
- return file_seek(wth->random_fh, 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;
+ ngsniffer_t *ngsniffer;
+ long delta;
+ GList *new, *next;
+ blob_info_t *next_blob, *new_blob;
- 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. */
+ if (wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED)
+ return file_seek(wth->random_fh, offset, whence, err);
ngsniffer = wth->capture.ngsniffer;
if (delta > 0) {
/* We're going forwards.
Is the place to which we're seeking within the current buffer? */
- if (ngsniffer->rand.nextout + delta >= ngsniffer->rand.nbytes) {
+ if ((size_t)(ngsniffer->rand.nextout + delta) >= ngsniffer->rand.nbytes) {
/* No. Search for a blob that contains the target offset in
the uncompressed byte stream, starting with the blob
following the current blob. */
/* Seek in the compressed file to the offset in the compressed file
of the beginning of that blob. */
- if (file_seek(wth->random_fh, new_blob->blob_comp_offset, SEEK_SET) == -1)
+ if (file_seek(wth->random_fh, new_blob->blob_comp_offset, SEEK_SET, err) == -1)
return -1;
/* Make the blob we found the current one. */
ngsniffer->rand.comp_offset = new_blob->blob_comp_offset;
/* Now fill the buffer. */
- if (read_blob(wth->random_fh, &ngsniffer->rand, &err) < 0)
+ if (read_blob(wth->random_fh, &ngsniffer->rand, err) < 0)
return -1;
/* Set "delta" to the amount to move within this blob; it had
the blob, as otherwise it'd mean we need to seek before
the beginning or after the end of this blob. */
delta = offset - ngsniffer->rand.uncomp_offset;
- g_assert(delta >= 0 && delta < ngsniffer->rand.nbytes);
+ g_assert(delta >= 0 && (unsigned long)delta < ngsniffer->rand.nbytes);
}
/* OK, the place to which we're seeking is in the buffer; adjust