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 unsigned 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 union wtap_pseudo_header *pseudo_header, guint8 *pd, int packet_size,
167 int *err, gchar **err_info);
168 static void visual_set_pseudo_header(int encap, struct visual_pkt_hdr *vpkt_hdr,
169 struct visual_atm_hdr *vatm_hdr, union wtap_pseudo_header *pseudo_header);
170 static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
171 const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err);
172 static gboolean visual_dump_close(wtap_dumper *wdh, int *err);
173 static void visual_dump_free(wtap_dumper *wdh);
176 /* Open a file for reading */
177 int visual_open(wtap *wth, int *err, gchar **err_info)
180 char magic[sizeof visual_magic];
181 struct visual_file_hdr vfile_hdr;
182 struct visual_read_info * visual;
185 /* Check the magic string at the start of the file */
186 errno = WTAP_ERR_CANT_READ;
187 bytes_read = file_read(magic, sizeof magic, wth->fh);
188 if (bytes_read != sizeof magic)
190 *err = file_error(wth->fh, err_info);
195 if (memcmp(magic, visual_magic, sizeof visual_magic) != 0)
200 /* Read the rest of the file header. */
201 errno = WTAP_ERR_CANT_READ;
202 bytes_read = file_read(&vfile_hdr, sizeof vfile_hdr, wth->fh);
203 if (bytes_read != sizeof vfile_hdr)
205 *err = file_error(wth->fh, err_info);
211 /* Verify the file version is known */
212 vfile_hdr.file_version = pletohs(&vfile_hdr.file_version);
213 if (vfile_hdr.file_version != 1)
215 *err = WTAP_ERR_UNSUPPORTED;
216 *err_info = g_strdup_printf("visual: file version %u unsupported", vfile_hdr.file_version);
220 /* Translate the encapsulation type; these values are SNMP ifType
221 values, as found in http://www.iana.org/assignments/smi-numbers.
223 Note that a file with media type 22 ("propPointToPointSerial") may
224 contain Cisco HDLC or PPP over HDLC. This will get sorted out after
225 the first packet is read.
227 XXX - should we use WTAP_ENCAP_PER_PACKET for that? */
228 switch (pletohs(&vfile_hdr.media_type))
230 case 6: /* ethernet-csmacd */
231 encap = WTAP_ENCAP_ETHERNET;
234 case 9: /* IEEE802.5 */
235 encap = WTAP_ENCAP_TOKEN_RING;
239 encap = WTAP_ENCAP_LAPB;
242 case 22: /* propPointToPointSerial */
244 encap = WTAP_ENCAP_CHDLC_WITH_PHDR;
247 case 32: /* frame-relay */
248 encap = WTAP_ENCAP_FRELAY_WITH_PHDR;
252 encap = WTAP_ENCAP_ATM_PDUS;
256 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
257 *err_info = g_strdup_printf("visual: network type %u unknown or unsupported",
258 vfile_hdr.media_type);
262 /* Fill in the wiretap struct with data from the file header */
263 wth->file_type = WTAP_FILE_VISUAL_NETWORKS;
264 wth->file_encap = encap;
265 wth->snapshot_length = pletohs(&vfile_hdr.max_length);
267 /* Set up the pointers to the handlers for this file type */
268 wth->subtype_read = visual_read;
269 wth->subtype_seek_read = visual_seek_read;
270 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
272 /* Add Visual-specific information to the wiretap struct for later use. */
273 visual = (struct visual_read_info *)g_malloc(sizeof(struct visual_read_info));
274 wth->priv = (void *)visual;
275 visual->num_pkts = pletohl(&vfile_hdr.num_pkts);
276 visual->start_time = ((double) pletohl(&vfile_hdr.start_time)) * 1000000;
277 visual->current_pkt = 1;
283 /* Read the next available packet from the file. This is called
284 in a loop to sequentially read the entire file one time. After
285 the file has been read once, any Future access to the packets is
286 done through seek_read. */
287 static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
290 struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
291 guint32 packet_size = 0;
293 struct visual_pkt_hdr vpkt_hdr;
294 struct visual_atm_hdr vatm_hdr;
295 int phdr_size = sizeof(vpkt_hdr);
296 int ahdr_size = sizeof(vatm_hdr);
301 /* Check for the end of the packet data. Note that a check for file EOF
302 will not work because there are index values stored after the last
304 if (visual->current_pkt > visual->num_pkts)
306 *err = 0; /* it's just an EOF, not an error */
309 visual->current_pkt++;
311 /* Read the packet header. */
312 errno = WTAP_ERR_CANT_READ;
313 bytes_read = file_read(&vpkt_hdr, phdr_size, wth->fh);
314 if (bytes_read != phdr_size)
316 *err = file_error(wth->fh, err_info);
317 if (*err == 0 && bytes_read != 0)
319 *err = WTAP_ERR_SHORT_READ;
324 /* Get the included length of data. This includes extra headers + payload */
325 packet_size = pletohs(&vpkt_hdr.incl_len);
327 /* Check for additional ATM packet header */
328 if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
330 /* Read the atm packet header. */
331 errno = WTAP_ERR_CANT_READ;
332 bytes_read = file_read(&vatm_hdr, ahdr_size, wth->fh);
333 if (bytes_read != ahdr_size)
335 *err = file_error(wth->fh, err_info);
336 if (*err == 0 && bytes_read != 0)
338 *err = WTAP_ERR_SHORT_READ;
343 /* Remove ATM header from length of included bytes in capture, as
344 this header was appended by the processor doing the packet reassembly,
345 and was not transmitted across the wire */
346 packet_size -= ahdr_size;
349 /* Read the packet data. */
350 if (packet_size > WTAP_MAX_PACKET_SIZE)
352 /* Probably a corrupt capture file; don't blow up trying
353 to allocate space for an immensely-large packet. */
354 *err = WTAP_ERR_BAD_FILE;
355 *err_info = g_strdup_printf("visual: File has %u-byte packet, bigger than maximum of %u",
356 packet_size, WTAP_MAX_PACKET_SIZE);
359 buffer_assure_space(wth->frame_buffer, packet_size);
360 *data_offset = file_tell(wth->fh);
361 errno = WTAP_ERR_CANT_READ;
362 bytes_read = file_read(buffer_start_ptr(wth->frame_buffer),
363 packet_size, wth->fh);
365 if (bytes_read != (int) packet_size)
367 *err = file_error(wth->fh, err_info);
369 *err = WTAP_ERR_SHORT_READ;
373 wth->phdr.presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
375 /* Set the packet time and length. */
376 t = visual->start_time;
377 t += ((double)pletohl(&vpkt_hdr.ts_delta))*1000;
378 secs = (time_t)(t/1000000);
379 usecs = (guint32)(t - secs*1000000);
380 wth->phdr.ts.secs = secs;
381 wth->phdr.ts.nsecs = usecs * 1000;
383 /* Most visual capture types include FCS checks in the original length value, but
384 * but don't include the FCS as part of the payload or captured length.
385 * This causes the RTP audio payload save to fail since then captured len != orig len.
386 * Adjusting the original length to remove the FCS bytes we counted based
387 * on the file encapsualtion type.
389 * Only downside to this fix is throughput calculations will be slightly lower
390 * as they won't include the FCS bytes.
393 wth->phdr.caplen = packet_size;
394 wth->phdr.len = pletohs(&vpkt_hdr.orig_len);
396 switch (wth->file_encap)
398 case WTAP_ENCAP_ETHERNET:
402 case WTAP_ENCAP_FRELAY_WITH_PHDR:
403 case WTAP_ENCAP_CHDLC_WITH_PHDR:
404 case WTAP_ENCAP_LAPB:
408 /* ATM original length doesn't include any FCS. Do nothing. */
409 case WTAP_ENCAP_ATM_PDUS:
410 /* Not sure about token ring. Just leaving alone for now. */
411 case WTAP_ENCAP_TOKEN_RING:
416 if (wth->phdr.len > WTAP_MAX_PACKET_SIZE) {
417 /* Check if wth->phdr.len is sane, small values of wth.phdr.len before
418 the case loop above can cause integer underflows */
419 *err = WTAP_ERR_BAD_FILE;
420 *err_info = g_strdup_printf("visual: File has %u-byte original packet, bigger than maximum of %u",
421 wth->phdr.len, WTAP_MAX_PACKET_SIZE);
426 if (wth->phdr.len < wth->phdr.caplen)
428 wth->phdr.len = wth->phdr.caplen;
431 /* Set the pseudo_header. */
432 visual_set_pseudo_header(wth->file_encap, &vpkt_hdr, &vatm_hdr, &wth->pseudo_header);
434 /* Fill in the encapsulation. Visual files have a media type in the
435 file header and an encapsulation type in each packet header. Files
436 with a media type of HDLC can be either Cisco EtherType or PPP.
438 The encapsulation hint values we've seen are:
440 2 - seen in an Ethernet capture
441 13 - seen in a PPP capture; possibly also seen in Cisco HDLC
443 14 - seen in a PPP capture; probably seen only for PPP */
444 if (wth->file_encap == WTAP_ENCAP_CHDLC_WITH_PHDR)
446 /* If PPP is specified in the encap hint, then use that */
447 if (vpkt_hdr.encap_hint == 14)
449 /* But first we need to examine the first three octets to
450 try to determine the proper encapsulation, see RFC 2364. */
451 guint8 *buf = buffer_start_ptr(wth->frame_buffer);
452 if ((0xfe == buf[0]) && (0xfe == buf[1]) && (0x03 == buf[2]))
454 /* It is actually LLC encapsulated PPP */
455 wth->phdr.pkt_encap = WTAP_ENCAP_ATM_RFC1483;
459 /* It is actually PPP */
460 wth->phdr.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
465 /* Otherwise, we need to examine the first two octets to
466 try to determine the encapsulation. */
467 guint8 *buf = buffer_start_ptr(wth->frame_buffer);
468 if ((0xff == buf[0]) && (0x03 == buf[1]))
470 /* It is actually PPP */
471 wth->phdr.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
478 /* Read packet data for random access.
479 This gets the packet data and rebuilds the pseudo header so that
480 the direction flag works. */
481 static gboolean visual_seek_read (wtap *wth, gint64 seek_off,
482 union wtap_pseudo_header *pseudo_header, guint8 *pd, int len,
483 int *err, gchar **err_info)
485 struct visual_pkt_hdr vpkt_hdr;
486 struct visual_atm_hdr vatm_hdr;
487 int phdr_size = sizeof(vpkt_hdr);
488 int ahdr_size = sizeof(vatm_hdr);
492 /* Get the size of the visual packet header to skip */
493 header_size = sizeof(struct visual_pkt_hdr);
495 /* If ATM capture, need to skip over visual ATM packet header too */
496 if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
498 header_size += (int)sizeof(struct visual_atm_hdr);
501 /* Seek to the packet header */
502 if (file_seek(wth->random_fh, seek_off - header_size,
503 SEEK_SET, err) == -1)
506 /* Read the packet header to get the status flags. */
507 errno = WTAP_ERR_CANT_READ;
508 bytes_read = file_read(&vpkt_hdr, phdr_size, wth->random_fh);
509 if (bytes_read != phdr_size) {
510 *err = file_error(wth->random_fh, err_info);
512 *err = WTAP_ERR_SHORT_READ;
516 /* Check for additional ATM packet header */
517 if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
519 /* Read the atm packet header */
520 errno = WTAP_ERR_CANT_READ;
521 bytes_read = file_read(&vatm_hdr, ahdr_size, wth->random_fh);
522 if (bytes_read != ahdr_size)
524 *err = file_error(wth->fh, err_info);
525 if (*err == 0 && bytes_read != 0)
527 *err = WTAP_ERR_SHORT_READ;
533 /* Read the packet data. */
534 errno = WTAP_ERR_CANT_READ;
535 bytes_read = file_read(pd, len, wth->random_fh);
536 if (bytes_read != len) {
538 *err = WTAP_ERR_SHORT_READ;
542 /* Set the pseudo_header. */
543 visual_set_pseudo_header(wth->file_encap, &vpkt_hdr, &vatm_hdr, pseudo_header);
548 static void visual_set_pseudo_header(int encap, struct visual_pkt_hdr *vpkt_hdr,
549 struct visual_atm_hdr *vatm_hdr, union wtap_pseudo_header *pseudo_header)
551 guint32 packet_status;
553 /* Set status flags. The only status currently supported for all
554 encapsulations is direction. This either goes in the p2p or the
555 X.25 pseudo header. It would probably be better to move this up
557 packet_status = pletohl(&vpkt_hdr->status);
560 case WTAP_ENCAP_ETHERNET:
561 /* XXX - is there an FCS in the frame? */
562 pseudo_header->eth.fcs_len = -1;
565 case WTAP_ENCAP_CHDLC_WITH_PHDR:
566 case WTAP_ENCAP_PPP_WITH_PHDR:
567 pseudo_header->p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
570 case WTAP_ENCAP_FRELAY_WITH_PHDR:
571 case WTAP_ENCAP_LAPB:
572 pseudo_header->x25.flags =
573 (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
576 case WTAP_ENCAP_ATM_PDUS:
578 pseudo_header->atm.type = TRAF_UNKNOWN;
579 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
580 pseudo_header->atm.aal5t_len = 0;
582 /* Next two items not supported. Defaulting to zero */
583 pseudo_header->atm.aal5t_u2u = 0;
584 pseudo_header->atm.aal5t_chksum = 0;
586 /* Flags appear only to convey that packet is a raw cell. Set to 0 */
587 pseudo_header->atm.flags = 0;
589 /* Not supported. Defaulting to zero */
590 pseudo_header->atm.aal2_cid = 0;
592 switch(vatm_hdr->category & VN_CAT_TYPE_MASK )
595 pseudo_header->atm.aal = AAL_1;
599 pseudo_header->atm.aal = AAL_2;
603 pseudo_header->atm.aal = AAL_3_4;
607 pseudo_header->atm.aal = AAL_5;
608 pseudo_header->atm.type = TRAF_LLCMX;
609 pseudo_header->atm.aal5t_len = pntohl(&vatm_hdr->data_length);
613 /* Marking next 3 as OAM versus unknown */
617 pseudo_header->atm.aal = AAL_OAMCELL;
622 pseudo_header->atm.aal = AAL_UNKNOWN;
626 pseudo_header->atm.vpi = pntohs(&vatm_hdr->vpi) & 0x0FFF;
627 pseudo_header->atm.vci = pntohs(&vatm_hdr->vci);
628 pseudo_header->atm.cells = pntohs(&vatm_hdr->cell_count);
630 /* Using bit value of 1 (DCE -> DTE) to indicate From Network */
631 pseudo_header->atm.channel = vatm_hdr->info & FROM_NETWORK;
637 /* Check for media types that may be written in Visual file format.
638 Returns 0 if the specified encapsulation type is supported,
639 an error indication otherwise. */
640 int visual_dump_can_write_encap(int encap)
642 /* Per-packet encapsulations aren't supported. */
643 if (encap == WTAP_ENCAP_PER_PACKET)
644 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
646 /* Check for supported encapsulation types */
649 case WTAP_ENCAP_ETHERNET:
650 case WTAP_ENCAP_TOKEN_RING:
651 case WTAP_ENCAP_LAPB:
652 case WTAP_ENCAP_CHDLC_WITH_PHDR:
653 case WTAP_ENCAP_FRELAY_WITH_PHDR:
655 case WTAP_ENCAP_PPP_WITH_PHDR:
659 return WTAP_ERR_UNSUPPORTED_ENCAP;
663 /* Open a file for writing.
664 Returns TRUE on success, FALSE on failure; sets "*err" to an
665 error code on failure */
666 gboolean visual_dump_open(wtap_dumper *wdh, int *err)
668 struct visual_write_info *visual;
670 /* Set the write routines for a visual file. */
671 wdh->subtype_write = visual_dump;
672 wdh->subtype_close = visual_dump_close;
674 /* Create a struct to hold file information for the duration
676 visual = (struct visual_write_info *)g_malloc(sizeof(struct visual_write_info));
677 wdh->priv = (void *)visual;
678 visual->index_table_index = 0;
679 visual->index_table_size = 1024;
680 visual->index_table = 0;
681 visual->next_offset = CAPTUREFILE_HEADER_SIZE;
683 /* All of the fields in the file header aren't known yet so
684 just skip over it for now. It will be created after all
685 of the packets have been written. */
686 if (fseek(wdh->fh, CAPTUREFILE_HEADER_SIZE, SEEK_SET) == -1) {
695 /* Write a packet to a Visual dump file.
696 Returns TRUE on success, FALSE on failure. */
697 static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
698 const union wtap_pseudo_header *pseudo_header, const guint8 *pd, int *err)
700 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
701 struct visual_pkt_hdr vpkt_hdr;
702 size_t hdr_size = sizeof vpkt_hdr;
704 guint32 packet_status;
706 /* If the visual structure was never allocated then nothing useful
711 /* Zero out unused and reserved fields in the packet header. */
712 memset(&vpkt_hdr, 0, hdr_size);
714 /* Visual UpTime capture files have a capture start time in the
715 file header. Each packet has a capture time (in msec) relative
716 to the file start time. Use the time of the first packet as the
718 if (visual->index_table_index == 0)
720 /* This is the first packet. Save its start time as the file time. */
721 visual->start_time = (guint32) phdr->ts.secs;
723 /* Initialize the index table */
724 visual->index_table = (guint32 *)g_malloc(1024 * sizeof *visual->index_table);
725 visual->index_table_size = 1024;
728 /* Calculate milliseconds since capture start. */
729 delta_msec = phdr->ts.nsecs / 1000000;
730 delta_msec += ( (guint32) phdr->ts.secs - visual->start_time) * 1000;
731 vpkt_hdr.ts_delta = htolel(delta_msec);
733 /* Fill in the length fields. */
734 vpkt_hdr.orig_len = htoles(phdr->len);
735 vpkt_hdr.incl_len = htoles(phdr->caplen);
737 /* Fill in the encapsulation hint for the file's media type. */
740 case WTAP_ENCAP_ETHERNET: /* Ethernet */
741 vpkt_hdr.encap_hint = 2;
743 case WTAP_ENCAP_TOKEN_RING: /* Token Ring */
744 vpkt_hdr.encap_hint = 3;
746 case WTAP_ENCAP_PPP: /* PPP */
747 case WTAP_ENCAP_PPP_WITH_PHDR:
748 vpkt_hdr.encap_hint = 14;
750 case WTAP_ENCAP_CHDLC_WITH_PHDR: /* HDLC Router */
751 vpkt_hdr.encap_hint = 13;
753 case WTAP_ENCAP_FRELAY_WITH_PHDR: /* Frame Relay Auto-detect */
754 vpkt_hdr.encap_hint = 12;
756 case WTAP_ENCAP_LAPB: /* Unknown */
758 vpkt_hdr.encap_hint = 1;
762 /* Set status flags. The only status currently supported for all
763 encapsulations is direction. This either goes in the p2p or the
764 X.25 pseudo header. It would probably be better to move this up
769 case WTAP_ENCAP_CHDLC_WITH_PHDR:
770 packet_status |= (pseudo_header->p2p.sent ? PS_SENT : 0x00);
773 case WTAP_ENCAP_FRELAY_WITH_PHDR:
774 case WTAP_ENCAP_LAPB:
776 ((pseudo_header->x25.flags & FROM_DCE) ? 0x00 : PS_SENT);
779 vpkt_hdr.status = htolel(packet_status);
781 /* Write the packet header. */
782 if (!wtap_dump_file_write(wdh, &vpkt_hdr, hdr_size, err))
785 /* Write the packet data */
786 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
789 /* Store the frame offset in the index table. */
790 if (visual->index_table_index >= visual->index_table_size)
792 /* End of table reached. Reallocate with a larger size */
793 visual->index_table_size *= 2;
794 visual->index_table = (guint32 *)g_realloc(visual->index_table,
795 visual->index_table_size * sizeof *visual->index_table);
797 visual->index_table[visual->index_table_index] = htolel(visual->next_offset);
799 /* Update the table index and offset for the next frame. */
800 visual->index_table_index++;
801 visual->next_offset += (guint32) hdr_size + phdr->caplen;
807 /* Finish writing to a dump file.
808 Returns TRUE on success, FALSE on failure. */
809 static gboolean visual_dump_close(wtap_dumper *wdh, int *err)
811 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
813 struct visual_file_hdr vfile_hdr;
817 /* If the visual structure was never allocated then nothing useful
822 /* Write out the frame table at the end of the file. */
823 if (visual->index_table)
825 /* Write the index table to the file. */
826 n_to_write = visual->index_table_index * sizeof *visual->index_table;
827 if (!wtap_dump_file_write(wdh, visual->index_table, n_to_write, err))
829 visual_dump_free(wdh);
834 /* Write the magic number at the start of the file. */
835 fseek(wdh->fh, 0, SEEK_SET);
836 magicp = visual_magic;
837 magic_size = sizeof visual_magic;
838 if (!wtap_dump_file_write(wdh, magicp, magic_size, err))
840 visual_dump_free(wdh);
844 /* Initialize the file header with zeroes for the reserved fields. */
845 memset(&vfile_hdr, '\0', sizeof vfile_hdr);
846 vfile_hdr.num_pkts = htolel(visual->index_table_index);
847 vfile_hdr.start_time = htolel(visual->start_time);
848 vfile_hdr.max_length = htoles(65535);
849 vfile_hdr.file_flags = htoles(1); /* indexes are present */
850 vfile_hdr.file_version = htoles(1);
851 g_strlcpy(vfile_hdr.description, "Wireshark file", 64);
853 /* Translate the encapsulation type */
856 case WTAP_ENCAP_ETHERNET:
857 vfile_hdr.media_type = htoles(6);
860 case WTAP_ENCAP_TOKEN_RING:
861 vfile_hdr.media_type = htoles(9);
864 case WTAP_ENCAP_LAPB:
865 vfile_hdr.media_type = htoles(16);
868 case WTAP_ENCAP_PPP: /* PPP is differentiated from CHDLC in PktHdr */
869 case WTAP_ENCAP_PPP_WITH_PHDR:
870 case WTAP_ENCAP_CHDLC_WITH_PHDR:
871 vfile_hdr.media_type = htoles(22);
874 case WTAP_ENCAP_FRELAY_WITH_PHDR:
875 vfile_hdr.media_type = htoles(32);
879 /* Write the file header following the magic bytes. */
880 if (!wtap_dump_file_write(wdh, &vfile_hdr, sizeof vfile_hdr, err))
882 visual_dump_free(wdh);
886 /* Deallocate the file write data */
887 visual_dump_free(wdh);
892 /* Free the memory allocated by a visual file writer. */
893 static void visual_dump_free(wtap_dumper *wdh)
895 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
899 /* Free the index table memory. */
900 if (visual->index_table)
901 g_free(visual->index_table);