Register a few more file extensions as belonging to Wireshark.
[metze/wireshark/wip.git] / wiretap / dbs-etherwatch.c
index 6a276045efdadd45d128235c1150ac1e1500179f..de173c37cc1fd3afce93b5e3ada40f614553a69c 100644 (file)
@@ -1,6 +1,4 @@
 /* dbs-etherwatch.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 "dbs-etherwatch.h"
 #include "file_wrappers.h"
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 
 /* This module reads the text output of the 'DBS-ETHERTRACE' command in VMS
  * It was initially based on vms.c.
@@ -79,63 +74,58 @@ static const char dbs_etherwatch_hdr_magic[]  =
 static const char dbs_etherwatch_rec_magic[]  =
 {'F', 'r', 'o', 'm', ' '};
 #define DBS_ETHERWATCH_REC_MAGIC_SIZE \
-       (sizeof dbs_etherwatch_rec_magic  / sizeof dbs_etherwatch_rec_magic[0])
+    (sizeof dbs_etherwatch_rec_magic  / sizeof dbs_etherwatch_rec_magic[0])
 
 /*
- * XXX - is this the biggest packet we can get?
+ * Default packet size - maximum normal Ethernet packet size, without an
+ * FCS.
  */
-#define DBS_ETHERWATCH_MAX_PACKET_LEN  16384
+#define DBS_ETHERWATCH_MAX_ETHERNET_PACKET_LEN   1514
 
 static gboolean dbs_etherwatch_read(wtap *wth, int *err, gchar **err_info,
-       gint64 *data_offset);
+    gint64 *data_offset);
 static gboolean dbs_etherwatch_seek_read(wtap *wth, gint64 seek_off,
-       struct wtap_pkthdr *phdr, guint8 *pd, int len,
-       int *err, gchar **err_info);
-static int parse_dbs_etherwatch_packet(wtap *wth, FILE_T fh, guint8* buf,
-       int *err, gchar **err_info);
+    struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
+static gboolean parse_dbs_etherwatch_packet(struct wtap_pkthdr *phdr, FILE_T fh,
+    Buffer* buf, int *err, gchar **err_info);
 static guint parse_single_hex_dump_line(char* rec, guint8 *buf,
-       int byte_offset);
+    int byte_offset);
 static guint parse_hex_dump(char* dump, guint8 *buf, char seperator, char end);
 
 /* Seeks to the beginning of the next packet, and returns the
    byte offset.  Returns -1 on failure, and sets "*err" to the error
    and "*err_info" to null or an additional error string. */
 static gint64 dbs_etherwatch_seek_next_packet(wtap *wth, int *err,
-    gchar **err_info)
+                                              gchar **err_info)
 {
-  int byte;
-  unsigned int level = 0;
-  gint64 cur_off;
-
-  while ((byte = file_getc(wth->fh)) != EOF) {
-    if (byte == dbs_etherwatch_rec_magic[level]) {
-      level++;
-      if (level >= DBS_ETHERWATCH_REC_MAGIC_SIZE) {
-        /* note: we're leaving file pointer right after the magic characters */
-        cur_off = file_tell(wth->fh);
-        if (cur_off == -1) {
-          /* Error. */
-          *err = file_error(wth->fh, err_info);
-          return -1;
+    int byte;
+    unsigned int level = 0;
+    gint64 cur_off;
+
+    while ((byte = file_getc(wth->fh)) != EOF) {
+        if (byte == dbs_etherwatch_rec_magic[level]) {
+            level++;
+            if (level >= DBS_ETHERWATCH_REC_MAGIC_SIZE) {
+                /* note: we're leaving file pointer right after the magic characters */
+                cur_off = file_tell(wth->fh);
+                if (cur_off == -1) {
+                    /* Error. */
+                    *err = file_error(wth->fh, err_info);
+                    return -1;
+                }
+                return cur_off + 1;
+            }
+        } else {
+            level = 0;
         }
-        return cur_off + 1;
-      }
-    } else {
-      level = 0;
     }
-  }
-  if (file_eof(wth->fh)) {
-    /* We got an EOF. */
-    *err = 0;
-  } else {
-    /* We got an error. */
+    /* EOF or error. */
     *err = file_error(wth->fh, err_info);
-  }
-  return -1;
+    return -1;
 }
 
-#define DBS_ETHERWATCH_HEADER_LINES_TO_CHECK   200
-#define DBS_ETHERWATCH_LINE_LENGTH             240
+#define DBS_ETHERWATCH_HEADER_LINES_TO_CHECK    200
+#define DBS_ETHERWATCH_LINE_LENGTH      240
 
 /* Look through the first part of a file to see if this is
  * a DBS Ethertrace text trace file.
@@ -147,129 +137,89 @@ static gint64 dbs_etherwatch_seek_next_packet(wtap *wth, int *err,
 static gboolean dbs_etherwatch_check_file_type(wtap *wth, int *err,
     gchar **err_info)
 {
-       char    buf[DBS_ETHERWATCH_LINE_LENGTH];
-       int     line, byte;
-       gsize   reclen;
-       unsigned int i, level;
-
-       buf[DBS_ETHERWATCH_LINE_LENGTH-1] = 0;
-
-       for (line = 0; line < DBS_ETHERWATCH_HEADER_LINES_TO_CHECK; line++) {
-               if (file_gets(buf, DBS_ETHERWATCH_LINE_LENGTH, wth->fh)!=NULL){
-
-                       reclen = strlen(buf);
-                       if (reclen < DBS_ETHERWATCH_HDR_MAGIC_SIZE)
-                               continue;
-
-                       level = 0;
-                       for (i = 0; i < reclen; i++) {
-                               byte = buf[i];
-                               if (byte == dbs_etherwatch_hdr_magic[level]) {
-                                       level++;
-                                       if (level >=
-                                             DBS_ETHERWATCH_HDR_MAGIC_SIZE) {
-                                               return TRUE;
-                                       }
-                               }
-                               else
-                                       level = 0;
-                       }
-               }
-               else {
-                       /* EOF or error. */
-                       if (file_eof(wth->fh))
-                               *err = 0;
-                       else
-                               *err = file_error(wth->fh, err_info);
-                       return FALSE;
-               }
-       }
-       *err = 0;
-       return FALSE;
+    char    buf[DBS_ETHERWATCH_LINE_LENGTH];
+    int line, byte;
+    gsize   reclen;
+    unsigned int i, level;
+
+    buf[DBS_ETHERWATCH_LINE_LENGTH-1] = 0;
+
+    for (line = 0; line < DBS_ETHERWATCH_HEADER_LINES_TO_CHECK; line++) {
+        if (file_gets(buf, DBS_ETHERWATCH_LINE_LENGTH, wth->fh) == NULL) {
+            /* EOF or error. */
+            *err = file_error(wth->fh, err_info);
+            return FALSE;
+        }
+
+        reclen = strlen(buf);
+        if (reclen < DBS_ETHERWATCH_HDR_MAGIC_SIZE)
+            continue;
+
+        level = 0;
+        for (i = 0; i < reclen; i++) {
+            byte = buf[i];
+            if (byte == dbs_etherwatch_hdr_magic[level]) {
+                level++;
+                if (level >=
+                      DBS_ETHERWATCH_HDR_MAGIC_SIZE) {
+                    return TRUE;
+                }
+            }
+            else
+                level = 0;
+        }
+    }
+    *err = 0;
+    return FALSE;
 }
 
 
