コード例 #1
0
/*
 * Do some basic sanity checking to ensure we can handle the
 * contents of this trace by checking the header page for
 * requisit requirements and additional information.
 */
static gboolean
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];
    iseries_t *iseries;

    /* Save trace format for passing between packets */
    iseries                = (iseries_t *) g_malloc (sizeof (iseries_t));
    wth->priv              = (void *) iseries;
    iseries->have_date     = FALSE;
    iseries->format        = format;

    for (line = 0; line < ISERIES_HDR_LINES_TO_CHECK; line++)
    {
        if (file_gets (buf, ISERIES_LINE_LENGTH, wth->fh) == NULL)
        {
            /* EOF or error. */
            *err = file_error (wth->fh, err_info);
            if (*err == WTAP_ERR_SHORT_READ)
                *err = 0;
            return FALSE;
        }

        /*
         * Check that we are dealing with an ETHERNET trace
         */
        if (iseries->format == ISERIES_FORMAT_UNICODE)
        {
            iseries_UNICODE_to_ASCII ((guint8 *)buf, ISERIES_LINE_LENGTH);
        }
        ascii_strup_inplace (buf);
        num_items_scanned = sscanf (buf,
                                    "%*[ \n\t]OBJECT PROTOCOL%*[ .:\n\t]%8s",
                                    protocol);
        if (num_items_scanned == 1)
        {
            if (memcmp (protocol, "ETHERNET", 8) != 0)
                return FALSE;
        }

        /*
         * The header is the only place where the date part of the timestamp is held, so
         * extract it here and store for all packets to access
         */
        num_items_scanned = sscanf (buf,
                                    "%*[ \n\t]START DATE/TIME%*[ .:\n\t]%2d/%2d/%2d",
                                    &iseries->month, &iseries->day,
                                    &iseries->year);
        if (num_items_scanned == 3)
        {
            iseries->have_date = TRUE;
        }
    }
    *err = 0;
    return TRUE;
}
コード例 #2
0
/*
 * Seeks to the beginning of the next packet, and returns the
 * byte offset.  Returns -1 on failure or EOF; on EOF, sets
 * *err to 0, and, on failure, 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, gchar **err_info)
{
    iseries_t *iseries = (iseries_t *)wth->priv;
    char       buf[ISERIES_LINE_LENGTH],type[5];
    int        line, num_items_scanned;
    gint64     cur_off;
    long       buflen;

    for (line = 0; line < ISERIES_MAX_TRACE_LEN; line++)
    {
        if (file_gets (buf, ISERIES_LINE_LENGTH, wth->fh) == NULL)
        {
            /* EOF or error. */
            *err = file_error (wth->fh, err_info);
            return -1;
        }
        /* Convert UNICODE to ASCII if required and determine    */
        /* the number of bytes to rewind to beginning of record. */
        if (iseries->format == ISERIES_FORMAT_UNICODE)
        {
            /* buflen is #bytes to 1st 0x0A */
            buflen = iseries_UNICODE_to_ASCII ((guint8 *) buf, ISERIES_LINE_LENGTH);
        }
        else
        {
            /* Else buflen is just length of the ASCII string */
            buflen = (long) strlen (buf);
        }
        ascii_strup_inplace (buf);
        /* If packet header found return the offset */
        num_items_scanned =
            sscanf (buf+78,
                    "%*[ \n\t]ETHV2%*[ .:\n\t]TYPE%*[ .:\n\t]%4s",type);
        if (num_items_scanned == 1)
        {
            /* Rewind to beginning of line */
            cur_off = file_tell (wth->fh);
            if (cur_off == -1)
            {
                *err = file_error (wth->fh, err_info);
                return -1;
            }
            if (file_seek (wth->fh, cur_off - buflen, SEEK_SET, err) == -1)
            {
                return -1;
            }
            return cur_off - buflen;
        }
    }

    *err = WTAP_ERR_BAD_FILE;
    *err_info =
        g_strdup_printf ("iseries: next packet header not found within %d lines",
                         ISERIES_MAX_TRACE_LEN);
    return -1;
}
コード例 #3
0
/* Parses a packet. */
static gboolean
iseries_parse_packet (wtap * wth, FILE_T fh, struct wtap_pkthdr *phdr,
                      Buffer *buf, int *err, gchar **err_info)
{
    iseries_t *iseries = (iseries_t *)wth->priv;
    gint64     cur_off;
    gboolean   isValid, isCurrentPacket;
    int        num_items_scanned, line, pktline, buflen;
    int        pkt_len, pktnum, hr, min, sec;
    char       direction[2], destmac[13], srcmac[13], type[5], csec[9+1];
    char       data[ISERIES_LINE_LENGTH * 2];
    int        offset;
    char      *ascii_buf;
    int        ascii_offset;
    struct tm  tm;

    /*
     * Check for packet headers in first 3 lines this should handle page breaks
     * situations and the header lines output at each page throw and ensure we
     * read both the captured and packet lengths.
     */
    isValid = FALSE;
    for (line = 1; line < ISERIES_PKT_LINES_TO_CHECK; line++)
    {
        if (file_gets (data, ISERIES_LINE_LENGTH, fh) == NULL)
        {
            *err = file_error (fh, err_info);
            return FALSE;
        }
        /* Convert UNICODE data to ASCII */
        if (iseries->format == ISERIES_FORMAT_UNICODE)
        {
            iseries_UNICODE_to_ASCII ((guint8 *)data, ISERIES_LINE_LENGTH);
        }
        ascii_strup_inplace (data);
        num_items_scanned =
            sscanf (data,
                    "%*[ \n\t]%6d%*[ *\n\t]%1s%*[ \n\t]%6d%*[ \n\t]%2d:%2d:%2d.%9[0-9]%*[ \n\t]"
                    "%12s%*[ \n\t]%12s%*[ \n\t]ETHV2%*[ \n\t]TYPE:%*[ \n\t]%4s",
                    &pktnum, direction, &pkt_len, &hr, &min, &sec, csec, destmac,
                    srcmac, type);
        if (num_items_scanned == 10)
        {
            /* OK! We found the packet header line */
            isValid = TRUE;
            /*
             * XXX - The Capture length returned by the iSeries trace doesn't
             * seem to include the Ethernet header, so we add its length here.
             */
            pkt_len += 14;
            break;
        }
    }

    /*
     * If no packet header found we exit at this point and inform the user.
     */
    if (!isValid)
    {
        *err = WTAP_ERR_BAD_FILE;
        *err_info = g_strdup ("iseries: packet header isn't valid");
        return FALSE;
    }

    phdr->presence_flags = WTAP_HAS_CAP_LEN;

    /*
     * If we have Wiretap Header then populate it here
     *
     * Timer resolution on the iSeries is hardware dependent.  We determine
     * the resolution based on how many digits we see.
     */
    if (iseries->have_date)
    {
        phdr->presence_flags |= WTAP_HAS_TS;
        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;
        tm.tm_isdst       = -1;
        phdr->ts.secs = mktime (&tm);
        switch (strlen(csec))
        {
        case 0:
            phdr->ts.nsecs = 0;
            break;
        case 1:
            phdr->ts.nsecs = atoi(csec) * 100000000;
            break;
        case 2:
            phdr->ts.nsecs = atoi(csec) * 10000000;
            break;
        case 3:
            phdr->ts.nsecs = atoi(csec) * 1000000;
            break;
        case 4:
            phdr->ts.nsecs = atoi(csec) * 100000;
            break;
        case 5:
            phdr->ts.nsecs = atoi(csec) * 10000;
            break;
        case 6:
            phdr->ts.nsecs = atoi(csec) * 1000;
            break;
        case 7:
            phdr->ts.nsecs = atoi(csec) * 100;
            break;
        case 8:
            phdr->ts.nsecs = atoi(csec) * 10;
            break;
        case 9:
            phdr->ts.nsecs = atoi(csec);
            break;
        }
    }

    phdr->len                       = pkt_len;
    phdr->pkt_encap                 = WTAP_ENCAP_ETHERNET;
    phdr->pseudo_header.eth.fcs_len = -1;

    ascii_buf = (char *)g_malloc (ISERIES_PKT_ALLOC_SIZE);
    g_snprintf(ascii_buf, ISERIES_PKT_ALLOC_SIZE, "%s%s%s", destmac, srcmac, type);
    ascii_offset = 14*2; /* 14-byte Ethernet header, 2 characters per byte */

    /*
     * Start reading packet contents
     */
    isCurrentPacket = TRUE;

    /* loop through packet lines and breakout when the next packet header is read */
    pktline = 0;
    while (isCurrentPacket)
    {
        pktline++;
        /* Read the next line */
        if (file_gets (data, ISERIES_LINE_LENGTH, fh) == NULL)
        {
            *err = file_error (fh, err_info);
            if (*err == 0)
            {
                /* Hit the EOF without an error */
                break;
            }
            goto errxit;
        }

        /* Convert UNICODE data to ASCII and determine line length */
        if (iseries->format == ISERIES_FORMAT_UNICODE)
        {
            buflen = iseries_UNICODE_to_ASCII ((guint8 *)data, ISERIES_LINE_LENGTH);
        }
        else
        {
            /* Else bytes to rewind is just length of ASCII string */
            buflen = (int) strlen (data);
        }

        /*
         * Skip leading white space.
         */
        for (offset = 0; isspace(data[offset]); offset++)
            ;

        /*
         * The higher-level header information starts at an offset of
         * 22 characters.  The header tags are 14 characters long.
         *
         * XXX - for IPv6, if the next header isn't the last header,
         * the intermediate headers do *NOT* appear to be shown in
         * the dump file *at all*, so the packet *cannot* be
         * reconstructed!
         */
        if (offset == 22)
        {
            if (strncmp(data + 22, "IP Header  :  ", 14) == 0 ||
                    strncmp(data + 22, "IPv6 Header:  ", 14) == 0 ||
                    strncmp(data + 22, "ARP Header :  ", 14) == 0 ||
                    strncmp(data + 22, "TCP Header :  ", 14) == 0 ||
                    strncmp(data + 22, "UDP Header :  ", 14) == 0 ||
                    strncmp(data + 22, "ICMP Header:  ", 14) == 0 ||
                    strncmp(data + 22, "ICMPv6  Hdr:  ", 14) == 0 ||
                    strncmp(data + 22, "Option  Hdr:  ", 14) == 0)
            {
                ascii_offset = append_hex_digits(ascii_buf, ascii_offset,
                                                 ISERIES_PKT_ALLOC_SIZE - 1,
                                                 data + 22 + 14, err,
                                                 err_info);
                if (ascii_offset == -1)
                {
                    /* Bad line. */
                    return FALSE;
                }
                continue;
            }
        }

        /*
         * Is this a data line?
         *
         * The "Data" starts at an offset of 8.
         */
        if (offset == 9)
        {
            if (strncmp(data + 9, "Data . . . . . :  ", 18) == 0)
            {
                ascii_offset = append_hex_digits(ascii_buf, ascii_offset,
                                                 ISERIES_PKT_ALLOC_SIZE - 1,
                                                 data + 9 + 18, err,
                                                 err_info);
                if (ascii_offset == -1)
                {
                    /* Bad line. */
                    return FALSE;
                }
                continue;
            }
        }

        /*
         * Is this a continuation of a previous header or data line?
         * That's blanks followed by hex digits; first try the
         * "no column separators" form.
         *
         * Continuations of header lines begin at an offset of 36;
         * continuations of data lines begin at an offset of 27.
         */
        if (offset == 36 || offset == 27)
        {
            ascii_offset = append_hex_digits(ascii_buf, ascii_offset,
                                             ISERIES_PKT_ALLOC_SIZE - 1,
                                             data + offset, err,
                                             err_info);
            if (ascii_offset == -1)
            {
                /* Bad line. */
                return FALSE;
            }
            continue;
        }

        /*
         * If we see the identifier for the next packet then rewind and set
         * isCurrentPacket FALSE
         */
        ascii_strup_inplace (data);
        /* If packet header found return the offset */
        num_items_scanned =
            sscanf (data+78,
                    "%*[ \n\t]ETHV2%*[ .:\n\t]TYPE%*[ .:\n\t]%4s",type);
        if ((num_items_scanned == 1) && pktline > 1)
        {
            isCurrentPacket = FALSE;
            cur_off = file_tell( fh);
            if (cur_off == -1)
            {
                /* Error. */
                *err = file_error (fh, err_info);
                goto errxit;
            }
            if (file_seek (fh, cur_off - buflen, SEEK_SET, err) == -1)
            {
                /* XXX: need to set err_info ?? */
                goto errxit;
            }
        }
    }
    ascii_buf[ascii_offset] = '\0';

    /*
     * Make the captured length be the amount of bytes we've read (which
     * is half the number of characters of hex dump we have).
     *
     * XXX - this can happen for IPv6 packets if the next header isn't the
     * last header.
     */
    phdr->caplen = ((guint32) strlen (ascii_buf))/2;

    /* Make sure we have enough room for the packet. */
    buffer_assure_space (buf, ISERIES_MAX_PACKET_LEN);
    /* Convert ascii data to binary and return in the frame buffer */
    iseries_parse_hex_string (ascii_buf, buffer_start_ptr (buf), strlen (ascii_buf));

    /* free buffer allocs and return */
    *err = 0;
    g_free (ascii_buf);
    return TRUE;

errxit:
    g_free (ascii_buf);
    return FALSE;
}
コード例 #4
0
ファイル: iseries.c プロジェクト: wireshark/wireshark
/* Parses a packet. */
static gboolean
iseries_parse_packet (wtap * wth, FILE_T fh, wtap_rec *rec,
                      Buffer *buf, int *err, gchar **err_info)
{
  iseries_t *iseries = (iseries_t *)wth->priv;
  gint64     cur_off;
  gboolean   isValid, isCurrentPacket;
  int        num_items_scanned, line, pktline, buflen;
  int        pkt_len, pktnum, hr, min, sec;
  char       direction[2], destmac[13], srcmac[13], type[5];
  guint32    csec;
  char       data[ISERIES_LINE_LENGTH * 2];
  int        offset;
  char      *ascii_buf;
  int        ascii_offset;
  struct tm  tm;

  /*
   * Check for packet headers in first 3 lines this should handle page breaks
   * situations and the header lines output at each page throw and ensure we
   * read both the captured and packet lengths.
   */
  isValid = FALSE;
  for (line = 1; line < ISERIES_PKT_LINES_TO_CHECK; line++)
    {
      if (file_gets (data, ISERIES_LINE_LENGTH, fh) == NULL)
        {
          *err = file_error (fh, err_info);
          return FALSE;
        }
      /* Convert UNICODE data to ASCII */
      if (iseries->format == ISERIES_FORMAT_UNICODE)
        {
         iseries_UNICODE_to_ASCII ((guint8 *)data, ISERIES_LINE_LENGTH);
        }
      ascii_strup_inplace (data);
      num_items_scanned =
        sscanf (data,
                "%*[ \n\t]%6d%*[ *\n\t]%1s%*[ \n\t]%6d%*[ \n\t]%2d:%2d:%2d.%9u%*[ \n\t]"
                "%12s%*[ \n\t]%12s%*[ \n\t]ETHV2%*[ \n\t]TYPE:%*[ \n\t]%4s",
                &pktnum, direction, &pkt_len, &hr, &min, &sec, &csec, destmac,
                srcmac, type);
      if (num_items_scanned == 10)
        {
          if (pktnum < 0)
            {
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup ("iseries: packet header has a negative packet number");
              return FALSE;
            }

          if (pkt_len < 0)
            {
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup ("iseries: packet header has a negative packet length");
              return FALSE;
            }

          if (hr < 0)
            {
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup ("iseries: packet header has a negative hour in the time stamp");
              return FALSE;
            }

          if (hr > 23)
            {
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup ("iseries: packet header has a hour in the time stamp greater than 23");
              return FALSE;
            }

          if (min < 0)
            {
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup ("iseries: packet header has a negative minute in the time stamp");
              return FALSE;
            }

          if (min > 59)
            {
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup ("iseries: packet header has a minute in the time stamp greater than 59");
              return FALSE;
            }

          if (sec < 0)
            {
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup ("iseries: packet header has a negative second in the time stamp");
              return FALSE;
            }

          /*
           * Yes, 60, even though the time-conversion routines on most OSes
           * might not handle leap seconds.
           */
          if (sec > 60)
            {
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup ("iseries: packet header has a second in the time stamp greater than 60");
              return FALSE;
            }

          if (strlen(destmac) != 12)
            {
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup ("iseries: packet header has a destination MAC address shorter than 6 bytes");
              return FALSE;
            }

          if (strlen(srcmac) != 12)
            {
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup ("iseries: packet header has a source MAC address shorter than 6 bytes");
              return FALSE;
            }

          if (strlen(type) != 4)
            {
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup ("iseries: packet header has an Ethernet type/length field than 2 bytes");
              return FALSE;
            }

          /* OK! We found the packet header line */
          isValid = TRUE;
          /*
           * XXX - The Capture length returned by the iSeries trace doesn't
           * seem to include the Ethernet header, so we add its length here.
           *
           * Check the length first, just in case it's *so* big that, after
           * adding the Ethernet header length, it overflows.
           */
          if (pkt_len > WTAP_MAX_PACKET_SIZE_STANDARD - 14)
            {
              /*
               * Probably a corrupt capture file; don't blow up trying
               * to allocate space for an immensely-large packet, and
               * don't think it's a really *small* packet because it
               * overflowed.  (Calculate the size as a 64-bit value in
               * the error message, to avoid an overflow.)
               */
              *err = WTAP_ERR_BAD_FILE;
              *err_info = g_strdup_printf("iseries: File has %" G_GUINT64_FORMAT "-byte packet, bigger than maximum of %u",
                                          (guint64)pkt_len + 14,
                                          WTAP_MAX_PACKET_SIZE_STANDARD);
              return FALSE;
            }
          pkt_len += 14;
          break;
        }
    }

  /*
   * If no packet header found we exit at this point and inform the user.
   */
  if (!isValid)
    {
      *err = WTAP_ERR_BAD_FILE;
      *err_info = g_strdup ("iseries: packet header isn't valid");
      return FALSE;
    }

  rec->rec_type = REC_TYPE_PACKET;
  rec->presence_flags = WTAP_HAS_CAP_LEN;

  /*
   * If we have Wiretap Header then populate it here
   *
   * Timer resolution on the iSeries is hardware dependent.  We determine
   * the resolution based on how many digits we see.
   */
  if (iseries->have_date)
    {
      rec->presence_flags |= WTAP_HAS_TS;
      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;
      tm.tm_isdst       = -1;
      rec->ts.secs = mktime (&tm);
      rec->ts.nsecs = csec * csec_multiplier(csec);
    }

  rec->rec_header.packet_header.len                       = pkt_len;
  rec->rec_header.packet_header.pkt_encap                 = WTAP_ENCAP_ETHERNET;
  rec->rec_header.packet_header.pseudo_header.eth.fcs_len = -1;

  /*
   * Allocate a buffer big enough to hold the claimed packet length
   * worth of byte values; each byte will be two hex digits, so the
   * buffer's size should be twice the packet length.
   *
   * (There is no need to null-terminate the buffer.)
   */
  ascii_buf = (char *)g_malloc (pkt_len*2);
  ascii_offset = 0;

  /*
   * Copy in the Ethernet header.
   *
   * The three fields have already been checked to have the right length
   * (6 bytes, hence 12 characters, of hex-dump destination and source
   * addresses, and 2 bytes, hence 4 characters, of hex-dump type/length).
   *
   * pkt_len is guaranteed to be >= 14, so 2*pkt_len is guaranteed to be
   * >= 28, so we don't need to do any bounds checking.
   */
  memcpy(&ascii_buf[0], destmac, 12);
  ascii_offset += 12;
  memcpy(&ascii_buf[12], srcmac, 12);
  ascii_offset += 12;
  memcpy(&ascii_buf[24], type, 4);
  ascii_offset += 4;

  /*
   * Start reading packet contents
   */
  isCurrentPacket = TRUE;

  /* loop through packet lines and breakout when the next packet header is read */
  pktline = 0;
  while (isCurrentPacket)
    {
      pktline++;
      /* Read the next line */
      if (file_gets (data, ISERIES_LINE_LENGTH, fh) == NULL)
        {
          *err = file_error (fh, err_info);
          if (*err == 0)
            {
              /* Hit the EOF without an error */
              break;
            }
          goto errxit;
        }

      /* Convert UNICODE data to ASCII and determine line length */
      if (iseries->format == ISERIES_FORMAT_UNICODE)
        {
         buflen = iseries_UNICODE_to_ASCII ((guint8 *)data, ISERIES_LINE_LENGTH);
        }
      else
        {
          /* Else bytes to rewind is just length of ASCII string */
          buflen = (int) strlen (data);
        }

      /*
       * Skip leading white space.
       */
      for (offset = 0; g_ascii_isspace(data[offset]); offset++)
        ;

      /*
       * The higher-level header information starts at an offset of
       * 22 characters.  The header tags are 14 characters long.
       *
       * XXX - for IPv6, if the next header isn't the last header,
       * the intermediate headers do *NOT* appear to be shown in
       * the dump file *at all*, so the packet *cannot* be
       * reconstructed!
       */
      if (offset == 22)
        {
          if (strncmp(data + 22, "IP Header  :  ", 14) == 0 ||
              strncmp(data + 22, "IPv6 Header:  ", 14) == 0 ||
              strncmp(data + 22, "ARP Header :  ", 14) == 0 ||
              strncmp(data + 22, "TCP Header :  ", 14) == 0 ||
              strncmp(data + 22, "UDP Header :  ", 14) == 0 ||
              strncmp(data + 22, "ICMP Header:  ", 14) == 0 ||
              strncmp(data + 22, "ICMPv6  Hdr:  ", 14) == 0 ||
              strncmp(data + 22, "Option  Hdr:  ", 14) == 0)
            {
              ascii_offset = append_hex_digits(ascii_buf, ascii_offset,
                                               pkt_len*2,
                                               data + 22 + 14, err,
                                               err_info);
              if (ascii_offset == -1)
                {
                  /* Bad line. */
                  return FALSE;
                }
              continue;
            }
        }

      /*
       * Is this a data line?
       *
       * The "Data" starts at an offset of 8.
       */
      if (offset == 9)
        {
          if (strncmp(data + 9, "Data . . . . . :  ", 18) == 0)
            {
              ascii_offset = append_hex_digits(ascii_buf, ascii_offset,
                                               pkt_len*2,
                                               data + 9 + 18, err,
                                               err_info);
              if (ascii_offset == -1)
                {
                  /* Bad line. */
                  return FALSE;
                }
              continue;
            }
        }

      /*
       * Is this a continuation of a previous header or data line?
       * That's blanks followed by hex digits; first try the
       * "no column separators" form.
       *
       * Continuations of header lines begin at an offset of 36;
       * continuations of data lines begin at an offset of 27.
       */
      if (offset == 36 || offset == 27)
        {
          ascii_offset = append_hex_digits(ascii_buf, ascii_offset,
                                           pkt_len*2,
                                           data + offset, err,
                                           err_info);
          if (ascii_offset == -1)
            {
              /* Bad line. */
              return FALSE;
            }
          continue;
        }

      /*
       * If we see the identifier for the next packet then rewind and set
       * isCurrentPacket FALSE
       */
      ascii_strup_inplace (data);
      /* If packet header found return the offset */
      num_items_scanned =
          sscanf (data+78,
          "%*[ \n\t]ETHV2%*[ .:\n\t]TYPE%*[ .:\n\t]%4s",type);
      if ((num_items_scanned == 1) && pktline > 1)
        {
          isCurrentPacket = FALSE;
          cur_off = file_tell( fh);
          if (cur_off == -1)
            {
              /* Error. */
              *err = file_error (fh, err_info);
              goto errxit;
            }
          if (file_seek (fh, cur_off - buflen, SEEK_SET, err) == -1)
            {
              /* XXX: need to set err_info ?? */
              goto errxit;
            }
        }
    }

  /*
   * Make the captured length be the amount of bytes we've read (which
   * is half the number of characters of hex dump we have).
   *
   * XXX - this can happen for IPv6 packets if the next header isn't the
   * last header.
   */
  rec->rec_header.packet_header.caplen = ((guint32) ascii_offset)/2;

  /* Make sure we have enough room for the packet. */
  ws_buffer_assure_space (buf, rec->rec_header.packet_header.caplen);
  /* Convert ascii data to binary and return in the frame buffer */
  iseries_parse_hex_string (ascii_buf, ws_buffer_start_ptr (buf), ascii_offset);

  /* free buffer allocs and return */
  *err = 0;
  g_free (ascii_buf);
  return TRUE;

errxit:
  g_free (ascii_buf);
  return FALSE;
}