Removed trailing whitespaces from .h and .c files using the
[obnox/wireshark/wip.git] / wiretap / ngsniffer.c
index aa543caee12c0f0324f4f276c8a2faed5a0936cc..8d45b07666049efe0c3c733512a2ae399a7b289c 100644 (file)
@@ -1,24 +1,23 @@
 /* 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
@@ -285,31 +284,32 @@ struct frame6_rec {
 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 );
@@ -317,8 +317,8 @@ static int ng_file_read(void *buffer, size_t elementsize, size_t numelements,
     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)
 {
@@ -348,8 +348,6 @@ 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) {
@@ -436,9 +434,16 @@ int ngsniffer_open(wtap *wth, int *err)
                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;
@@ -452,8 +457,10 @@ int ngsniffer_open(wtap *wth, int *err)
         * 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));
@@ -478,9 +485,8 @@ int ngsniffer_open(wtap *wth, int *err)
        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);
 
@@ -545,6 +551,9 @@ skip_header_records(wtap *wth, int *err, gint16 version)
 
                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
@@ -553,7 +562,8 @@ skip_header_records(wtap *wth, int *err, gint16 version)
                         * 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;
                }
 
@@ -583,11 +593,9 @@ skip_header_records(wtap *wth, int *err, gint16 version)
                         * 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) {
@@ -595,10 +603,18 @@ skip_header_records(wtap *wth, int *err, gint16 version)
                                        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
@@ -624,23 +640,17 @@ skip_header_records(wtap *wth, int *err, gint16 version)
                                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;
@@ -649,7 +659,7 @@ static gboolean ngsniffer_read(wtap *wth, int *err, int *data_offset)
        struct frame6_rec frame6;
        double  t;
        guint16 time_low, time_med, time_high, true_size, size;
-       u_char  *pd;
+       guchar  *pd;
 
        for (;;) {
                /*
@@ -678,8 +688,7 @@ static gboolean ngsniffer_read(wtap *wth, int *err, int *data_offset)
                        }
 
                        /* 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;
                        }
@@ -710,7 +719,10 @@ static gboolean ngsniffer_read(wtap *wth, int *err, int *data_offset)
                        }
 
                        /* 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);
@@ -739,7 +751,10 @@ static gboolean ngsniffer_read(wtap *wth, int *err, int *data_offset)
                        }
 
                        /* 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);
@@ -775,7 +790,8 @@ static gboolean ngsniffer_read(wtap *wth, int *err, int *data_offset)
                 * 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;
        }
 
@@ -801,7 +817,7 @@ found:
         */
        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;
 
@@ -853,32 +869,36 @@ found:
        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 */
@@ -888,7 +908,10 @@ static int ngsniffer_seek_read(wtap *wth, int seek_off,
 
        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 */
 
@@ -897,7 +920,10 @@ static int ngsniffer_seek_read(wtap *wth, int seek_off,
 
        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 */
 
@@ -909,7 +935,7 @@ static int ngsniffer_seek_read(wtap *wth, int seek_off,
                 * "Can't happen".
                 */
                g_assert_not_reached();
-               return -1;
+               return FALSE;
        }
 
        /*
@@ -921,7 +947,7 @@ static int ngsniffer_seek_read(wtap *wth, int seek_off,
        /*
         * 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,
@@ -956,7 +982,7 @@ 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;
@@ -967,9 +993,9 @@ static int ngsniffer_read_frame2(wtap *wth, gboolean is_random,
        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,
@@ -996,10 +1022,10 @@ 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;
@@ -1010,26 +1036,256 @@ static int ngsniffer_read_frame4(wtap *wth, gboolean is_random,
        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;
@@ -1040,19 +1296,20 @@ static int ngsniffer_read_frame6(wtap *wth, gboolean is_random,
        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;
 
@@ -1061,9 +1318,9 @@ static int ngsniffer_read_rec_data(wtap *wth, gboolean is_random, u_char *pd,
        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,
@@ -1090,15 +1347,17 @@ static void ngsniffer_sequential_close(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) {
@@ -1114,7 +1373,7 @@ static const int wtap_encap[] = {
     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 */
@@ -1128,13 +1387,13 @@ static const int wtap_encap[] = {
 
 /* 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;
@@ -1142,9 +1401,9 @@ int ngsniffer_dump_can_write_encap(int filetype, int encap)
 
 /* 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 */
@@ -1158,7 +1417,7 @@ gboolean ngsniffer_dump_open(wtap_dumper *wdh, int *err)
     /* 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;
@@ -1166,7 +1425,7 @@ gboolean ngsniffer_dump_open(wtap_dumper *wdh, int *err)
     }
     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;
@@ -1179,11 +1438,11 @@ gboolean ngsniffer_dump_open(wtap_dumper *wdh, int *err)
 /* 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;
@@ -1199,11 +1458,16 @@ static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
     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;
@@ -1222,7 +1486,7 @@ static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
        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;
@@ -1238,7 +1502,7 @@ static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
     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;
@@ -1254,7 +1518,7 @@ static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
     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;
@@ -1262,7 +1526,7 @@ static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
     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;
@@ -1270,7 +1534,7 @@ static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
     }
     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;
@@ -1285,14 +1549,16 @@ static gboolean ngsniffer_dump_close(wtap_dumper *wdh, int *err)
 {
     /* 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;
@@ -1315,7 +1581,7 @@ static gboolean ngsniffer_dump_close(wtap_dumper *wdh, int *err)
    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;
@@ -1376,7 +1642,7 @@ SnifferDecompress( unsigned char * inbuf, size_t inlen,
                     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 )
@@ -1391,12 +1657,12 @@ SnifferDecompress( unsigned char * inbuf, size_t inlen,
                 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 */
@@ -1418,12 +1684,12 @@ SnifferDecompress( unsigned char * inbuf, size_t inlen,
                 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 */
@@ -1454,12 +1720,12 @@ SnifferDecompress( unsigned char * inbuf, size_t inlen,
                 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 )
@@ -1597,7 +1863,7 @@ ng_file_read(void *buffer, size_t elementsize, size_t numelements, wtap *wth,
                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;
@@ -1672,15 +1938,14 @@ read_blob(FILE_T infile, ngsniffer_comp_stream_t *comp_stream, int *err)
 /* 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) {
 
@@ -1702,9 +1967,9 @@ ng_file_seek_seq(wtap *wth, long offset, int 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;
     }
@@ -1720,33 +1985,15 @@ ng_file_seek_seq(wtap *wth, long offset, int whence)
    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;
 
@@ -1772,7 +2019,7 @@ ng_file_seek_rand(wtap *wth, long offset, int whence)
     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. */
@@ -1821,7 +2068,7 @@ ng_file_seek_rand(wtap *wth, long offset, int whence)
 
        /* 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. */
@@ -1833,7 +2080,7 @@ ng_file_seek_rand(wtap *wth, long offset, int whence)
        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
@@ -1841,7 +2088,7 @@ ng_file_seek_rand(wtap *wth, long offset, int whence)
           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