-int dbs_etherwatch_open(wtap *wth, int *err, gchar **err_info)
+wtap_open_return_val dbs_etherwatch_open(wtap *wth, int *err, gchar **err_info)
 {
-       /* Look for DBS ETHERWATCH header */
-       if (!dbs_etherwatch_check_file_type(wth, err, err_info)) {
-               if (*err == 0)
-                       return 0;
-               else
-                       return -1;
-       }
-
-       wth->file_encap = WTAP_ENCAP_ETHERNET;
-       wth->file_type = WTAP_FILE_DBS_ETHERWATCH;
-       wth->snapshot_length = 0;       /* not known */
-       wth->subtype_read = dbs_etherwatch_read;
-       wth->subtype_seek_read = dbs_etherwatch_seek_read;
-       wth->tsprecision = WTAP_FILE_TSPREC_CSEC;
-
-       return 1;
+    /* Look for DBS ETHERWATCH header */
+    if (!dbs_etherwatch_check_file_type(wth, err, err_info)) {
+        if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
+            return WTAP_OPEN_ERROR;
+        return WTAP_OPEN_NOT_MINE;
+    }
+
+    wth->file_encap = WTAP_ENCAP_ETHERNET;
+    wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_DBS_ETHERWATCH;
+    wth->snapshot_length = 0;   /* not known */
+    wth->subtype_read = dbs_etherwatch_read;
+    wth->subtype_seek_read = dbs_etherwatch_seek_read;
+    wth->file_tsprec = WTAP_TSPREC_CSEC;
+
+    return WTAP_OPEN_MINE;
 }
 
 /* Find the next packet and parse it; called from wtap_read(). */
 static gboolean dbs_etherwatch_read(wtap *wth, int *err, gchar **err_info,
     gint64 *data_offset)
 {
-       gint64  offset;
-       guint8  *buf;
-       int     pkt_len;
-
-       /* Find the next packet */
-       offset = dbs_etherwatch_seek_next_packet(wth, err, err_info);
-       if (offset < 1)
-               return FALSE;
-
-       /* Make sure we have enough room for the packet */
-       buffer_assure_space(wth->frame_buffer, DBS_ETHERWATCH_MAX_PACKET_LEN);
-       buf = buffer_start_ptr(wth->frame_buffer);
-
-       /* Parse the packet */
-       pkt_len = parse_dbs_etherwatch_packet(wth, wth->fh, buf, err, err_info);
-       if (pkt_len == -1)
-               return FALSE;
-
-       /*
-        * We don't have an FCS in this frame.
-        */
-       wth->phdr.pseudo_header.eth.fcs_len = 0;
-
-       *data_offset = offset;
-       return TRUE;
+    gint64  offset;
+
+    /* Find the next packet */
+    offset = dbs_etherwatch_seek_next_packet(wth, err, err_info);
+    if (offset < 1)
+        return FALSE;
+    *data_offset = offset;
+
+    /* Parse the packet */
+    return parse_dbs_etherwatch_packet(&wth->phdr, wth->fh,
+         wth->frame_buffer, err, err_info);
 }
 
 /* Used to read packets in random-access fashion */
 static gboolean
