Rename WTAP_ERR_REC_TYPE_UNSUPPORTED to WTAP_ERR_UNWRITABLE_REC_TYPE.
[metze/wireshark/wip.git] / wiretap / netscaler.c
index 9772567ae7c724a6b1649e950a26960ed9f51099..ad2840bf827ace35596a0b9cfa49ef6c8b940c8c 100644 (file)
@@ -23,7 +23,7 @@
 #include <string.h>
 #include "wtap-int.h"
 #include "file_wrappers.h"
-#include "buffer.h"
+#include <wsutil/buffer.h>
 #include "netscaler.h"
 
 /* Defines imported from netscaler code: nsperfrc.h */
@@ -513,6 +513,7 @@ typedef struct nspr_pktracepart_v26
     TRACE_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)
 
 #define TRACE_PART_V10_REC_LEN_OFF(phdr,enumprefix,structprefix,structname) \
+    (phdr)->rec_type = REC_TYPE_PACKET;\
     (phdr)->presence_flags |= WTAP_HAS_CAP_LEN;\
     (phdr)->len =  pletoh16(&pp->pp_PktSizeOrg) + nspr_pktracepart_v10_s;\
     (phdr)->caplen =  pletoh16(&pp->nsprRecordSize);\
@@ -639,7 +640,7 @@ static gboolean nstrace_set_start_time(wtap *wth);
 static guint64 ns_hrtime2nsec(guint32 tm);
 
 static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
-                             const guint8 *pd, int *err);
+                             const guint8 *pd, int *err, gchar **err_info);
 
 
 /*
@@ -666,18 +667,16 @@ static guint64 ns_hrtime2nsec(guint32 tm)
 /*
 ** Netscaler trace format open routines
 */
-int nstrace_open(wtap *wth, int *err, gchar **err_info)
+wtap_open_return_val nstrace_open(wtap *wth, int *err, gchar **err_info)
 {
     gchar *nstrace_buf;
     gint64 file_size;
     gint32 page_size;
     nstrace_t *nstrace;
-    int bytes_read;
 
-    errno = WTAP_ERR_CANT_READ;
 
     if ((file_size = wtap_file_size(wth, err)) == -1)
-        return 0;
+        return WTAP_OPEN_NOT_MINE;
 
     nstrace_buf = (gchar *)g_malloc(NSPR_PAGESIZE);
     page_size = GET_READ_PAGE_SIZE(file_size);
@@ -700,27 +699,23 @@ int nstrace_open(wtap *wth, int *err, gchar **err_info)
         break;
 
     default:
-        *err = WTAP_ERR_UNSUPPORTED;
-        *err_info = g_strdup_printf("nstrace: file type %d unsupported", wth->file_type_subtype);
+        /* No known signature found, assume it's not NetScaler */
         g_free(nstrace_buf);
-        return 0;
+        return WTAP_OPEN_NOT_MINE;
     }
 
     if ((file_seek(wth->fh, 0, SEEK_SET, err)) == -1)
     {
-        *err = file_error(wth->fh, err_info);
         g_free(nstrace_buf);
-        return 0;
+        return WTAP_OPEN_ERROR;
     }
 
-    bytes_read = file_read(nstrace_buf, page_size, wth->fh);
-    if (bytes_read != page_size)
+    if (!wtap_read_bytes(wth->fh, nstrace_buf, page_size, err, err_info))
     {
-        *err = file_error(wth->fh, err_info);
         g_free(nstrace_buf);
-        if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
-            return -1;
-        return 0;
+        if (*err != WTAP_ERR_SHORT_READ)
+            return WTAP_OPEN_ERROR;
+        return WTAP_OPEN_NOT_MINE;
     }
 
     switch (wth->file_type_subtype)
@@ -761,32 +756,29 @@ int nstrace_open(wtap *wth, int *err, gchar **err_info)
         /* Reset the read pointer to start of the file. */
         if ((file_seek(wth->fh, 0, SEEK_SET, err)) == -1)
         {
-            *err = file_error(wth->fh, err_info);
             g_free(nstrace->pnstrace_buf);
             g_free(nstrace);
-            return 0;
+            return WTAP_OPEN_ERROR;
         }
 
         /* Read the first page of data */
