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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include "file_wrappers.h"
36 * A Visual Networks traffic capture file contains three sections. The
37 * first is a 192 octet file header. This is followed by the captured
38 * packet header, and for ATM captures, there is an additional atm packet header.
39 * The data follows the packet header. The last section is the packet index block.
40 * The index block contains one 4 octet pointer for each captured packet.
41 * The first packet index is (4 * num_pkts) octets from the end of the file
42 * and the last index is in the last four octets of the file.
44 * All integer and time values are stored in little-endian format, except for
45 * the ATM Packet Header, which is stored in network byte order.
50 * [ Packet Header 1 ] [(opt) ATM Packet Header] [ Data ]
52 * [ Packet Header n ] [(opt) ATM Packet Header] [ Data ]
55 * [ Index Block 1 ] ... [ Index Block n ]
58 /* Capture file header, INCLUDING the magic number, is 192 bytes. */
59 #define CAPTUREFILE_HEADER_SIZE 192
61 /* Magic number for Visual Networks traffic capture files. */
62 static const char visual_magic[] = {
67 /* Visual File Header (minus magic number). */
68 /* This structure is used to extract information */
69 struct visual_file_hdr
71 guint32 num_pkts; /* Number of packets in the file */
72 guint32 start_time; /* Capture start time in PC format */
73 guint16 media_type; /* IANA ifType of packet source */
74 guint16 max_length; /* Max allowable stored packet length */
75 guint16 file_flags; /* File type flags */
76 /* Bit 0 indicates indexes present */
77 guint16 file_version; /* Version number of this file format */
78 guint32 media_speed; /* ifSpeed of packet source in bits/sec. */
79 guint16 media_param; /* Media-specific extra parameter. */
80 char RESERVED_[102]; /* MUST BE ALL ZEROS FOR FUTURE COMPATABILITY */
81 char description[64]; /* File description (null terminated) */
85 /* Packet status bits */
88 #define PS_ERRORED 0x04
89 #define PS_1ST_AFTER_DROP 0x08
90 #define PS_APPROX_ORDER 0x10
92 #define PS_ABORTED 0x80
94 /* Visual Packet Header */
95 /* This structure is used to extract information */
98 guint32 ts_delta; /* Time stamp - msecs since start of capture */
99 guint16 orig_len; /* Actual length of packet */
100 guint16 incl_len; /* Number of octets captured in file */
101 guint32 status; /* Packet status flags (media specific) */
102 guint8 encap_hint; /* Encapsulation type hint */
103 guint8 encap_skip; /* Number of bytes to skip before decoding */
104 char RESERVED_[6]; /* RESERVED - must be zero */
107 /* Optional Visual ATM Packet Header */
108 /* This structure is used to extract information */
109 struct visual_atm_hdr
111 guint16 vpi; /* 4 bits of zeros; 12 bits of ATM VPI */
112 guint16 vci; /* ATM VCI */
113 guint8 info; /* 4 bits version; 3 bits unused-zero; 1 bit direction */
114 guint8 category; /* indicates type of traffic. 4 bits of status + 4 bits of type */
115 guint16 cell_count; /* number of cells that make up this pdu */
116 guint32 data_length; /* PDU data length for AAL-5 PDUs, all others - cellcount * 48 */
117 guint32 ts_secs; /* seonds value of sysUpTime when the last cell of this PDU was captured */
118 guint32 ts_nsec; /* nanoseonds value of sysUpTime when the last cell of this PDU was captured */
122 /* visual_atm_hdr info bit definitions */
123 #define FROM_NETWORK 0x01
124 #define ATM_VER_MASK 0xf0 /* Not currently displayed */
126 /* visual_atm_hdr category definitions */
127 /* High nibble - not currently displayed */
128 #define VN_INCOMPLETE 0x40
129 #define VN_BAD_CRC 0x80
130 #define VN_CAT_STAT_MASK 0xf0
132 #define VN_UNKNOWN 0x00
135 #define VN_AAL34 0x03
141 #define VN_CAT_TYPE_MASK 0x0f
144 /* Additional information for reading Visual files */
145 struct visual_read_info
147 guint32 num_pkts; /* Number of pkts in the file */
148 guint32 current_pkt; /* Next packet to be read */
149 double start_time; /* Capture start time in microseconds */
153 /* Additional information for writing Visual files */
154 struct visual_write_info
156 unsigned start_time; /* Capture start time in seconds */
157 int index_table_index; /* Index of the next index entry */
158 int index_table_size; /* Allocated size of the index table */
159 guint32 * index_table; /* File offsets for the packets */
160 guint32 next_offset; /* Offset of next packet */
164 /* Local functions to handle file reads and writes */
165 static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
166 gint64 *data_offset);
167 static gboolean visual_seek_read(wtap *wth, gint64 seek_off,
168 union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size,
169 int *err, gchar **err_info);
170 static void visual_set_pseudo_header(int encap, struct visual_pkt_hdr *vpkt_hdr,
171 struct visual_atm_hdr *vatm_hdr, union wtap_pseudo_header *pseudo_header);
172 static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
173 const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
174 static gboolean visual_dump_close(wtap_dumper *wdh, int *err);
175 static void visual_dump_free(wtap_dumper *wdh);
178 /* Open a file for reading */
179 int visual_open(wtap *wth, int *err, gchar **err_info)
182 char magic[sizeof visual_magic];
183 struct visual_file_hdr vfile_hdr;
184 struct visual_read_info * visual;
187 /* Check the magic string at the start of the file */
188 errno = WTAP_ERR_CANT_READ;
189 bytes_read = file_read(magic, sizeof magic, wth->fh);
190 if (bytes_read != sizeof magic)
192 *err = file_error(wth->fh, err_info);
197 if (memcmp(magic, visual_magic, sizeof visual_magic) != 0)
202 /* Read the rest of the file header. */
203 errno = WTAP_ERR_CANT_READ;
204 bytes_read = file_read(&vfile_hdr, sizeof vfile_hdr, wth->fh);
205 if (bytes_read != sizeof vfile_hdr)
207 *err = file_error(wth->fh, err_info);
213 /* Verify the file version is known */
214 vfile_hdr.file_version = pletohs(&vfile_hdr.file_version);
215 if (vfile_hdr.file_version != 1)
217 *err = WTAP_ERR_UNSUPPORTED;
218 *err_info = g_strdup_printf("visual: file version %u unsupported", vfile_hdr.file_version);
222 /* Translate the encapsulation type; these values are SNMP ifType
223 values, as found in http://www.iana.org/assignments/smi-numbers.
225 Note that a file with media type 22 ("propPointToPointSerial") may
226 contain Cisco HDLC or PPP over HDLC. This will get sorted out after
227 the first packet is read.
229 XXX - should we use WTAP_ENCAP_PER_PACKET for that? */
230 switch (pletohs(&vfile_hdr.media_type))
232 case 6: /* ethernet-csmacd */
233 encap = WTAP_ENCAP_ETHERNET;
236 case 9: /* IEEE802.5 */
237 encap = WTAP_ENCAP_TOKEN_RING;
241 encap = WTAP_ENCAP_LAPB;
244 case 22: /* propPointToPointSerial */
246 encap = WTAP_ENCAP_CHDLC_WITH_PHDR;
249 case 32: /* frame-relay */
250 encap = WTAP_ENCAP_FRELAY_WITH_PHDR;
254 encap = WTAP_ENCAP_ATM_PDUS;
258 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
259 *err_info = g_strdup_printf("visual: network type %u unknown or unsupported",
260 vfile_hdr.media_type);
264 /* Fill in the wiretap struct with data from the file header */
265 wth->file_type = WTAP_FILE_VISUAL_NETWORKS;
266 wth->file_encap = encap;
267 wth->snapshot_length = pletohs(&vfile_hdr.max_length);
269 /* Save the pointer to the beginning of the packet data so
270 that the later seek_reads work correctly. */
271 wth->data_offset = CAPTUREFILE_HEADER_SIZE;
273 /* Set up the pointers to the handlers for this file type */
274 wth->subtype_read = visual_read;
275 wth->subtype_seek_read = visual_seek_read;
276 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
278 /* Add Visual-specific information to the wiretap struct for later use. */
279 visual = (struct visual_read_info *)g_malloc(sizeof(struct visual_read_info));
280 wth->priv = (void *)visual;
281 visual->num_pkts = pletohl(&vfile_hdr.num_pkts);
282 visual->start_time = ((double) pletohl(&vfile_hdr.start_time)) * 1000000;
283 visual->current_pkt = 1;
289 /* Read the next available packet from the file. This is called
290 in a loop to sequentially read the entire file one time. After
291 the file has been read once, any Future access to the packets is
292 done through seek_read. */
293 static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
296 struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
297 guint32 packet_size = 0;
299 struct visual_pkt_hdr vpkt_hdr;
300 struct visual_atm_hdr vatm_hdr;
301 int phdr_size = sizeof(vpkt_hdr);
302 int ahdr_size = sizeof(vatm_hdr);
307 /* Check for the end of the packet data. Note that a check for file EOF
308 will not work because there are index values stored after the last
310 if (visual->current_pkt > visual->num_pkts)
312 *err = 0; /* it's just an EOF, not an error */
315 visual->current_pkt++;
317 /* Read the packet header. */
318 errno = WTAP_ERR_CANT_READ;
319 bytes_read = file_read(&vpkt_hdr, phdr_size, wth->fh);
320 if (bytes_read != phdr_size)
322 *err = file_error(wth->fh, err_info);
323 if (*err == 0 && bytes_read != 0)
325 *err = WTAP_ERR_SHORT_READ;
329 wth->data_offset += phdr_size;
331 /* Get the included length of data. This includes extra headers + payload */
332 packet_size = pletohs(&vpkt_hdr.incl_len);
334 /* Check for additional ATM packet header */
335 if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
337 /* Read the atm packet header. */
338 errno = WTAP_ERR_CANT_READ;
339 bytes_read = file_read(&vatm_hdr, ahdr_size, wth->fh);
340 if (bytes_read != ahdr_size)
342 *err = file_error(wth->fh, err_info);
343 if (*err == 0 && bytes_read != 0)
345 *err = WTAP_ERR_SHORT_READ;
349 wth->data_offset += ahdr_size;
351 /* Remove ATM header from length of included bytes in capture, as
352 this header was appended by the processor doing the packet reassembly,
353 and was not transmitted across the wire */
354 packet_size -= ahdr_size;
357 /* Read the packet data. */
358 if (packet_size > WTAP_MAX_PACKET_SIZE)
360 /* Probably a corrupt capture file; don't blow up trying
361 to allocate space for an immensely-large packet. */
362 *err = WTAP_ERR_BAD_RECORD;
363 *err_info = g_strdup_printf("visual: File has %u-byte packet, bigger than maximum of %u",
364 packet_size, WTAP_MAX_PACKET_SIZE);
367 buffer_assure_space(wth->frame_buffer, packet_size);
368 *data_offset = wth->data_offset;
369 errno = WTAP_ERR_CANT_READ;
370 bytes_read = file_read(buffer_start_ptr(wth->frame_buffer),
371 packet_size, wth->fh);
373 if (bytes_read != (int) packet_size)
375 *err = file_error(wth->fh, err_info);
377 *err = WTAP_ERR_SHORT_READ;
380 wth->data_offset += packet_size;
382 /* Set the packet time and length. */
383 t = visual->start_time;
384 t += ((double)pletohl(&vpkt_hdr.ts_delta))*1000;
385 secs = (time_t)(t/1000000);
386 usecs = (guint32)(t - secs*1000000);
387 wth->phdr.ts.secs = secs;
388 wth->phdr.ts.nsecs = usecs * 1000;
390 /* Most visual capture types include FCS checks in the original length value, but
391 * but don't include the FCS as part of the payload or captured length.
392 * This causes the RTP audio payload save to fail since then captured len != orig len.
393 * Adjusting the original length to remove the FCS bytes we counted based
394 * on the file encapsualtion type.
396 * Only downside to this fix is throughput calculations will be slightly lower
397 * as they won't include the FCS bytes.
400 wth->phdr.caplen = packet_size;
401 wth->phdr.len = pletohs(&vpkt_hdr.orig_len);
403 switch (wth->file_encap)
405 case WTAP_ENCAP_ETHERNET:
409 case WTAP_ENCAP_FRELAY_WITH_PHDR:
410 case WTAP_ENCAP_CHDLC_WITH_PHDR:
411 case WTAP_ENCAP_LAPB:
415 /* ATM original length doesn't include any FCS. Do nothing. */
416 case WTAP_ENCAP_ATM_PDUS:
417 /* Not sure about token ring. Just leaving alone for now. */
418 case WTAP_ENCAP_TOKEN_RING:
424 if (wth->phdr.len < wth->phdr.caplen)
426 wth->phdr.len = wth->phdr.caplen;
429 /* Set the pseudo_header. */
430 visual_set_pseudo_header(wth->file_encap, &vpkt_hdr, &vatm_hdr, &wth->pseudo_header);
432 /* Fill in the encapsulation. Visual files have a media type in the
433 file header and an encapsulation type in each packet header. Files
434 with a media type of HDLC can be either Cisco EtherType or PPP.
436 The encapsulation hint values we've seen are:
438 2 - seen in an Ethernet capture
439 13 - seen in a PPP capture; possibly also seen in Cisco HDLC
441 14 - seen in a PPP capture; probably seen only for PPP */
442 if (wth->file_encap == WTAP_ENCAP_CHDLC_WITH_PHDR)
444 /* If PPP is specified in the encap hint, then use that */
445 if (vpkt_hdr.encap_hint == 14)
447 /* But first we need to examine the first three octets to
448 try to determine the proper encapsulation, see RFC 2364. */
449 guint8 *buf = buffer_start_ptr(wth->frame_buffer);
450 if ((0xfe == buf[0]) && (0xfe == buf[1]) && (0x03 == buf[2]))
452 /* It is actually LLC encapsulated PPP */
453 wth->phdr.pkt_encap = WTAP_ENCAP_ATM_RFC1483;
457 /* It is actually PPP */
458 wth->phdr.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
463 /* Otherwise, we need to examine the first two octets to
464 try to determine the encapsulation. */
465 guint8 *buf = buffer_start_ptr(wth->frame_buffer);
466 if ((0xff == buf[0]) && (0x03 == buf[1]))
468 /* It is actually PPP */
469 wth->phdr.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
476 /* Read packet data for random access.
477 This gets the packet data and rebuilds the pseudo header so that
478 the direction flag works. */
479 static gboolean visual_seek_read (wtap *wth, gint64 seek_off,
480 union wtap_pseudo_header *pseudo_header, guint8 *pd, int len,
481 int *err, gchar **err_info)
483 struct visual_pkt_hdr vpkt_hdr;
484 struct visual_atm_hdr vatm_hdr;
485 int phdr_size = sizeof(vpkt_hdr);
486 int ahdr_size = sizeof(vatm_hdr);
490 /* Get the size of the visual packet header to skip */
491 header_size = sizeof(struct visual_pkt_hdr);
493 /* If ATM capture, need to skip over visual ATM packet header too */
494 if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
496 header_size += (int)sizeof(struct visual_atm_hdr);
499 /* Seek to the packet header */
500 if (file_seek(wth->random_fh, seek_off - header_size,
501 SEEK_SET, err) == -1)
504 /* Read the packet header to get the status flags. */
505 errno = WTAP_ERR_CANT_READ;
506 bytes_read = file_read(&vpkt_hdr, phdr_size, wth->random_fh);
507 if (bytes_read != phdr_size) {
508 *err = file_error(wth->random_fh, err_info);
510 *err = WTAP_ERR_SHORT_READ;
514 /* Check for additional ATM packet header */
515 if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
517 /* Read the atm packet header */
518 errno = WTAP_ERR_CANT_READ;
519 bytes_read = file_read(&vatm_hdr, ahdr_size, wth->random_fh);
520 if (bytes_read != ahdr_size)
522 *err = file_error(wth->fh, err_info);
523 if (*err == 0 && bytes_read != 0)
525 *err = WTAP_ERR_SHORT_READ;
531 /* Read the packet data. */
532 errno = WTAP_ERR_CANT_READ;
533 bytes_read = file_read(pd, len, wth->random_fh);
534 if (bytes_read != len) {
536 *err = WTAP_ERR_SHORT_READ;
540 /* Set the pseudo_header. */
541 visual_set_pseudo_header(wth->file_encap, &vpkt_hdr, &vatm_hdr, pseudo_header);
546 static void visual_set_pseudo_header(int encap, struct visual_pkt_hdr *vpkt_hdr,
547 struct visual_atm_hdr *vatm_hdr, union wtap_pseudo_header *pseudo_header)
549 guint32 packet_status;
551 /* Set status flags. The only status currently supported for all
552 encapsulations is direction. This either goes in the p2p or the
553 X.25 pseudo header. It would probably be better to move this up
555 packet_status = pletohl(&vpkt_hdr->status);
558 case WTAP_ENCAP_ETHERNET:
559 /* XXX - is there an FCS in the frame? */
560 pseudo_header->eth.fcs_len = -1;
563 case WTAP_ENCAP_CHDLC_WITH_PHDR:
564 case WTAP_ENCAP_PPP_WITH_PHDR:
565 pseudo_header->p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
568 case WTAP_ENCAP_FRELAY_WITH_PHDR:
569 case WTAP_ENCAP_LAPB:
570 pseudo_header->x25.flags =
571 (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
574 case WTAP_ENCAP_ATM_PDUS:
576 pseudo_header->atm.type = TRAF_UNKNOWN;
577 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
578 pseudo_header->atm.aal5t_len = 0;
580 /* Next two items not supported. Defaulting to zero */
581 pseudo_header->atm.aal5t_u2u = 0;
582 pseudo_header->atm.aal5t_chksum = 0;
584 /* Flags appear only to convey that packet is a raw cell. Set to 0 */
585 pseudo_header->atm.flags = 0;
587 /* Not supported. Defaulting to zero */
588 pseudo_header->atm.aal2_cid = 0;
590 switch(vatm_hdr->category & VN_CAT_TYPE_MASK )
593 pseudo_header->atm.aal = AAL_1;
597 pseudo_header->atm.aal = AAL_2;
601 pseudo_header->atm.aal = AAL_3_4;
605 pseudo_header->atm.aal = AAL_5;
606 pseudo_header->atm.type = TRAF_LLCMX;
607 pseudo_header->atm.aal5t_len = pntohl(&vatm_hdr->data_length);
611 /* Marking next 3 as OAM versus unknown */
615 pseudo_header->atm.aal = AAL_OAMCELL;
620 pseudo_header->atm.aal = AAL_UNKNOWN;
624 pseudo_header->atm.vpi = pntohs(&vatm_hdr->vpi) & 0x0FFF;
625 pseudo_header->atm.vci = pntohs(&vatm_hdr->vci);
626 pseudo_header->atm.cells = pntohs(&vatm_hdr->cell_count);
628 /* Using bit value of 1 (DCE -> DTE) to indicate From Network */
629 pseudo_header->atm.channel = vatm_hdr->info & FROM_NETWORK;
635 /* Check for media types that may be written in Visual file format.
636 Returns 0 if the specified encapsulation type is supported,
637 an error indication otherwise. */
638 int visual_dump_can_write_encap(int encap)
640 /* Per-packet encapsulations aren't supported. */
641 if (encap == WTAP_ENCAP_PER_PACKET)
642 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
644 /* Check for supported encapsulation types */
647 case WTAP_ENCAP_ETHERNET:
648 case WTAP_ENCAP_TOKEN_RING:
649 case WTAP_ENCAP_LAPB:
650 case WTAP_ENCAP_CHDLC_WITH_PHDR:
651 case WTAP_ENCAP_FRELAY_WITH_PHDR:
653 case WTAP_ENCAP_PPP_WITH_PHDR:
657 return WTAP_ERR_UNSUPPORTED_ENCAP;
661 /* Open a file for writing.
662 Returns TRUE on success, FALSE on failure; sets "*err" to an
663 error code on failure */
664 gboolean visual_dump_open(wtap_dumper *wdh, int *err)
666 struct visual_write_info *visual;
668 /* Set the write routines for a visual file. */
669 wdh->subtype_write = visual_dump;
670 wdh->subtype_close = visual_dump_close;
672 /* Create a struct to hold file information for the duration
674 visual = (struct visual_write_info *)g_malloc(sizeof(struct visual_write_info));
675 wdh->priv = (void *)visual;
676 visual->index_table_index = 0;
677 visual->index_table_size = 1024;
678 visual->index_table = 0;
679 visual->next_offset = CAPTUREFILE_HEADER_SIZE;
681 /* All of the fields in the file header aren't known yet so
682 just skip over it for now. It will be created after all
683 of the packets have been written. */
684 if (fseek(wdh->fh, CAPTUREFILE_HEADER_SIZE, SEEK_SET) == -1) {
693 /* Write a packet to a Visual dump file.
694 Returns TRUE on success, FALSE on failure. */
695 static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
696 const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
698 struct visual_write_info * visual = wdh->priv;
699 struct visual_pkt_hdr vpkt_hdr;
700 size_t hdr_size = sizeof vpkt_hdr;
702 guint32 packet_status;
704 /* If the visual structure was never allocated then nothing useful
709 /* Zero out unused and reserved fields in the packet header. */
710 memset(&vpkt_hdr, 0, hdr_size);
712 /* Visual UpTime capture files have a capture start time in the
713 file header. Each packet has a capture time (in msec) relative
714 to the file start time. Use the time of the first packet as the
716 if (visual->index_table_index == 0)
718 /* This is the first packet. Save its start time as the file time. */
719 visual->start_time = (guint32) phdr->ts.secs;
721 /* Initialize the index table */
722 visual->index_table = g_malloc(1024 * sizeof *visual->index_table);
723 visual->index_table_size = 1024;
726 /* Calculate milliseconds since capture start. */
727 delta_msec = phdr->ts.nsecs / 1000000;
728 delta_msec += ( (guint32) phdr->ts.secs - visual->start_time) * 1000;
729 vpkt_hdr.ts_delta = htolel(delta_msec);
731 /* Fill in the length fields. */
732 vpkt_hdr.orig_len = htoles(phdr->len);
733 vpkt_hdr.incl_len = htoles(phdr->caplen);
735 /* Fill in the encapsulation hint for the file's media type. */
738 case WTAP_ENCAP_ETHERNET: /* Ethernet */
739 vpkt_hdr.encap_hint = 2;
741 case WTAP_ENCAP_TOKEN_RING: /* Token Ring */
742 vpkt_hdr.encap_hint = 3;
744 case WTAP_ENCAP_PPP: /* PPP */
745 case WTAP_ENCAP_PPP_WITH_PHDR:
746 vpkt_hdr.encap_hint = 14;
748 case WTAP_ENCAP_CHDLC_WITH_PHDR: /* HDLC Router */
749 vpkt_hdr.encap_hint = 13;
751 case WTAP_ENCAP_FRELAY_WITH_PHDR: /* Frame Relay Auto-detect */
752 vpkt_hdr.encap_hint = 12;
754 case WTAP_ENCAP_LAPB: /* Unknown */
756 vpkt_hdr.encap_hint = 1;
760 /* Set status flags. The only status currently supported for all
761 encapsulations is direction. This either goes in the p2p or the
762 X.25 pseudo header. It would probably be better to move this up
767 case WTAP_ENCAP_CHDLC_WITH_PHDR:
768 packet_status |= (pseudo_header->p2p.sent ? PS_SENT : 0x00);
771 case WTAP_ENCAP_FRELAY_WITH_PHDR:
772 case WTAP_ENCAP_LAPB:
774 ((pseudo_header->x25.flags & FROM_DCE) ? 0x00 : PS_SENT);
777 vpkt_hdr.status = htolel(packet_status);
779 /* Write the packet header. */
780 if (!wtap_dump_file_write(wdh, &vpkt_hdr, hdr_size, err))
783 /* Write the packet data */
784 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
787 /* Store the frame offset in the index table. */
788 if (visual->index_table_index >= visual->index_table_size)
790 /* End of table reached. Reallocate with a larger size */
791 visual->index_table_size *= 2;
792 visual->index_table = g_realloc(visual->index_table,
793 visual->index_table_size * sizeof *visual->index_table);
795 visual->index_table[visual->index_table_index] = htolel(visual->next_offset);
797 /* Update the table index and offset for the next frame. */
798 visual->index_table_index++;
799 visual->next_offset += (guint32) hdr_size + phdr->caplen;
805 /* Finish writing to a dump file.
806 Returns TRUE on success, FALSE on failure. */
807 static gboolean visual_dump_close(wtap_dumper *wdh, int *err)
809 struct visual_write_info * visual = wdh->priv;
811 struct visual_file_hdr vfile_hdr;
815 /* If the visual structure was never allocated then nothing useful
820 /* Write out the frame table at the end of the file. */
821 if (visual->index_table)
823 /* Write the index table to the file. */
824 n_to_write = visual->index_table_index * sizeof *visual->index_table;
825 if (!wtap_dump_file_write(wdh, visual->index_table, n_to_write, err))
827 visual_dump_free(wdh);
832 /* Write the magic number at the start of the file. */
833 fseek(wdh->fh, 0, SEEK_SET);
834 magicp = visual_magic;
835 magic_size = sizeof visual_magic;
836 if (!wtap_dump_file_write(wdh, magicp, magic_size, err))
838 visual_dump_free(wdh);
842 /* Initialize the file header with zeroes for the reserved fields. */
843 memset(&vfile_hdr, '\0', sizeof vfile_hdr);
844 vfile_hdr.num_pkts = htolel(visual->index_table_index);
845 vfile_hdr.start_time = htolel(visual->start_time);
846 vfile_hdr.max_length = htoles(65535);
847 vfile_hdr.file_flags = htoles(1); /* indexes are present */
848 vfile_hdr.file_version = htoles(1);
849 g_strlcpy(vfile_hdr.description, "Wireshark file", 64);
851 /* Translate the encapsulation type */
854 case WTAP_ENCAP_ETHERNET:
855 vfile_hdr.media_type = htoles(6);
858 case WTAP_ENCAP_TOKEN_RING:
859 vfile_hdr.media_type = htoles(9);
862 case WTAP_ENCAP_LAPB:
863 vfile_hdr.media_type = htoles(16);
866 case WTAP_ENCAP_PPP: /* PPP is differentiated from CHDLC in PktHdr */
867 case WTAP_ENCAP_PPP_WITH_PHDR:
868 case WTAP_ENCAP_CHDLC_WITH_PHDR:
869 vfile_hdr.media_type = htoles(22);
872 case WTAP_ENCAP_FRELAY_WITH_PHDR:
873 vfile_hdr.media_type = htoles(32);
877 /* Write the file header following the magic bytes. */
878 if (!wtap_dump_file_write(wdh, &vfile_hdr, sizeof vfile_hdr, err))
880 visual_dump_free(wdh);
884 /* Deallocate the file write data */
885 visual_dump_free(wdh);
890 /* Free the memory allocated by a visual file writer. */
891 static void visual_dump_free(wtap_dumper *wdh)
893 struct visual_write_info * visual = wdh->priv;
897 /* Free the index table memory. */
898 if (visual->index_table)
899 g_free(visual->index_table);