-dbs_etherwatch_seek_read (wtap *wth, gint64 seek_off,
-       struct wtap_pkthdr *phdr,
-       guint8 *pd, int len, int *err, gchar **err_info)
+dbs_etherwatch_seek_read(wtap *wth, gint64 seek_off,
+    struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
 {
-       union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
-       int     pkt_len;
-
-       if (file_seek(wth->random_fh, seek_off - 1, SEEK_SET, err) == -1)
-               return FALSE;
-
-       pkt_len = parse_dbs_etherwatch_packet(NULL, wth->random_fh, pd, err,
-           err_info);
-
-       if (pkt_len != len) {
-               if (pkt_len != -1) {
-                       *err = WTAP_ERR_BAD_FILE;
-                       *err_info = g_strdup_printf("dbs_etherwatch: packet length %d doesn't match requested length %d",
-                           pkt_len, len);
-               }
-               return FALSE;
-       }
-
-       /*
-        * We don't have an FCS in this frame.
-        */
-       pseudo_header->eth.fcs_len = 0;
-
-       return TRUE;
+    if (file_seek(wth->random_fh, seek_off - 1, SEEK_SET, err) == -1)
+        return FALSE;
+
+    return parse_dbs_etherwatch_packet(phdr, wth->random_fh, buf, err,
+        err_info);
 }
 
 /* Parse a packet */
@@ -280,22 +230,22 @@ Packet header:
 From 00-D0-C0-D2-4D-60 [MF1] to AA-00-04-00-FC-94 [PSERVB]
 Protocol 08-00 00 00-00-00-00-00,   50 byte buffer at 10-OCT-2001 10:20:45.17
 */
-#define MAC_ADDR_LENGTH                6                       /* Length MAC address */
-#define DEST_MAC_PREFIX                "] to "         /* Prefix to the dest. MAC address */
-#define PROTOCOL_LENGTH                2                       /* Length protocol */
-#define PROTOCOL_POS           9                       /* Position protocol */
-#define SAP_LENGTH                     2                       /* Length DSAP+SSAP */
-#define SAP_POS                                9                       /* Position DSAP+SSAP */
-#define CTL_UNNUMB_LENGTH      1                       /* Length unnumbered control field */
-#define CTL_NUMB_LENGTH                2                       /* Length numbered control field */
-#define CTL_POS                                15                      /* Position control field */
-#define PID_LENGTH                     5                       /* Length PID */
-#define PID_POS                                18                      /* Position PID */
-#define LENGTH_POS                     33                      /* Position length */
-#define HEX_HDR_SPR                    '-'                     /* Seperator char header hex values */
-#define HEX_HDR_END                    ' '                     /* End char hdr. hex val. except PID */
-#define HEX_PID_END                    ','                     /* End char PID hex value */
-#define IEEE802_LEN_LEN                2                       /* Length of the IEEE 802 len. field */
+#define MAC_ADDR_LENGTH     6           /* Length MAC address */
+#define DEST_MAC_PREFIX     "] to "     /* Prefix to the dest. MAC address */
+#define PROTOCOL_LENGTH     2           /* Length protocol */
+#define PROTOCOL_POS        9           /* Position protocol */
+#define SAP_LENGTH          2           /* Length DSAP+SSAP */
+#define SAP_POS             9           /* Position DSAP+SSAP */
+#define CTL_UNNUMB_LENGTH   1           /* Length unnumbered control field */
+#define CTL_NUMB_LENGTH     2           /* Length numbered control field */
+#define CTL_POS             15          /* Position control field */
+#define PID_LENGTH          5           /* Length PID */
+#define PID_POS             18          /* Position PID */
+#define LENGTH_POS          33          /* Position length */
+#define HEX_HDR_SPR         '-'         /* Seperator char header hex values */
+#define HEX_HDR_END         ' '         /* End char hdr. hex val. except PID */
+#define HEX_PID_END         ','         /* End char PID hex value */
+#define IEEE802_LEN_LEN     2           /* Length of the IEEE 802 len. field */
 /*
 To check whether it is Ethernet II or IEEE 802 we check the values of the
 control field and PID, when they are all 0's we assume it is Ethernet II
@@ -308,211 +258,242 @@ length in the IEEE data we have to construct.
 To check whether it IEEE 802.3 with SNAP we check that both the DSAP & SSAP
 values are 0xAA and the control field 0x03.
 */
-#define SNAP_CHECK_POS         9
-#define SNAP_CHECK_STR         "AA-AA 03"
+#define SNAP_CHECK_POS      9
+#define SNAP_CHECK_STR      "AA-AA 03"
 /*
 To check whether the control field is 1 or two octets we check if it is
 unnumbered. Unnumbered has length 1, numbered 2.
 */
-#define CTL_UNNUMB_MASK                0x03
-#define CTL_UNNUMB_VALUE       0x03
-static int
-parse_dbs_etherwatch_packet(wtap *wth, FILE_T fh, guint8* buf, int *err,
-    gchar **err_info)
+#define CTL_UNNUMB_MASK     0x03
+#define CTL_UNNUMB_VALUE    0x03
+static gboolean
+parse_dbs_etherwatch_packet(struct wtap_pkthdr *phdr, FILE_T fh, Buffer* buf,
+    int *err, gchar **err_info)
 {
-       char    line[DBS_ETHERWATCH_LINE_LENGTH];
-       int     num_items_scanned;
-       int     eth_hdr_len, pkt_len, csec;
-       int length_pos, length_from, length;
-       struct tm tm;
-       char mon[4] = "xxx";
-       gchar *p;
-       static const gchar months[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
-       int     count, line_count;
-
-       eth_hdr_len = 0;
-       memset(&tm, 0, sizeof(tm));
-       /* Our file pointer should be on the first line containing the
-        * summary information for a packet. Read in that line and
-        * extract the useful information
-        */
-       if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) {
-               *err = file_error(fh, err_info);
-               if (*err == 0) {
-                       *err = WTAP_ERR_SHORT_READ;
-               }
-               return -1;
-       }
-
-       /* Get the destination address */
-       p = strstr(line, DEST_MAC_PREFIX);
-       if(!p) {
-               *err = WTAP_ERR_BAD_FILE;
-               *err_info = g_strdup("dbs_etherwatch: destination address not found");
-               return -1;
-       }
-       p += strlen(DEST_MAC_PREFIX);
-       if(parse_hex_dump(p, &buf[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END)
-                               != MAC_ADDR_LENGTH) {
-               *err = WTAP_ERR_BAD_FILE;
-               *err_info = g_strdup("dbs_etherwatch: destination address not valid");
-               return -1;
-       }
-       eth_hdr_len += MAC_ADDR_LENGTH;
-
-       /* Get the source address */
-       /*
-        * Since the first part of the line is already skipped in order to find
-        * the start of the record we cannot index, just look for the first
-        * 'HEX' character
-        */
-       p = line;
-       while(!isxdigit((guchar)*p)) {
-               p++;
-       }
-       if(parse_hex_dump(p, &buf[eth_hdr_len], HEX_HDR_SPR,
-               HEX_HDR_END) != MAC_ADDR_LENGTH) {
-               *err = WTAP_ERR_BAD_FILE;
-               *err_info = g_strdup("dbs_etherwatch: source address not valid");
-               return -1;
-       }
-       eth_hdr_len += MAC_ADDR_LENGTH;
-
-       /* Read the next line of the record header */
-       if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) {
-               *err = file_error(fh, err_info);
-               if (*err == 0) {
-                       *err = WTAP_ERR_SHORT_READ;
-               }
-               return -1;
-       }
-
-       /* Check the lines is as least as long as the length position */
-       if(strlen(line) < LENGTH_POS) {
-               *err = WTAP_ERR_BAD_FILE;
-               *err_info = g_strdup("dbs_etherwatch: line too short");
-               return -1;
-       }
-
-       num_items_scanned = sscanf(line + LENGTH_POS,
-                               "%9d byte buffer at %2d-%3s-%4d %2d:%2d:%2d.%9d",
-                               &pkt_len,
-                               &tm.tm_mday, mon,
-                               &tm.tm_year, &tm.tm_hour, &tm.tm_min,
-                               &tm.tm_sec, &csec);
-
-       if (num_items_scanned != 8) {
-               *err = WTAP_ERR_BAD_FILE;
-               *err_info = g_strdup("dbs_etherwatch: header line not valid");
-               return -1;
-       }
-
-       /* Determine whether it is Ethernet II or IEEE 802 */
-       if(strncmp(&line[ETH_II_CHECK_POS], ETH_II_CHECK_STR,
-               strlen(ETH_II_CHECK_STR)) == 0) {
-               /* Ethernet II */
-               /* Get the Protocol */
-               if(parse_hex_dump(&line[PROTOCOL_POS], &buf[eth_hdr_len], HEX_HDR_SPR,
-                                       HEX_HDR_END) != PROTOCOL_LENGTH) {
-                       *err = WTAP_ERR_BAD_FILE;
-                       *err_info = g_strdup("dbs_etherwatch: Ethernet II protocol value not valid");
-                       return -1;
-               }
-               eth_hdr_len += PROTOCOL_LENGTH;
-       } else {
-               /* IEEE 802 */
-               /* Remember where to put the length in the header */
-               length_pos = eth_hdr_len;
-               /* Leave room in the header for the length */
-               eth_hdr_len += IEEE802_LEN_LEN;
-               /* Remember how much of the header should not be added to the length */
-               length_from = eth_hdr_len;
-               /* Get the DSAP + SSAP */
-               if(parse_hex_dump(&line[SAP_POS], &buf[eth_hdr_len], HEX_HDR_SPR,
-                                       HEX_HDR_END) != SAP_LENGTH) {
-                       *err = WTAP_ERR_BAD_FILE;
-                       *err_info = g_strdup("dbs_etherwatch: 802.2 DSAP+SSAP value not valid");
-                       return -1;
-               }
-               eth_hdr_len += SAP_LENGTH;
-               /* Get the (first part of the) control field */
-               if(parse_hex_dump(&line[CTL_POS], &buf[eth_hdr_len], HEX_HDR_SPR,
-                                       HEX_HDR_END) != CTL_UNNUMB_LENGTH) {
-                       *err = WTAP_ERR_BAD_FILE;
-                       *err_info = g_strdup("dbs_etherwatch: 802.2 control field first part not valid");
-                       return -1;
-               }
-               /* Determine whether the control is numbered, and thus longer */
-               if((buf[eth_hdr_len] & CTL_UNNUMB_MASK) != CTL_UNNUMB_VALUE) {
-                       /* Get the rest of the control field, the first octet in the PID */
-                       if(parse_hex_dump(&line[PID_POS],
-                                               &buf[eth_hdr_len + CTL_UNNUMB_LENGTH], HEX_HDR_END,
-                                               HEX_HDR_SPR) != CTL_NUMB_LENGTH - CTL_UNNUMB_LENGTH) {
-                               *err = WTAP_ERR_BAD_FILE;
-                               *err_info = g_strdup("dbs_etherwatch: 802.2 control field second part value not valid");
-                               return -1;
-                       }
-                       eth_hdr_len += CTL_NUMB_LENGTH;
-               } else {
-                       eth_hdr_len += CTL_UNNUMB_LENGTH;
-               }
-               /* Determine whether it is SNAP */
-               if(strncmp(&line[SNAP_CHECK_POS], SNAP_CHECK_STR,
-                               strlen(SNAP_CHECK_STR)) == 0) {
-                       /* Get the PID */
-                       if(parse_hex_dump(&line[PID_POS], &buf[eth_hdr_len], HEX_HDR_SPR,
-                                               HEX_PID_END) != PID_LENGTH) {
-                               *err = WTAP_ERR_BAD_FILE;
-                               *err_info = g_strdup("dbs_etherwatch: 802.2 PID value not valid");
-                               return -1;
-                       }
-                       eth_hdr_len += PID_LENGTH;
-               }
-               /* Write the length in the header */
-               length = eth_hdr_len - length_from + pkt_len;
-               buf[length_pos] = (length) >> 8;
-               buf[length_pos+1] = (length) & 0xFF;
-       }
-
-       if (wth) {
-               wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
-
-               p = strstr(months, mon);
-               if (p)
-                       tm.tm_mon = (int)(p - months) / 3;
-               tm.tm_year -= 1900;
-
-               tm.tm_isdst = -1;
-               wth->phdr.ts.secs = mktime(&tm);
-               wth->phdr.ts.nsecs = csec * 10000000;
-               wth->phdr.caplen = eth_hdr_len + pkt_len;
-               wth->phdr.len = eth_hdr_len + pkt_len;
-       }
-
-       /* Parse the hex dump */
-       count = 0;
-       while (count < pkt_len) {
-               if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) {
-                       *err = file_error(fh, err_info);
-                       if (*err == 0) {
-                               *err = WTAP_ERR_SHORT_READ;
-                       }
-                       return -1;
-               }
-               if (!(line_count = parse_single_hex_dump_line(line,
-                               &buf[eth_hdr_len + count], count))) {
-                       *err = WTAP_ERR_BAD_FILE;
-                       *err_info = g_strdup("dbs_etherwatch: packet data value not valid");
-                       return -1;
-               }
-               count += line_count;
-               if (count > pkt_len) {
-                       *err = WTAP_ERR_BAD_FILE;
-                       *err_info = g_strdup("dbs_etherwatch: packet data value has too many bytes");
-                       return -1;
-               }
-       }
-       return eth_hdr_len + pkt_len;
+    guint8 *pd;
+    char    line[DBS_ETHERWATCH_LINE_LENGTH];
+    int num_items_scanned;
+    int eth_hdr_len, pkt_len, csec;
+    int length_pos, length_from, length;
+    struct tm tm;
+    char mon[4] = "xxx";
+    gchar *p;
+    static const gchar months[] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
+    int count, line_count;
+
+    /* Make sure we have enough room for a regular Ethernet packet */
+    ws_buffer_assure_space(buf, DBS_ETHERWATCH_MAX_ETHERNET_PACKET_LEN);
+    pd = ws_buffer_start_ptr(buf);
+
+    eth_hdr_len = 0;
+    memset(&tm, 0, sizeof(tm));
+    /* Our file pointer should be on the first line containing the
+     * summary information for a packet. Read in that line and
+     * extract the useful information
+     */
+    if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) {
+        *err = file_error(fh, err_info);
+        if (*err == 0) {
+            *err = WTAP_ERR_SHORT_READ;
+        }
+        return FALSE;
+    }
+
+    /* Get the destination address */
+    p = strstr(line, DEST_MAC_PREFIX);
+    if(!p) {
+        *err = WTAP_ERR_BAD_FILE;
+        *err_info = g_strdup("dbs_etherwatch: destination address not found");
+        return FALSE;
+    }
+    p += strlen(DEST_MAC_PREFIX);
+    if(parse_hex_dump(p, &pd[eth_hdr_len], HEX_HDR_SPR, HEX_HDR_END)
+                != MAC_ADDR_LENGTH) {
+        *err = WTAP_ERR_BAD_FILE;
+        *err_info = g_strdup("dbs_etherwatch: destination address not valid");
+        return FALSE;
+    }
+    eth_hdr_len += MAC_ADDR_LENGTH;
+
+    /* Get the source address */
+    /*
+     * Since the first part of the line is already skipped in order to find
+     * the start of the record we cannot index, just look for the first
+     * 'HEX' character
+     */
+    p = line;
+    while(!g_ascii_isxdigit(*p)) {
+        p++;
+    }
+    if(parse_hex_dump(p, &pd[eth_hdr_len], HEX_HDR_SPR,
+        HEX_HDR_END) != MAC_ADDR_LENGTH) {
+        *err = WTAP_ERR_BAD_FILE;
+        *err_info = g_strdup("dbs_etherwatch: source address not valid");
+        return FALSE;
+    }
+    eth_hdr_len += MAC_ADDR_LENGTH;
+
+    /* Read the next line of the record header */
+    if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) {
+        *err = file_error(fh, err_info);
+        if (*err == 0) {
+            *err = WTAP_ERR_SHORT_READ;
+        }
+        return FALSE;
+    }
+
+    /* Check the lines is as least as long as the length position */
+    if(strlen(line) < LENGTH_POS) {
+        *err = WTAP_ERR_BAD_FILE;
+        *err_info = g_strdup("dbs_etherwatch: line too short");
+        return FALSE;
+    }
+
+    num_items_scanned = sscanf(line + LENGTH_POS,
+                "%9d byte buffer at %2d-%3s-%4d %2d:%2d:%2d.%9d",
+                &pkt_len,
+                &tm.tm_mday, mon,
+                &tm.tm_year, &tm.tm_hour, &tm.tm_min,
+                &tm.tm_sec, &csec);
+
+    if (num_items_scanned != 8) {
+        *err = WTAP_ERR_BAD_FILE;
+        *err_info = g_strdup("dbs_etherwatch: header line not valid");
+        return FALSE;
+    }
+
+    if (pkt_len < 0) {
+        *err = WTAP_ERR_BAD_FILE;
+        *err_info = g_strdup("dbs_etherwatch: packet header has a negative packet length");
+        return FALSE;
+    }
+
+    /* Determine whether it is Ethernet II or IEEE 802 */
+    if(strncmp(&line[ETH_II_CHECK_POS], ETH_II_CHECK_STR,
+        strlen(ETH_II_CHECK_STR)) == 0) {
+        /* Ethernet II */
+        /* Get the Protocol */
+        if(parse_hex_dump(&line[PROTOCOL_POS], &pd[eth_hdr_len], HEX_HDR_SPR,
+                    HEX_HDR_END) != PROTOCOL_LENGTH) {
+            *err = WTAP_ERR_BAD_FILE;
+            *err_info = g_strdup("dbs_etherwatch: Ethernet II protocol value not valid");
+            return FALSE;
+        }
+        eth_hdr_len += PROTOCOL_LENGTH;
+    } else {
+        /* IEEE 802 */
+        /* Remember where to put the length in the header */
+        length_pos = eth_hdr_len;
+        /* Leave room in the header for the length */
+        eth_hdr_len += IEEE802_LEN_LEN;
+        /* Remember how much of the header should not be added to the length */
+        length_from = eth_hdr_len;
+        /* Get the DSAP + SSAP */
+        if(parse_hex_dump(&line[SAP_POS], &pd[eth_hdr_len], HEX_HDR_SPR,
+                    HEX_HDR_END) != SAP_LENGTH) {
+            *err = WTAP_ERR_BAD_FILE;
+            *err_info = g_strdup("dbs_etherwatch: 802.2 DSAP+SSAP value not valid");
+            return FALSE;
+        }
+        eth_hdr_len += SAP_LENGTH;
+        /* Get the (first part of the) control field */
+        if(parse_hex_dump(&line[CTL_POS], &pd[eth_hdr_len], HEX_HDR_SPR,
+                    HEX_HDR_END) != CTL_UNNUMB_LENGTH) {
+            *err = WTAP_ERR_BAD_FILE;
+            *err_info = g_strdup("dbs_etherwatch: 802.2 control field first part not valid");
+            return FALSE;
+        }
+        /* Determine whether the control is numbered, and thus longer */
+        if((pd[eth_hdr_len] & CTL_UNNUMB_MASK) != CTL_UNNUMB_VALUE) {
+            /* Get the rest of the control field, the first octet in the PID */
+            if(parse_hex_dump(&line[PID_POS],
+                        &pd[eth_hdr_len + CTL_UNNUMB_LENGTH], HEX_HDR_END,
+                        HEX_HDR_SPR) != CTL_NUMB_LENGTH - CTL_UNNUMB_LENGTH) {
+                *err = WTAP_ERR_BAD_FILE;
+                *err_info = g_strdup("dbs_etherwatch: 802.2 control field second part value not valid");
+                return FALSE;
+            }
+            eth_hdr_len += CTL_NUMB_LENGTH;
+        } else {
+            eth_hdr_len += CTL_UNNUMB_LENGTH;
+        }
+        /* Determine whether it is SNAP */
+        if(strncmp(&line[SNAP_CHECK_POS], SNAP_CHECK_STR,
+                strlen(SNAP_CHECK_STR)) == 0) {
+            /* Get the PID */
+            if(parse_hex_dump(&line[PID_POS], &pd[eth_hdr_len], HEX_HDR_SPR,
+                        HEX_PID_END) != PID_LENGTH) {
+                *err = WTAP_ERR_BAD_FILE;
+                *err_info = g_strdup("dbs_etherwatch: 802.2 PID value not valid");
+                return FALSE;
+            }
+            eth_hdr_len += PID_LENGTH;
+        }
+        /* Write the length in the header */
+        length = eth_hdr_len - length_from + pkt_len;
+        pd[length_pos] = (length) >> 8;
+        pd[length_pos+1] = (length) & 0xFF;
+    }
+
+    phdr->rec_type = REC_TYPE_PACKET;
+    phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
+
+    p = strstr(months, mon);
+    if (p)
+        tm.tm_mon = (int)(p - months) / 3;
+    tm.tm_year -= 1900;
+
+    tm.tm_isdst = -1;
+    phdr->ts.secs = mktime(&tm);
+    phdr->ts.nsecs = csec * 10000000;
+    phdr->caplen = eth_hdr_len + pkt_len;
+    phdr->len = eth_hdr_len + pkt_len;
+
+    if (phdr->caplen > 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("dbs_etherwatch: File has %u-byte packet, bigger than maximum of %u",
+                                    phdr->caplen, WTAP_MAX_PACKET_SIZE);
+        return FALSE;
+    }
+
+    /* Make sure we have enough room, even for an oversized Ethernet packet */
+    ws_buffer_assure_space(buf, phdr->caplen);
+    pd = ws_buffer_start_ptr(buf);
+
+    /*
+     * We don't have an FCS in this frame.
+     */
+    phdr->pseudo_header.eth.fcs_len = 0;
+
+    /* Parse the hex dump */
+    count = 0;
+    while (count < pkt_len) {
+        if (file_gets(line, DBS_ETHERWATCH_LINE_LENGTH, fh) == NULL) {
+            *err = file_error(fh, err_info);
+            if (*err == 0) {
+                *err = WTAP_ERR_SHORT_READ;
+            }
+            return FALSE;
+        }
+        if (!(line_count = parse_single_hex_dump_line(line,
+                &pd[eth_hdr_len + count], count))) {
+            *err = WTAP_ERR_BAD_FILE;
+            *err_info = g_strdup("dbs_etherwatch: packet data value not valid");
+            return FALSE;
+        }
+        count += line_count;
+        if (count > pkt_len) {
+            *err = WTAP_ERR_BAD_FILE;
+            *err_info = g_strdup("dbs_etherwatch: packet data value has too many bytes");
+            return FALSE;
+        }
+    }
+    return TRUE;
 }
 
 /* Parse a hex dump line */
