#include <ctype.h>
#include <errno.h>
+#include <wsutil/str_util.h>
+
#define ISERIES_HDR_MAGIC_STR " COMMUNICATIONS TRACE"
#define ISERIES_HDR_MAGIC_LEN 21
#define ISERIES_PKT_MAGIC_STR "ETHV2"
#define ISERIES_FORMAT_ASCII 1
#define ISERIES_FORMAT_UNICODE 2
+typedef struct {
+ gboolean have_date; /* TRUE if we found a capture start date */
+ int year, month, day; /* The start date */
+ gboolean tcp_formatted; /* TCP/IP data formated Y/N */
+ int format; /* Trace format type */
+} iseries_t;
+
static gboolean iseries_read (wtap * wth, int *err, gchar ** err_info,
gint64 *data_offset);
static gboolean iseries_seek_read (wtap * wth, gint64 seek_off,
union wtap_pseudo_header *pseudo_header,
guint8 * pd, int len, int *err,
gchar ** err_info);
-static gboolean iseries_check_file_type (wtap * wth, int *err, int format);
-static gint64 iseries_seek_next_packet (wtap * wth, int *err);
+static gboolean iseries_check_file_type (wtap * wth, int *err, gchar **err_info,
+ int format);
+static gint64 iseries_seek_next_packet (wtap * wth, int *err, gchar **err_info);
static int iseries_parse_packet (wtap * wth, FILE_T fh,
union wtap_pseudo_header *pseudo_header,
guint8 * pd, int *err, gchar ** err_info);
static int iseries_UNICODE_to_ASCII (guint8 * buf, guint bytes);
-static gboolean iseries_parse_hex_string (guint8 * ascii, guint8 * buf,
+static gboolean iseries_parse_hex_string (const char * ascii, guint8 * buf,
int len);
int
-iseries_open (wtap * wth, int *err, gchar ** err_info _U_)
+iseries_open (wtap * wth, int *err, gchar ** err_info)
{
int bytes_read;
char magic[ISERIES_HDR_MAGIC_LEN];
* Check that file starts with a valid iSeries COMMS TRACE header
*/
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read (&magic, 1, sizeof magic, wth->fh);
+ bytes_read = file_read (&magic, sizeof magic, wth->fh);
if (bytes_read != sizeof magic)
{
- *err = file_error (wth->fh);
+ *err = file_error (wth->fh, err_info);
if (*err != 0)
return -1;
return 0;
* Do some basic sanity checking to ensure we can handle the
* contents of this trace
*/
- if (!iseries_check_file_type (wth, err, ISERIES_FORMAT_ASCII))
+ if (!iseries_check_file_type (wth, err, err_info, ISERIES_FORMAT_ASCII))
{
if (*err == 0)
return 0;
return -1;
}
wth->data_offset = 0;
- wth->file_encap = WTAP_ENCAP_PER_PACKET;
+ wth->file_encap = WTAP_ENCAP_ETHERNET;
wth->file_type = WTAP_FILE_ISERIES;
wth->snapshot_length = 0;
wth->subtype_read = iseries_read;
* Do some basic sanity checking to ensure we can handle the
* contents of this trace
*/
- if (!iseries_check_file_type (wth, err, ISERIES_FORMAT_UNICODE))
+ if (!iseries_check_file_type (wth, err, err_info, ISERIES_FORMAT_UNICODE))
{
if (*err == 0)
return 0;
return -1;
}
wth->data_offset = 0;
- wth->file_encap = WTAP_ENCAP_PER_PACKET;
+ wth->file_encap = WTAP_ENCAP_ETHERNET;
wth->file_type = WTAP_FILE_ISERIES_UNICODE;
wth->snapshot_length = 0;
wth->subtype_read = iseries_read;
* requisit requirements and additional information.
*/
static gboolean
-iseries_check_file_type (wtap * wth, int *err, int format)
+iseries_check_file_type (wtap * wth, int *err, gchar **err_info, int format)
{
guint line;
int num_items_scanned;
- char buf[ISERIES_LINE_LENGTH], protocol[9], tcpformat[2];
- guint8 *sdate;
+ char buf[ISERIES_LINE_LENGTH], protocol[9], tcpformat[2] = "";
+ iseries_t *iseries;
/* Save trace format for passing between packets */
- sdate = g_malloc (10);
- wth->capture.iseries = g_malloc (sizeof (iseries_t));
- wth->capture.iseries->sdate = NULL;
- wth->capture.iseries->format = format;
- wth->capture.iseries->tcp_formatted = FALSE;
+ iseries = (iseries_t *) g_malloc (sizeof (iseries_t));
+ wth->priv = (void *)iseries;
+ iseries->have_date = FALSE;
+ iseries->format = format;
+ iseries->tcp_formatted = FALSE;
for (line = 0; line < ISERIES_HDR_LINES_TO_CHECK; line++)
{
/*
* Check that we are dealing with an ETHERNET trace
*/
- if (wth->capture.iseries->format == ISERIES_FORMAT_UNICODE)
+ if (iseries->format == ISERIES_FORMAT_UNICODE)
{
- iseries_UNICODE_to_ASCII (buf, ISERIES_LINE_LENGTH);
+ iseries_UNICODE_to_ASCII ((guint8 *)buf, ISERIES_LINE_LENGTH);
}
- g_strup(buf);
+ ascii_strup_inplace(buf);
num_items_scanned = sscanf (buf,
" OBJECT PROTOCOL . . . . . . : %8s",
protocol);
{
if (strncmp (tcpformat, "Y", 1) == 0)
{
- wth->capture.iseries->tcp_formatted = TRUE;
+ iseries->tcp_formatted = TRUE;
}
else
{
- wth->capture.iseries->tcp_formatted = FALSE;
+ iseries->tcp_formatted = FALSE;
}
}
* extract it here and store for all packets to access
*/
num_items_scanned = sscanf (buf,
- " START DATE/TIME . . . . . . : %8s",
- sdate);
- if (num_items_scanned == 1)
+ " START DATE/TIME . . . . . . : %2d/%2d/%4d",
+ &iseries->month, &iseries->day,
+ &iseries->year);
+ if (num_items_scanned == 3)
{
- wth->capture.iseries->sdate = sdate;
+ iseries->have_date = TRUE;
}
}
if (file_eof (wth->fh))
*err = 0;
else
- *err = file_error (wth->fh);
+ *err = file_error (wth->fh, err_info);
return FALSE;
}
}
/*
* Locate the next packet
*/
- offset = iseries_seek_next_packet (wth, err);
+ offset = iseries_seek_next_packet (wth, err, err_info);
if (offset < 1)
return FALSE;
/*
* Seeks to the beginning of the next packet, and returns the
- * byte offset. Returns -1 on failure, and sets "*err" to the error.
+ * byte offset. Returns -1 on failure, and sets "*err" to the error
+ * and "*err_info" to null or an additional error string.
*/
static gint64
-iseries_seek_next_packet (wtap * wth, int *err)
+iseries_seek_next_packet (wtap * wth, int *err, gchar **err_info)
{
+ iseries_t *iseries = (iseries_t *)wth->priv;
char buf[ISERIES_LINE_LENGTH];
int line;
gint64 cur_off;
/*
* Seeks to the beginning of the next packet, and returns the
- * byte offset. Returns -1 on failure, and sets "*err" to the error.
+ * byte offset. Returns -1 on failure, and sets "*err" to the error
+ * and "*err_info" to null or an additional error string.
*/
for (line = 0; line < ISERIES_MAX_TRACE_LEN; line++)
{
/* Convert UNICODE to ASCII if required and determine */
/* the number of bytes to rewind to beginning of record. */
- if (wth->capture.iseries->format == ISERIES_FORMAT_UNICODE)
+ if (iseries->format == ISERIES_FORMAT_UNICODE)
{
/* buflen is #bytes to 1st 0x0A */
- buflen = iseries_UNICODE_to_ASCII (buf, ISERIES_LINE_LENGTH);
+ buflen = iseries_UNICODE_to_ASCII ((guint8 *)buf, ISERIES_LINE_LENGTH);
}
else
{
/* Else buflen is just length of the ASCII string */
- buflen = strlen (buf);
+ buflen = (long) strlen (buf);
}
/* If packet header found return the offset */
if (strncmp (buf + 80, ISERIES_PKT_MAGIC_STR, ISERIES_PKT_MAGIC_LEN)
cur_off = file_tell (wth->fh);
if (cur_off == -1)
{
- *err = file_error (wth->fh);
+ *err = file_error (wth->fh, err_info);
return -1;
}
if (file_seek (wth->fh, cur_off - buflen, SEEK_SET, err) == -1)
{
if (file_eof (wth->fh))
{
+ /* We got an EOF. */
*err = 0;
}
else
{
- /* We (presumably) got an error (there's no equivalent to "ferror()"
- in zlib, alas, so we don't have a wrapper to check for an error). */
- *err = file_error (wth->fh);
+ /* We got an error. */
+ *err = file_error (wth->fh, err_info);
}
return -1;
}
union wtap_pseudo_header *pseudo_header, guint8 * pd,
int *err, gchar ** err_info)
{
+ iseries_t *iseries = (iseries_t *)wth->priv;
gint64 cur_off;
gboolean isValid, isCurrentPacket, IPread, TCPread, isDATA;
int num_items_scanned, line, pktline, buflen, i;
guint32 pkt_len;
- int cap_len, pktnum, month, day, year, hr, min, sec, csec;
+ int cap_len, pktnum, hr, min, sec, csec;
char direction[2], destmac[13], srcmac[13], type[5], ipheader[41],
tcpheader[81];
char hex1[17], hex2[17], hex3[17], hex4[17];
char data[ISERIES_LINE_LENGTH * 2];
- guint8 *buf, *asciibuf, *tcpdatabuf, *workbuf;
+ guint8 *buf;
+ char *tcpdatabuf, *workbuf, *asciibuf;
struct tm tm;
/*
cur_off = file_tell (fh);
if (file_gets (data, ISERIES_LINE_LENGTH, fh) == NULL)
{
- *err = file_error (fh);
+ *err = file_error (fh, err_info);
if (*err == 0)
{
*err = WTAP_ERR_SHORT_READ;
return -1;
}
/* Convert UNICODE data to ASCII */
- if (wth->capture.iseries->format == ISERIES_FORMAT_UNICODE)
+ if (iseries->format == ISERIES_FORMAT_UNICODE)
{
- iseries_UNICODE_to_ASCII (data, ISERIES_LINE_LENGTH);
+ iseries_UNICODE_to_ASCII ((guint8 *)data, ISERIES_LINE_LENGTH);
}
/* look for packet header */
- for (i=0; i<8; i++) {
- if (strncmp(data+i,"*",1) == 0)
- strncpy(data+i," ",1);
+ for (i=0; i<8; i++) {
+ if (strncmp(data+i,"*",1) == 0)
+ g_strlcpy(data+i," ",(ISERIES_LINE_LENGTH * 2));
}
num_items_scanned =
sscanf (data,
- "%6d %1s %6d %d:%d:%d.%d %12s %12s ETHV2 Type: %s",
+ "%6d %1s %6d %2d:%2d:%2d.%9d %12s %12s ETHV2 Type: %4s",
&pktnum, direction, &cap_len, &hr, &min, &sec, &csec, destmac,
srcmac, type);
if (num_items_scanned == 10)
/*
* If we have Wiretap Header then populate it here
*
- * XXX - Timer resolution on the iSeries is hardware dependant, the value for csec may be
+ * XXX - Timer resolution on the iSeries is hardware dependant; the value for csec may be
* different on other platforms though all the traces I've seen seem to show resolution
* to Milliseconds (i.e HH:MM:SS.nnnnn) or Nanoseconds (i.e HH:MM:SS.nnnnnn)
*/
- if (wth->capture.iseries->sdate)
+ if (iseries->have_date)
{
- num_items_scanned =
- sscanf (wth->capture.iseries->sdate, "%d/%d/%d", &month, &day, &year);
- tm.tm_year = 100 + year;
- tm.tm_mon = month - 1;
- tm.tm_mday = day;
+ tm.tm_year = 100 + iseries->year;
+ tm.tm_mon = iseries->month - 1;
+ tm.tm_mday = iseries->day;
tm.tm_hour = hr;
tm.tm_min = min;
tm.tm_sec = sec;
{
wth->phdr.ts.nsecs = csec * 10000;
}
- wth->phdr.caplen = cap_len;
- wth->phdr.pkt_encap = WTAP_ENCAP_ETHERNET;
- pseudo_header->eth.fcs_len = -1;
}
+ wth->phdr.caplen = cap_len;
+ wth->phdr.pkt_encap = WTAP_ENCAP_ETHERNET;
+ pseudo_header->eth.fcs_len = -1;
+
/*
* Start Reading packet contents
*/
}
else
{
- *err = file_error (fh);
+ *err = file_error (fh, err_info);
if (*err == 0)
{
*err = WTAP_ERR_SHORT_READ;
}
/* Convert UNICODE data to ASCII and determine line length */
- if (wth->capture.iseries->format == ISERIES_FORMAT_UNICODE)
+ if (iseries->format == ISERIES_FORMAT_UNICODE)
{
- buflen = iseries_UNICODE_to_ASCII (data, ISERIES_LINE_LENGTH);
+ buflen = iseries_UNICODE_to_ASCII ((guint8 *)data, ISERIES_LINE_LENGTH);
}
else
{
/* Else bytes to rewind is just length of ASCII string */
- buflen = strlen (data);
+ buflen = (int) strlen (data);
}
/* If this is a IP header hex string then set flag */
if (cur_off == -1)
{
/* Error. */
- *err = file_error (fh);
+ *err = file_error (fh, err_info);
return -1;
}
if (file_seek (fh, cur_off - buflen, SEEK_SET, err) == -1)
* For a formated trace ensure we have read at least the IP and TCP headers otherwise
* exit and pass error message to user.
*/
- if (wth->capture.iseries->tcp_formatted)
+ if (iseries->tcp_formatted)
{
if (!IPread)
{
if (isDATA)
{
/* packet contained data */
- if (wth->capture.iseries->tcp_formatted)
+ if (iseries->tcp_formatted)
{
/* build string for formatted fields */
g_snprintf (asciibuf, ISERIES_PKT_ALLOC_SIZE, "%s%s%s%s%s%s",
buffer_assure_space (wth->frame_buffer, ISERIES_MAX_PACKET_LEN);
buf = buffer_start_ptr (wth->frame_buffer);
/* Convert ascii data to binary and return in the frame buffer */
- iseries_parse_hex_string (asciibuf, buf, strlen (asciibuf));
+ iseries_parse_hex_string (asciibuf, buf, (int) strlen (asciibuf));
}
else
{
/* Convert ascii data to binary and return in the frame buffer */
- iseries_parse_hex_string (asciibuf, pd, strlen (asciibuf));
+ iseries_parse_hex_string (asciibuf, pd, (int) strlen (asciibuf));
}
/* free buffers allocs and return */
*err = 0;
- free (asciibuf);
- free (tcpdatabuf);
- free (workbuf);
+ g_free (asciibuf);
+ g_free (tcpdatabuf);
+ g_free (workbuf);
return wth->phdr.len;
}
* Requires ASCII hex data and buffer to populate with binary data
*/
static gboolean
-iseries_parse_hex_string (guint8 * ascii, guint8 * buf, int len)
+iseries_parse_hex_string (const char * ascii, guint8 * buf, int len)
{
int i, byte;
- char hexvalue[3] = { 0, 0, 0 };
+ gint hexvalue;
+ guint8 bytevalue;
byte = 0;
- for (i = 0; i < len; i++)
+ i = 0;
+ for (;;)
{
- hexvalue[0] = ascii[i];
+ if (i >= len)
+ break;
+ hexvalue = g_ascii_xdigit_value(ascii[i]);
+ i++;
+ if (hexvalue == -1)
+ return FALSE; /* not a valid hex digit */
+ bytevalue = (guint8)(hexvalue << 4);
+ if (i >= len)
+ return FALSE; /* only one hex digit of the byte is present */
+ hexvalue = g_ascii_xdigit_value(ascii[i]);
i++;
- hexvalue[1] = ascii[i];
- buf[byte] = (guint8) strtoul (hexvalue, NULL, 16);
+ if (hexvalue == -1)
+ return FALSE; /* not a valid hex digit */
+ bytevalue |= (guint8) hexvalue;
+ buf[byte] = bytevalue;
byte++;
}
return TRUE;