/* cosine.c
- *
- * $Id$
*
* CoSine IPNOS L2 debug output parsing
* Copyright (c) 2002 by Motonori Shindo <motonori@shin.do>
*
* 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 gint64 cosine_seek_next_packet(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,
- union wtap_pseudo_header *pseudo_header, guint8 *pd,
- int len, int *err, gchar **err_info);
-static int parse_cosine_rec_hdr(wtap *wth, const char *line,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
-static int parse_cosine_hex_dump(FILE_T fh, int pkt_len, guint8* buf,
- int *err, gchar **err_info);
+ 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((guchar)*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, sets "*err_info" to null or an
- additional error string, and sets hdr to NULL. */
+ 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)
{
if (cur_off == -1) {
/* Error */
*err = file_error(wth->fh, err_info);
- hdr = NULL;
return -1;
}
- if (file_gets(buf, sizeof(buf), wth->fh) != NULL) {
- if (strstr(buf, COSINE_REC_MAGIC_STR1) ||
- strstr(buf, COSINE_REC_MAGIC_STR2)) {
- g_strlcpy(hdr, buf, COSINE_LINE_LENGTH);
- return cur_off;
- }
- } else {
- if (file_eof(wth->fh)) {
- /* We got an EOF. */
- *err = 0;
- } else {
- /* We got an error. */
- *err = file_error(wth->fh, err_info);
- }
- 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;
}
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_info);
+ *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, gchar **err_info)
+wtap_open_return_val cosine_open(wtap *wth, int *err, gchar **err_info)
{
/* Look for CoSine header */
if (!cosine_check_file_type(wth, err, err_info)) {
- if (*err == 0)
- return 0;
- else
- return -1;
+ 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->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->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;
- guint8 *buf;
- int pkt_len, caplen;
char line[COSINE_LINE_LENGTH];
/* Find the next packet */
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,
- err_info);
- 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,
- err_info)) == -1)
- return FALSE;
-
- wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
- 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, gint64 seek_off,
- union wtap_pseudo_header *pseudo_header, guint8 *pd, int len,
- int *err, gchar **err_info)
+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 (parse_cosine_rec_hdr(NULL, line, pseudo_header, err, err_info) == -1)
- return FALSE;
-
- return parse_cosine_hex_dump(wth->random_fh, len, pd, err, err_info);
+ /* 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, gchar **err_info)
+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] = "";
struct tm tm;
+ guint8 *pd;
+ int i, hex_lines, n, caplen = 0;
if (sscanf(line, "%4d-%2d-%2d,%2d:%2d:%2d.%9d:",
&yy, &mm, &dd, &hr, &min, &sec, &csec) == 7) {
if (num_items_scanned != 17) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup("cosine: purported control blade line doesn't have code values");
- return -1;
+ return FALSE;
}
} else {
/* appears to be output to PE */
if (num_items_scanned != 10) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup("cosine: header line is neither control blade nor PE output");
- return -1;
+ 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.secs = mktime(&tm);
- wth->phdr.ts.nsecs = csec * 10000000;
- wth->phdr.len = pkt_len;
+ 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) {
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 **err_info)
-{
- 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 */
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) {
+ 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 -1;
+ 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:
+ */