-        bytes_read = file_read(nstrace_buf, page_size, wth->fh);
-        if (bytes_read != page_size)
+        if (!wtap_read_bytes(wth->fh, nstrace_buf, page_size, err, err_info))
         {
-            *err = file_error(wth->fh, err_info);
             g_free(nstrace->pnstrace_buf);
             g_free(nstrace);
-            return 0;
+            return WTAP_OPEN_ERROR;
         }
 
         /* reset the buffer offset */
         nstrace->nstrace_buf_offset = 0;
     }
 
-    wth->tsprecision = WTAP_FILE_TSPREC_NSEC;
+    wth->file_tsprec = WTAP_TSPREC_NSEC;
     wth->phdr.ts.secs = nstrace->nspm_curtime;
     wth->phdr.ts.nsecs = 0;
 
     *err = 0;
-    return 1;
+    return WTAP_OPEN_MINE;
 }
 
 
@@ -800,10 +792,12 @@ nspm_signature_func(20)
 nspm_signature_func(30)
 
 /*
-** Check signature and return the version number of the signature.
-** If not found, it returns 0. At the time of return from this function
-** we might not be at the first page. So after a call to this function, there
-** has to be a file seek to return to the start of the first page.
+** Check signature and return the file type and subtype for files with
+** that signature.  If it finds no signature that it recognizes, it
+** returns WTAP_FILE_TYPE_SUBTYPE_UNKNOWN. At the time of return from
+** this function we might not be at the first page. So after a call to
+** this function, there has to be a file seek to return to the start
+** of the first page.
 */
 static guint32
 nspm_signature_version(wtap *wth, gchar *nstrace_buf, gint32 len)
@@ -838,7 +832,7 @@ nspm_signature_version(wtap *wth, gchar *nstrace_buf, gint32 len)
         }
     }
 
-    return 0;    /* no version found */
+    return WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;    /* no version found */
 }
 
 #define nspr_getv10recordtype(hdp) (pletoh16(&(hdp)->nsprRecordType))
@@ -954,13 +948,14 @@ static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info, gint64 *
              * as the time stamps in the records are relative to\
              * the previous packet.\
              */\
+            (phdr)->rec_type = REC_TYPE_PACKET;\
             (phdr)->presence_flags = WTAP_HAS_TS;\
             nsg_creltime += ns_hrtime2nsec(pletoh32(&fp->fp_RelTimeHr));\
             (phdr)->ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);\
             (phdr)->ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
             TRACE_FULL_V##type##_REC_LEN_OFF(phdr,v##type##_full,fp,pktracefull_v##type);\
-            buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
-            memcpy(buffer_start_ptr(wth->frame_buffer), fp, (phdr)->caplen);\
+            ws_buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
+            memcpy(ws_buffer_start_ptr(wth->frame_buffer), fp, (phdr)->caplen);\
             *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
             nstrace->nstrace_buf_offset = nstrace_buf_offset + (phdr)->len;\
             nstrace->nstrace_buflen = nstrace_buflen;\
@@ -977,13 +972,14 @@ static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info, gint64 *
              * as the time stamps in the records are relative to\
              * the previous packet.\
              */\
+            (phdr)->rec_type = REC_TYPE_PACKET;\
             (phdr)->presence_flags = WTAP_HAS_TS;\
             nsg_creltime += ns_hrtime2nsec(pletoh32(&pp->pp_RelTimeHr));\
             (phdr)->ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);\
             (phdr)->ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
             TRACE_PART_V##type##_REC_LEN_OFF(phdr,v##type##_part,pp,pktracepart_v##type);\
-            buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
-            memcpy(buffer_start_ptr(wth->frame_buffer), pp, (phdr)->caplen);\
+            ws_buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
+            memcpy(ws_buffer_start_ptr(wth->frame_buffer), pp, (phdr)->caplen);\
             *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
             nstrace->nstrace_buf_offset = nstrace_buf_offset + (phdr)->caplen;\
             nstrace->nsg_creltime = nsg_creltime;\
