/* cosine.c
- *
- * $Id: cosine.c,v 1.7 2004/01/24 16:48:12 jmayer Exp $
*
* CoSine IPNOS L2 debug output parsing
- * Copyright (c) 2002 by Motonori Shindo <mshindo@mshindo.net>
+ * Copyright (c) 2002 by Motonori Shindo <motonori@shin.do>
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifdef HAVE_CONFIG_H
#include "config.h"
-#endif
#include "wtap-int.h"
-#include "buffer.h"
#include "cosine.h"
#include "file_wrappers.h"
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
/*
#define COSINE_REC_MAGIC_STR2 COSINE_HDR_MAGIC_STR2
#define COSINE_HEADER_LINES_TO_CHECK 200
-#define COSINE_LINE_LENGTH 240
-
-#define COSINE_MAX_PACKET_LEN 65536
+#define COSINE_LINE_LENGTH 240
static gboolean empty_line(const gchar *line);
-static long cosine_seek_next_packet(wtap *wth, int *err, char *hdr);
-static gboolean cosine_check_file_type(wtap *wth, int *err);
-static gboolean cosine_read(wtap *wth, int *err, long *data_offset);
-static gboolean cosine_seek_read(wtap *wth, long seek_off,
- union wtap_pseudo_header *pseudo_header, guint8 *pd,
- int len, int *err);
-static int parse_cosine_rec_hdr(wtap *wth, const char *line,
- union wtap_pseudo_header *pseudo_header, int *err);
-static int parse_cosine_hex_dump(FILE_T fh, int pkt_len, guint8* buf,
- int *err);
+static gint64 cosine_seek_next_packet(wtap *wth, int *err, gchar **err_info,
+ char *hdr);
+static gboolean cosine_check_file_type(wtap *wth, int *err, gchar **err_info);
+static gboolean cosine_read(wtap *wth, int *err, gchar **err_info,
+ gint64 *data_offset);
+static gboolean cosine_seek_read(wtap *wth, gint64 seek_off,
+ struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
+static int parse_cosine_packet(FILE_T fh, struct wtap_pkthdr *phdr, Buffer* buf,
+ char *line, int *err, gchar **err_info);
static int parse_single_hex_dump_line(char* rec, guint8 *buf,
guint byte_offset);
static gboolean empty_line(const gchar *line)
{
while (*line) {
- if (isspace(*line)) {
+ if (g_ascii_isspace(*line)) {
line++;
continue;
} else {
/* Seeks to the beginning of the next packet, and returns the
byte offset. Copy the header line to hdr. Returns -1 on failure,
- and sets "*err" to the error and set hdr as NULL. */
-static long cosine_seek_next_packet(wtap *wth, int *err, char *hdr)
+ and sets "*err" to the error and sets "*err_info" to null or an
+ additional error string. */
+static gint64 cosine_seek_next_packet(wtap *wth, int *err, gchar **err_info,
+ char *hdr)
{
- long cur_off;
+ gint64 cur_off;
char buf[COSINE_LINE_LENGTH];
while (1) {
cur_off = file_tell(wth->fh);
if (cur_off == -1) {
/* Error */
- *err = file_error(wth->fh);
- hdr = NULL;
+ *err = file_error(wth->fh, err_info);
return -1;
}
- if (file_gets(buf, sizeof(buf), wth->fh) != NULL) {
- if (strstr(buf, COSINE_REC_MAGIC_STR1) ||
- strstr(buf, COSINE_REC_MAGIC_STR2)) {
- strncpy(hdr, buf, COSINE_LINE_LENGTH-1);
- hdr[COSINE_LINE_LENGTH-1] = '\0';
- return cur_off;
- }
- } else {
- 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);
- }
- break;
+ if (file_gets(buf, sizeof(buf), wth->fh) == NULL) {
+ *err = file_error(wth->fh, err_info);
+ return -1;
+ }
+ if (strstr(buf, COSINE_REC_MAGIC_STR1) ||
+ strstr(buf, COSINE_REC_MAGIC_STR2)) {
+ g_strlcpy(hdr, buf, COSINE_LINE_LENGTH);
+ return cur_off;
}
}
- hdr = NULL;
return -1;
}
* a CoSine L2 debug output.
*
* Returns TRUE if it is, FALSE if it isn't or if we get an I/O error;
- * if we get an I/O error, "*err" will be set to a non-zero value.
+ * if we get an I/O error, "*err" will be set to a non-zero value and
+ * "*err_info" will be set to null or an additional error string.
*/
-static gboolean cosine_check_file_type(wtap *wth, int *err)
+static gboolean cosine_check_file_type(wtap *wth, int *err, gchar **err_info)
{
char buf[COSINE_LINE_LENGTH];
- guint reclen, line;
+ gsize reclen;
+ guint line;
buf[COSINE_LINE_LENGTH-1] = '\0';
for (line = 0; line < COSINE_HEADER_LINES_TO_CHECK; line++) {
- if (file_gets(buf, COSINE_LINE_LENGTH, wth->fh) != NULL) {
-
- reclen = strlen(buf);
- if (reclen < strlen(COSINE_HDR_MAGIC_STR1) ||
- reclen < strlen(COSINE_HDR_MAGIC_STR2)) {
- continue;
- }
-
- if (strstr(buf, COSINE_HDR_MAGIC_STR1) ||
- strstr(buf, COSINE_HDR_MAGIC_STR2)) {
- return TRUE;
- }
- } else {
+ if (file_gets(buf, COSINE_LINE_LENGTH, wth->fh) == NULL) {
/* EOF or error. */
- if (file_eof(wth->fh))
- *err = 0;
- else
- *err = file_error(wth->fh);
+ *err = file_error(wth->fh, err_info);
return FALSE;
}
+
+ reclen = strlen(buf);
+ if (reclen < strlen(COSINE_HDR_MAGIC_STR1) ||
+ reclen < strlen(COSINE_HDR_MAGIC_STR2)) {
+ continue;
+ }
+
+ if (strstr(buf, COSINE_HDR_MAGIC_STR1) ||
+ strstr(buf, COSINE_HDR_MAGIC_STR2)) {
+ return TRUE;
+ }
}
*err = 0;
return FALSE;
}
-int cosine_open(wtap *wth, int *err)
+wtap_open_return_val cosine_open(wtap *wth, int *err, gchar **err_info)
{
/* Look for CoSine header */
- if (!cosine_check_file_type(wth, err)) {
- if (*err == 0)
- return 0;
- else
- return -1;
+ if (!cosine_check_file_type(wth, err, err_info)) {
+ if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
+ return WTAP_OPEN_ERROR;
+ return WTAP_OPEN_NOT_MINE;
}
if (file_seek(wth->fh, 0L, SEEK_SET, err) == -1) /* rewind */
- return -1;
+ return WTAP_OPEN_ERROR;
- wth->data_offset = 0;
wth->file_encap = WTAP_ENCAP_COSINE;
- wth->file_type = WTAP_FILE_COSINE;
+ wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_COSINE;
wth->snapshot_length = 0; /* not known */
wth->subtype_read = cosine_read;
wth->subtype_seek_read = cosine_seek_read;
+ wth->file_tsprec = WTAP_TSPREC_CSEC;
- return 1;
+ return WTAP_OPEN_MINE;
}
-/* Find the next packet and parse it; called from wtap_loop(). */
-static gboolean cosine_read(wtap *wth, int *err, long *data_offset)
+/* Find the next packet and parse it; called from wtap_read(). */
+static gboolean cosine_read(wtap *wth, int *err, gchar **err_info,
+ gint64 *data_offset)
{
- long offset;
- guint8 *buf;
- int pkt_len, caplen;
+ gint64 offset;
char line[COSINE_LINE_LENGTH];
/* Find the next packet */
- offset = cosine_seek_next_packet(wth, err, line);
+ offset = cosine_seek_next_packet(wth, err, err_info, line);
if (offset < 0)
return FALSE;
-
- /* Parse the header */
- pkt_len = parse_cosine_rec_hdr(wth, line, &wth->pseudo_header, err);
- if (pkt_len == -1)
- return FALSE;
-
- /* Make sure we have enough room for the packet */
- buffer_assure_space(wth->frame_buffer, COSINE_MAX_PACKET_LEN);
- buf = buffer_start_ptr(wth->frame_buffer);
-
- /* Convert the ASCII hex dump to binary data */
- if ((caplen = parse_cosine_hex_dump(wth->fh, pkt_len, buf, err)) == -1)
- return FALSE;
-
- wth->data_offset = offset;
- wth->phdr.caplen = caplen;
*data_offset = offset;
- return TRUE;
+
+ /* Parse the header and convert the ASCII hex dump to binary data */
+ return parse_cosine_packet(wth->fh, &wth->phdr, wth->frame_buffer,
+ line, err, err_info);
}
/* Used to read packets in random-access fashion */
static gboolean
-cosine_seek_read (wtap *wth, long seek_off,
- union wtap_pseudo_header *pseudo_header, guint8 *pd, int len, int *err)
+cosine_seek_read(wtap *wth, gint64 seek_off, struct wtap_pkthdr *phdr,
+ Buffer *buf, int *err, gchar **err_info)
{
char line[COSINE_LINE_LENGTH];
return FALSE;
if (file_gets(line, COSINE_LINE_LENGTH, wth->random_fh) == NULL) {
- *err = file_error(wth->random_fh);
+ *err = file_error(wth->random_fh, err_info);
if (*err == 0) {
*err = WTAP_ERR_SHORT_READ;
}
return FALSE;
}
- if (parse_cosine_rec_hdr(NULL, line, pseudo_header, err) == -1)
- return FALSE;
-
- return parse_cosine_hex_dump(wth->random_fh, len, pd, err);
+ /* Parse the header and convert the ASCII hex dump to binary data */
+ return parse_cosine_packet(wth->random_fh, phdr, buf, line, err,
+ err_info);
}
/* Parses a packet record header. There are two possible formats:
2002-5-10,20:1:31.4: l2-tx (FR:3/7/1:1), Length:18, Pro:0, Off:0, Pri:0, RM:0, Err:0 [0x4000, 0x0]
2) output to PE without date and time
l2-tx (FR:3/7/1:1), Length:18, Pro:0, Off:0, Pri:0, RM:0, Err:0 [0x4000, 0x0] */
-static int
-parse_cosine_rec_hdr(wtap *wth, const char *line, union wtap_pseudo_header *pseudo_header, int *err)
+static gboolean
+parse_cosine_packet(FILE_T fh, struct wtap_pkthdr *phdr, Buffer *buf,
+ char *line, int *err, gchar **err_info)
{
+ union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
int num_items_scanned;
int yy, mm, dd, hr, min, sec, csec, pkt_len;
int pro, off, pri, rm, error;
guint code1, code2;
- char if_name[COSINE_MAX_IF_NAME_LEN], direction[6];
+ char if_name[COSINE_MAX_IF_NAME_LEN] = "", direction[6] = "";
struct tm tm;
+ guint8 *pd;
+ int i, hex_lines, n, caplen = 0;
- if (sscanf(line, "%d-%d-%d,%d:%d:%d.%d:",
+ if (sscanf(line, "%4d-%2d-%2d,%2d:%2d:%2d.%9d:",
&yy, &mm, &dd, &hr, &min, &sec, &csec) == 7) {
/* appears to be output to a control blade */
num_items_scanned = sscanf(line,
- "%d-%d-%d,%d:%d:%d.%d: %5s (%127[A-Za-z0-9/:]), Length:%d, Pro:%d, Off:%d, Pri:%d, RM:%d, Err:%d [%x, %x]",
+ "%4d-%2d-%2d,%2d:%2d:%2d.%9d: %5s (%127[A-Za-z0-9/:]), Length:%9d, Pro:%9d, Off:%9d, Pri:%9d, RM:%9d, Err:%9d [%8x, %8x]",
&yy, &mm, &dd, &hr, &min, &sec, &csec,
direction, if_name, &pkt_len,
&pro, &off, &pri, &rm, &error,
&code1, &code2);
if (num_items_scanned != 17) {
- *err = WTAP_ERR_BAD_RECORD;
- return -1;
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup("cosine: purported control blade line doesn't have code values");
+ return FALSE;
}
} else {
/* appears to be output to PE */
num_items_scanned = sscanf(line,
- "%5s (%127[A-Za-z0-9/:]), Length:%d, Pro:%d, Off:%d, Pri:%d, RM:%d, Err:%d [%x, %x]",
+ "%5s (%127[A-Za-z0-9/:]), Length:%9d, Pro:%9d, Off:%9d, Pri:%9d, RM:%9d, Err:%9d [%8x, %8x]",
direction, if_name, &pkt_len,
&pro, &off, &pri, &rm, &error,
&code1, &code2);
if (num_items_scanned != 10) {
- *err = WTAP_ERR_BAD_RECORD;
- return -1;
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup("cosine: header line is neither control blade nor PE output");
+ return FALSE;
}
yy = mm = dd = hr = min = sec = csec = 0;
}
-
- if (wth) {
- tm.tm_year = yy - 1900;
- tm.tm_mon = mm - 1;
- tm.tm_mday = dd;
- tm.tm_hour = hr;
- tm.tm_min = min;
- tm.tm_sec = sec;
- tm.tm_isdst = -1;
- wth->phdr.ts.tv_sec = mktime(&tm);
- wth->phdr.ts.tv_usec = csec * 10000;
- wth->phdr.len = pkt_len;
- wth->phdr.pkt_encap = WTAP_ENCAP_COSINE;
+ if (pkt_len < 0) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup("cosine: packet header has a negative packet length");
+ return FALSE;
+ }
+ if (pkt_len > WTAP_MAX_PACKET_SIZE) {
+ /*
+ * Probably a corrupt capture file; don't blow up trying
+ * to allocate space for an immensely-large packet.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("cosine: File has %u-byte packet, bigger than maximum of %u",
+ pkt_len, WTAP_MAX_PACKET_SIZE);
+ return FALSE;
}
+
+ phdr->rec_type = REC_TYPE_PACKET;
+ phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
+ tm.tm_year = yy - 1900;
+ tm.tm_mon = mm - 1;
+ tm.tm_mday = dd;
+ tm.tm_hour = hr;
+ tm.tm_min = min;
+ tm.tm_sec = sec;
+ tm.tm_isdst = -1;
+ phdr->ts.secs = mktime(&tm);
+ phdr->ts.nsecs = csec * 10000000;
+ phdr->len = pkt_len;
+
/* XXX need to handle other encapsulations like Cisco HDLC,
Frame Relay and ATM */
if (strncmp(if_name, "TEST:", 5) == 0) {
} else if (strncmp(direction, "l2-rx", 5) == 0) {
pseudo_header->cosine.direction = COSINE_DIR_RX;
}
- strncpy(pseudo_header->cosine.if_name, if_name,
- COSINE_MAX_IF_NAME_LEN - 1);
+ g_strlcpy(pseudo_header->cosine.if_name, if_name,
+ COSINE_MAX_IF_NAME_LEN);
pseudo_header->cosine.pro = pro;
pseudo_header->cosine.off = off;
pseudo_header->cosine.pri = pri;
pseudo_header->cosine.rm = rm;
pseudo_header->cosine.err = error;
- return pkt_len;
-}
-
-/* Converts ASCII hex dump to binary data. Returns the capture length.
- If any error is encountered, -1 is returned. */
-static int
-parse_cosine_hex_dump(FILE_T fh, int pkt_len, guint8* buf, int *err)
-{
- gchar line[COSINE_LINE_LENGTH];
- int i, hex_lines, n, caplen = 0;
+ /* Make sure we have enough room for the packet */
+ ws_buffer_assure_space(buf, pkt_len);
+ pd = ws_buffer_start_ptr(buf);
/* Calculate the number of hex dump lines, each
* containing 16 bytes of data */
for (i = 0; i < hex_lines; i++) {
if (file_gets(line, COSINE_LINE_LENGTH, fh) == NULL) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0) {
*err = WTAP_ERR_SHORT_READ;
}
- return -1;
+ return FALSE;
}
if (empty_line(line)) {
break;
}
- if ((n = parse_single_hex_dump_line(line, buf, i*16)) == -1) {
- *err = WTAP_ERR_BAD_RECORD;
- return -1;
+ if ((n = parse_single_hex_dump_line(line, pd, i*16)) == -1) {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup("cosine: hex dump line doesn't have 16 numbers");
+ return FALSE;
}
caplen += n;
}
- return caplen;
+ phdr->caplen = caplen;
+ return TRUE;
}
-
/* Take a string representing one line from a hex dump and converts
* the text to binary data. We place the bytes in the buffer at the
* specified offset.
return num_items_scanned;
}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */