Move the new files to the same places as in automake.
[obnox/wireshark/wip.git] / wiretap / lanalyzer.c
index 1621772c6fff7ab303adc46889abc9c14c48ef21..75331c665b48778a54ceeff803917144d12e04bb 100644 (file)
 /* The LANalyzer format is documented (at least in part) in Novell document
    TID022037, which can be found at, among other places:
 
-       http://secinf.net/info/nw/lan/trace.txt
+       http://www.windowsecurity.com/whitepapers/Description_of_the_LANalysers_output_file.html
  */
 
+/*    Record header format */
+
+typedef struct {
+       guint8  record_type[2];
+       guint8  record_length[2];
+} LA_RecordHeader;
+
+#define LA_RecordHeaderSize 4
+
+/*    Record type codes:                */
+
+#define     RT_HeaderRegular       0x1001
+#define     RT_HeaderCyclic        0x1007
+#define     RT_RxChannelName       0x1006
+#define     RT_TxChannelName       0x100b
+#define     RT_FilterName          0x1032
+#define     RT_RxTemplateName      0x1035
+#define     RT_TxTemplateName      0x1036
+#define     RT_DisplayOptions      0x100a
+#define     RT_Summary             0x1002
+#define     RT_SubfileSummary      0x1003
+#define     RT_CyclicInformation   0x1009
+#define     RT_Index               0x1004
+#define     RT_PacketData          0x1005
+
+#define     LA_ProFileLimit       (1024 * 1024 * 32)
+
+typedef guint8  Eadr[6];
+typedef guint16 TimeStamp[3];  /* 0.5 microseconds since start of trace */
+
+/*
+ * These records have only 2-byte alignment for 4-byte quantities,
+ * so the structures aren't necessarily valid; they're kept as comments
+ * for reference purposes.
+ */
+
+/*
+ * typedef struct {
+ *       guint8      day;
+ *       guint8      mon;
+ *       gint16      year;
+ *       } Date;
+ */
+
+/*
+ * typedef struct {
+ *       guint8      second;
+ *       guint8      minute;
+ *       guint8      hour;
+ *       guint8      day;
+ *       gint16      reserved;
+ *       } Time;
+ */
+
+/*
+ * RT_Summary:
+ *
+ * typedef struct {
+ *       Date        datcre;
+ *       Date        datclo;
+ *       Time        timeopn;
+ *       Time        timeclo;
+ *       Eadr        statadr;
+ *       gint16      mxseqno;
+ *       gint16      slcoff;
+ *       gint16      mxslc;
+ *       gint32      totpktt;
+ *       gint32      statrg;
+ *       gint32      stptrg;
+ *       gint32      mxpkta[36];
+ *       gint16      board_type;
+ *       gint16      board_version;
+ *       gint8       reserved[18];
+ *       } Summary;
+ */
+
+#define SummarySize (18+22+(4*36)+6+6+6+4+4)
+
+/*
+ * typedef struct {
+ *       gint16      rid;
+ *       gint16      rlen;
+ *       Summary     s;
+ *       } LA_SummaryRecord;
+ */
+
+#define LA_SummaryRecordSize (SummarySize + 4)
+
 /* LANalyzer board types (which indicate the type of network on which
    the capture was done). */
 #define BOARD_325              226     /* LANalyzer 325 (Ethernet) */
 #define BOARD_325TR            227     /* LANalyzer 325TR (Token-ring) */
 
 
+/*
+ * typedef struct {
+ *       gint16      rid;
+ *       gint16      rlen;
+ *       gint16      seqno;
+ *       gint32      totpktf;
+ *       } LA_SubfileSummaryRecord;
+ */
+
+#define LA_SubfileSummaryRecordSize 10
+
+
+#define LA_IndexSize 500
+
+/*
+ * typedef struct {
+ *       gint16      rid;
+ *       gint16      rlen;
+ *       gint16      idxsp;                    = LA_IndexSize
+ *       gint16      idxct;
+ *       gint8       idxgranu;
+ *       gint8       idxvd;
+ *       gint32      trcidx[LA_IndexSize + 2]; +2 undocumented but used by La 2.2
+ *       } LA_IndexRecord;
+ */
+
+#define LA_IndexRecordSize (10 + 4 * (LA_IndexSize + 2))
+
+
+/*
+ * typedef struct {
+ *       guint16     rx_channels;
+ *       guint16     rx_errors;
+ *       gint16      rx_frm_len;
+ *       gint16      rx_frm_sln;
+ *       TimeStamp   rx_time;
+ *       guint32     pktno;
+ *       gint16      prvlen;
+ *       gint16      offset;
+ *       gint16      tx_errs;
+ *       gint16      rx_filters;
+ *       gint8       unused[2];
+ *       gint16      hwcolls;
+ *       gint16      hwcollschans;
+ *       Packetdata ....;
+ *       } LA_PacketRecord;
+ */
+
+#define LA_PacketRecordSize 32
+
+typedef struct {
+      gboolean        init;
+      struct timeval  start;
+      guint32         pkts;
+      int             encap;
+      int             lastlen;
+      } LA_TmpInfo;
+
 static const guint8 LA_HeaderRegularFake[] = {
 0x01,0x10,0x4c,0x00,0x01,0x05,0x54,0x72,0x61,0x63,0x65,0x20,0x44,0x69,0x73,0x70,
 0x6c,0x61,0x79,0x20,0x54,0x72,0x61,0x63,0x65,0x20,0x46,0x69,0x6c,0x65,0x00,0x00,
@@ -117,92 +263,123 @@ static const guint8 LA_CyclicInformationFake[] = {
 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
       };
 
+typedef struct {
+       time_t  start;
+} lanalyzer_t;
+
 static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info,
     gint64 *data_offset);
 static gboolean lanalyzer_seek_read(wtap *wth, gint64 seek_off,
-    union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
+    union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
     int *err, gchar **err_info);
