* File read and write routines for Visual Networks cap files.
* Copyright (c) 2001, Tom Nisbet tnisbet@visualnetworks.com
*
- * $Id$
- *
* 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 <errno.h>
#include <string.h>
#include "wtap-int.h"
#include "file_wrappers.h"
-#include "buffer.h"
+#include <wsutil/buffer.h>
#include "visual.h"
/*
* The first packet index is (4 * num_pkts) octets from the end of the file
* and the last index is in the last four octets of the file.
*
- * All integer and time values are stored in little-endian format, except for
+ * All integer and time values are stored in little-endian format, except for
* the ATM Packet Header, which is stored in network byte order.
*
- * [ File Header ]
- *
+ * [ File Header ]
+ *
*
* [ Packet Header 1 ] [(opt) ATM Packet Header] [ Data ]
* ...
/* This structure is used to extract information */
struct visual_atm_hdr
{
- guint16 vpi; /* 4 bits of zeros; 12 bits of ATM VPI */
+ guint16 vpi; /* 4 bits of zeros; 12 bits of ATM VPI */
guint16 vci; /* ATM VCI */
guint8 info; /* 4 bits version; 3 bits unused-zero; 1 bit direction */
guint8 category; /* indicates type of traffic. 4 bits of status + 4 bits of type */
/* Additional information for writing Visual files */
struct visual_write_info
{
- unsigned start_time; /* Capture start time in seconds */
+ guint start_time; /* Capture start time in seconds */
int index_table_index; /* Index of the next index entry */
int index_table_size; /* Allocated size of the index table */
guint32 * index_table; /* File offsets for the packets */
/* Local functions to handle file reads and writes */
static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
gint64 *data_offset);
-static void visual_close(wtap *wth);
static gboolean visual_seek_read(wtap *wth, gint64 seek_off,
- union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size,
- int *err, gchar **err_info);
-static void visual_set_pseudo_header(int encap, struct visual_pkt_hdr *vpkt_hdr,
- struct visual_atm_hdr *vatm_hdr, union wtap_pseudo_header *pseudo_header);
+ struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
+static gboolean visual_read_packet(wtap *wth, FILE_T fh,
+ struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
- const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
+ const guint8 *pd, int *err, gchar **err_info);
static gboolean visual_dump_close(wtap_dumper *wdh, int *err);
static void visual_dump_free(wtap_dumper *wdh);
/* Open a file for reading */
-int visual_open(wtap *wth, int *err, gchar **err_info)
+wtap_open_return_val visual_open(wtap *wth, int *err, gchar **err_info)
{
- int bytes_read;
char magic[sizeof visual_magic];
struct visual_file_hdr vfile_hdr;
struct visual_read_info * visual;
int encap;
/* Check the magic string at the start of the file */
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(magic, 1, sizeof magic, wth->fh);
- if (bytes_read != sizeof magic)
+ if (!wtap_read_bytes(wth->fh, magic, sizeof magic, err, err_info))
{
- *err = file_error(wth->fh);
- if (*err != 0)
- return -1;
- return 0;
+ if (*err != WTAP_ERR_SHORT_READ)
+ return WTAP_OPEN_ERROR;
+ return WTAP_OPEN_NOT_MINE;
}
if (memcmp(magic, visual_magic, sizeof visual_magic) != 0)
{
- return 0;
+ return WTAP_OPEN_NOT_MINE;
}
/* Read the rest of the file header. */
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(&vfile_hdr, 1, sizeof vfile_hdr, wth->fh);
- if (bytes_read != sizeof vfile_hdr)
+ if (!wtap_read_bytes(wth->fh, &vfile_hdr, sizeof vfile_hdr, err, err_info))
{
- *err = file_error(wth->fh);
- if (*err != 0)
- return -1;
- return 0;
+ return WTAP_OPEN_ERROR;
}
/* Verify the file version is known */
- vfile_hdr.file_version = pletohs(&vfile_hdr.file_version);
+ vfile_hdr.file_version = pletoh16(&vfile_hdr.file_version);
if (vfile_hdr.file_version != 1)
{
*err = WTAP_ERR_UNSUPPORTED;
*err_info = g_strdup_printf("visual: file version %u unsupported", vfile_hdr.file_version);
- return -1;
+ return WTAP_OPEN_ERROR;
}
/* Translate the encapsulation type; these values are SNMP ifType
the first packet is read.
XXX - should we use WTAP_ENCAP_PER_PACKET for that? */
- switch (pletohs(&vfile_hdr.media_type))
+ switch (pletoh16(&vfile_hdr.media_type))
{
case 6: /* ethernet-csmacd */
encap = WTAP_ENCAP_ETHERNET;
break;
default:
- *err = WTAP_ERR_UNSUPPORTED_ENCAP;
+ *err = WTAP_ERR_UNSUPPORTED;
*err_info = g_strdup_printf("visual: network type %u unknown or unsupported",
vfile_hdr.media_type);
- return -1;
+ return WTAP_OPEN_ERROR;
}
/* Fill in the wiretap struct with data from the file header */
- wth->file_type = WTAP_FILE_VISUAL_NETWORKS;
+ wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS;
wth->file_encap = encap;
- wth->snapshot_length = pletohs(&vfile_hdr.max_length);
-
- /* Save the pointer to the beginning of the packet data so
- that the later seek_reads work correctly. */
- wth->data_offset = CAPTUREFILE_HEADER_SIZE;
+ wth->snapshot_length = pletoh16(&vfile_hdr.max_length);
/* Set up the pointers to the handlers for this file type */
wth->subtype_read = visual_read;
wth->subtype_seek_read = visual_seek_read;
- wth->subtype_close = visual_close;
- wth->tsprecision = WTAP_FILE_TSPREC_USEC;
+ wth->file_tsprec = WTAP_TSPREC_USEC;
/* Add Visual-specific information to the wiretap struct for later use. */
- visual = g_malloc(sizeof(struct visual_read_info));
- wth->capture.generic = visual;
- visual->num_pkts = pletohl(&vfile_hdr.num_pkts);
- visual->start_time = ((double) pletohl(&vfile_hdr.start_time)) * 1000000;
+ visual = (struct visual_read_info *)g_malloc(sizeof(struct visual_read_info));
+ wth->priv = (void *)visual;
+ visual->num_pkts = pletoh32(&vfile_hdr.num_pkts);
+ visual->start_time = ((double) pletoh32(&vfile_hdr.start_time)) * 1000000;
visual->current_pkt = 1;
- return 1;
+ return WTAP_OPEN_MINE;
}
static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
gint64 *data_offset)
{
- struct visual_read_info *visual = wth->capture.generic;
- guint32 packet_size = 0;
- int bytes_read;
- struct visual_pkt_hdr vpkt_hdr;
- struct visual_atm_hdr vatm_hdr;
- int phdr_size = sizeof(vpkt_hdr);
- int ahdr_size = sizeof(vatm_hdr);
- time_t secs;
- guint32 usecs;
- double t;
+ struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
/* Check for the end of the packet data. Note that a check for file EOF
will not work because there are index values stored after the last
}
visual->current_pkt++;
- /* Read the packet header. */
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(&vpkt_hdr, 1, phdr_size, wth->fh);
- if (bytes_read != phdr_size)
- {
- *err = file_error(wth->fh);
- if (*err == 0 && bytes_read != 0)
- {
- *err = WTAP_ERR_SHORT_READ;
- }
- return FALSE;
- }
- wth->data_offset += phdr_size;
+ *data_offset = file_tell(wth->fh);
- /* Get the included length of data. This includes extra headers + payload */
- packet_size = pletohs(&vpkt_hdr.incl_len);
+ return visual_read_packet(wth, wth->fh, &wth->phdr, wth->frame_buffer,
+ err, err_info);
+}
- /* Check for additional ATM packet header */
- if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
- {
- /* Read the atm packet header. */
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(&vatm_hdr, 1, ahdr_size, wth->fh);
- if (bytes_read != ahdr_size)
- {
- *err = file_error(wth->fh);
- if (*err == 0 && bytes_read != 0)
- {
- *err = WTAP_ERR_SHORT_READ;
- }
- return FALSE;
- }
- wth->data_offset += ahdr_size;
-
- /* Remove ATM header from length of included bytes in capture, as
- this header was appended by the processor doing the packet reassembly,
- and was not transmitted across the wire */
- packet_size -= ahdr_size;
- }
+/* Read packet header and data for random access. */
+static gboolean visual_seek_read(wtap *wth, gint64 seek_off,
+ struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
+{
+ /* Seek to the packet header */
+ if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
+ return FALSE;
- /* Read the packet data. */
- if (packet_size > 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_RECORD;
- *err_info = g_strdup_printf("visual: File has %u-byte packet, bigger than maximum of %u",
- packet_size, WTAP_MAX_PACKET_SIZE);
+ /* Read the packet. */
+ if (!visual_read_packet(wth, wth->random_fh, phdr, buf, err, err_info)) {
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
return FALSE;
}
- buffer_assure_space(wth->frame_buffer, packet_size);
- *data_offset = wth->data_offset;
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1,
- packet_size, wth->fh);
+ return TRUE;
+}
+
+static gboolean
+visual_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
+ Buffer *buf, int *err, gchar **err_info)
+{
+ struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
+ struct visual_pkt_hdr vpkt_hdr;
+ guint32 packet_size;
+ struct visual_atm_hdr vatm_hdr;
+ double t;
+ time_t secs;
+ guint32 usecs;
+ guint32 packet_status;
+ guint8 *pd;
- if (bytes_read != (int) packet_size)
+ /* Read the packet header. */
+ if (!wtap_read_bytes_or_eof(fh, &vpkt_hdr, (unsigned int)sizeof vpkt_hdr, err, err_info))
{
- *err = file_error(wth->fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
return FALSE;
}
- wth->data_offset += packet_size;
+
+ /* Get the included length of data. This includes extra headers + payload */
+ packet_size = pletoh16(&vpkt_hdr.incl_len);
+
+ phdr->rec_type = REC_TYPE_PACKET;
+ phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
/* Set the packet time and length. */
t = visual->start_time;
- t += ((double)pletohl(&vpkt_hdr.ts_delta))*1000;
+ t += ((double)pletoh32(&vpkt_hdr.ts_delta))*1000;
secs = (time_t)(t/1000000);
usecs = (guint32)(t - secs*1000000);
- wth->phdr.ts.secs = secs;
- wth->phdr.ts.nsecs = usecs * 1000;
-
- /* Most visual capture types include FCS checks in the original length value, but
- * but don't include the FCS as part of the payload or captured length.
- * This causes the RTP audio payload save to fail since then captured len != orig len.
- * Adjusting the original length to remove the FCS bytes we counted based
- * on the file encapsualtion type.
- *
- * Only downside to this fix is throughput calculations will be slightly lower
- * as they won't include the FCS bytes.
- */
-
- wth->phdr.caplen = packet_size;
- wth->phdr.len = pletohs(&vpkt_hdr.orig_len);
+ phdr->ts.secs = secs;
+ phdr->ts.nsecs = usecs * 1000;
+
+ phdr->len = pletoh16(&vpkt_hdr.orig_len);
+ packet_status = pletoh32(&vpkt_hdr.status);
+
+ /* Do encapsulation-specific processing.
+
+ Most Visual capture types include the FCS in the original length
+ value, but don't include the FCS as part of the payload or captured
+ length. This is different from the model used in most other capture
+ file formats, including pcap and pcap-ng in cases where the FCS isn't
+ captured (which are the typical cases), and causes the RTP audio
+ payload save to fail since then captured len != orig len.
+
+ We adjust the original length to remove the FCS bytes we counted based
+ on the file encapsualtion type. The only downside to this fix is
+ throughput calculations will be slightly lower as it won't include
+ the FCS bytes. However, as noted, that problem also exists with
+ other capture formats.
+
+ We also set status flags. The only status currently supported for
+ all encapsulations is direction. This either goes in the p2p or the
+ X.25 pseudo header. It would probably be better to move this up
+ into the phdr. */
switch (wth->file_encap)
{
case WTAP_ENCAP_ETHERNET:
- wth->phdr.len -= 4;
- break;
-
- case WTAP_ENCAP_FRELAY_WITH_PHDR:
- case WTAP_ENCAP_CHDLC_WITH_PHDR:
- case WTAP_ENCAP_LAPB:
- wth->phdr.len -= 2;
- break;
+ /* Ethernet has a 4-byte FCS. */
+ if (phdr->len < 4)
+ {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("visual: Ethernet packet has %u-byte original packet, less than the FCS length",
+ phdr->len);
+ return FALSE;
+ }
+ phdr->len -= 4;
- /* ATM original length doesn't include any FCS. Do nothing. */
- case WTAP_ENCAP_ATM_PDUS:
- /* Not sure about token ring. Just leaving alone for now. */
- case WTAP_ENCAP_TOKEN_RING:
- default:
- break;
- }
+ /* XXX - the above implies that there's never an FCS; should this
+ set the FCS length to 0? */
+ phdr->pseudo_header.eth.fcs_len = -1;
+ break;
- /* Sanity check */
- if (wth->phdr.len < wth->phdr.caplen)
- {
- wth->phdr.len = wth->phdr.caplen;
- }
+ case WTAP_ENCAP_CHDLC_WITH_PHDR:
+ /* This has a 2-byte FCS. */
+ if (phdr->len < 2)
+ {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("visual: Cisco HDLC packet has %u-byte original packet, less than the FCS length",
+ phdr->len);
+ return FALSE;
+ }
+ phdr->len -= 2;
- /* Set the pseudo_header. */
- visual_set_pseudo_header(wth->file_encap, &vpkt_hdr, &vatm_hdr, &wth->pseudo_header);
+ phdr->pseudo_header.p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
+ break;
- /* Fill in the encapsulation. Visual files have a media type in the
- file header and an encapsulation type in each packet header. Files
- with a media type of HDLC can be either Cisco EtherType or PPP.
+ case WTAP_ENCAP_PPP_WITH_PHDR:
+ /* No FCS.
+ XXX - true? Note that PPP can negotiate no FCS, a 2-byte FCS,
+ or a 4-byte FCS. */
+ phdr->pseudo_header.p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
+ break;
- The encapsulation hint values we've seen are:
+ case WTAP_ENCAP_FRELAY_WITH_PHDR:
+ /* This has a 2-byte FCS. */
+ if (phdr->len < 2)
+ {
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("visual: Frame Relay packet has %u-byte original packet, less than the FCS length",
+ phdr->len);
+ return FALSE;
+ }
+ phdr->len -= 2;
- 2 - seen in an Ethernet capture
- 13 - seen in a PPP capture; possibly also seen in Cisco HDLC
- captures
- 14 - seen in a PPP capture; probably seen only for PPP */
- if (wth->file_encap == WTAP_ENCAP_CHDLC_WITH_PHDR)
- {
- /* If PPP is specified in the encap hint, then use that */
- if (vpkt_hdr.encap_hint == 14)
+ phdr->pseudo_header.x25.flags =
+ (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
+ break;
+
+ case WTAP_ENCAP_LAPB:
+ /* This has a 2-byte FCS. */
+ if (phdr->len < 2)
{
- wth->phdr.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("visual: Frame Relay packet has %u-byte original packet, less than the FCS length",
+ phdr->len);
+ return FALSE;
}
- else
+ phdr->len -= 2;
+
+ phdr->pseudo_header.x25.flags =
+ (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
+ break;
+
+ case WTAP_ENCAP_ATM_PDUS:
+ /* ATM original length doesn't include any FCS. Do nothing to
+ the packet length.
+
+ ATM packets have an additional packet header; read and
+ process it. */
+ if (!wtap_read_bytes(fh, &vatm_hdr, (unsigned int)sizeof vatm_hdr, err, err_info))
{
- /* Otherwise, we need to evaluate the first two
- /* examine first two octets to verify encapsulation */
- guint8 *buf = buffer_start_ptr(wth->frame_buffer);
- if ((0xff == buf[0]) && (0x03 == buf[1]))
- {
- /* It is actually PPP */
- wth->phdr.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
- }
+ return FALSE;
}
- }
- return TRUE;
-}
+ /* Remove ATM header from length of included bytes in capture, as
+ this header was appended by the processor doing the packet
+ reassembly, and was not transmitted across the wire */
+ packet_size -= (guint32)sizeof vatm_hdr;
-/* Close a file opened for reading. */
-static void visual_close(wtap *wth)
-{
- /* Free the info allocated by a Visual file reader. */
- if (wth->capture.generic)
- g_free(wth->capture.generic);
- wth->capture.generic = 0;
-}
+ /* Set defaults */
+ phdr->pseudo_header.atm.type = TRAF_UNKNOWN;
+ phdr->pseudo_header.atm.subtype = TRAF_ST_UNKNOWN;
+ phdr->pseudo_header.atm.aal5t_len = 0;
+ /* Next two items not supported. Defaulting to zero */
+ phdr->pseudo_header.atm.aal5t_u2u = 0;
+ phdr->pseudo_header.atm.aal5t_chksum = 0;
-/* Read packet data for random access.
- This gets the packet data and rebuilds the pseudo header so that
- the direction flag works. */
-static gboolean visual_seek_read (wtap *wth, gint64 seek_off,
- union wtap_pseudo_header *pseudo_header, guint8 *pd, int len,
- int *err, gchar **err_info _U_)
-{
- struct visual_pkt_hdr vpkt_hdr;
- struct visual_atm_hdr vatm_hdr;
- int phdr_size = sizeof(vpkt_hdr);
- int ahdr_size = sizeof(vatm_hdr);
- int bytes_read;
- int header_size;
+ /* Flags appear only to convey that packet is a raw cell. Set to 0 */
+ phdr->pseudo_header.atm.flags = 0;
- /* Get the size of the visual packet header to skip */
- header_size = sizeof(struct visual_pkt_hdr);
+ /* Not supported. Defaulting to zero */
+ phdr->pseudo_header.atm.aal2_cid = 0;
- /* If ATM capture, need to skip over visual ATM packet header too */
- if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
- {
- header_size += sizeof(struct visual_atm_hdr);
- }
-
- /* Seek to the packet header */
- if (file_seek(wth->random_fh, seek_off - header_size,
- SEEK_SET, err) == -1)
- return FALSE;
+ switch(vatm_hdr.category & VN_CAT_TYPE_MASK )
+ {
+ case VN_AAL1:
+ phdr->pseudo_header.atm.aal = AAL_1;
+ break;
+
+ case VN_AAL2:
+ phdr->pseudo_header.atm.aal = AAL_2;
+ break;
+
+ case VN_AAL34:
+ phdr->pseudo_header.atm.aal = AAL_3_4;
+ break;
+
+ case VN_AAL5:
+ phdr->pseudo_header.atm.aal = AAL_5;
+ phdr->pseudo_header.atm.type = TRAF_LLCMX;
+ phdr->pseudo_header.atm.aal5t_len = pntoh32(&vatm_hdr.data_length);
+ break;
+
+ case VN_OAM:
+ /* Marking next 3 as OAM versus unknown */
+ case VN_O191:
+ case VN_IDLE:
+ case VN_RM:
+ phdr->pseudo_header.atm.aal = AAL_OAMCELL;
+ break;
+
+ case VN_UNKNOWN:
+ default:
+ phdr->pseudo_header.atm.aal = AAL_UNKNOWN;
+ break;
+ }
+ phdr->pseudo_header.atm.vpi = pntoh16(&vatm_hdr.vpi) & 0x0FFF;
+ phdr->pseudo_header.atm.vci = pntoh16(&vatm_hdr.vci);
+ phdr->pseudo_header.atm.cells = pntoh16(&vatm_hdr.cell_count);
- /* Read the packet header to get the status flags. */
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(&vpkt_hdr, 1, phdr_size, wth->random_fh);
- if (bytes_read != phdr_size) {
- *err = file_error(wth->random_fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
-
- /* Check for additional ATM packet header */
- if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
- {
- /* Read the atm packet header */
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(&vatm_hdr, 1, ahdr_size, wth->random_fh);
- if (bytes_read != ahdr_size)
- {
- *err = file_error(wth->fh);
- if (*err == 0 && bytes_read != 0)
- {
- *err = WTAP_ERR_SHORT_READ;
- }
- return FALSE;
- }
- }
+ /* Using bit value of 1 (DCE -> DTE) to indicate From Network */
+ phdr->pseudo_header.atm.channel = vatm_hdr.info & FROM_NETWORK;
+ break;
- /* Read the packet data. */
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(pd, sizeof(guint8), len, wth->random_fh);
- if (bytes_read != len) {
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
+ /* Not sure about token ring. Just leaving alone for now. */
+ case WTAP_ENCAP_TOKEN_RING:
+ default:
+ break;
}
- /* Set the pseudo_header. */
- visual_set_pseudo_header(wth->file_encap, &vpkt_hdr, &vatm_hdr, pseudo_header);
+ phdr->caplen = packet_size;
- return TRUE;
-}
+ /* Check for too-large packet. */
+ if (packet_size > 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("visual: File has %u-byte packet, bigger than maximum of %u",
+ packet_size, WTAP_MAX_PACKET_SIZE);
+ return FALSE;
+ }
-static void visual_set_pseudo_header(int encap, struct visual_pkt_hdr *vpkt_hdr,
- struct visual_atm_hdr *vatm_hdr, union wtap_pseudo_header *pseudo_header)
-{
- guint32 packet_status;
+ /* Read the packet data */
+ if (!wtap_read_packet_bytes(fh, buf, packet_size, err, err_info))
+ return FALSE;
- /* Set status flags. The only status currently supported for all
- encapsulations is direction. This either goes in the p2p or the
- X.25 pseudo header. It would probably be better to move this up
- into the phdr. */
- packet_status = pletohl(&vpkt_hdr->status);
- switch (encap)
+ if (wth->file_encap == WTAP_ENCAP_CHDLC_WITH_PHDR)
{
- case WTAP_ENCAP_ETHERNET:
- /* XXX - is there an FCS in the frame? */
- pseudo_header->eth.fcs_len = -1;
- break;
+ /* Fill in the encapsulation. Visual files have a media type in the
+ file header and an encapsulation type in each packet header. Files
+ with a media type of HDLC can be either Cisco EtherType or PPP.
- case WTAP_ENCAP_CHDLC_WITH_PHDR:
- case WTAP_ENCAP_PPP_WITH_PHDR:
- pseudo_header->p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
- break;
+ The encapsulation hint values we've seen are:
- case WTAP_ENCAP_FRELAY_WITH_PHDR:
- case WTAP_ENCAP_LAPB:
- pseudo_header->x25.flags =
- (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
- break;
+ 2 - seen in an Ethernet capture
+ 13 - seen in a PPP capture; possibly also seen in Cisco HDLC
+ captures
+ 14 - seen in a PPP capture; probably seen only for PPP.
- case WTAP_ENCAP_ATM_PDUS:
- /* Set defaults */
- pseudo_header->atm.type = TRAF_UNKNOWN;
- pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
- pseudo_header->atm.aal5t_len = 0;
-
- /* Next two items not supported. Defaulting to zero */
- pseudo_header->atm.aal5t_u2u = 0;
- pseudo_header->atm.aal5t_chksum = 0;
-
- /* Flags appear only to convey that packet is a raw cell. Set to 0 */
- pseudo_header->atm.flags = 0;
-
- /* Not supported. Defaulting to zero */
- pseudo_header->atm.aal2_cid = 0;
-
- switch(vatm_hdr->category & VN_CAT_TYPE_MASK )
- {
- case VN_AAL1:
- pseudo_header->atm.aal = AAL_1;
- break;
-
- case VN_AAL2:
- pseudo_header->atm.aal = AAL_2;
- break;
-
- case VN_AAL34:
- pseudo_header->atm.aal = AAL_3_4;
- break;
-
- case VN_AAL5:
- pseudo_header->atm.aal = AAL_5;
- pseudo_header->atm.type = TRAF_LLCMX;
- pseudo_header->atm.aal5t_len = pntohl(&vatm_hdr->data_length);
- break;
-
- case VN_OAM:
- /* Marking next 3 as OAM versus unknown */
- case VN_O191:
- case VN_IDLE:
- case VN_RM:
- pseudo_header->atm.aal = AAL_OAMCELL;
- break;
-
- case VN_UNKNOWN:
- default:
- pseudo_header->atm.aal = AAL_UNKNOWN;
- break;
-
- }
- pseudo_header->atm.vpi = pntohs(&vatm_hdr->vpi) & 0x0FFF;
- pseudo_header->atm.vci = pntohs(&vatm_hdr->vci);
- pseudo_header->atm.cells = pntohs(&vatm_hdr->cell_count);
-
- /* Using bit value of 1 (DCE -> DTE) to indicate From Network */
- pseudo_header->atm.channel = vatm_hdr->info & FROM_NETWORK;
-
- break;
+ According to bug 2005, the collection probe can be configured
+ for PPP, in which case the encapsulation hint is 14, or can
+ be configured for auto-detect, in which case the encapsulation
+ hint is 13, and the encapsulation must be guessed from the
+ packet contents. Auto-detect is the default. */
+ pd = ws_buffer_start_ptr(buf);
+
+ /* If PPP is specified in the encap hint, then use that */
+ if (vpkt_hdr.encap_hint == 14)
+ {
+ /* But first we need to examine the first three octets to
+ try to determine the proper encapsulation, see RFC 2364. */
+ if (packet_size >= 3 &&
+ (0xfe == pd[0]) && (0xfe == pd[1]) && (0x03 == pd[2]))
+ {
+ /* It is actually LLC encapsulated PPP */
+ phdr->pkt_encap = WTAP_ENCAP_ATM_RFC1483;
+ }
+ else
+ {
+ /* It is actually PPP */
+ phdr->pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
+ }
+ }
+ else
+ {
+ /* Otherwise, we need to examine the first two octets to
+ try to determine the encapsulation. */
+ if (packet_size >= 2 && (0xff == pd[0]) && (0x03 == pd[1]))
+ {
+ /* It is actually PPP */
+ phdr->pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
+ }
+ }
}
+
+ return TRUE;
}
/* Check for media types that may be written in Visual file format.
return 0;
}
- return WTAP_ERR_UNSUPPORTED_ENCAP;
+ return WTAP_ERR_UNWRITABLE_ENCAP;
}
/* Open a file for writing.
Returns TRUE on success, FALSE on failure; sets "*err" to an
error code on failure */
-gboolean visual_dump_open(wtap_dumper *wdh, gboolean cant_seek, int *err)
+gboolean visual_dump_open(wtap_dumper *wdh, int *err)
{
struct visual_write_info *visual;
- /* We can't fill in some fields in the header until all the packets
- have been written, so we can't write to a pipe. */
- if (cant_seek) {
- *err = WTAP_ERR_CANT_WRITE_TO_PIPE;
- return FALSE;
- }
-
/* Set the write routines for a visual file. */
wdh->subtype_write = visual_dump;
wdh->subtype_close = visual_dump_close;
/* Create a struct to hold file information for the duration
of the write */
- visual = g_malloc(sizeof(struct visual_write_info));
- wdh->dump.opaque = visual;
+ visual = (struct visual_write_info *)g_malloc(sizeof(struct visual_write_info));
+ wdh->priv = (void *)visual;
visual->index_table_index = 0;
visual->index_table_size = 1024;
visual->index_table = 0;
/* All of the fields in the file header aren't known yet so
just skip over it for now. It will be created after all
of the packets have been written. */
- if (fseek(wdh->fh, CAPTUREFILE_HEADER_SIZE, SEEK_SET) == -1) {
- *err = errno;
+ if (wtap_dump_file_seek(wdh, CAPTUREFILE_HEADER_SIZE, SEEK_SET, err) == -1)
return FALSE;
- }
return TRUE;
}
/* Write a packet to a Visual dump file.
Returns TRUE on success, FALSE on failure. */
static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
- const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
+ const guint8 *pd, int *err, gchar **err_info _U_)
{
- struct visual_write_info * visual = wdh->dump.opaque;
+ const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
+ struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
struct visual_pkt_hdr vpkt_hdr;
size_t hdr_size = sizeof vpkt_hdr;
- size_t nwritten;
- unsigned delta_msec;
+ guint delta_msec;
guint32 packet_status;
+ /* We can only write packet records. */
+ if (phdr->rec_type != REC_TYPE_PACKET) {
+ *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
+ return FALSE;
+ }
+
+ /* Don't write anything we're not willing to read. */
+ if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
+ *err = WTAP_ERR_PACKET_TOO_LARGE;
+ return FALSE;
+ }
+
/* If the visual structure was never allocated then nothing useful
can be done. */
if (visual == 0)
visual->start_time = (guint32) phdr->ts.secs;
/* Initialize the index table */
- visual->index_table = g_malloc(1024 * sizeof *visual->index_table);
+ visual->index_table = (guint32 *)g_malloc(1024 * sizeof *visual->index_table);
visual->index_table_size = 1024;
}
/* Calculate milliseconds since capture start. */
delta_msec = phdr->ts.nsecs / 1000000;
delta_msec += ( (guint32) phdr->ts.secs - visual->start_time) * 1000;
- vpkt_hdr.ts_delta = htolel(delta_msec);
+ vpkt_hdr.ts_delta = GUINT32_TO_LE(delta_msec);
/* Fill in the length fields. */
- vpkt_hdr.orig_len = htoles(phdr->len);
- vpkt_hdr.incl_len = htoles(phdr->caplen);
+ vpkt_hdr.orig_len = GUINT16_TO_LE(phdr->len);
+ vpkt_hdr.incl_len = GUINT16_TO_LE(phdr->caplen);
/* Fill in the encapsulation hint for the file's media type. */
switch (wdh->encap)
((pseudo_header->x25.flags & FROM_DCE) ? 0x00 : PS_SENT);
break;
}
- vpkt_hdr.status = htolel(packet_status);
+ vpkt_hdr.status = GUINT32_TO_LE(packet_status);
/* Write the packet header. */
- nwritten = fwrite(&vpkt_hdr, 1, hdr_size, wdh->fh);
- if (nwritten != hdr_size)
- {
- if (nwritten == 0 && ferror(wdh->fh))
- *err = errno;
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ if (!wtap_dump_file_write(wdh, &vpkt_hdr, hdr_size, err))
return FALSE;
- }
/* Write the packet data */
- nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
- if (nwritten != phdr->caplen)
- {
- if (nwritten == 0 && ferror(wdh->fh))
- *err = errno;
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
return FALSE;
- }
/* Store the frame offset in the index table. */
if (visual->index_table_index >= visual->index_table_size)
{
/* End of table reached. Reallocate with a larger size */
visual->index_table_size *= 2;
- visual->index_table = g_realloc(visual->index_table,
+ visual->index_table = (guint32 *)g_realloc(visual->index_table,
visual->index_table_size * sizeof *visual->index_table);
}
- visual->index_table[visual->index_table_index] = htolel(visual->next_offset);
+ visual->index_table[visual->index_table_index] = GUINT32_TO_LE(visual->next_offset);
/* Update the table index and offset for the next frame. */
visual->index_table_index++;
- visual->next_offset += hdr_size + phdr->caplen;
+ visual->next_offset += (guint32) hdr_size + phdr->caplen;
return TRUE;
}
Returns TRUE on success, FALSE on failure. */
static gboolean visual_dump_close(wtap_dumper *wdh, int *err)
{
- struct visual_write_info * visual = wdh->dump.opaque;
+ struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
size_t n_to_write;
- size_t nwritten;
struct visual_file_hdr vfile_hdr;
const char *magicp;
size_t magic_size;
{
/* Write the index table to the file. */
n_to_write = visual->index_table_index * sizeof *visual->index_table;
- nwritten = fwrite(visual->index_table, 1, n_to_write, wdh->fh);
- if (nwritten != n_to_write)
+ if (!wtap_dump_file_write(wdh, visual->index_table, n_to_write, err))
{
- if (err != NULL)
- {
- if (nwritten == 0 && ferror(wdh->fh))
- *err = errno;
- else
- *err = WTAP_ERR_SHORT_WRITE;
- }
visual_dump_free(wdh);
return FALSE;
}
}
/* Write the magic number at the start of the file. */
- fseek(wdh->fh, 0, SEEK_SET);
+ if (wtap_dump_file_seek(wdh, 0, SEEK_SET, err) == -1)
+ return FALSE;
magicp = visual_magic;
magic_size = sizeof visual_magic;
- nwritten = fwrite(magicp, 1, magic_size, wdh->fh);
- if (nwritten != magic_size)
+ if (!wtap_dump_file_write(wdh, magicp, magic_size, err))
{
- if (err != NULL)
- {
- if (nwritten == 0 && ferror(wdh->fh))
- *err = errno;
- else
- *err = WTAP_ERR_SHORT_WRITE;
- }
visual_dump_free(wdh);
return FALSE;
}
/* Initialize the file header with zeroes for the reserved fields. */
memset(&vfile_hdr, '\0', sizeof vfile_hdr);
- vfile_hdr.num_pkts = htolel(visual->index_table_index);
- vfile_hdr.start_time = htolel(visual->start_time);
- vfile_hdr.max_length = htoles(65535);
- vfile_hdr.file_flags = htoles(1); /* indexes are present */
- vfile_hdr.file_version = htoles(1);
- strcpy(vfile_hdr.description, "Wireshark file");
+ vfile_hdr.num_pkts = GUINT32_TO_LE(visual->index_table_index);
+ vfile_hdr.start_time = GUINT32_TO_LE(visual->start_time);
+ vfile_hdr.max_length = GUINT16_TO_LE(65535);
+ vfile_hdr.file_flags = GUINT16_TO_LE(1); /* indexes are present */
+ vfile_hdr.file_version = GUINT16_TO_LE(1);
+ g_strlcpy(vfile_hdr.description, "Wireshark file", 64);
/* Translate the encapsulation type */
switch (wdh->encap)
{
case WTAP_ENCAP_ETHERNET:
- vfile_hdr.media_type = htoles(6);
+ vfile_hdr.media_type = GUINT16_TO_LE(6);
break;
case WTAP_ENCAP_TOKEN_RING:
- vfile_hdr.media_type = htoles(9);
+ vfile_hdr.media_type = GUINT16_TO_LE(9);
break;
case WTAP_ENCAP_LAPB:
- vfile_hdr.media_type = htoles(16);
+ vfile_hdr.media_type = GUINT16_TO_LE(16);
break;
case WTAP_ENCAP_PPP: /* PPP is differentiated from CHDLC in PktHdr */
case WTAP_ENCAP_PPP_WITH_PHDR:
case WTAP_ENCAP_CHDLC_WITH_PHDR:
- vfile_hdr.media_type = htoles(22);
+ vfile_hdr.media_type = GUINT16_TO_LE(22);
break;
case WTAP_ENCAP_FRELAY_WITH_PHDR:
- vfile_hdr.media_type = htoles(32);
+ vfile_hdr.media_type = GUINT16_TO_LE(32);
break;
}
/* Write the file header following the magic bytes. */
- nwritten = fwrite(&vfile_hdr, 1, sizeof vfile_hdr, wdh->fh);
- if (nwritten != sizeof vfile_hdr)
+ if (!wtap_dump_file_write(wdh, &vfile_hdr, sizeof vfile_hdr, err))
{
- if (err != NULL)
- {
- if (nwritten == 0 && ferror(wdh->fh))
- *err = errno;
- else
- *err = WTAP_ERR_SHORT_WRITE;
- }
visual_dump_free(wdh);
return FALSE;
}
/* Free the memory allocated by a visual file writer. */
static void visual_dump_free(wtap_dumper *wdh)
{
- struct visual_write_info * visual = wdh->dump.opaque;
+ struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
if (visual)
{
/* Free the index table memory. */
if (visual->index_table)
g_free(visual->index_table);
-
- /* Free the write file info struct. */
- g_free(visual);
- wdh->dump.opaque = 0;
}
}