@@ -536,14 +517,14 @@ parse_dbs_etherwatch_packet(wtap *wth, FILE_T fh, guint8* buf, int *err,
 
 */
 
-#define TYPE_CHECK_POS         2       /* Position to check the type of hex dump */
-#define TYPE_CHECK_BOTH                '['     /* Value at pos. that indicates BOTH type */
-#define COUNT_POS_BOTH         21      /* Count position BOTH type */
-#define COUNT_POS_HEX          1       /* Count position HEX type */
-#define COUNT_SIZE             5       /* Length counter */
-#define HEX_DUMP_START         '['     /* Start char */
-#define HEX_DUMP_SPR           ' ' /* Seperator char */
-#define HEX_DUMP_END           ']' /* End char */
+#define TYPE_CHECK_POS      2   /* Position to check the type of hex dump */
+#define TYPE_CHECK_BOTH     '[' /* Value at pos. that indicates BOTH type */
+#define COUNT_POS_BOTH      21  /* Count position BOTH type */
+#define COUNT_POS_HEX       1   /* Count position HEX type */
+#define COUNT_SIZE      5   /* Length counter */
+#define HEX_DUMP_START      '[' /* Start char */
+#define HEX_DUMP_SPR        ' ' /* Seperator char */
+#define HEX_DUMP_END        ']' /* End char */
 
 /* Take a string representing one line from a hex dump and converts the
  * text to binary data. We check the printed offset with the offset
@@ -555,97 +536,110 @@ parse_dbs_etherwatch_packet(wtap *wth, FILE_T fh, guint8* buf, int *err,
 static guint
 parse_single_hex_dump_line(char* rec, guint8 *buf, int byte_offset) {
 
-       int             pos, i;
-       int             value;
-
-
-       /* Check that the record is as least as long as the check offset */
-       for(i = 0; i < TYPE_CHECK_POS; i++)
-       {
-               if(rec[i] == '\0') {
-                       return 0;
-               }
-       }
-       /* determine the format and thus the counter offset and hex dump length */
-       if(rec[TYPE_CHECK_POS] == TYPE_CHECK_BOTH)
-       {
-               pos = COUNT_POS_BOTH;
-       }
-       else
-       {
-               pos = COUNT_POS_HEX;
-       }
-
-       /* Check that the record is as least as long as the start position */
-       while(i < pos)
-       {
-               if(rec[i] == '\0') {
-                       return 0;
-               }
-               i++;
-       }
-
-       /* Get the byte_offset directly from the record */
-       value = 0;
-       for(i = 0; i < COUNT_SIZE; i++) {
-               if(!isspace((guchar)rec[pos])) {
-                       if(isdigit((guchar)rec[pos])) {
-                               value *= 10;
-                               value += rec[pos] - '0';
-                       } else {
-                               return 0;
-                       }
-               }
-               pos++;
-       }
-
-       if (value != byte_offset) {
-               return 0;
-       }
-
-       /* find the start of the hex dump */
-       while(rec[pos] != HEX_DUMP_START) {
-               if(rec[pos] == '\0') {
-                       return 0;
-               }
-               pos++;
-       }
-       pos++;
-       return parse_hex_dump(&rec[pos], buf, HEX_DUMP_SPR, HEX_DUMP_END);
+    int     pos, i;
+    int     value;
+
+
+    /* Check that the record is as least as long as the check offset */
+    for(i = 0; i < TYPE_CHECK_POS; i++)
+    {
+        if(rec[i] == '\0') {
+            return 0;
+        }
+    }
+    /* determine the format and thus the counter offset and hex dump length */
+    if(rec[TYPE_CHECK_POS] == TYPE_CHECK_BOTH)
+    {
+        pos = COUNT_POS_BOTH;
+    }
+    else
+    {
+        pos = COUNT_POS_HEX;
+    }
+
+    /* Check that the record is as least as long as the start position */
+    while(i < pos)
+    {
+        if(rec[i] == '\0') {
+            return 0;
+        }
+        i++;
+    }
+
+    /* Get the byte_offset directly from the record */
+    value = 0;
+    for(i = 0; i < COUNT_SIZE; i++) {
+        if(!g_ascii_isspace(rec[pos])) {
+            if(g_ascii_isdigit(rec[pos])) {
+                value *= 10;
+                value += rec[pos] - '0';
+            } else {
+                return 0;
+            }
+        }
+        pos++;
+    }
+
+    if (value != byte_offset) {
+        return 0;
+    }
+
+    /* find the start of the hex dump */
+    while(rec[pos] != HEX_DUMP_START) {
+        if(rec[pos] == '\0') {
+            return 0;
+        }
+        pos++;
+    }
+    pos++;
+    return parse_hex_dump(&rec[pos], buf, HEX_DUMP_SPR, HEX_DUMP_END);
 }
 
 /* Parse a hex dump */
 static guint
 parse_hex_dump(char* dump, guint8 *buf, char seperator, char end) {
-       int             pos, count;
-
-       /* Parse the hex dump */
-       pos = 0;
-       count = 0;
-       while(dump[pos] != end) {
-               /* Check the hex value */
-               if(!(isxdigit((guchar)dump[pos]) &&
-                   isxdigit((guchar)dump[pos + 1]))) {
-                       return 0;
-               }
-               /* Get the hex value value */
-               if(isdigit((guchar)dump[pos])) {
-                       buf[count] = (dump[pos] - '0') << 4;
-               } else {
-                       buf[count] = (toupper(dump[pos]) - 'A' + 10) << 4;
-               }
-               pos++;
-               if(isdigit((guchar)dump[pos])) {
-                       buf[count] += dump[pos] - '0';
-               } else {
-                       buf[count] += toupper(dump[pos]) - 'A' + 10;
-               }
-               pos++;
-               count++;
-               /* Skip the seperator characters */
-               while(dump[pos] == seperator) {
-                       pos++;
-               }
-       }
-       return count;
+    int     pos, count;
+
+    /* Parse the hex dump */
+    pos = 0;
+    count = 0;
+    while(dump[pos] != end) {
+        /* Check the hex value */
+        if(!(g_ascii_isxdigit(dump[pos]) &&
+            g_ascii_isxdigit(dump[pos + 1]))) {
+            return 0;
+        }
+        /* Get the hex value value */
+        if(g_ascii_isdigit(dump[pos])) {
+            buf[count] = (dump[pos] - '0') << 4;
+        } else {
+            buf[count] = (g_ascii_toupper(dump[pos]) - 'A' + 10) << 4;
+        }
+        pos++;
+        if(g_ascii_isdigit(dump[pos])) {
+            buf[count] += dump[pos] - '0';
+        } else {
+            buf[count] += g_ascii_toupper(dump[pos]) - 'A' + 10;
+        }
+        pos++;
+        count++;
+        /* Skip the seperator characters */
+        while(dump[pos] == seperator) {
+            pos++;
+        }
+    }
+    return count;
 }
+
+/*
+ * 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:
+ */