@@ -1035,6 +1031,7 @@ static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info, gint64 *
 
 #define TIMEDEFV20(fp,type) \
     do {\
+        wth->phdr.rec_type = REC_TYPE_PACKET;\
         wth->phdr.presence_flags |= WTAP_HAS_TS;\
         nsg_creltime += ns_hrtime2nsec(pletoh32(fp->type##_RelTimeHr));\
         wth->phdr.ts.secs = nstrace->nspm_curtime + (guint32) (nsg_creltime / 1000000000);\
@@ -1043,6 +1040,7 @@ static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info, gint64 *
 
 #define TIMEDEFV23(fp,type) \
     do {\
+        wth->phdr.rec_type = REC_TYPE_PACKET;\
         wth->phdr.presence_flags |= WTAP_HAS_TS;\
         /* access _AbsTimeHr as a 64bit value */\
         nsg_creltime = pletoh64(fp->type##_AbsTimeHr);\
@@ -1052,6 +1050,7 @@ static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info, gint64 *
 
 #define TIMEDEFV30(fp,type) \
     do {\
+        wth->phdr.rec_type = REC_TYPE_PACKET;\
         wth->phdr.presence_flags |= WTAP_HAS_TS;\
         /* access _AbsTimeHr as a 64bit value */\
         nsg_creltime = pletoh64(fp->type##_AbsTimeHr);\
@@ -1067,6 +1066,7 @@ static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info, gint64 *
 
 #define PPSIZEDEFV20(phdr,pp,ver) \
     do {\
+        (phdr)->rec_type = REC_TYPE_PACKET;\
         (phdr)->presence_flags |= WTAP_HAS_CAP_LEN;\
         (phdr)->len = pletoh16(&pp->pp_PktSizeOrg) + nspr_pktracepart_v##ver##_s;\
         (phdr)->caplen = nspr_getv20recordsize((nspr_hd_v20_t *)pp);\
@@ -1094,9 +1094,10 @@ static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info, gint64 *
 
 #define FPSIZEDEFV30(phdr,fp,ver)\
     do {\
+        (phdr)->rec_type = REC_TYPE_PACKET;\
+        (phdr)->presence_flags |= WTAP_HAS_CAP_LEN;\
         (phdr)->len = pletoh16(&fp->fp_PktSizeOrg) + nspr_pktracefull_v##ver##_s;\
         (phdr)->caplen = nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
-        (phdr)->presence_flags |= WTAP_HAS_CAP_LEN;\
     }while(0)
 
 #define PACKET_DESCRIBE(phdr,FPTIMEDEF,SIZEDEF,ver,enumprefix,type,structname,TYPE)\
@@ -1106,8 +1107,8 @@ static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info, gint64 *
         SIZEDEF##ver((phdr),fp,ver);\
         TRACE_V##ver##_REC_LEN_OFF((phdr),enumprefix,type,structname);\
         (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##TYPE;\
-        buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
-        memcpy(buffer_start_ptr(wth->frame_buffer), fp, (phdr)->caplen);\
+        ws_buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
+        memcpy(ws_buffer_start_ptr(wth->frame_buffer), fp, (phdr)->caplen);\
         *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
         nstrace->nstrace_buf_offset = nstrace_buf_offset + nspr_getv20recordsize((nspr_hd_v20_t *)fp);\
         nstrace->nstrace_buflen = nstrace_buflen;\
@@ -1231,7 +1232,7 @@ static gboolean nstrace_read_v20(wtap *wth, int *err, gchar **err_info, gint64 *
     SIZEDEF##ver((phdr),fp,ver);\
     TRACE_V##ver##_REC_LEN_OFF((phdr),enumprefix,type,structname);\
     (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##TYPE;\
-    buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
+    ws_buffer_assure_space(wth->frame_buffer, (phdr)->caplen);\
     *data_offset = nstrace->xxx_offset + nstrace_buf_offset;\
     while (nstrace_tmpbuff_off < nspr_##structname##_s) {\
         nstrace_tmpbuff[nstrace_tmpbuff_off++] = nstrace_buf[nstrace_buf_offset++];\
@@ -1259,7 +1260,7 @@ static gboolean nstrace_read_v20(wtap *wth, int *err, gchar **err_info, gint64 *
     while (nstrace_tmpbuff_off < nst_dataSize) {\
         nstrace_tmpbuff[nstrace_tmpbuff_off++] = nstrace_buf[nstrace_buf_offset++];\
     }\
-    memcpy(buffer_start_ptr(wth->frame_buffer), nstrace_tmpbuff, (phdr)->caplen);\
+    memcpy(ws_buffer_start_ptr(wth->frame_buffer), nstrace_tmpbuff, (phdr)->caplen);\
     nstrace->nstrace_buf_offset = nstrace_buf_offset;\
     nstrace->nstrace_buflen = nstrace_buflen = ((gint32)NSPR_PAGESIZE_TRACE);\
     nstrace->nsg_creltime = nsg_creltime;\
@@ -1269,7 +1270,7 @@ static gboolean nstrace_read_v20(wtap *wth, int *err, gchar **err_info, gint64 *
 static gboolean nstrace_read_v30(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
 {
     nstrace_t *nstrace = (nstrace_t *)wth->priv;
-    guint64 nsg_creltime = nstrace->nsg_creltime;
+    guint64 nsg_creltime;
     gchar *nstrace_buf = nstrace->pnstrace_buf;
     gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;
     gint32 nstrace_buflen = nstrace->nstrace_buflen;
@@ -1289,14 +1290,16 @@ static gboolean nstrace_read_v30(wtap *wth, int *err, gchar **err_info, gint64 *
             switch (hdp->phd_RecordType)
             {
 
-#define GENERATE_CASE_V30(phdr,type,acttype) \
+#define GENERATE_CASE_FULL_V30(phdr,type,acttype) \
         case NSPR_PDPKTRACEFULLTX_V##type:\
         case NSPR_PDPKTRACEFULLTXB_V##type:\
         case NSPR_PDPKTRACEFULLRX_V##type:\
         case NSPR_PDPKTRACEFULLNEWRX_V##type:\
-        PACKET_DESCRIBE(phdr, TIMEDEF, FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
-        GENERATE_CASE_V30(&wth->phdr,30, 300);
-#undef GENERATE_CASE_V30
+            PACKET_DESCRIBE(phdr,TIMEDEF,FPSIZEDEFV,type,v##type##_full,fp,pktracefull_v##type,acttype);
+
+                GENERATE_CASE_FULL_V30(&wth->phdr,30,300);
+
+#undef GENERATE_CASE_FULL_V30
 
                 case NSPR_ABSTIME_V20:
                 {
@@ -1333,7 +1336,6 @@ static gboolean nstrace_seek_read_v10(wtap *wth, gint64 seek_off,
     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
 {
     nspr_hd_v10_t hdr;
-    int bytes_read;
     guint record_length;
     guint8 *pd;
     unsigned int bytes_to_read;
@@ -1348,13 +1350,9 @@ static gboolean nstrace_seek_read_v10(wtap *wth, gint64 seek_off,
     /*
     ** Read the record header.
     */
-    bytes_read = file_read((void *)&hdr, sizeof hdr, wth->random_fh);
-    if (bytes_read != sizeof hdr) {
-        *err = file_error(wth->random_fh, err_info);
-        if (*err == 0)
-            *err = WTAP_ERR_SHORT_READ;
+    if (!wtap_read_bytes(wth->random_fh, (void *)&hdr, sizeof hdr,
+                         err, err_info))
         return FALSE;
-    }
 
     /*
     ** Get the record length.
@@ -1364,18 +1362,14 @@ static gboolean nstrace_seek_read_v10(wtap *wth, gint64 seek_off,
     /*
     ** Copy the header to the buffer and read the rest of the record..
     */
-    buffer_assure_space(buf, record_length);
-    pd = buffer_start_ptr(buf);
+    ws_buffer_assure_space(buf, record_length);
+    pd = ws_buffer_start_ptr(buf);
     memcpy(pd, (void *)&hdr, sizeof hdr);
     if (record_length > sizeof hdr) {
-       bytes_to_read = (unsigned int)(record_length - sizeof hdr);
-        bytes_read = file_read(pd + sizeof hdr, bytes_to_read, wth->random_fh);
-        if (bytes_read < 0 || (unsigned int)bytes_read != bytes_to_read) {
-            *err = file_error(wth->random_fh, err_info);
-            if (*err == 0)
-                *err = WTAP_ERR_SHORT_READ;
+        bytes_to_read = (unsigned int)(record_length - sizeof hdr);
+        if (!wtap_read_bytes(wth->random_fh, pd + sizeof hdr, bytes_to_read,
+                             err, err_info))
             return FALSE;
-        }
     }
 
     /*
@@ -1424,7 +1418,6 @@ static gboolean nstrace_seek_read_v20(wtap *wth, gint64 seek_off,
     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
 {
     nspr_hd_v20_t hdr;
-    int bytes_read;
     guint record_length;
     guint hdrlen;
     guint8 *pd;
@@ -1438,26 +1431,17 @@ static gboolean nstrace_seek_read_v20(wtap *wth, gint64 seek_off,
     /*
     ** Read the first 2 bytes of the record header.
     */
-    bytes_read = file_read((void *)&hdr, 2, wth->random_fh);
-    if (bytes_read != 2) {
-        *err = file_error(wth->random_fh, err_info);
-        if (*err == 0)
-            *err = WTAP_ERR_SHORT_READ;
+    if (!wtap_read_bytes(wth->random_fh, (void *)&hdr, 2, err, err_info))
         return FALSE;
-    }
     hdrlen = 2;
 
     /*
     ** Is there a third byte?  If so, read it.
     */
     if (hdr.phd_RecordSizeLow & NSPR_V20RECORDSIZE_2BYTES) {
-        bytes_read = file_read((void *)&hdr.phd_RecordSizeHigh, 1, wth->random_fh);
-        if (bytes_read != 1) {
-            *err = file_error(wth->random_fh, err_info);
-            if (*err == 0)
-                *err = WTAP_ERR_SHORT_READ;
+        if (!wtap_read_bytes(wth->random_fh, (void *)&hdr.phd_RecordSizeHigh, 1,
+                             err, err_info))
             return FALSE;
-        }
         hdrlen = 3;
     }
 
@@ -1469,18 +1453,14 @@ static gboolean nstrace_seek_read_v20(wtap *wth, gint64 seek_off,
     /*
     ** Copy the header to the buffer and read the rest of the record..
     */
-    buffer_assure_space(buf, record_length);
-    pd = buffer_start_ptr(buf);
+    ws_buffer_assure_space(buf, record_length);
+    pd = ws_buffer_start_ptr(buf);
     memcpy(pd, (void *)&hdr, hdrlen);
     if (record_length > hdrlen) {
-       bytes_to_read = (unsigned int)(record_length - hdrlen);
-        bytes_read = file_read(pd + hdrlen, bytes_to_read, wth->random_fh);
-        if (bytes_read < 0 || (unsigned int)bytes_read != bytes_to_read) {
-            *err = file_error(wth->random_fh, err_info);
-            if (*err == 0)
-                *err = WTAP_ERR_SHORT_READ;
+        bytes_to_read = (unsigned int)(record_length - hdrlen);
+        if (!wtap_read_bytes(wth->random_fh, pd + hdrlen, bytes_to_read,
+                             err, err_info))
             return FALSE;
-        }
     }
 
 #define GENERATE_CASE_FULL(phdr,type,acttype) \
@@ -1540,7 +1520,6 @@ static gboolean nstrace_seek_read_v30(wtap *wth, gint64 seek_off,
     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
 {
     nspr_hd_v20_t hdr;
-    int bytes_read;
     guint record_length;
     guint hdrlen;
     guint8 *pd;
@@ -1553,26 +1532,17 @@ static gboolean nstrace_seek_read_v30(wtap *wth, gint64 seek_off,
     /*
     ** Read the first 2 bytes of the record header.
     */
-    bytes_read = file_read((void *)&hdr, 2, wth->random_fh);
-    if (bytes_read != 2) {
-        *err = file_error(wth->random_fh, err_info);
-        if (*err == 0)
-            *err = WTAP_ERR_SHORT_READ;
+    if (!wtap_read_bytes(wth->random_fh, (void *)&hdr, 2, err, err_info))
         return FALSE;
-    }
     hdrlen = 2;
 
     /*
     ** Is there a third byte?  If so, read it.
     */
     if (hdr.phd_RecordSizeLow & NSPR_V20RECORDSIZE_2BYTES) {
-        bytes_read = file_read((void *)&hdr.phd_RecordSizeHigh, 1, wth->random_fh);
-        if (bytes_read != 1) {
-            *err = file_error(wth->random_fh, err_info);
-            if (*err == 0)
-                *err = WTAP_ERR_SHORT_READ;
+        if (!wtap_read_bytes(wth->random_fh, (void *)&hdr.phd_RecordSizeHigh, 1,
+                             err, err_info))
             return FALSE;
-        }
         hdrlen = 3;
     }
 
@@ -1584,18 +1554,14 @@ static gboolean nstrace_seek_read_v30(wtap *wth, gint64 seek_off,
     /*
     ** Copy the header to the buffer and read the rest of the record..
     */
-    buffer_assure_space(buf, record_length);
-    pd = buffer_start_ptr(buf);
+    ws_buffer_assure_space(buf, record_length);
+    pd = ws_buffer_start_ptr(buf);
     memcpy(pd, (void *)&hdr, hdrlen);
     if (record_length > hdrlen) {
         bytes_to_read = (unsigned int)(record_length - hdrlen);
-        bytes_read = file_read(pd + hdrlen, bytes_to_read, wth->random_fh);
-        if (bytes_read < 0 || (unsigned int)bytes_read != bytes_to_read) {
-            *err = file_error(wth->random_fh, err_info);
-            if (*err == 0)
-                *err = WTAP_ERR_SHORT_READ;
+        if (!wtap_read_bytes(wth->random_fh, pd + hdrlen, bytes_to_read,
+                             err, err_info))
             return FALSE;
-        }
     }
 
 #define GENERATE_CASE_V30(phdr,type,acttype) \
@@ -1640,7 +1606,7 @@ int nstrace_10_dump_can_write_encap(int encap)
     if (encap == WTAP_ENCAP_NSTRACE_1_0)
         return 0;
 
-    return WTAP_ERR_UNSUPPORTED_ENCAP;
+    return WTAP_ERR_UNWRITABLE_ENCAP;
 }
 
 
@@ -1651,7 +1617,7 @@ int nstrace_20_dump_can_write_encap(int encap)
     if (encap == WTAP_ENCAP_NSTRACE_2_0)
         return 0;
 
-    return WTAP_ERR_UNSUPPORTED_ENCAP;
+    return WTAP_ERR_UNWRITABLE_ENCAP;
 }
 
 /* Returns 0 if we could write the specified encapsulation type,
@@ -1661,7 +1627,7 @@ int nstrace_30_dump_can_write_encap(int encap)
     if (encap == WTAP_ENCAP_NSTRACE_3_0)
         return 0;
 
-    return WTAP_ERR_UNSUPPORTED_ENCAP;
+    return WTAP_ERR_UNWRITABLE_ENCAP;
 }
 
 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
@@ -1818,10 +1784,16 @@ nstrace_add_abstime(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
 /* Write a record for a packet to a dump file.
    Returns TRUE on success, FALSE on failure. */
 static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
-    const guint8 *pd, int *err)
+    const guint8 *pd, int *err, gchar **err_info _U_)
 {
     nstrace_dump_t *nstrace = (nstrace_dump_t *)wdh->priv;
 
+    /* We can only write packet records. */
+    if (phdr->rec_type != REC_TYPE_PACKET) {
+        *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
+        return FALSE;
+    }
+
     if (nstrace->page_offset == 0)
     {
         /* Add the signature record and abs time record */
@@ -1873,7 +1845,7 @@ static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
             nstrace->page_offset += (guint16) phdr->caplen;
         } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
         {
-            *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
+            *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
             return FALSE;
         }
 
@@ -1888,7 +1860,7 @@ static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
     case NSPR_HEADER_VERSION206:
         if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
         {
-            *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
+            *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
             return FALSE;
         } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
         {
@@ -1917,11 +1889,11 @@ static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
     case NSPR_HEADER_VERSION300:
         if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
         {
-            *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
+            *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
             return FALSE;
         } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
         {
-            *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE;
+            *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
             return FALSE;
         } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0)
         {
@@ -1957,4 +1929,3 @@ static gboolean nstrace_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
 
     return TRUE;
 }
-