aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap/netscaler.c
diff options
context:
space:
mode:
Diffstat (limited to 'wiretap/netscaler.c')
-rw-r--r--wiretap/netscaler.c129
1 files changed, 93 insertions, 36 deletions
diff --git a/wiretap/netscaler.c b/wiretap/netscaler.c
index 687b5ac1c5..307f2bc044 100644
--- a/wiretap/netscaler.c
+++ b/wiretap/netscaler.c
@@ -602,7 +602,7 @@ typedef struct {
guint64 file_size;
} nstrace_t;
-static guint32 nspm_signature_version(wtap*, gchar*, gint32);
+static guint32 nspm_signature_version(gchar*, gint32);
static gboolean nstrace_read_v10(wtap *wth, int *err, gchar **err_info,
gint64 *data_offset);
static gboolean nstrace_read_v20(wtap *wth, int *err, gchar **err_info,
@@ -697,16 +697,33 @@ wtap_open_return_val nstrace_open(wtap *wth, int *err, gchar **err_info)
gchar *nstrace_buf;
gint64 file_size;
gint32 page_size;
+ int bytes_read;
nstrace_t *nstrace;
-
if ((file_size = wtap_file_size(wth, err)) == -1)
+ return WTAP_OPEN_ERROR;
+ if (file_size == 0)
return WTAP_OPEN_NOT_MINE;
+ /* The size is 64 bits; we assume it fits in 63 bits, so it's positive */
nstrace_buf = (gchar *)g_malloc(NSPR_PAGESIZE);
page_size = GET_READ_PAGE_SIZE(file_size);
- switch ((wth->file_type_subtype = nspm_signature_version(wth, nstrace_buf, page_size)))
+ /* Read the first page, so we can look for a signature */
+ bytes_read = file_read(nstrace_buf, page_size, wth->fh);
+ if (bytes_read < 0 || bytes_read != page_size) {
+ *err = file_error(wth->fh, err_info);
+ if (*err == 0 && bytes_read > 0)
+ return WTAP_OPEN_NOT_MINE;
+ return WTAP_OPEN_ERROR;
+ }
+
+ /*
+ * Scan it for a signature block.
+ */
+ wth->file_type_subtype = nspm_signature_version(nstrace_buf, page_size);
+
+ switch (wth->file_type_subtype)
{
case WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0:
wth->file_encap = WTAP_ENCAP_NSTRACE_1_0;
@@ -736,12 +753,14 @@ wtap_open_return_val nstrace_open(wtap *wth, int *err, gchar **err_info)
return WTAP_OPEN_NOT_MINE;
}
+ /* Seek back to the beginning of the file after reading the first byte. */
if ((file_seek(wth->fh, 0, SEEK_SET, err)) == -1)
{
g_free(nstrace_buf);
return WTAP_OPEN_ERROR;
}
+ /* XXX - didn't the read above already handle this? */
if (!wtap_read_bytes(wth->fh, nstrace_buf, page_size, err, err_info))
{
g_free(nstrace_buf);
@@ -830,7 +849,12 @@ wtap_open_return_val nstrace_open(wtap *wth, int *err, gchar **err_info)
** the version specified as an argument to the macro.
**
** The function does so by checking whether the signature string for
-** the version in question is a prefix of the signature field.
+** the version in question is a prefix of the signature field. The
+** signature field appears to be a blob of text, with one or more
+** lines, with lines separated by '\n', and the last line terminated
+** with '\0'. The first lign is the signature field; it may end with
+** '\n', meaning there's another line following it, or it may end
+** with '\0', meaning it's the last line.
**
** For that to be true, the field must have a size >= to the size (not
** counting the terminating'\0') of the version's signature string,
@@ -838,7 +862,8 @@ wtap_open_return_val nstrace_open(wtap *wth, int *err, gchar **err_info)
** version string of the version (again, not counting the terminating
** '\0'), are equal to the version's signature string.
**
-** XXX - should this do an exact match rather than a prefix match?
+** XXX - should this do an exact match rather than a prefix match,
+** checking whether either a '\n' or '\0' follows the first line?
*/
#define nspm_signature_func(ver) \
static guint32 nspm_signature_isv##ver(gchar *sigp, size_t sigsize) {\
@@ -852,49 +877,81 @@ nspm_signature_func(30)
nspm_signature_func(35)
/*
-** 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.
+** Scan a page for something that looks like a signature record and,
+** if we find one, check the signature against the ones we support.
+** If we find one we support, return the file type/subtype for that
+** file version. If we don't find a signature record with a signature
+** we support, return WTAP_FILE_TYPE_SUBTYPE_UNKNOWN.
+**
+** We don't know what version the file is, so we can't make
+** assumptions about the format of the records.
+**
+** XXX - can we assume the signature block is the first block?
*/
static guint32
-nspm_signature_version(wtap *wth, gchar *nstrace_buf, gint32 len)
+nspm_signature_version(gchar *nstrace_buf, gint32 len)
{
gchar *dp = nstrace_buf;
- int bytes_read;
-
- bytes_read = file_read(dp, len, wth->fh);
- if (bytes_read == len) {
- for ( ; len > (gint32)(MIN(sizeof(NSPR_SIGSTR_V10), sizeof(NSPR_SIGSTR_V20))); dp++, len--)
- {
+ for ( ; len > (gint32)(MIN(nspr_signature_v10_s, nspr_signature_v20_s)); dp++, len--)
+ {
#define sigv10p ((nspr_signature_v10_t*)dp)
- if ((pletoh16(&sigv10p->nsprRecordType) == NSPR_SIGNATURE_V10) &&
- (pletoh16(&sigv10p->nsprRecordSize) <= len) &&
- (pletoh16(&sigv10p->nsprRecordSize) > 0) &&
- ((gint32)sizeof(NSPR_SIGSTR_V10) <= len) &&
- (nspm_signature_isv10(sigv10p->sig_Signature, sizeof sigv10p->sig_Signature)))
+ /*
+ * If this is a V10 signature record, then:
+ *
+ * 1) we have a full signature record's worth of data in what
+ * remains of the first page;
+ *
+ * 2) it appears to have a record type of NSPR_SIGNATURE_V10;
+ *
+ * 3) the length field specifies a length that fits in what
+ * remains of the first page;
+ *
+ * 4) it also specifies something as large as, or larger than,
+ * the declared size of a V10 signature record.
+ *
+ * (XXX - are all V10 signature records that size, or might they
+ * be smaller, with a shorter signature field?)
+ */
+ if ((size_t)len >= nspr_signature_v10_s &&
+ (pletoh16(&sigv10p->nsprRecordType) == NSPR_SIGNATURE_V10) &&
+ (pletoh16(&sigv10p->nsprRecordSize) <= len) &&
+ (pletoh16(&sigv10p->nsprRecordSize) >= nspr_signature_v10_s))
+ {
+ if ((nspm_signature_isv10(sigv10p->sig_Signature, sizeof sigv10p->sig_Signature)))
return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_1_0;
+ }
#undef sigv10p
#define sigv20p ((nspr_signature_v20_t*)dp)
- if ((sigv20p->sig_RecordType == NSPR_SIGNATURE_V20) &&
- (sigv20p->sig_RecordSize <= len) &&
- ((gint32)sizeof(NSPR_SIGSTR_V20) <= len))
- {
- sigv20p->sig_Signature[sigv20p->sig_RecordSize] = '\0';
- if (nspm_signature_isv20(sigv20p->sig_Signature, sizeof sigv20p->sig_Signature)){
- return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0;
- } else if (nspm_signature_isv30(sigv20p->sig_Signature, sizeof sigv20p->sig_Signature)){
- return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0;
- }else if (nspm_signature_isv35(sigv20p->sig_Signature, sizeof sigv20p->sig_Signature)){
- return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_5;
- }
+ /*
+ * If this is a V20-or-later signature record, then:
+ *
+ * 1) we have a full signature record's worth of data in what
+ * remains of the first page;
+ *
+ * 2) it appears to have a record type of NSPR_SIGNATURE_V20;
+ *
+ * 3) the length field specifies a length that fits in what
+ * remains of the first page;
+ *
+ * 4) it also specifies something as large as, or larger than,
+ * the declared size of a V20 signature record.
+ */
+ if ((size_t)len >= nspr_signature_v20_s &&
+ (sigv20p->sig_RecordType == NSPR_SIGNATURE_V20) &&
+ (sigv20p->sig_RecordSize <= len) &&
+ (sigv20p->sig_RecordSize >= nspr_signature_v20_s))
+ {
+ if (nspm_signature_isv20(sigv20p->sig_Signature, sizeof sigv20p->sig_Signature)){
+ return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_2_0;
+ } else if (nspm_signature_isv30(sigv20p->sig_Signature, sizeof sigv20p->sig_Signature)){
+ return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_0;
+ } else if (nspm_signature_isv35(sigv20p->sig_Signature, sizeof sigv20p->sig_Signature)){
+ return WTAP_FILE_TYPE_SUBTYPE_NETSCALER_3_5;
}
-#undef sigv20p
}
+#undef sigv20p
}
return WTAP_FILE_TYPE_SUBTYPE_UNKNOWN; /* no version found */