2 * File read and write routines for Visual Networks cap files.
3 * Copyright (c) 2001, Tom Nisbet tnisbet@visualnetworks.com
8 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "file_wrappers.h"
34 * A Visual Networks traffic capture file contains three sections. The
35 * first is a 192 octet file header. This is followed by the captured
36 * packet header, and for ATM captures, there is an additional atm packet header.
37 * The data follows the packet header. The last section is the packet index block.
38 * The index block contains one 4 octet pointer for each captured packet.
39 * The first packet index is (4 * num_pkts) octets from the end of the file
40 * and the last index is in the last four octets of the file.
42 * All integer and time values are stored in little-endian format, except for
43 * the ATM Packet Header, which is stored in network byte order.
48 * [ Packet Header 1 ] [(opt) ATM Packet Header] [ Data ]
50 * [ Packet Header n ] [(opt) ATM Packet Header] [ Data ]
53 * [ Index Block 1 ] ... [ Index Block n ]
56 /* Capture file header, INCLUDING the magic number, is 192 bytes. */
57 #define CAPTUREFILE_HEADER_SIZE 192
59 /* Magic number for Visual Networks traffic capture files. */
60 static const char visual_magic[] = {
65 /* Visual File Header (minus magic number). */
66 /* This structure is used to extract information */
67 struct visual_file_hdr
69 guint32 num_pkts; /* Number of packets in the file */
70 guint32 start_time; /* Capture start time in PC format */
71 guint16 media_type; /* IANA ifType of packet source */
72 guint16 max_length; /* Max allowable stored packet length */
73 guint16 file_flags; /* File type flags */
74 /* Bit 0 indicates indexes present */
75 guint16 file_version; /* Version number of this file format */
76 guint32 media_speed; /* ifSpeed of packet source in bits/sec. */
77 guint16 media_param; /* Media-specific extra parameter. */
78 char RESERVED_[102]; /* MUST BE ALL ZEROS FOR FUTURE COMPATABILITY */
79 char description[64]; /* File description (null terminated) */
83 /* Packet status bits */
86 #define PS_ERRORED 0x04
87 #define PS_1ST_AFTER_DROP 0x08
88 #define PS_APPROX_ORDER 0x10
90 #define PS_ABORTED 0x80
92 /* Visual Packet Header */
93 /* This structure is used to extract information */
96 guint32 ts_delta; /* Time stamp - msecs since start of capture */
97 guint16 orig_len; /* Actual length of packet */
98 guint16 incl_len; /* Number of octets captured in file */
99 guint32 status; /* Packet status flags (media specific) */
100 guint8 encap_hint; /* Encapsulation type hint */
101 guint8 encap_skip; /* Number of bytes to skip before decoding */
102 char RESERVED_[6]; /* RESERVED - must be zero */
105 /* Optional Visual ATM Packet Header */
106 /* This structure is used to extract information */
107 struct visual_atm_hdr
109 guint16 vpi; /* 4 bits of zeros; 12 bits of ATM VPI */
110 guint16 vci; /* ATM VCI */
111 guint8 info; /* 4 bits version; 3 bits unused-zero; 1 bit direction */
112 guint8 category; /* indicates type of traffic. 4 bits of status + 4 bits of type */
113 guint16 cell_count; /* number of cells that make up this pdu */
114 guint32 data_length; /* PDU data length for AAL-5 PDUs, all others - cellcount * 48 */
115 guint32 ts_secs; /* seonds value of sysUpTime when the last cell of this PDU was captured */
116 guint32 ts_nsec; /* nanoseonds value of sysUpTime when the last cell of this PDU was captured */
120 /* visual_atm_hdr info bit definitions */
121 #define FROM_NETWORK 0x01
122 #define ATM_VER_MASK 0xf0 /* Not currently displayed */
124 /* visual_atm_hdr category definitions */
125 /* High nibble - not currently displayed */
126 #define VN_INCOMPLETE 0x40
127 #define VN_BAD_CRC 0x80
128 #define VN_CAT_STAT_MASK 0xf0
130 #define VN_UNKNOWN 0x00
133 #define VN_AAL34 0x03
139 #define VN_CAT_TYPE_MASK 0x0f
142 /* Additional information for reading Visual files */
143 struct visual_read_info
145 guint32 num_pkts; /* Number of pkts in the file */
146 guint32 current_pkt; /* Next packet to be read */
147 double start_time; /* Capture start time in microseconds */
151 /* Additional information for writing Visual files */
152 struct visual_write_info
154 guint start_time; /* Capture start time in seconds */
155 int index_table_index; /* Index of the next index entry */
156 int index_table_size; /* Allocated size of the index table */
157 guint32 * index_table; /* File offsets for the packets */
158 guint32 next_offset; /* Offset of next packet */
162 /* Local functions to handle file reads and writes */
163 static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
164 gint64 *data_offset);
165 static gboolean visual_seek_read(wtap *wth, gint64 seek_off,
166 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
167 static gboolean visual_read_packet(wtap *wth, FILE_T fh,
168 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
169 static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
170 const guint8 *pd, int *err);
171 static gboolean visual_dump_close(wtap_dumper *wdh, int *err);
172 static void visual_dump_free(wtap_dumper *wdh);
175 /* Open a file for reading */
176 int visual_open(wtap *wth, int *err, gchar **err_info)
179 char magic[sizeof visual_magic];
180 struct visual_file_hdr vfile_hdr;
181 struct visual_read_info * visual;
184 /* Check the magic string at the start of the file */
185 errno = WTAP_ERR_CANT_READ;
186 bytes_read = file_read(magic, sizeof magic, wth->fh);
187 if (bytes_read != sizeof magic)
189 *err = file_error(wth->fh, err_info);
190 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
194 if (memcmp(magic, visual_magic, sizeof visual_magic) != 0)
199 /* Read the rest of the file header. */
200 errno = WTAP_ERR_CANT_READ;
201 bytes_read = file_read(&vfile_hdr, sizeof vfile_hdr, wth->fh);
202 if (bytes_read != sizeof vfile_hdr)
204 *err = file_error(wth->fh, err_info);
206 *err = WTAP_ERR_SHORT_READ;
210 /* Verify the file version is known */
211 vfile_hdr.file_version = pletoh16(&vfile_hdr.file_version);
212 if (vfile_hdr.file_version != 1)
214 *err = WTAP_ERR_UNSUPPORTED;
215 *err_info = g_strdup_printf("visual: file version %u unsupported", vfile_hdr.file_version);
219 /* Translate the encapsulation type; these values are SNMP ifType
220 values, as found in http://www.iana.org/assignments/smi-numbers.
222 Note that a file with media type 22 ("propPointToPointSerial") may
223 contain Cisco HDLC or PPP over HDLC. This will get sorted out after
224 the first packet is read.
226 XXX - should we use WTAP_ENCAP_PER_PACKET for that? */
227 switch (pletoh16(&vfile_hdr.media_type))
229 case 6: /* ethernet-csmacd */
230 encap = WTAP_ENCAP_ETHERNET;
233 case 9: /* IEEE802.5 */
234 encap = WTAP_ENCAP_TOKEN_RING;
238 encap = WTAP_ENCAP_LAPB;
241 case 22: /* propPointToPointSerial */
243 encap = WTAP_ENCAP_CHDLC_WITH_PHDR;
246 case 32: /* frame-relay */
247 encap = WTAP_ENCAP_FRELAY_WITH_PHDR;
251 encap = WTAP_ENCAP_ATM_PDUS;
255 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
256 *err_info = g_strdup_printf("visual: network type %u unknown or unsupported",
257 vfile_hdr.media_type);
261 /* Fill in the wiretap struct with data from the file header */
262 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS;
263 wth->file_encap = encap;
264 wth->snapshot_length = pletoh16(&vfile_hdr.max_length);
266 /* Set up the pointers to the handlers for this file type */
267 wth->subtype_read = visual_read;
268 wth->subtype_seek_read = visual_seek_read;
269 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
271 /* Add Visual-specific information to the wiretap struct for later use. */
272 visual = (struct visual_read_info *)g_malloc(sizeof(struct visual_read_info));
273 wth->priv = (void *)visual;
274 visual->num_pkts = pletoh32(&vfile_hdr.num_pkts);
275 visual->start_time = ((double) pletoh32(&vfile_hdr.start_time)) * 1000000;
276 visual->current_pkt = 1;
282 /* Read the next available packet from the file. This is called
283 in a loop to sequentially read the entire file one time. After
284 the file has been read once, any Future access to the packets is
285 done through seek_read. */
286 static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
289 struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
291 /* Check for the end of the packet data. Note that a check for file EOF
292 will not work because there are index values stored after the last
294 if (visual->current_pkt > visual->num_pkts)
296 *err = 0; /* it's just an EOF, not an error */
299 visual->current_pkt++;
301 *data_offset = file_tell(wth->fh);
303 return visual_read_packet(wth, wth->fh, &wth->phdr, wth->frame_buffer,
307 /* Read packet header and data for random access. */
308 static gboolean visual_seek_read(wtap *wth, gint64 seek_off,
309 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
311 /* Seek to the packet header */
312 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
315 /* Read the packet. */
316 if (!visual_read_packet(wth, wth->random_fh, phdr, buf, err, err_info)) {
318 *err = WTAP_ERR_SHORT_READ;
325 visual_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
326 Buffer *buf, int *err, gchar **err_info)
328 struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
329 struct visual_pkt_hdr vpkt_hdr;
332 struct visual_atm_hdr vatm_hdr;
336 guint32 packet_status;
339 /* Read the packet header. */
340 errno = WTAP_ERR_CANT_READ;
341 bytes_read = file_read(&vpkt_hdr, (unsigned int)sizeof vpkt_hdr, fh);
342 if (bytes_read < 0 || (size_t)bytes_read != sizeof vpkt_hdr)
344 *err = file_error(fh, err_info);
345 if (*err == 0 && bytes_read != 0)
347 *err = WTAP_ERR_SHORT_READ;
352 /* Get the included length of data. This includes extra headers + payload */
353 packet_size = pletoh16(&vpkt_hdr.incl_len);
355 phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
357 /* Set the packet time and length. */
358 t = visual->start_time;
359 t += ((double)pletoh32(&vpkt_hdr.ts_delta))*1000;
360 secs = (time_t)(t/1000000);
361 usecs = (guint32)(t - secs*1000000);
362 phdr->ts.secs = secs;
363 phdr->ts.nsecs = usecs * 1000;
365 phdr->len = pletoh16(&vpkt_hdr.orig_len);
367 packet_status = pletoh32(&vpkt_hdr.status);
369 /* Do encapsulation-specific processing.
371 Most Visual capture types include the FCS in the original length
372 value, but don't include the FCS as part of the payload or captured
373 length. This is different from the model used in most other capture
374 file formats, including pcap and pcap-ng in cases where the FCS isn't
375 captured (which are the typical cases), and causes the RTP audio
376 payload save to fail since then captured len != orig len.
378 We adjust the original length to remove the FCS bytes we counted based
379 on the file encapsualtion type. The only downside to this fix is
380 throughput calculations will be slightly lower as it won't include
381 the FCS bytes. However, as noted, that problem also exists with
382 other capture formats.
384 We also set status flags. The only status currently supported for
385 all encapsulations is direction. This either goes in the p2p or the
386 X.25 pseudo header. It would probably be better to move this up
388 switch (wth->file_encap)
390 case WTAP_ENCAP_ETHERNET:
391 /* Ethernet has a 4-byte FCS. */
394 *err = WTAP_ERR_BAD_FILE;
395 *err_info = g_strdup_printf("visual: Ethernet packet has %u-byte original packet, less than the FCS length",
401 /* XXX - the above implies that there's never an FCS; should this
402 set the FCS length to 0? */
403 phdr->pseudo_header.eth.fcs_len = -1;
406 case WTAP_ENCAP_CHDLC_WITH_PHDR:
407 /* This has a 2-byte FCS. */
410 *err = WTAP_ERR_BAD_FILE;
411 *err_info = g_strdup_printf("visual: Cisco HDLC packet has %u-byte original packet, less than the FCS length",
417 phdr->pseudo_header.p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
420 case WTAP_ENCAP_PPP_WITH_PHDR:
422 XXX - true? Note that PPP can negotiate no FCS, a 2-byte FCS,
424 phdr->pseudo_header.p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
427 case WTAP_ENCAP_FRELAY_WITH_PHDR:
428 /* This has a 2-byte FCS. */
431 *err = WTAP_ERR_BAD_FILE;
432 *err_info = g_strdup_printf("visual: Frame Relay packet has %u-byte original packet, less than the FCS length",
438 phdr->pseudo_header.x25.flags =
439 (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
442 case WTAP_ENCAP_LAPB:
443 /* This has a 2-byte FCS. */
446 *err = WTAP_ERR_BAD_FILE;
447 *err_info = g_strdup_printf("visual: Frame Relay packet has %u-byte original packet, less than the FCS length",
453 phdr->pseudo_header.x25.flags =
454 (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
457 case WTAP_ENCAP_ATM_PDUS:
458 /* ATM original length doesn't include any FCS. Do nothing to
461 ATM packets have an additional packet header; read and
463 errno = WTAP_ERR_CANT_READ;
464 bytes_read = file_read(&vatm_hdr, (unsigned int)sizeof vatm_hdr, fh);
465 if (bytes_read < 0 || (size_t)bytes_read != sizeof vatm_hdr)
467 *err = file_error(fh, err_info);
470 *err = WTAP_ERR_SHORT_READ;
475 /* Remove ATM header from length of included bytes in capture, as
476 this header was appended by the processor doing the packet
477 reassembly, and was not transmitted across the wire */
478 packet_size -= (guint32)sizeof vatm_hdr;
481 phdr->pseudo_header.atm.type = TRAF_UNKNOWN;
482 phdr->pseudo_header.atm.subtype = TRAF_ST_UNKNOWN;
483 phdr->pseudo_header.atm.aal5t_len = 0;
485 /* Next two items not supported. Defaulting to zero */
486 phdr->pseudo_header.atm.aal5t_u2u = 0;
487 phdr->pseudo_header.atm.aal5t_chksum = 0;
489 /* Flags appear only to convey that packet is a raw cell. Set to 0 */
490 phdr->pseudo_header.atm.flags = 0;
492 /* Not supported. Defaulting to zero */
493 phdr->pseudo_header.atm.aal2_cid = 0;
495 switch(vatm_hdr.category & VN_CAT_TYPE_MASK )
498 phdr->pseudo_header.atm.aal = AAL_1;
502 phdr->pseudo_header.atm.aal = AAL_2;
506 phdr->pseudo_header.atm.aal = AAL_3_4;
510 phdr->pseudo_header.atm.aal = AAL_5;
511 phdr->pseudo_header.atm.type = TRAF_LLCMX;
512 phdr->pseudo_header.atm.aal5t_len = pntoh32(&vatm_hdr.data_length);
516 /* Marking next 3 as OAM versus unknown */
520 phdr->pseudo_header.atm.aal = AAL_OAMCELL;
525 phdr->pseudo_header.atm.aal = AAL_UNKNOWN;
528 phdr->pseudo_header.atm.vpi = pntoh16(&vatm_hdr.vpi) & 0x0FFF;
529 phdr->pseudo_header.atm.vci = pntoh16(&vatm_hdr.vci);
530 phdr->pseudo_header.atm.cells = pntoh16(&vatm_hdr.cell_count);
532 /* Using bit value of 1 (DCE -> DTE) to indicate From Network */
533 phdr->pseudo_header.atm.channel = vatm_hdr.info & FROM_NETWORK;
536 /* Not sure about token ring. Just leaving alone for now. */
537 case WTAP_ENCAP_TOKEN_RING:
542 phdr->caplen = packet_size;
544 /* Check for too-large packet. */
545 if (packet_size > WTAP_MAX_PACKET_SIZE)
547 /* Probably a corrupt capture file; don't blow up trying
548 to allocate space for an immensely-large packet. */
549 *err = WTAP_ERR_BAD_FILE;
550 *err_info = g_strdup_printf("visual: File has %u-byte packet, bigger than maximum of %u",
551 packet_size, WTAP_MAX_PACKET_SIZE);
556 if (phdr->len < phdr->caplen)
558 phdr->len = phdr->caplen;
561 /* Read the packet data */
562 if (!wtap_read_packet_bytes(fh, buf, packet_size, err, err_info))
565 if (wth->file_encap == WTAP_ENCAP_CHDLC_WITH_PHDR)
567 /* Fill in the encapsulation. Visual files have a media type in the
568 file header and an encapsulation type in each packet header. Files
569 with a media type of HDLC can be either Cisco EtherType or PPP.
571 The encapsulation hint values we've seen are:
573 2 - seen in an Ethernet capture
574 13 - seen in a PPP capture; possibly also seen in Cisco HDLC
576 14 - seen in a PPP capture; probably seen only for PPP.
578 According to bug 2005, the collection probe can be configured
579 for PPP, in which case the encapsulation hint is 14, or can
580 be configured for auto-detect, in which case the encapsulation
581 hint is 13, and the encapsulation must be guessed from the
582 packet contents. Auto-detect is the default. */
583 pd = buffer_start_ptr(buf);
585 /* If PPP is specified in the encap hint, then use that */
586 if (vpkt_hdr.encap_hint == 14)
588 /* But first we need to examine the first three octets to
589 try to determine the proper encapsulation, see RFC 2364. */
590 if (packet_size >= 3 &&
591 (0xfe == pd[0]) && (0xfe == pd[1]) && (0x03 == pd[2]))
593 /* It is actually LLC encapsulated PPP */
594 phdr->pkt_encap = WTAP_ENCAP_ATM_RFC1483;
598 /* It is actually PPP */
599 phdr->pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
604 /* Otherwise, we need to examine the first two octets to
605 try to determine the encapsulation. */
606 if (packet_size >= 2 && (0xff == pd[0]) && (0x03 == pd[1]))
608 /* It is actually PPP */
609 phdr->pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
617 /* Check for media types that may be written in Visual file format.
618 Returns 0 if the specified encapsulation type is supported,
619 an error indication otherwise. */
620 int visual_dump_can_write_encap(int encap)
622 /* Per-packet encapsulations aren't supported. */
623 if (encap == WTAP_ENCAP_PER_PACKET)
624 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
626 /* Check for supported encapsulation types */
629 case WTAP_ENCAP_ETHERNET:
630 case WTAP_ENCAP_TOKEN_RING:
631 case WTAP_ENCAP_LAPB:
632 case WTAP_ENCAP_CHDLC_WITH_PHDR:
633 case WTAP_ENCAP_FRELAY_WITH_PHDR:
635 case WTAP_ENCAP_PPP_WITH_PHDR:
639 return WTAP_ERR_UNSUPPORTED_ENCAP;
643 /* Open a file for writing.
644 Returns TRUE on success, FALSE on failure; sets "*err" to an
645 error code on failure */
646 gboolean visual_dump_open(wtap_dumper *wdh, int *err)
648 struct visual_write_info *visual;
650 /* Set the write routines for a visual file. */
651 wdh->subtype_write = visual_dump;
652 wdh->subtype_close = visual_dump_close;
654 /* Create a struct to hold file information for the duration
656 visual = (struct visual_write_info *)g_malloc(sizeof(struct visual_write_info));
657 wdh->priv = (void *)visual;
658 visual->index_table_index = 0;
659 visual->index_table_size = 1024;
660 visual->index_table = 0;
661 visual->next_offset = CAPTUREFILE_HEADER_SIZE;
663 /* All of the fields in the file header aren't known yet so
664 just skip over it for now. It will be created after all
665 of the packets have been written. */
666 if (wtap_dump_file_seek(wdh, CAPTUREFILE_HEADER_SIZE, SEEK_SET, err) == -1)
673 /* Write a packet to a Visual dump file.
674 Returns TRUE on success, FALSE on failure. */
675 static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
676 const guint8 *pd, int *err)
678 const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
679 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
680 struct visual_pkt_hdr vpkt_hdr;
681 size_t hdr_size = sizeof vpkt_hdr;
683 guint32 packet_status;
685 /* Don't write anything we're not willing to read. */
686 if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
687 *err = WTAP_ERR_PACKET_TOO_LARGE;
691 /* If the visual structure was never allocated then nothing useful
696 /* Zero out unused and reserved fields in the packet header. */
697 memset(&vpkt_hdr, 0, hdr_size);
699 /* Visual UpTime capture files have a capture start time in the
700 file header. Each packet has a capture time (in msec) relative
701 to the file start time. Use the time of the first packet as the
703 if (visual->index_table_index == 0)
705 /* This is the first packet. Save its start time as the file time. */
706 visual->start_time = (guint32) phdr->ts.secs;
708 /* Initialize the index table */
709 visual->index_table = (guint32 *)g_malloc(1024 * sizeof *visual->index_table);
710 visual->index_table_size = 1024;
713 /* Calculate milliseconds since capture start. */
714 delta_msec = phdr->ts.nsecs / 1000000;
715 delta_msec += ( (guint32) phdr->ts.secs - visual->start_time) * 1000;
716 vpkt_hdr.ts_delta = GUINT32_TO_LE(delta_msec);
718 /* Fill in the length fields. */
719 vpkt_hdr.orig_len = GUINT16_TO_LE(phdr->len);
720 vpkt_hdr.incl_len = GUINT16_TO_LE(phdr->caplen);
722 /* Fill in the encapsulation hint for the file's media type. */
725 case WTAP_ENCAP_ETHERNET: /* Ethernet */
726 vpkt_hdr.encap_hint = 2;
728 case WTAP_ENCAP_TOKEN_RING: /* Token Ring */
729 vpkt_hdr.encap_hint = 3;
731 case WTAP_ENCAP_PPP: /* PPP */
732 case WTAP_ENCAP_PPP_WITH_PHDR:
733 vpkt_hdr.encap_hint = 14;
735 case WTAP_ENCAP_CHDLC_WITH_PHDR: /* HDLC Router */
736 vpkt_hdr.encap_hint = 13;
738 case WTAP_ENCAP_FRELAY_WITH_PHDR: /* Frame Relay Auto-detect */
739 vpkt_hdr.encap_hint = 12;
741 case WTAP_ENCAP_LAPB: /* Unknown */
743 vpkt_hdr.encap_hint = 1;
747 /* Set status flags. The only status currently supported for all
748 encapsulations is direction. This either goes in the p2p or the
749 X.25 pseudo header. It would probably be better to move this up
754 case WTAP_ENCAP_CHDLC_WITH_PHDR:
755 packet_status |= (pseudo_header->p2p.sent ? PS_SENT : 0x00);
758 case WTAP_ENCAP_FRELAY_WITH_PHDR:
759 case WTAP_ENCAP_LAPB:
761 ((pseudo_header->x25.flags & FROM_DCE) ? 0x00 : PS_SENT);
764 vpkt_hdr.status = GUINT32_TO_LE(packet_status);
766 /* Write the packet header. */
767 if (!wtap_dump_file_write(wdh, &vpkt_hdr, hdr_size, err))
770 /* Write the packet data */
771 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
774 /* Store the frame offset in the index table. */
775 if (visual->index_table_index >= visual->index_table_size)
777 /* End of table reached. Reallocate with a larger size */
778 visual->index_table_size *= 2;
779 visual->index_table = (guint32 *)g_realloc(visual->index_table,
780 visual->index_table_size * sizeof *visual->index_table);
782 visual->index_table[visual->index_table_index] = GUINT32_TO_LE(visual->next_offset);
784 /* Update the table index and offset for the next frame. */
785 visual->index_table_index++;
786 visual->next_offset += (guint32) hdr_size + phdr->caplen;
792 /* Finish writing to a dump file.
793 Returns TRUE on success, FALSE on failure. */
794 static gboolean visual_dump_close(wtap_dumper *wdh, int *err)
796 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
798 struct visual_file_hdr vfile_hdr;
802 /* If the visual structure was never allocated then nothing useful
807 /* Write out the frame table at the end of the file. */
808 if (visual->index_table)
810 /* Write the index table to the file. */
811 n_to_write = visual->index_table_index * sizeof *visual->index_table;
812 if (!wtap_dump_file_write(wdh, visual->index_table, n_to_write, err))
814 visual_dump_free(wdh);
819 /* Write the magic number at the start of the file. */
820 if (wtap_dump_file_seek(wdh, 0, SEEK_SET, err) == -1)
822 magicp = visual_magic;
823 magic_size = sizeof visual_magic;
824 if (!wtap_dump_file_write(wdh, magicp, magic_size, err))
826 visual_dump_free(wdh);
830 /* Initialize the file header with zeroes for the reserved fields. */
831 memset(&vfile_hdr, '\0', sizeof vfile_hdr);
832 vfile_hdr.num_pkts = GUINT32_TO_LE(visual->index_table_index);
833 vfile_hdr.start_time = GUINT32_TO_LE(visual->start_time);
834 vfile_hdr.max_length = GUINT16_TO_LE(65535);
835 vfile_hdr.file_flags = GUINT16_TO_LE(1); /* indexes are present */
836 vfile_hdr.file_version = GUINT16_TO_LE(1);
837 g_strlcpy(vfile_hdr.description, "Wireshark file", 64);
839 /* Translate the encapsulation type */
842 case WTAP_ENCAP_ETHERNET:
843 vfile_hdr.media_type = GUINT16_TO_LE(6);
846 case WTAP_ENCAP_TOKEN_RING:
847 vfile_hdr.media_type = GUINT16_TO_LE(9);
850 case WTAP_ENCAP_LAPB:
851 vfile_hdr.media_type = GUINT16_TO_LE(16);
854 case WTAP_ENCAP_PPP: /* PPP is differentiated from CHDLC in PktHdr */
855 case WTAP_ENCAP_PPP_WITH_PHDR:
856 case WTAP_ENCAP_CHDLC_WITH_PHDR:
857 vfile_hdr.media_type = GUINT16_TO_LE(22);
860 case WTAP_ENCAP_FRELAY_WITH_PHDR:
861 vfile_hdr.media_type = GUINT16_TO_LE(32);
865 /* Write the file header following the magic bytes. */
866 if (!wtap_dump_file_write(wdh, &vfile_hdr, sizeof vfile_hdr, err))
868 visual_dump_free(wdh);
872 /* Deallocate the file write data */
873 visual_dump_free(wdh);
878 /* Free the memory allocated by a visual file writer. */
879 static void visual_dump_free(wtap_dumper *wdh)
881 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
885 /* Free the index table memory. */
886 if (visual->index_table)
887 g_free(visual->index_table);