/* vms.c
- *
- * $Id$
*
* Wiretap Library
* Copyright (c) 2001 by Marc Milgram <ethereal@mmilgram.NOSPAMmail.net>
*/
#include "config.h"
#include "wtap-int.h"
-#include "buffer.h"
#include "vms.h"
#include "file_wrappers.h"
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
/* This module reads the output of the various VMS TCPIP trace utilities
* such as TCPIPTRACE, TCPTRACE and UCX$TRACE
... packet seq # = nn at DD-MMM-YYYY hh:mm:ss.ss
-If there are other formats then code will have to be written in parse_vms_rec_hdr()
+If there are other formats then code will have to be written in parse_vms_packet()
to handle them.
--------------------------------------------------------------------------------
/* Magic text to check for VMS-ness of file using possible utility names
*
*/
-#define VMS_HDR_MAGIC_STR1 "TCPIPtrace"
-#define VMS_HDR_MAGIC_STR2 "TCPtrace"
-#define VMS_HDR_MAGIC_STR3 "INTERnet trace"
+#define VMS_HDR_MAGIC_STR1 "TCPIPtrace"
+#define VMS_HDR_MAGIC_STR2 "TCPtrace"
+#define VMS_HDR_MAGIC_STR3 "INTERnet trace"
/* Magic text for start of packet */
-#define VMS_REC_MAGIC_STR1 VMS_HDR_MAGIC_STR1
-#define VMS_REC_MAGIC_STR2 VMS_HDR_MAGIC_STR2
-#define VMS_REC_MAGIC_STR3 VMS_HDR_MAGIC_STR3
+#define VMS_REC_MAGIC_STR1 VMS_HDR_MAGIC_STR1
+#define VMS_REC_MAGIC_STR2 VMS_HDR_MAGIC_STR2
+#define VMS_REC_MAGIC_STR3 VMS_HDR_MAGIC_STR3
#define VMS_HEADER_LINES_TO_CHECK 200
#define VMS_LINE_LENGTH 240
static gboolean vms_read(wtap *wth, int *err, gchar **err_info,
gint64 *data_offset);
static gboolean vms_seek_read(wtap *wth, gint64 seek_off,
- struct wtap_pkthdr *phdr, guint8 *pd, int len,
- int *err, gchar **err_info);
+ struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
static gboolean parse_single_hex_dump_line(char* rec, guint8 *buf,
long byte_offset, int in_off, int remaining_bytes);
-static gboolean parse_vms_hex_dump(FILE_T fh, int pkt_len, guint8* buf,
- int *err, gchar **err_info);
-static gboolean parse_vms_rec_hdr(FILE_T fh, struct wtap_pkthdr *phdr,
- int *err, gchar **err_info);
+static gboolean parse_vms_packet(FILE_T fh, struct wtap_pkthdr *phdr,
+ Buffer *buf, int *err, gchar **err_info);
#ifdef TCPIPTRACE_FRAGMENTS_HAVE_HEADER_LINE
/* Seeks to the beginning of the next packet, and returns the
}
-int vms_open(wtap *wth, int *err, gchar **err_info)
+wtap_open_return_val vms_open(wtap *wth, int *err, gchar **err_info)
{
/* Look for VMS header */
if (!vms_check_file_type(wth, err, err_info)) {
if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
- return -1;
- return 0;
+ return WTAP_OPEN_ERROR;
+ return WTAP_OPEN_NOT_MINE;
}
wth->file_encap = WTAP_ENCAP_RAW_IP;
- wth->file_type = WTAP_FILE_VMS;
+ wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_VMS;
wth->snapshot_length = 0; /* not known */
wth->subtype_read = vms_read;
wth->subtype_seek_read = vms_seek_read;
- wth->tsprecision = WTAP_FILE_TSPREC_CSEC;
+ wth->file_tsprec = WTAP_TSPREC_CSEC;
- return 1;
+ return WTAP_OPEN_MINE;
}
/* Find the next packet and parse it; called from wtap_read(). */
gint64 *data_offset)
{
gint64 offset = 0;
- guint8 *buf;
/* Find the next packet */
#ifdef TCPIPTRACE_FRAGMENTS_HAVE_HEADER_LINE
*err = file_error(wth->fh, err_info);
return FALSE;
}
-
- /* Parse the header */
- if (!parse_vms_rec_hdr(wth->fh, &wth->phdr, err, err_info))
- return FALSE;
-
- /* Make sure we have enough room for the packet */
- buffer_assure_space(wth->frame_buffer, wth->phdr.caplen);
- buf = buffer_start_ptr(wth->frame_buffer);
-
- /* Convert the ASCII hex dump to binary data */
- if (!parse_vms_hex_dump(wth->fh, wth->phdr.caplen, buf, err, err_info))
- return FALSE;
-
*data_offset = offset;
- return TRUE;
+
+ /* Parse the packet */
+ return parse_vms_packet(wth->fh, &wth->phdr, wth->frame_buffer, err, err_info);
}
/* Used to read packets in random-access fashion */
static gboolean
-vms_seek_read (wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr,
- guint8 *pd, int len, int *err, gchar **err_info)
+vms_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr,
+ Buffer *buf, int *err, gchar **err_info)
{
if (file_seek(wth->random_fh, seek_off - 1, SEEK_SET, err) == -1)
return FALSE;
- if (!parse_vms_rec_hdr(wth->random_fh, phdr, err, err_info))
- return FALSE;
-
- if (phdr->caplen != (guint32)len) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("vms: requested length %d doesn't match length %d",
- len, phdr->caplen);
+ if (!parse_vms_packet(wth->random_fh, phdr, buf, err, err_info)) {
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
return FALSE;
}
-
- return parse_vms_hex_dump(wth->random_fh, phdr->caplen, pd, err, err_info);
+ return TRUE;
}
/* isdumpline assumes that dump lines start with some non-alphanumerics
{
int i, j;
- while (*line && !isalnum((guchar)*line))
- line++;
+ while (*line && !g_ascii_isalnum(*line))
+ line++;
for (j=0; j<4; j++) {
- for (i=0; i<8; i++, line++)
- if (! isxdigit((guchar)*line))
- return FALSE;
+ for (i=0; i<8; i++, line++)
+ if (! g_ascii_isxdigit(*line))
+ return FALSE;
- for (i=0; i<3; i++, line++)
- if (*line != ' ')
- return FALSE;
+ for (i=0; i<3; i++, line++)
+ if (*line != ' ')
+ return FALSE;
}
- return isspace((guchar)*line);
+ return g_ascii_isspace(*line);
}
-/* Parses a packet record header. */
+/* Parses a packet record. */
static gboolean
-parse_vms_rec_hdr(FILE_T fh, struct wtap_pkthdr *phdr, int *err, gchar **err_info)
+parse_vms_packet(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
{
char line[VMS_LINE_LENGTH + 1];
int num_items_scanned;
- int pkt_len = 0;
- int pktnum;
- int csec = 101;
+ int pkt_len = 0;
+ int pktnum;
+ int csec = 101;
struct tm tm;
char mon[4] = {'J', 'A', 'N', 0};
gchar *p;
static const gchar months[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
+ int i;
+ int offset = 0;
+ guint8 *pd;
tm.tm_year = 1970;
tm.tm_mon = 0;
do {
if (file_gets(line, VMS_LINE_LENGTH, fh) == NULL) {
*err = file_error(fh, err_info);
- if ((*err == 0) && (csec != 101)) {
- *err = WTAP_ERR_SHORT_READ;
+ if ((*err == 0) && (csec != 101)) {
+ *err = WTAP_ERR_SHORT_READ;
}
return FALSE;
}
- line[VMS_LINE_LENGTH] = '\0';
-
- if ((csec == 101) && (p = strstr(line, "packet ")) != NULL
- && (! strstr(line, "could not save "))) {
- /* Find text in line starting with "packet ". */
-
- /* First look for the Format 1 type sequencing */
- num_items_scanned = sscanf(p,
- "packet %9d at %2d-%3s-%4d %2d:%2d:%2d.%9d",
- &pktnum, &tm.tm_mday, mon,
- &tm.tm_year, &tm.tm_hour,
- &tm.tm_min, &tm.tm_sec, &csec);
- /* Next look for the Format 2 type sequencing */
- if (num_items_scanned != 8) {
- num_items_scanned = sscanf(p,
- "packet seq # = %9d at %2d-%3s-%4d %2d:%2d:%2d.%9d",
- &pktnum, &tm.tm_mday, mon,
- &tm.tm_year, &tm.tm_hour,
- &tm.tm_min, &tm.tm_sec, &csec);
- }
- /* if unknown format then exit with error */
- /* We will need to add code to handle new format */
- if (num_items_scanned != 8) {
- *err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("vms: header line not valid");
- return FALSE;
- }
- }
+ line[VMS_LINE_LENGTH] = '\0';
+
+ if ((csec == 101) && (p = strstr(line, "packet ")) != NULL
+ && (! strstr(line, "could not save "))) {
+ /* Find text in line starting with "packet ". */
+
+ /* First look for the Format 1 type sequencing */
+ num_items_scanned = sscanf(p,
+ "packet %9d at %2d-%3s-%4d %2d:%2d:%2d.%9d",
+ &pktnum, &tm.tm_mday, mon,
+ &tm.tm_year, &tm.tm_hour,
+ &tm.tm_min, &tm.tm_sec, &csec);
+ /* Next look for the Format 2 type sequencing */
+ if (num_items_scanned != 8) {
+ num_items_scanned = sscanf(p,
+ "packet seq # = %9d at %2d-%3s-%4d %2d:%2d:%2d.%9d",
+ &pktnum, &tm.tm_mday, mon,
+ &tm.tm_year, &tm.tm_hour,
+ &tm.tm_min, &tm.tm_sec, &csec);
+ }
+ /* if unknown format then exit with error */
+ /* We will need to add code to handle new format */
+ if (num_items_scanned != 8) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup("vms: header line not valid");
+ return FALSE;
+ }
+ }
if ( (! pkt_len) && (p = strstr(line, "Length"))) {
p += sizeof("Length ");
- while (*p && ! isdigit((guchar)*p))
+ while (*p && ! g_ascii_isdigit(*p))
p++;
if ( !*p ) {
*err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("vms: Length field not valid");
+ *err_info = g_strdup("vms: Length field not valid");
return FALSE;
}
pkt_len = atoi(p);
- break;
+ break;
}
} while (! isdumpline(line));
+ if (pkt_len > WTAP_MAX_PACKET_SIZE) {
+ /*
+ * Probably a corrupt capture file; return an error,
+ * so that our caller doesn't blow up trying to allocate
+ * space for an immensely-large packet.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("vms: File has %u-byte packet, bigger than maximum of %u",
+ pkt_len, WTAP_MAX_PACKET_SIZE);
+ return FALSE;
+ }
p = strstr(months, mon);
if (p)
tm.tm_year -= 1900;
tm.tm_isdst = -1;
+ phdr->rec_type = REC_TYPE_PACKET;
phdr->presence_flags = WTAP_HAS_TS;
phdr->ts.secs = mktime(&tm);
phdr->ts.nsecs = csec * 10000000;
phdr->caplen = pkt_len;
phdr->len = pkt_len;
- return TRUE;
-}
-
-/* Converts ASCII hex dump to binary data */
-static gboolean
-parse_vms_hex_dump(FILE_T fh, int pkt_len, guint8* buf, int *err,
- gchar **err_info)
-{
- gchar line[VMS_LINE_LENGTH + 1];
- int i;
- int offset = 0;
+ /* Make sure we have enough room for the packet */
+ ws_buffer_assure_space(buf, pkt_len);
+ pd = ws_buffer_start_ptr(buf);
+ /* Convert the ASCII hex dump to binary data */
for (i = 0; i < pkt_len; i += 16) {
if (file_gets(line, VMS_LINE_LENGTH, fh) == NULL) {
*err = file_error(fh, err_info);
}
return FALSE;
}
- line[VMS_LINE_LENGTH] = '\0';
+ line[VMS_LINE_LENGTH] = '\0';
if (i == 0) {
- while (! isdumpline(line)) { /* advance to start of hex data */
- if (file_gets(line, VMS_LINE_LENGTH, fh) == NULL) {
- *err = file_error(fh, err_info);
- if (*err == 0) {
- *err = WTAP_ERR_SHORT_READ;
- }
- return FALSE;
- }
- line[VMS_LINE_LENGTH] = '\0';
- }
- while (line[offset] && !isxdigit((guchar)line[offset]))
+ while (! isdumpline(line)) { /* advance to start of hex data */
+ if (file_gets(line, VMS_LINE_LENGTH, fh) == NULL) {
+ *err = file_error(fh, err_info);
+ if (*err == 0) {
+ *err = WTAP_ERR_SHORT_READ;
+ }
+ return FALSE;
+ }
+ line[VMS_LINE_LENGTH] = '\0';
+ }
+ while (line[offset] && !g_ascii_isxdigit(line[offset]))
offset++;
- }
- if (!parse_single_hex_dump_line(line, buf, i,
- offset, pkt_len - i)) {
+ }
+ if (!parse_single_hex_dump_line(line, pd, i,
+ offset, pkt_len - i)) {
*err = WTAP_ERR_BAD_FILE;
- *err_info = g_strdup_printf("vms: hex dump not valid");
+ *err_info = g_strdup("vms: hex dump not valid");
return FALSE;
}
}
/* Get the byte_offset directly from the record */
s = rec;
- value = (int)strtoul(s + 45 + in_off, NULL, 16); /* XXX - error check? */
+ value = (int)strtoul(s + 45 + in_off, NULL, 16); /* XXX - error check? */
if (value != byte_offset) {
return FALSE;
}
if (remaining > 16)
- remaining = 16;
+ remaining = 16;
/* Read the octets right to left, as that is how they are displayed
* in VMS.
return TRUE;
}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */