/* netscaler.c
- *
- * $Id$
*
* Wiretap Library
* Copyright (c) 2006 by Ravi Kondamuru <Ravi.Kondamuru@citrix.com>
#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 */
#define NSPR_SIGSTR_V10 "NetScaler Performance Data"
#define NSPR_SIGSTR_V20 "NetScaler V20 Performance Data"
#define NSPR_SIGSTR NSPR_SIGSTR_V20
+#define NSPR_SIGSTR_V30 "Netscaler V30 Performance Data"
/* Defined but not used */
#define NSPR_SIGSTR_V21 "NetScaler V21 Performance Data"
#define NSPR_SIGSTR_V22 "NetScaler V22 Performance Data"
* other than the type and zero or more additional padding bytes).
*/
#define NSPR_PAGESIZE 8192
+#define NSPR_PAGESIZE_TRACE (2*NSPR_PAGESIZE)
/* The different record types
** NOTE: The Record Type is two byte fields and unused space is recognized by
#define NSPR_UNUSEDSPACE_V20 0x00 /* rest of the page is unused */
#define NSPR_SIGNATURE_V10 0x0101 /* signature */
#define NSPR_SIGNATURE_V20 0x01 /* signature */
+#define NSPR_SIGNATURE_V30 NSPR_SIGNATURE_V20
#define NSPR_ABSTIME_V10 0x0107 /* data capture time in secs from 1970*/
#define NSPR_ABSTIME_V20 0x07 /* data capture time in secs from 1970*/
#define NSPR_RELTIME_V10 0x0108 /* relative time in ms from last time */
/* end of declaration */
#define NSPR_HEADER3B_V21 NSPR_HEADER3B_V20
#define NSPR_HEADER3B_V22 NSPR_HEADER3B_V20
+#define NSPR_HEADER3B_V30 NSPR_HEADER3B_V20
typedef struct nspr_hd_v20
{
} nspr_signature_v20_t;
#define nspr_signature_v20_s ((guint32)sizeof(nspr_signature_v20_t))
+/* NSPR_SIGNATURE_V30 structure */
+#define NSPR_SIGSIZE_V30 sizeof(NSPR_SIGSTR_V30) /* signature value size in bytes */
+typedef struct nspr_signature_v30
+{
+ NSPR_HEADER_V20(sig); /* short performance header */
+ guint8 sig_EndianType; /* Endian Type for the data */
+ gchar sig_Signature[NSPR_SIGSIZE_V30]; /* Signature value */
+} nspr_signature_v30_t;
+#define nspr_signature_v30_s ((guint32)sizeof(nspr_signature_v30_t))
+
/* NSPR_ABSTIME_V10 and NSPR_SYSTARTIME_V10 structure */
typedef struct nspr_abstime_v10
{
#define pp_src_vmname pp_Data
#define pp_dst_vmname pp_Data
+
+/* New full packet trace structure v30 for multipage spanning data */
+typedef struct nspr_pktracefull_v30
+{
+ NSPR_HEADER3B_V30(fp); /* long performance header */
+ guint8 fp_DevNo; /* Network Device (NIC) number */
+ guint8 fp_AbsTimeHr[8]; /*High resolution absolute time in nanosec*/
+ guint8 fp_PcbDevNo[4]; /* PCB devno */
+ guint8 fp_lPcbDevNo[4]; /* link PCB devno */
+ guint8 fp_PktSizeOrg[2]; /* Original packet size */
+ guint8 fp_VlanTag[2]; /* vlan tag */
+ guint8 fp_Coreid[2]; /* coreid of the packet */
+ guint8 fp_srcNodeId[2]; /* cluster nodeid of the packet */
+ guint8 fp_destNodeId[2];
+ guint8 fp_clFlags;
+ guint8 fp_src_vmname_len;
+ guint8 fp_dst_vmname_len;
+ guint8 fp_reserved[3];
+ guint8 fp_ns_activity[4];
+ guint8 fp_reserved_32[12];
+ guint8 fp_Data[0]; /* packet data starts here */
+} nspr_pktracefull_v30_t;
+#define nspr_pktracefull_v30_s ((guint32)(sizeof(nspr_pktracefull_v30_t)))
+#define fp_src_vmname fp_Data
+#define fp_dst_vmname fp_Data
+
/* New partial packet trace structure v26 for vm info tracing */
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);\
TRACE_V25_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
__TNO(phdr,enumprefix,structprefix,structname,ns_activity,ns_activity)\
+#define TRACE_V30_REC_LEN_OFF(phdr, enumprefix, structprefix, structname) \
+ TRACE_V26_REC_LEN_OFF(phdr,enumprefix,structprefix,structname)\
+
TRACE_V10_REC_LEN_OFF(NULL,v10_part,pp,pktracepart_v10)
TRACE_V10_REC_LEN_OFF(NULL,v10_full,fp,pktracefull_v10)
TRACE_V20_REC_LEN_OFF(NULL,v20_part,pp,pktracepart_v20)
TRACE_V25_REC_LEN_OFF(NULL,v25_full,fp,pktracefull_v25)
TRACE_V26_REC_LEN_OFF(NULL,v26_part,pp,pktracepart_v26)
TRACE_V26_REC_LEN_OFF(NULL,v26_full,fp,pktracefull_v26)
+ TRACE_V30_REC_LEN_OFF(NULL,v30_full,fp,pktracefull_v30)
#undef __TNV1O
#undef __TNV1L
gint64 *data_offset);
static gboolean nstrace_read_v20(wtap *wth, int *err, gchar **err_info,
gint64 *data_offset);
+static gboolean nstrace_read_v30(wtap *wth, int *err, gchar **err_info,
+ gint64 *data_offset);
static gboolean nstrace_seek_read_v10(wtap *wth, gint64 seek_off,
struct wtap_pkthdr *phdr,
- Buffer *buf, int length,
+ Buffer *buf,
int *err, gchar **err_info);
static gboolean nstrace_seek_read_v20(wtap *wth, gint64 seek_off,
struct wtap_pkthdr *phdr,
- Buffer *buf, int length,
+ Buffer *buf,
+ int *err, gchar **err_info);
+static gboolean nstrace_seek_read_v30(wtap *wth, gint64 seek_off,
+ struct wtap_pkthdr *phdr,
+ Buffer *buf,
int *err, gchar **err_info);
static void nstrace_close(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);
/*
* the last page of a file can be short.
*/
#define GET_READ_PAGE_SIZE(remaining_file_size) ((gint32)((remaining_file_size>NSPR_PAGESIZE)?NSPR_PAGESIZE:remaining_file_size))
-
+#define GET_READ_PAGE_SIZEV3(remaining_file_size) ((gint32)((remaining_file_size>NSPR_PAGESIZE_TRACE)?NSPR_PAGESIZE_TRACE:remaining_file_size))
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);
wth->file_encap = WTAP_ENCAP_NSTRACE_2_0;
break;
+ case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0:
+ wth->file_encap = WTAP_ENCAP_NSTRACE_3_0;
+ g_free(nstrace_buf);
+ nstrace_buf = (gchar *)g_malloc(NSPR_PAGESIZE_TRACE);
+ page_size = GET_READ_PAGE_SIZEV3(file_size);
+ 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)
wth->subtype_read = nstrace_read_v20;
wth->subtype_seek_read = nstrace_seek_read_v20;
break;
+
+ case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0:
+ wth->subtype_read = nstrace_read_v30;
+ wth->subtype_seek_read = nstrace_seek_read_v30;
+ break;
}
wth->subtype_close = nstrace_close;
/* 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;
}
nspm_signature_func(10)
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)
#define sigv20p ((nspr_signature_v20_t*)dp)
if ((sigv20p->sig_RecordType == NSPR_SIGNATURE_V20) &&
(sigv20p->sig_RecordSize <= len) &&
- ((gint32)sizeof(NSPR_SIGSTR_V20) <= len) &&
- (!nspm_signature_isv20(sigv20p->sig_Signature)))
- return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0;
+ ((gint32)sizeof(NSPR_SIGSTR_V20) <= len))
+ {
+ if (!nspm_signature_isv20(sigv20p->sig_Signature))
+ return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0;
+ else if (!nspm_signature_isv30(sigv20p->sig_Signature))
+ return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0;
+ }
#undef sigv20p
}
}
- return 0; /* no version found */
+ return WTAP_FILE_TYPE_SUBTYPE_UNKNOWN; /* no version found */
}
-#define nspr_getv10recordtype(hdp) (pletoh16(&hdp->nsprRecordType))
-#define nspr_getv10recordsize(hdp) (pletoh16(&hdp->nsprRecordSize))
-#define nspr_getv20recordtype(hdp) (hdp->phd_RecordType)
+#define nspr_getv10recordtype(hdp) (pletoh16(&(hdp)->nsprRecordType))
+#define nspr_getv10recordsize(hdp) (pletoh16(&(hdp)->nsprRecordSize))
+#define nspr_getv20recordtype(hdp) ((hdp)->phd_RecordType)
#define nspr_getv20recordsize(hdp) \
(((hdp)->phd_RecordSizeLow & NSPR_V20RECORDSIZE_2BYTES)? \
(((hdp)->phd_RecordSizeHigh * NSPR_V20RECORDSIZE_2BYTES)+ \
#undef nspr_getv10recordtype
#undef nspr_getv20recordtype
-#undef nspr_getv10recordsize
/*
** Set the start time of the trace file. We look for the first ABSTIME record. We use that
return nstrace_set_start_time_v10(wth);
else if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
return nstrace_set_start_time_v20(wth);
-
+ else if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0)
+ return nstrace_set_start_time_v20(wth);
return FALSE;
}
* 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;\
* 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;\
#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);\
#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);\
+ wth->phdr.ts.secs = (guint32) (nsg_creltime / 1000000000);\
+ wth->phdr.ts.nsecs = (guint32) (nsg_creltime % 1000000000);\
+ }while(0)
+
+#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);\
#define TIMEDEFV24(fp,type) TIMEDEFV23(fp,type)
#define TIMEDEFV25(fp,type) TIMEDEFV24(fp,type)
#define TIMEDEFV26(fp,type) TIMEDEFV24(fp,type)
+
#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);\
#define FPSIZEDEFV25(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
#define FPSIZEDEFV26(phdr,fp,ver) FPSIZEDEFV20(phdr,fp,ver)
+#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);\
+ }while(0)
+
#define PACKET_DESCRIBE(phdr,FPTIMEDEF,SIZEDEF,ver,enumprefix,type,structname,TYPE)\
do {\
nspr_##structname##_t *fp= (nspr_##structname##_t*)&nstrace_buf[nstrace_buf_offset];\
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;\
#undef PACKET_DESCRIBE
+#define PACKET_DESCRIBE(phdr,FPTIMEDEF,SIZEDEF,ver,enumprefix,type,structname,TYPE)\
+ do {\
+ nspr_##structname##_t *fp = (nspr_##structname##_t *) &nstrace_buf[nstrace_buf_offset];\
+ TIMEDEFV##ver(fp,type);\
+ 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;\
+ 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++];\
+ }\
+ nst_dataSize = nspr_getv20recordsize(hdp);\
+ rec_size = nst_dataSize - nstrace_tmpbuff_off;\
+ nsg_nextPageOffset = ((nstrace_buf_offset + rec_size) >= NSPR_PAGESIZE_TRACE) ?\
+ ((nstrace_buf_offset + rec_size) - (NSPR_PAGESIZE_TRACE - 1)) : 0;\
+ while (nsg_nextPageOffset) {\
+ while (nstrace_buf_offset < NSPR_PAGESIZE_TRACE) {\
+ nstrace_tmpbuff[nstrace_tmpbuff_off++] = nstrace_buf[nstrace_buf_offset++];\
+ }\
+ nstrace_buflen = NSPR_PAGESIZE_TRACE;\
+ nstrace->xxx_offset += nstrace_buflen;\
+ bytes_read = file_read(nstrace_buf, NSPR_PAGESIZE_TRACE, wth->fh);\
+ if (bytes_read != NSPR_PAGESIZE_TRACE) {\
+ return FALSE;\
+ } else {\
+ nstrace_buf_offset = 0;\
+ }\
+ rec_size = nst_dataSize - nstrace_tmpbuff_off;\
+ nsg_nextPageOffset = ((nstrace_buf_offset + rec_size) >= NSPR_PAGESIZE_TRACE) ?\
+ ((nstrace_buf_offset + rec_size) - (NSPR_PAGESIZE_TRACE- 1)): 0;\
+ } \
+ while (nstrace_tmpbuff_off < nst_dataSize) {\
+ nstrace_tmpbuff[nstrace_tmpbuff_off++] = nstrace_buf[nstrace_buf_offset++];\
+ }\
+ 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;\
+ return TRUE;\
+} while(0)
+
+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;
+ gchar *nstrace_buf = nstrace->pnstrace_buf;
+ gint32 nstrace_buf_offset = nstrace->nstrace_buf_offset;
+ gint32 nstrace_buflen = nstrace->nstrace_buflen;
+ guint8 nstrace_tmpbuff[65536];
+ guint32 nstrace_tmpbuff_off=0,nst_dataSize=0,rec_size=0,nsg_nextPageOffset=0;
+ nspr_hd_v20_t *hdp;
+ int bytes_read;
+ *err = 0;
+ *err_info = NULL;
+
+ do
+ {
+ while ((nstrace_buf_offset < NSPR_PAGESIZE_TRACE) &&
+ nstrace_buf[nstrace_buf_offset])
+ {
+ hdp = (nspr_hd_v20_t *) &nstrace_buf[nstrace_buf_offset];
+ switch (hdp->phd_RecordType)
+ {
+
+#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_FULL_V30(&wth->phdr,30,300);
+
+#undef GENERATE_CASE_FULL_V30
+
+ case NSPR_ABSTIME_V20:
+ {
+ nstrace_buf_offset += nspr_getv20recordsize(hdp);
+ ns_setabstime(nstrace, pletoh32(&((nspr_abstime_v20_t *) &nstrace_buf[nstrace_buf_offset])->abs_Time), pletoh16(&((nspr_abstime_v20_t *) &nstrace_buf[nstrace_buf_offset])->abs_RelTime));
+ break;
+ }
+
+ case NSPR_RELTIME_V20:
+ {
+ ns_setrelativetime(nstrace, pletoh16(&((nspr_abstime_v20_t *) &nstrace_buf[nstrace_buf_offset])->abs_RelTime));
+ nstrace_buf_offset += nspr_getv20recordsize(hdp);
+ break;
+ }
+
+ default:
+ {
+ nstrace_buf_offset += nspr_getv20recordsize(hdp);
+ break;
+ }
+ }
+ }
+ nstrace_buf_offset = 0;
+ nstrace->xxx_offset += nstrace_buflen;
+ nstrace_buflen = NSPR_PAGESIZE_TRACE;
+ } while((nstrace_buflen > 0) && (bytes_read = file_read(nstrace_buf, nstrace_buflen, wth->fh)) && (bytes_read == nstrace_buflen));
+
+ return FALSE;
+}
+
+#undef PACKET_DESCRIBE
+
static gboolean nstrace_seek_read_v10(wtap *wth, gint64 seek_off,
- struct wtap_pkthdr *phdr, Buffer *buf, int length,
- int *err, gchar **err_info)
+ struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
{
+ nspr_hd_v10_t hdr;
+ guint record_length;
guint8 *pd;
- int bytes_read;
+ unsigned int bytes_to_read;
nspr_pktracefull_v10_t *fp;
nspr_pktracepart_v10_t *pp;
return FALSE;
/*
- ** Read the packet data.
+ ** Read the record header.
*/
- buffer_assure_space(buf, length);
- pd = buffer_start_ptr(buf);
- bytes_read = file_read(pd, length, wth->random_fh);
- if (bytes_read != length) {
- *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.
+ */
+ record_length = nspr_getv10recordsize(&hdr);
+
+ /*
+ ** Copy the header to the buffer and read the rest of the record..
+ */
+ 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);
+ if (!wtap_read_bytes(wth->random_fh, pd + sizeof hdr, bytes_to_read,
+ err, err_info))
+ return FALSE;
}
+ /*
+ ** Fill in what part of the struct wtap_pkthdr we can.
+ */
#define GENERATE_CASE_FULL(phdr,type,acttype) \
case NSPR_PDPKTRACEFULLTX_V##type:\
case NSPR_PDPKTRACEFULLTXB_V##type:\
}while(0)
static gboolean nstrace_seek_read_v20(wtap *wth, gint64 seek_off,
- struct wtap_pkthdr *phdr, Buffer *buf, int length,
- int *err, gchar **err_info)
+ struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
{
+ nspr_hd_v20_t hdr;
+ guint record_length;
+ guint hdrlen;
guint8 *pd;
- int bytes_read;
+ unsigned int bytes_to_read;
*err = 0;
return FALSE;
/*
- ** Read the packet data.
+ ** Read the first 2 bytes of the record header.
*/
- buffer_assure_space(buf, length);
- pd = buffer_start_ptr(buf);
- bytes_read = file_read(pd, length, wth->random_fh);
- if (bytes_read != length) {
- *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) {
+ if (!wtap_read_bytes(wth->random_fh, (void *)&hdr.phd_RecordSizeHigh, 1,
+ err, err_info))
+ return FALSE;
+ hdrlen = 3;
+ }
+
+ /*
+ ** Get the record length.
+ */
+ record_length = nspr_getv20recordsize(&hdr);
+
+ /*
+ ** Copy the header to the buffer and read the rest of the record..
+ */
+ 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);
+ if (!wtap_read_bytes(wth->random_fh, pd + hdrlen, bytes_to_read,
+ err, err_info))
+ return FALSE;
}
#define GENERATE_CASE_FULL(phdr,type,acttype) \
return TRUE;
}
+
+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;
+ guint record_length;
+ guint hdrlen;
+ guint8 *pd;
+ unsigned int bytes_to_read;
+
+ *err = 0;
+
+ if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
+ return FALSE;
+ /*
+ ** Read the first 2 bytes of the record header.
+ */
+ 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) {
+ if (!wtap_read_bytes(wth->random_fh, (void *)&hdr.phd_RecordSizeHigh, 1,
+ err, err_info))
+ return FALSE;
+ hdrlen = 3;
+ }
+
+ /*
+ ** Get the record length.
+ */
+ record_length = nspr_getv20recordsize(&hdr);
+
+ /*
+ ** Copy the header to the buffer and read the rest of the record..
+ */
+ 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);
+ if (!wtap_read_bytes(wth->random_fh, pd + hdrlen, bytes_to_read,
+ err, err_info))
+ return FALSE;
+ }
+
+#define GENERATE_CASE_V30(phdr,type,acttype) \
+ case NSPR_PDPKTRACEFULLTX_V##type:\
+ case NSPR_PDPKTRACEFULLTXB_V##type:\
+ case NSPR_PDPKTRACEFULLRX_V##type:\
+ case NSPR_PDPKTRACEFULLNEWRX_V##type:\
+ TRACE_V##type##_REC_LEN_OFF((phdr),v##type##_full,fp,pktracefull_v##type);\
+ (phdr)->pseudo_header.nstr.rec_type = NSPR_HEADER_VERSION##acttype;\
+ break;
+
+ switch ((( nspr_hd_v20_t*)pd)->phd_RecordType)
+ {
+ GENERATE_CASE_V30(phdr,30, 300);
+ }
+
+ return TRUE;
+}
+
+
/*
** Netscaler trace format close routines.
*/
if (encap == WTAP_ENCAP_NSTRACE_1_0)
return 0;
- return WTAP_ERR_UNSUPPORTED_ENCAP;
+ return WTAP_ERR_UNWRITABLE_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,
+** an error indication otherwise. */
+int nstrace_30_dump_can_write_encap(int encap)
+{
+ if (encap == WTAP_ENCAP_NSTRACE_3_0)
+ return 0;
+
+ return WTAP_ERR_UNWRITABLE_ENCAP;
+}
/* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
** failure */
/* Move forward the page offset */
nstrace->page_offset += (guint16) sig20.sig_RecordSize;
+ } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0)
+ {
+ nspr_signature_v30_t sig30;
+
+ sig30.sig_RecordType = NSPR_SIGNATURE_V30;
+ sig30.sig_RecordSize = nspr_signature_v30_s;
+ memcpy(sig30.sig_Signature, NSPR_SIGSTR_V30, sizeof(NSPR_SIGSTR_V30));
+
+ /* Write the record into the file */
+ if (!wtap_dump_file_write(wdh, &sig30, sig30.sig_RecordSize,
+ err))
+ return FALSE;
+
+ /* Move forward the page offset */
+ nstrace->page_offset += (guint16) sig30.sig_RecordSize;
} else
{
g_assert_not_reached();
/* Move forward the page offset */
nstrace->page_offset += nspr_abstime_v10_s;
- } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
- {
+ } else if ((wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0) ||
+ (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0)) {
guint32 reltime;
guint64 abstime;
nspr_abstime_v20_t abs20;
/* 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 */
!nstrace_add_abstime(wdh, phdr, pd, err))
return FALSE;
} else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
+ {
+ if (!nstrace_add_signature(wdh, err) ||
+ !nstrace_add_abstime(wdh, phdr, pd, err))
+ return FALSE;
+ } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0)
{
if (!nstrace_add_signature(wdh, err) ||
!nstrace_add_abstime(wdh, phdr, pd, err))
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;
}
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)
{
break;
+ case NSPR_HEADER_VERSION300:
+ if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0)
+ {
+ *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
+ return FALSE;
+ } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0)
+ {
+ *err = WTAP_ERR_UNWRITABLE_FILE_TYPE;
+ return FALSE;
+ } else if (wdh->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0)
+ {
+ if (nstrace->page_offset + phdr->caplen >= nstrace->page_len)
+ {
+ /* Start on the next page */
+ if (wtap_dump_file_seek(wdh, (nstrace->page_len - nstrace->page_offset), SEEK_CUR, err) == -1)
+ return FALSE;
+
+ nstrace->page_offset = 0;
+
+ /* Possibly add signature and abstime records and increment offset */
+ if (!nstrace_add_signature(wdh, err))
+ return FALSE;
+ }
+
+ /* Write the actual record as is */
+ if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
+ return FALSE;
+
+ nstrace->page_offset += (guint16) phdr->caplen;
+ } else
+ {
+ g_assert_not_reached();
+ return FALSE;
+ }
+ break;
+
default:
g_assert_not_reached();
return FALSE;
return TRUE;
}
-