-static void     lanalyzer_close(wtap *wth);
 static gboolean lanalyzer_dump_close(wtap_dumper *wdh, int *err);
 
 int lanalyzer_open(wtap *wth, int *err, gchar **err_info)
 {
        int bytes_read;
-       char LE_record_type[2];
-       char LE_record_length[2];
+       LA_RecordHeader rec_header;
+       char header_fixed[2];
+       char *comment;
        char summary[210];
        guint16 board_type, mxslc;
        guint16 record_type, record_length;
        guint8 cr_day, cr_month;
        guint16 cr_year;
        struct tm tm;
+       lanalyzer_t *lanalyzer;
 
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(LE_record_type, 1, 2, wth->fh);
-       bytes_read += file_read(LE_record_length, 1, 2, wth->fh);
-       if (bytes_read != 4) {
-               *err = file_error(wth->fh);
+       bytes_read = file_read(&rec_header, LA_RecordHeaderSize, wth->fh);
+       if (bytes_read != LA_RecordHeaderSize) {
+               *err = file_error(wth->fh, err_info);
                if (*err != 0)
                        return -1;
                return 0;
        }
-       wth->data_offset += 4;
-       record_type = pletohs(LE_record_type);
-       record_length = pletohs(LE_record_length); /* make sure to do this for while() loop */
+       wth->data_offset += LA_RecordHeaderSize;
+       record_type = pletohs(rec_header.record_type);
+       record_length = pletohs(rec_header.record_length); /* make sure to do this for while() loop */
 
        if (record_type != RT_HeaderRegular && record_type != RT_HeaderCyclic) {
                return 0;
        }
 
+       /* Read the major and minor version numbers */
+       if (record_length < 2) {
+               /* Not enough room for the major and minor version numbers. */
+               *err = WTAP_ERR_BAD_FILE;
+               *err_info = g_strdup_printf("lanalyzer: trace header record length %u < 2",
+                   record_length);
+               return -1;
+       }
+       bytes_read = file_read(&header_fixed, sizeof header_fixed, wth->fh);
+       if (bytes_read != sizeof header_fixed) {
+               *err = file_error(wth->fh, err_info);
+               if (*err == 0)
+                       *err = WTAP_ERR_SHORT_READ;
+               return -1;
+       }
+       wth->data_offset += sizeof header_fixed;
+       record_length -= sizeof header_fixed;
+
+       if (record_length != 0) {
+               /* Read the rest of the record as a comment. */
+               comment = g_malloc(record_length + 1);
+               bytes_read = file_read(comment, record_length, wth->fh);
+               if (bytes_read != record_length) {
+                       *err = file_error(wth->fh, err_info);
+                       if (*err == 0)
+                               *err = WTAP_ERR_SHORT_READ;
+                       return -1;
+               }
+               comment[record_length] = '\0';
+               wth->data_offset += record_length;
+               wth->shb_hdr.opt_comment = comment;
+       }
+
        /* If we made it this far, then the file is a LANAlyzer file.
         * Let's get some info from it. Note that we get wth->snapshot_length
         * from a record later in the file. */
        wth->file_type = WTAP_FILE_LANALYZER;
-       wth->capture.lanalyzer = g_malloc(sizeof(lanalyzer_t));
+       lanalyzer = (lanalyzer_t *)g_malloc(sizeof(lanalyzer_t));;
+       wth->priv = (void *)lanalyzer;
        wth->subtype_read = lanalyzer_read;
        wth->subtype_seek_read = lanalyzer_seek_read;
-       wth->subtype_close = lanalyzer_close;
        wth->snapshot_length = 0;
        wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
 
        /* Read records until we find the start of packets */
        while (1) {
-               if (file_seek(wth->fh, record_length, SEEK_CUR, err) == -1) {
-                       g_free(wth->capture.lanalyzer);
-                       return -1;
-               }
-               wth->data_offset += record_length;
                errno = WTAP_ERR_CANT_READ;
-               bytes_read = file_read(LE_record_type, 1, 2, wth->fh);
-               bytes_read += file_read(LE_record_length, 1, 2, wth->fh);
-               if (bytes_read != 4) {
-                       *err = file_error(wth->fh);
+               bytes_read = file_read(&rec_header, LA_RecordHeaderSize, wth->fh);
+               if (bytes_read != LA_RecordHeaderSize) {
+                       *err = file_error(wth->fh, err_info);
                        if (*err != 0) {
-                               g_free(wth->capture.lanalyzer);
+                               g_free(wth->priv);
                                return -1;
                        }
-                       g_free(wth->capture.lanalyzer);
+                       g_free(wth->priv);
                        return 0;
                }
-               wth->data_offset += 4;
+               wth->data_offset += LA_RecordHeaderSize;
 
-               record_type = pletohs(LE_record_type);
-               record_length = pletohs(LE_record_length);
+               record_type = pletohs(rec_header.record_type);
+               record_length = pletohs(rec_header.record_length);
 
                /*g_message("Record 0x%04X Length %d", record_type, record_length);*/
                switch (record_type) {
                        /* Trace Summary Record */
                        case RT_Summary:
                                errno = WTAP_ERR_CANT_READ;
-                               bytes_read = file_read(summary, 1, sizeof summary,
+                               bytes_read = file_read(summary, sizeof summary,
                                    wth->fh);
                                if (bytes_read != sizeof summary) {
-                                       *err = file_error(wth->fh);
+                                       *err = file_error(wth->fh, err_info);
                                        if (*err != 0) {
-                                               g_free(wth->capture.lanalyzer);
+                                               g_free(wth->priv);
                                                return -1;
                                        }
-                                       g_free(wth->capture.lanalyzer);
+                                       g_free(wth->priv);
                                        return 0;
                                }
                                wth->data_offset += sizeof summary;
@@ -229,13 +406,12 @@ int lanalyzer_open(wtap *wth, int *err, gchar **err_info)
                                tm.tm_min = 0;
                                tm.tm_sec = 0;
                                tm.tm_isdst = -1;
-                               wth->capture.lanalyzer->start = mktime(&tm);
+                               lanalyzer->start = mktime(&tm);
                                /*g_message("Day %d Month %d Year %d", tm.tm_mday,
                                                tm.tm_mon, tm.tm_year);*/
                                mxslc = pletohs(&summary[30]);
                                wth->snapshot_length = mxslc;
 
-                               record_length = 0; /* to fake the next iteration of while() */
                                board_type = pletohs(&summary[188]);
                                switch (board_type) {
                                        case BOARD_325:
@@ -245,7 +421,7 @@ int lanalyzer_open(wtap *wth, int *err, gchar **err_info)
                                                wth->file_encap = WTAP_ENCAP_TOKEN_RING;
                                                break;
                                        default:
-                                               g_free(wth->capture.lanalyzer);
+                                               g_free(wth->priv);
                                                *err = WTAP_ERR_UNSUPPORTED_ENCAP;
                                                *err_info = g_strdup_printf("lanalyzer: board type %u unknown",
                                                    board_type);
@@ -255,17 +431,22 @@ int lanalyzer_open(wtap *wth, int *err, gchar **err_info)
 
                        /* Trace Packet Data Record */
                        case RT_PacketData:
-                               /* Go back header number oytes so that lanalyzer_read
+                               /* Go back header number of bytes so that lanalyzer_read
                                 * can read this header */
-                               if (file_seek(wth->fh, -bytes_read, SEEK_CUR, err) == -1) {
-                                       g_free(wth->capture.lanalyzer);
+                               if (file_seek(wth->fh, -LA_RecordHeaderSize, SEEK_CUR, err) == -1) {
+                                       g_free(wth->priv);
                                        return -1;
                                }
-                               wth->data_offset -= bytes_read;
+                               wth->data_offset -= LA_RecordHeaderSize;
                                return 1;
 
                        default:
-                               ; /* no action */
+                               if (file_seek(wth->fh, record_length, SEEK_CUR, err) == -1) {
+                                       g_free(wth->priv);
+                                       return -1;
+                               }
+                               wth->data_offset += record_length;
+                               break;
                }
        }
 }
@@ -285,21 +466,22 @@ static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info,
        guint16         time_low, time_med, time_high, true_size;
        guint64         t;
        time_t          tsecs;
+       lanalyzer_t     *lanalyzer;
 
        /* read the record type and length. */
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(LE_record_type, 1, 2, wth->fh);
+       bytes_read = file_read(LE_record_type, 2, wth->fh);
        if (bytes_read != 2) {
-               *err = file_error(wth->fh);
+               *err = file_error(wth->fh, err_info);
                if (*err == 0 && bytes_read != 0) {
                        *err = WTAP_ERR_SHORT_READ;
                }
                return FALSE;
        }
        wth->data_offset += 2;
-       bytes_read = file_read(LE_record_length, 1, 2, wth->fh);
+       bytes_read = file_read(LE_record_length, 2, wth->fh);
        if (bytes_read != 2) {
-               *err = file_error(wth->fh);
+               *err = file_error(wth->fh, err_info);
                if (*err == 0)
                        *err = WTAP_ERR_SHORT_READ;
                return FALSE;
@@ -313,20 +495,30 @@ static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info,
         * the middle of reading packets.  If any other record type exists
         * after a Trace Packet Data Record, mark it as an error. */
        if (record_type != RT_PacketData) {
-               *err = WTAP_ERR_BAD_RECORD;
+               *err = WTAP_ERR_BAD_FILE;
                *err_info = g_strdup_printf("lanalyzer: record type %u seen after trace summary record",
                    record_type);
                return FALSE;
        }
        else {
+               if (record_length < DESCRIPTOR_LEN) {
+                       /*
+                        * Uh-oh, the record isn't big enough to even have a
+                        * descriptor.
+                        */
+                       *err = WTAP_ERR_BAD_FILE;
+                       *err_info = g_strdup_printf("lanalyzer: file has a %u-byte record, too small to have even a packet descriptor",
+                           record_length);
+                       return FALSE;
+               }
                packet_size = record_length - DESCRIPTOR_LEN;
        }
 
        /* Read the descriptor data */
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(descriptor, 1, DESCRIPTOR_LEN, wth->fh);
+       bytes_read = file_read(descriptor, DESCRIPTOR_LEN, wth->fh);
        if (bytes_read != DESCRIPTOR_LEN) {
-               *err = file_error(wth->fh);
+               *err = file_error(wth->fh, err_info);
                if (*err == 0)
                        *err = WTAP_ERR_SHORT_READ;
                return FALSE;
@@ -337,11 +529,11 @@ static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info,
        buffer_assure_space(wth->frame_buffer, packet_size);
        *data_offset = wth->data_offset;
        errno = WTAP_ERR_CANT_READ;
-       bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1,
+       bytes_read = file_read(buffer_start_ptr(wth->frame_buffer),
                packet_size, wth->fh);
 
        if (bytes_read != packet_size) {
-               *err = file_error(wth->fh);
+               *err = file_error(wth->fh, err_info);
                if (*err == 0)
                        *err = WTAP_ERR_SHORT_READ;
                return FALSE;
@@ -359,18 +551,21 @@ static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info,
                /*
                 * Yes - treat this as an error.
                 */
-               *err = WTAP_ERR_BAD_RECORD;
+               *err = WTAP_ERR_BAD_FILE;
                *err_info = g_strdup("lanalyzer: Record length is less than packet size");
                return FALSE;
        }
 
+       wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
+
        time_low = pletohs(&descriptor[8]);
        time_med = pletohs(&descriptor[10]);
        time_high = pletohs(&descriptor[12]);
        t = (((guint64)time_low) << 0) + (((guint64)time_med) << 16) +
            (((guint64)time_high) << 32);
        tsecs = (time_t) (t/2000000);
-       wth->phdr.ts.secs = tsecs + wth->capture.lanalyzer->start;
+       lanalyzer = (lanalyzer_t *)wth->priv;
+       wth->phdr.ts.secs = tsecs + lanalyzer->start;
        wth->phdr.ts.nsecs = ((guint32) (t - tsecs*2000000)) * 500;
 
        if (true_size - 4 >= packet_size) {
@@ -397,8 +592,8 @@ static gboolean lanalyzer_read(wtap *wth, int *err, gchar **err_info,
 }
 
 static gboolean lanalyzer_seek_read(wtap *wth, gint64 seek_off,
-    union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
-    int *err, gchar **err_info _U_)
+    union wtap_pseudo_header *pseudo_header, guint8 *pd, int length,
+    int *err, gchar **err_info)
 {
        int bytes_read;
 
@@ -408,9 +603,9 @@ static gboolean lanalyzer_seek_read(wtap *wth, gint64 seek_off,
        /*
         * Read the packet data.
         */
-       bytes_read = file_read(pd, sizeof(guint8), length, wth->random_fh);
+       bytes_read = file_read(pd, length, wth->random_fh);
        if (bytes_read != length) {
-               *err = file_error(wth->random_fh);
+               *err = file_error(wth->random_fh, err_info);
                if (*err == 0)
                        *err = WTAP_ERR_SHORT_READ;
                return FALSE;
@@ -427,104 +622,48 @@ static gboolean lanalyzer_seek_read(wtap *wth, gint64 seek_off,
        return TRUE;
 }
 
-static void
-lanalyzer_close(wtap *wth)
-{
-       g_free(wth->capture.lanalyzer);
-}
-
-/*---------------------------------------------------
- * Returns 0 or error
- * Write one block with error control
- *---------------------------------------------------*/
-static int swrite(const void* what, guint size, FILE *hd)
-{
-       size_t nwritten;
-
-       nwritten = fwrite(what, 1, size, hd);
-       if (nwritten != size) {
-               if (nwritten == 0 && ferror(hd))
-                       return errno;
-               else
-                       return WTAP_ERR_SHORT_WRITE;
-            }
-       return 0; /* ok */
-}
-
 /*---------------------------------------------------
- * Returns 0 or error
- * Write one block with error control
+ * Returns TRUE on success, FALSE on error
+ * Write "cnt" bytes of zero with error control
  *---------------------------------------------------*/
-static int s0write(size_t cnt, FILE *hd)
+static gboolean s0write(wtap_dumper *wdh, size_t cnt, int *err)
 {
-       static guint8 z64[64];
-       size_t nwritten;
+       static const guint8 z64[64];
        size_t snack;
 
        while (cnt) {
-            snack = cnt > 64 ? 64 : cnt;
-            nwritten = fwrite(z64, 1, snack, hd);
-            if (nwritten != snack) {
-                     if (nwritten == 0 && ferror(hd))
-                             return errno;
-                     else
-                             return WTAP_ERR_SHORT_WRITE;
-                  }
-            cnt -= snack;
-            }
-       return 0; /* ok */
+               snack = cnt > 64 ? 64 : cnt;
+
+               if (!wtap_dump_file_write(wdh, z64, snack, err))
+                       return FALSE;
+               cnt -= snack;
+       }
+       return TRUE; /* ok */
 }
 
 /*---------------------------------------------------
- * Returns 0 or error
- * Write one block with error control
+ * Returns TRUE on success, FALSE on error
+ * Write an 8-bit value with error control
  *---------------------------------------------------*/
-static int s8write(const guint8 s8, FILE *hd)
+static gboolean s8write(wtap_dumper *wdh, const guint8 s8, int *err)
 {
-       size_t nwritten;
-
-       nwritten = fwrite(&s8, 1, 1, hd);
-       if (nwritten != 1) {
-               if (nwritten == 0 && ferror(hd))
-                       return errno;
-               else
-                       return WTAP_ERR_SHORT_WRITE;
-            }
-       return 0; /* ok */
+       return wtap_dump_file_write(wdh, &s8, 1, err);
 }
 /*---------------------------------------------------
- * Returns 0 or error
- * Write one block with error control
+ * Returns TRUE on success, FALSE on error
+ * Write a 16-bit value with error control
  *---------------------------------------------------*/
-static int s16write(const guint16 s16, FILE *hd)
+static gboolean s16write(wtap_dumper *wdh, const guint16 s16, int *err)
 {
-       size_t nwritten;
-
-       nwritten = fwrite(&s16, 1, 2, hd);
-       if (nwritten != 2) {
-               if (nwritten == 0 && ferror(hd))
-                       return errno;
-               else
-                       return WTAP_ERR_SHORT_WRITE;
-            }
-       return 0; /* ok */
+       return wtap_dump_file_write(wdh, &s16, 2, err);
 }
 /*---------------------------------------------------
- * Returns 0 or error
- * Write one block with error control
+ * Returns TRUE on success, FALSE on error
+ * Write a 32-bit value with error control
  *---------------------------------------------------*/
-static int s32write(const guint32 s32, FILE *hd)
+static gboolean s32write(wtap_dumper *wdh, const guint32 s32, int *err)
 {
-       size_t nwritten;
-
-       nwritten = fwrite(&s32, 1, 4, hd);
-       if (nwritten != 4) {
-               if (nwritten == 0 && ferror(hd))
-                       return errno;
-               else
-                       return WTAP_ERR_SHORT_WRITE;
-            }
-       return 0; /* ok */
+       return wtap_dump_file_write(wdh, &s32, 4, err);
 }
 /*---------------------------------------------------
  *
@@ -550,14 +689,14 @@ static void my_timersub(const struct timeval *a,
 static gboolean lanalyzer_dump(wtap_dumper *wdh,
        const struct wtap_pkthdr *phdr,
        const union wtap_pseudo_header *pseudo_header _U_,
-       const guchar *pd, int *err)
+       const guint8 *pd, int *err)
 {
       double x;
       int    i;
       int    len;
          struct timeval tv;
 
-      LA_TmpInfo *itmp = (LA_TmpInfo*)(wdh->dump.opaque);
+      LA_TmpInfo *itmp = (LA_TmpInfo*)(wdh->priv);
       struct timeval td;
       int    thisSize = phdr->caplen + LA_PacketRecordSize + LA_RecordHeaderSize;
 
@@ -569,15 +708,13 @@ static gboolean lanalyzer_dump(wtap_dumper *wdh,
 
       len = phdr->caplen + (phdr->caplen ? LA_PacketRecordSize : 0);
 
-      *err = s16write(htoles(0x1005), wdh->fh);
-      if (*err)
+      if (!s16write(wdh, htoles(0x1005), err))
             return FALSE;
-      *err = s16write(htoles(len), wdh->fh);
-      if (*err)
+      if (!s16write(wdh, htoles(len), err))
             return FALSE;
 
-         tv.tv_sec  = (long int) phdr->ts.secs;
-         tv.tv_usec = phdr->ts.nsecs / 1000;
+      tv.tv_sec  = (long int) phdr->ts.secs;
+      tv.tv_usec = phdr->ts.nsecs / 1000;
 
       if (!itmp->init) {
             /* collect some information for the
@@ -597,41 +734,32 @@ static gboolean lanalyzer_dump(wtap_dumper *wdh,
       x  += (double) td.tv_sec * 1000000;
       x  *= 2;
 
-      *err = s16write(htoles(0x0001), wdh->fh);           /* pr.rx_channels */
-      if (*err)
+      if (!s16write(wdh, htoles(0x0001), err))             /* pr.rx_channels */
             return FALSE;
-      *err = s16write(htoles(0x0008), wdh->fh);           /* pr.rx_errors   */
-      if (*err)
+      if (!s16write(wdh, htoles(0x0008), err))             /* pr.rx_errors   */
             return FALSE;
-      *err = s16write(htoles(phdr->len + 4), wdh->fh);    /* pr.rx_frm_len  */
-      if (*err)
+      if (!s16write(wdh, htoles(phdr->len + 4), err))      /* pr.rx_frm_len  */
             return FALSE;
-      *err = s16write(htoles(phdr->caplen), wdh->fh);     /* pr.rx_frm_sln  */
-      if (*err)
+      if (!s16write(wdh, htoles(phdr->caplen), err))       /* pr.rx_frm_sln  */
             return FALSE;
 
       for (i = 0; i < 3; i++) {
-            *err = s16write(htoles((guint16) x), wdh->fh);/* pr.rx_time[i]  */
-            if (*err)
+            if (!s16write(wdh, htoles((guint16) x), err))  /* pr.rx_time[i]  */
                   return FALSE;
             x /= 0xffff;
-            }
+      }
 
-      *err = s32write(htolel(++itmp->pkts), wdh->fh);      /* pr.pktno      */
-      if (*err)
+      if (!s32write(wdh, htolel(++itmp->pkts), err))       /* pr.pktno      */
             return FALSE;
-      *err = s16write(htoles(itmp->lastlen), wdh->fh);     /* pr.prlen      */
-      if (*err)
+      if (!s16write(wdh, htoles(itmp->lastlen), err))      /* pr.prlen      */
             return FALSE;
       itmp->lastlen = len;
 
-      *err = s0write(12, wdh->fh);
-      if (*err)
-               return FALSE;
+      if (!s0write(wdh, 12, err))
+            return FALSE;
 
-      *err = swrite(pd , phdr->caplen , wdh->fh);
-      if (*err)
-               return FALSE;
+      if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
+            return FALSE;
 
       wdh->bytes_dumped += thisSize;
 
@@ -661,19 +789,11 @@ int lanalyzer_dump_can_write_encap(int encap)
  * Returns TRUE on success, FALSE on failure; sets "*err" to an
  * error code on failure
  *---------------------------------------------------*/
-gboolean lanalyzer_dump_open(wtap_dumper *wdh, gboolean cant_seek, int *err)
+gboolean lanalyzer_dump_open(wtap_dumper *wdh, int *err)
 {
       int   jump;
       void  *tmp;
 
-      /* This is a LANalyzer file.  We can't fill in some fields in the
-         header until all the packets have been written, so we can't
-         write to a pipe. */
-      if (cant_seek) {
-             *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
-             return FALSE;
-            }
-
       tmp = g_malloc(sizeof(LA_TmpInfo));
       if (!tmp) {
              *err = errno;
@@ -681,9 +801,9 @@ gboolean lanalyzer_dump_open(wtap_dumper *wdh, gboolean cant_seek, int *err)
             }
 
       ((LA_TmpInfo*)tmp)->init = FALSE;
-      wdh->dump.opaque         = tmp;
-      wdh->subtype_write       = lanalyzer_dump;
-      wdh->subtype_close       = lanalyzer_dump_close;
+      wdh->priv          = tmp;
+      wdh->subtype_write = lanalyzer_dump;
+      wdh->subtype_close = lanalyzer_dump_close;
 
       /* Some of the fields in the file header aren't known yet so
        just skip over it for now.  It will be created after all
@@ -713,146 +833,127 @@ gboolean lanalyzer_dump_open(wtap_dumper *wdh, gboolean cant_seek, int *err)
  *---------------------------------------------------*/
 static gboolean lanalyzer_dump_header(wtap_dumper *wdh, int *err)
 {
-      LA_TmpInfo *itmp   = (LA_TmpInfo*)(wdh->dump.opaque);
-      struct tm  *fT     = localtime( (time_t *) &(itmp->start.tv_sec));
+      LA_TmpInfo *itmp   = (LA_TmpInfo*)(wdh->priv);
       guint16 board_type = itmp->encap == WTAP_ENCAP_TOKEN_RING
                               ? BOARD_325TR     /* LANalyzer Board Type */
                               : BOARD_325;      /* LANalyzer Board Type */
+      time_t secs;
+      struct tm *fT;
+
+      /* The secs variable is needed to work around 32/64-bit time_t issues.
+         itmp->start is a timeval struct, which declares its tv_sec field
+         (itmp->start.tv_sec) as a long (typically 32 bits). time_t can be 32
+         or 64 bits, depending on the platform. Invoking as follows could
+         pass a pointer to a 32-bit long where a pointer to a 64-bit time_t
+         is expected: localtime((time_t*) &(itmp->start.tv_sec)) */
+      secs = itmp->start.tv_sec;
+      fT = localtime(&secs);
+      if (fT == NULL)
+            return FALSE;
 
       fseek(wdh->fh, 0, SEEK_SET);
 
-      *err = swrite(&LA_HeaderRegularFake,  sizeof LA_HeaderRegularFake, wdh->fh);
-      if (*err)
+      if (!wtap_dump_file_write(wdh, &LA_HeaderRegularFake,
+                                sizeof LA_HeaderRegularFake, err))
                return FALSE;
-      *err = swrite(&LA_RxChannelNameFake , sizeof LA_RxChannelNameFake , wdh->fh);
-      if (*err)
+      if (!wtap_dump_file_write(wdh, &LA_RxChannelNameFake,
+                                sizeof LA_RxChannelNameFake, err))
                return FALSE;
-      *err = swrite(&LA_TxChannelNameFake , sizeof LA_TxChannelNameFake , wdh->fh);
-      if (*err)
+      if (!wtap_dump_file_write(wdh, &LA_TxChannelNameFake,
+                                sizeof LA_TxChannelNameFake, err))
                return FALSE;
-      *err = swrite(&LA_RxTemplateNameFake, sizeof LA_RxTemplateNameFake, wdh->fh);
-      if (*err)
+      if (!wtap_dump_file_write(wdh, &LA_RxTemplateNameFake,
+                                sizeof LA_RxTemplateNameFake, err))
                return FALSE;
-      *err = swrite(&LA_TxTemplateNameFake, sizeof LA_TxTemplateNameFake, wdh->fh);
-      if (*err)
+      if (!wtap_dump_file_write(wdh, &LA_TxTemplateNameFake,
+                                sizeof LA_TxTemplateNameFake, err))
                return FALSE;
-      *err = swrite(&LA_DisplayOptionsFake, sizeof LA_DisplayOptionsFake, wdh->fh);
-      if (*err)
+      if (!wtap_dump_file_write(wdh, &LA_DisplayOptionsFake,
+                                sizeof LA_DisplayOptionsFake, err))
                return FALSE;
       /*-----------------------------------------------------------------*/
-      *err = s16write(htoles(RT_Summary), wdh->fh);        /* rid */
-      if (*err)
+      if (!s16write(wdh, htoles(RT_Summary), err))         /* rid */
             return FALSE;
-      *err = s16write(htoles(SummarySize), wdh->fh);       /* rlen */
-      if (*err)
+      if (!s16write(wdh, htoles(SummarySize), err))        /* rlen */
             return FALSE;
-      *err = s8write((guint8) fT->tm_mday, wdh->fh);       /* s.datcre.day */
-      if (*err)
+      if (!s8write(wdh, (guint8) fT->tm_mday, err))        /* s.datcre.day */
             return FALSE;
-      *err = s8write((guint8) (fT->tm_mon+1), wdh->fh);    /* s.datcre.mon */
-      if (*err)
+      if (!s8write(wdh, (guint8) (fT->tm_mon+1), err))     /* s.datcre.mon */
             return FALSE;
-      *err = s16write(htoles(fT->tm_year + 1900), wdh->fh);/* s.datcre.year */
-      if (*err)
+      if (!s16write(wdh, htoles(fT->tm_year + 1900), err)) /* s.datcre.year */
             return FALSE;
-      *err = s8write((guint8) fT->tm_mday, wdh->fh);       /* s.datclo.day */
-      if (*err)
+      if (!s8write(wdh, (guint8) fT->tm_mday, err))        /* s.datclo.day */
             return FALSE;
-      *err = s8write((guint8) (fT->tm_mon+1), wdh->fh);    /* s.datclo.mon */
-      if (*err)
+      if (!s8write(wdh, (guint8) (fT->tm_mon+1), err))     /* s.datclo.mon */
             return FALSE;
-      *err = s16write(htoles(fT->tm_year + 1900), wdh->fh);/* s.datclo.year */
-      if (*err)
+      if (!s16write(wdh, htoles(fT->tm_year + 1900), err)) /* s.datclo.year */
             return FALSE;
-      *err = s8write((guint8) fT->tm_sec, wdh->fh);        /* s.timeopn.second */
-      if (*err)
+      if (!s8write(wdh, (guint8) fT->tm_sec, err))         /* s.timeopn.second */
             return FALSE;
-      *err = s8write((guint8) fT->tm_min, wdh->fh);        /* s.timeopn.minute */
-      if (*err)
+      if (!s8write(wdh, (guint8) fT->tm_min, err))         /* s.timeopn.minute */
             return FALSE;
-      *err = s8write((guint8) fT->tm_hour, wdh->fh);       /* s.timeopn.hour */
-      if (*err)
+      if (!s8write(wdh, (guint8) fT->tm_hour, err))        /* s.timeopn.hour */
             return FALSE;
-      *err = s8write((guint8) fT->tm_mday, wdh->fh);       /* s.timeopn.mday */
-      if (*err)
+      if (!s8write(wdh, (guint8) fT->tm_mday, err))        /* s.timeopn.mday */
             return FALSE;
-      *err = s0write(2, wdh->fh);
-      if (*err)
-               return FALSE;
-      *err = s8write((guint8) fT->tm_sec, wdh->fh);        /* s.timeclo.second */
-      if (*err)
+      if (!s0write(wdh, 2, err))
             return FALSE;
-      *err = s8write((guint8) fT->tm_min, wdh->fh);        /* s.timeclo.minute */
-      if (*err)
+      if (!s8write(wdh, (guint8) fT->tm_sec, err))         /* s.timeclo.second */
             return FALSE;
-      *err = s8write((guint8) fT->tm_hour, wdh->fh);       /* s.timeclo.hour */
-      if (*err)
+      if (!s8write(wdh, (guint8) fT->tm_min, err))         /* s.timeclo.minute */
             return FALSE;
-      *err = s8write((guint8) fT->tm_mday, wdh->fh);       /* s.timeclo.mday */
-      if (*err)
+      if (!s8write(wdh, (guint8) fT->tm_hour, err))        /* s.timeclo.hour */
             return FALSE;
-      *err = s0write(2, wdh->fh);
-      if (*err)
-               return FALSE;
-      *err = s0write(6, wdh->fh);                          /* EAddr  == 0      */
-      if (*err)
-               return FALSE;
-      *err = s16write(htoles(1), wdh->fh);                 /* s.mxseqno */
-      if (*err)
+      if (!s8write(wdh, (guint8) fT->tm_mday, err))        /* s.timeclo.mday */
             return FALSE;
-      *err = s16write(htoles(0), wdh->fh);                 /* s.slcoffo */
-      if (*err)
+      if (!s0write(wdh, 2, err))
             return FALSE;
-      *err = s16write(htoles(1514), wdh->fh);              /* s.mxslc */
-      if (*err)
+      if (!s0write(wdh, 6, err))                           /* EAddr  == 0      */
             return FALSE;
-      *err = s32write(htolel(itmp->pkts), wdh->fh);        /* s.totpktt */
-      if (*err)
+      if (!s16write(wdh, htoles(1), err))                  /* s.mxseqno */
             return FALSE;
-      *err = s0write(12, wdh->fh);                         /* statrg == 0; ? -1*/
-      if (*err)                                            /* stptrg == 0; ? -1*/
-               return FALSE;                                  /* s.mxpkta[0]=0    */
-      *err = s32write(htolel(itmp->pkts), wdh->fh);        /* sr.s.mxpkta[1]  */
-      if (*err)
+      if (!s16write(wdh, htoles(0), err))                  /* s.slcoffo */
             return FALSE;
-      *err = s0write(34*4, wdh->fh);                       /* s.mxpkta[2-33]=0  */
-      if (*err)
-               return FALSE;
-      *err = s16write(htoles(board_type), wdh->fh);
-      if (*err)
+      if (!s16write(wdh, htoles(1514), err))               /* s.mxslc */
+            return FALSE;
+      if (!s32write(wdh, htolel(itmp->pkts), err))         /* s.totpktt */
+            return FALSE;
+      /*
+       * statrg == 0; ? -1
+       * stptrg == 0; ? -1
+       * s.mxpkta[0]=0
+       */
+      if (!s0write(wdh, 12, err))
             return FALSE;
-      *err = s0write(20, wdh->fh);                         /* board_version == 0 */
-      if (*err)
+      if (!s32write(wdh, htolel(itmp->pkts), err))         /* sr.s.mxpkta[1]  */
+            return FALSE;
+      if (!s0write(wdh, 34*4, err))                        /* s.mxpkta[2-33]=0  */
+            return FALSE;
+      if (!s16write(wdh, htoles(board_type), err))
+            return FALSE;
+      if (!s0write(wdh, 20, err))                             /* board_version == 0 */
             return FALSE;
       /*-----------------------------------------------------------------*/
-      *err = s16write(htoles(RT_SubfileSummary), wdh->fh);    /* ssr.rid */
-      if (*err)
+      if (!s16write(wdh, htoles(RT_SubfileSummary), err))     /* ssr.rid */
             return FALSE;
-      *err = s16write(htoles(LA_SubfileSummaryRecordSize-4), wdh->fh);    /* ssr.rlen */
-      if (*err)
+      if (!s16write(wdh, htoles(LA_SubfileSummaryRecordSize-4), err)) /* ssr.rlen */
             return FALSE;
-      *err = s16write(htoles(1), wdh->fh);                    /* ssr.seqno */
-      if (*err)
+      if (!s16write(wdh, htoles(1), err))                     /* ssr.seqno */
             return FALSE;
-      *err = s32write(htolel(itmp->pkts), wdh->fh);           /* ssr.totpkts */
-      if (*err)
+      if (!s32write(wdh, htolel(itmp->pkts), err))            /* ssr.totpkts */
             return FALSE;
       /*-----------------------------------------------------------------*/
-      *err = swrite(&LA_CyclicInformationFake, sizeof LA_CyclicInformationFake, wdh->fh);
-      if (*err)
-               return FALSE;
+      if (!wtap_dump_file_write(wdh, &LA_CyclicInformationFake,
+                                sizeof LA_CyclicInformationFake, err))
+            return FALSE;
       /*-----------------------------------------------------------------*/
-      *err = s16write(htoles(RT_Index), wdh->fh);             /* rid */
-      if (*err)
+      if (!s16write(wdh, htoles(RT_Index), err))              /* rid */
             return FALSE;
-      *err = s16write(htoles(LA_IndexRecordSize -4), wdh->fh);/* rlen */
-      if (*err)
+      if (!s16write(wdh, htoles(LA_IndexRecordSize -4), err)) /* rlen */
             return FALSE;
-      *err = s16write(htoles(LA_IndexSize), wdh->fh);         /* idxsp */
-      if (*err)
+      if (!s16write(wdh, htoles(LA_IndexSize), err))          /* idxsp */
             return FALSE;
-      *err = s0write(LA_IndexRecordSize - 6, wdh->fh);
-      if (*err)
+      if (!s0write(wdh, LA_IndexRecordSize - 6, err))
             return FALSE;
 
       return TRUE;