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 packet_size
,
167 int *err
, gchar
**err_info
);
168 static gboolean
visual_read_packet(wtap
*wth
, FILE_T fh
,
169 struct wtap_pkthdr
*phdr
, Buffer
*buf
, int *err
, gchar
**err_info
);
170 static gboolean
visual_dump(wtap_dumper
*wdh
, const struct wtap_pkthdr
*phdr
,
171 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
);
191 if (*err
!= 0 && *err
!= WTAP_ERR_SHORT_READ
)
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
);
207 *err
= WTAP_ERR_SHORT_READ
;
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_subtype
= WTAP_FILE_TYPE_SUBTYPE_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
;
292 /* Check for the end of the packet data. Note that a check for file EOF
293 will not work because there are index values stored after the last
295 if (visual
->current_pkt
> visual
->num_pkts
)
297 *err
= 0; /* it's just an EOF, not an error */
300 visual
->current_pkt
++;
302 *data_offset
= file_tell(wth
->fh
);
304 return visual_read_packet(wth
, wth
->fh
, &wth
->phdr
, wth
->frame_buffer
,
308 /* Read packet header and data for random access. */
309 static gboolean
visual_seek_read(wtap
*wth
, gint64 seek_off
,
310 struct wtap_pkthdr
*phdr
, Buffer
*buf
, int len _U_
,
311 int *err
, gchar
**err_info
)
313 /* Seek to the packet header */
314 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
317 /* Read the packet. */
318 if (!visual_read_packet(wth
, wth
->random_fh
, phdr
, buf
, err
, err_info
)) {
320 *err
= WTAP_ERR_SHORT_READ
;
327 visual_read_packet(wtap
*wth
, FILE_T fh
, struct wtap_pkthdr
*phdr
,
328 Buffer
*buf
, int *err
, gchar
**err_info
)
330 struct visual_read_info
*visual
= (struct visual_read_info
*)wth
->priv
;
331 struct visual_pkt_hdr vpkt_hdr
;
334 struct visual_atm_hdr vatm_hdr
;
338 guint32 packet_status
;
341 /* Read the packet header. */
342 errno
= WTAP_ERR_CANT_READ
;
343 bytes_read
= file_read(&vpkt_hdr
, (unsigned int)sizeof vpkt_hdr
, fh
);
344 if (bytes_read
< 0 || (size_t)bytes_read
!= sizeof vpkt_hdr
)
346 *err
= file_error(fh
, err_info
);
347 if (*err
== 0 && bytes_read
!= 0)
349 *err
= WTAP_ERR_SHORT_READ
;
354 /* Get the included length of data. This includes extra headers + payload */
355 packet_size
= pletohs(&vpkt_hdr
.incl_len
);
357 phdr
->presence_flags
= WTAP_HAS_TS
|WTAP_HAS_CAP_LEN
;
359 /* Set the packet time and length. */
360 t
= visual
->start_time
;
361 t
+= ((double)pletohl(&vpkt_hdr
.ts_delta
))*1000;
362 secs
= (time_t)(t
/1000000);
363 usecs
= (guint32
)(t
- secs
*1000000);
364 phdr
->ts
.secs
= secs
;
365 phdr
->ts
.nsecs
= usecs
* 1000;
367 phdr
->len
= pletohs(&vpkt_hdr
.orig_len
);
369 packet_status
= pletohl(&vpkt_hdr
.status
);
371 /* Do encapsulation-specific processing.
373 Most Visual capture types include the FCS in the original length
374 value, but don't include the FCS as part of the payload or captured
375 length. This is different from the model used in most other capture
376 file formats, including pcap and pcap-ng in cases where the FCS isn't
377 captured (which are the typical cases), and causes the RTP audio
378 payload save to fail since then captured len != orig len.
380 We adjust the original length to remove the FCS bytes we counted based
381 on the file encapsualtion type. The only downside to this fix is
382 throughput calculations will be slightly lower as it won't include
383 the FCS bytes. However, as noted, that problem also exists with
384 other capture formats.
386 We also set status flags. The only status currently supported for
387 all encapsulations is direction. This either goes in the p2p or the
388 X.25 pseudo header. It would probably be better to move this up
390 switch (wth
->file_encap
)
392 case WTAP_ENCAP_ETHERNET
:
393 /* Ethernet has a 4-byte FCS. */
396 *err
= WTAP_ERR_BAD_FILE
;
397 *err_info
= g_strdup_printf("visual: Ethernet packet has %u-byte original packet, less than the FCS length",
403 /* XXX - the above implies that there's never an FCS; should this
404 set the FCS length to 0? */
405 phdr
->pseudo_header
.eth
.fcs_len
= -1;
408 case WTAP_ENCAP_CHDLC_WITH_PHDR
:
409 /* This has a 2-byte FCS. */
412 *err
= WTAP_ERR_BAD_FILE
;
413 *err_info
= g_strdup_printf("visual: Cisco HDLC packet has %u-byte original packet, less than the FCS length",
419 phdr
->pseudo_header
.p2p
.sent
= (packet_status
& PS_SENT
) ? TRUE
: FALSE
;
422 case WTAP_ENCAP_PPP_WITH_PHDR
:
424 XXX - true? Note that PPP can negotiate no FCS, a 2-byte FCS,
426 phdr
->pseudo_header
.p2p
.sent
= (packet_status
& PS_SENT
) ? TRUE
: FALSE
;
429 case WTAP_ENCAP_FRELAY_WITH_PHDR
:
430 /* This has a 2-byte FCS. */
433 *err
= WTAP_ERR_BAD_FILE
;
434 *err_info
= g_strdup_printf("visual: Frame Relay packet has %u-byte original packet, less than the FCS length",
440 phdr
->pseudo_header
.x25
.flags
=
441 (packet_status
& PS_SENT
) ? 0x00 : FROM_DCE
;
444 case WTAP_ENCAP_LAPB
:
445 /* This has a 2-byte FCS. */
448 *err
= WTAP_ERR_BAD_FILE
;
449 *err_info
= g_strdup_printf("visual: Frame Relay packet has %u-byte original packet, less than the FCS length",
455 phdr
->pseudo_header
.x25
.flags
=
456 (packet_status
& PS_SENT
) ? 0x00 : FROM_DCE
;
459 case WTAP_ENCAP_ATM_PDUS
:
460 /* ATM original length doesn't include any FCS. Do nothing to
463 ATM packets have an additional packet header; read and
465 errno
= WTAP_ERR_CANT_READ
;
466 bytes_read
= file_read(&vatm_hdr
, (unsigned int)sizeof vatm_hdr
, fh
);
467 if (bytes_read
< 0 || (size_t)bytes_read
!= sizeof vatm_hdr
)
469 *err
= file_error(fh
, err_info
);
472 *err
= WTAP_ERR_SHORT_READ
;
477 /* Remove ATM header from length of included bytes in capture, as
478 this header was appended by the processor doing the packet
479 reassembly, and was not transmitted across the wire */
480 packet_size
-= (guint32
)sizeof vatm_hdr
;
483 phdr
->pseudo_header
.atm
.type
= TRAF_UNKNOWN
;
484 phdr
->pseudo_header
.atm
.subtype
= TRAF_ST_UNKNOWN
;
485 phdr
->pseudo_header
.atm
.aal5t_len
= 0;
487 /* Next two items not supported. Defaulting to zero */
488 phdr
->pseudo_header
.atm
.aal5t_u2u
= 0;
489 phdr
->pseudo_header
.atm
.aal5t_chksum
= 0;
491 /* Flags appear only to convey that packet is a raw cell. Set to 0 */
492 phdr
->pseudo_header
.atm
.flags
= 0;
494 /* Not supported. Defaulting to zero */
495 phdr
->pseudo_header
.atm
.aal2_cid
= 0;
497 switch(vatm_hdr
.category
& VN_CAT_TYPE_MASK
)
500 phdr
->pseudo_header
.atm
.aal
= AAL_1
;
504 phdr
->pseudo_header
.atm
.aal
= AAL_2
;
508 phdr
->pseudo_header
.atm
.aal
= AAL_3_4
;
512 phdr
->pseudo_header
.atm
.aal
= AAL_5
;
513 phdr
->pseudo_header
.atm
.type
= TRAF_LLCMX
;
514 phdr
->pseudo_header
.atm
.aal5t_len
= pntohl(&vatm_hdr
.data_length
);
518 /* Marking next 3 as OAM versus unknown */
522 phdr
->pseudo_header
.atm
.aal
= AAL_OAMCELL
;
527 phdr
->pseudo_header
.atm
.aal
= AAL_UNKNOWN
;
530 phdr
->pseudo_header
.atm
.vpi
= pntohs(&vatm_hdr
.vpi
) & 0x0FFF;
531 phdr
->pseudo_header
.atm
.vci
= pntohs(&vatm_hdr
.vci
);
532 phdr
->pseudo_header
.atm
.cells
= pntohs(&vatm_hdr
.cell_count
);
534 /* Using bit value of 1 (DCE -> DTE) to indicate From Network */
535 phdr
->pseudo_header
.atm
.channel
= vatm_hdr
.info
& FROM_NETWORK
;
538 /* Not sure about token ring. Just leaving alone for now. */
539 case WTAP_ENCAP_TOKEN_RING
:
544 phdr
->caplen
= packet_size
;
546 /* Check for too-large packet. */
547 if (packet_size
> WTAP_MAX_PACKET_SIZE
)
549 /* Probably a corrupt capture file; don't blow up trying
550 to allocate space for an immensely-large packet. */
551 *err
= WTAP_ERR_BAD_FILE
;
552 *err_info
= g_strdup_printf("visual: File has %u-byte packet, bigger than maximum of %u",
553 packet_size
, WTAP_MAX_PACKET_SIZE
);
558 if (phdr
->len
< phdr
->caplen
)
560 phdr
->len
= phdr
->caplen
;
563 /* Read the packet data */
564 if (!wtap_read_packet_bytes(fh
, buf
, packet_size
, err
, err_info
))
567 if (wth
->file_encap
== WTAP_ENCAP_CHDLC_WITH_PHDR
)
569 /* Fill in the encapsulation. Visual files have a media type in the
570 file header and an encapsulation type in each packet header. Files
571 with a media type of HDLC can be either Cisco EtherType or PPP.
573 The encapsulation hint values we've seen are:
575 2 - seen in an Ethernet capture
576 13 - seen in a PPP capture; possibly also seen in Cisco HDLC
578 14 - seen in a PPP capture; probably seen only for PPP.
580 According to bug 2005, the collection probe can be configured
581 for PPP, in which case the encapsulation hint is 14, or can
582 be configured for auto-detect, in which case the encapsulation
583 hint is 13, and the encapsulation must be guessed from the
584 packet contents. Auto-detect is the default. */
585 pd
= buffer_start_ptr(buf
);
587 /* If PPP is specified in the encap hint, then use that */
588 if (vpkt_hdr
.encap_hint
== 14)
590 /* But first we need to examine the first three octets to
591 try to determine the proper encapsulation, see RFC 2364. */
592 if (packet_size
>= 3 &&
593 (0xfe == pd
[0]) && (0xfe == pd
[1]) && (0x03 == pd
[2]))
595 /* It is actually LLC encapsulated PPP */
596 phdr
->pkt_encap
= WTAP_ENCAP_ATM_RFC1483
;
600 /* It is actually PPP */
601 phdr
->pkt_encap
= WTAP_ENCAP_PPP_WITH_PHDR
;
606 /* Otherwise, we need to examine the first two octets to
607 try to determine the encapsulation. */
608 if (packet_size
>= 2 && (0xff == pd
[0]) && (0x03 == pd
[1]))
610 /* It is actually PPP */
611 phdr
->pkt_encap
= WTAP_ENCAP_PPP_WITH_PHDR
;
619 /* Check for media types that may be written in Visual file format.
620 Returns 0 if the specified encapsulation type is supported,
621 an error indication otherwise. */
622 int visual_dump_can_write_encap(int encap
)
624 /* Per-packet encapsulations aren't supported. */
625 if (encap
== WTAP_ENCAP_PER_PACKET
)
626 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED
;
628 /* Check for supported encapsulation types */
631 case WTAP_ENCAP_ETHERNET
:
632 case WTAP_ENCAP_TOKEN_RING
:
633 case WTAP_ENCAP_LAPB
:
634 case WTAP_ENCAP_CHDLC_WITH_PHDR
:
635 case WTAP_ENCAP_FRELAY_WITH_PHDR
:
637 case WTAP_ENCAP_PPP_WITH_PHDR
:
641 return WTAP_ERR_UNSUPPORTED_ENCAP
;
645 /* Open a file for writing.
646 Returns TRUE on success, FALSE on failure; sets "*err" to an
647 error code on failure */
648 gboolean
visual_dump_open(wtap_dumper
*wdh
, int *err
)
650 struct visual_write_info
*visual
;
652 /* Set the write routines for a visual file. */
653 wdh
->subtype_write
= visual_dump
;
654 wdh
->subtype_close
= visual_dump_close
;
656 /* Create a struct to hold file information for the duration
658 visual
= (struct visual_write_info
*)g_malloc(sizeof(struct visual_write_info
));
659 wdh
->priv
= (void *)visual
;
660 visual
->index_table_index
= 0;
661 visual
->index_table_size
= 1024;
662 visual
->index_table
= 0;
663 visual
->next_offset
= CAPTUREFILE_HEADER_SIZE
;
665 /* All of the fields in the file header aren't known yet so
666 just skip over it for now. It will be created after all
667 of the packets have been written. */
668 if (wtap_dump_file_seek(wdh
, CAPTUREFILE_HEADER_SIZE
, SEEK_SET
, err
) == -1)
675 /* Write a packet to a Visual dump file.
676 Returns TRUE on success, FALSE on failure. */
677 static gboolean
visual_dump(wtap_dumper
*wdh
, const struct wtap_pkthdr
*phdr
,
678 const guint8
*pd
, int *err
)
680 const union wtap_pseudo_header
*pseudo_header
= &phdr
->pseudo_header
;
681 struct visual_write_info
* visual
= (struct visual_write_info
*)wdh
->priv
;
682 struct visual_pkt_hdr vpkt_hdr
;
683 size_t hdr_size
= sizeof vpkt_hdr
;
685 guint32 packet_status
;
687 /* If the visual structure was never allocated then nothing useful
692 /* Zero out unused and reserved fields in the packet header. */
693 memset(&vpkt_hdr
, 0, hdr_size
);
695 /* Visual UpTime capture files have a capture start time in the
696 file header. Each packet has a capture time (in msec) relative
697 to the file start time. Use the time of the first packet as the
699 if (visual
->index_table_index
== 0)
701 /* This is the first packet. Save its start time as the file time. */
702 visual
->start_time
= (guint32
) phdr
->ts
.secs
;
704 /* Initialize the index table */
705 visual
->index_table
= (guint32
*)g_malloc(1024 * sizeof *visual
->index_table
);
706 visual
->index_table_size
= 1024;
709 /* Calculate milliseconds since capture start. */
710 delta_msec
= phdr
->ts
.nsecs
/ 1000000;
711 delta_msec
+= ( (guint32
) phdr
->ts
.secs
- visual
->start_time
) * 1000;
712 vpkt_hdr
.ts_delta
= htolel(delta_msec
);
714 /* Fill in the length fields. */
715 vpkt_hdr
.orig_len
= htoles(phdr
->len
);
716 vpkt_hdr
.incl_len
= htoles(phdr
->caplen
);
718 /* Fill in the encapsulation hint for the file's media type. */
721 case WTAP_ENCAP_ETHERNET
: /* Ethernet */
722 vpkt_hdr
.encap_hint
= 2;
724 case WTAP_ENCAP_TOKEN_RING
: /* Token Ring */
725 vpkt_hdr
.encap_hint
= 3;
727 case WTAP_ENCAP_PPP
: /* PPP */
728 case WTAP_ENCAP_PPP_WITH_PHDR
:
729 vpkt_hdr
.encap_hint
= 14;
731 case WTAP_ENCAP_CHDLC_WITH_PHDR
: /* HDLC Router */
732 vpkt_hdr
.encap_hint
= 13;
734 case WTAP_ENCAP_FRELAY_WITH_PHDR
: /* Frame Relay Auto-detect */
735 vpkt_hdr
.encap_hint
= 12;
737 case WTAP_ENCAP_LAPB
: /* Unknown */
739 vpkt_hdr
.encap_hint
= 1;
743 /* Set status flags. The only status currently supported for all
744 encapsulations is direction. This either goes in the p2p or the
745 X.25 pseudo header. It would probably be better to move this up
750 case WTAP_ENCAP_CHDLC_WITH_PHDR
:
751 packet_status
|= (pseudo_header
->p2p
.sent
? PS_SENT
: 0x00);
754 case WTAP_ENCAP_FRELAY_WITH_PHDR
:
755 case WTAP_ENCAP_LAPB
:
757 ((pseudo_header
->x25
.flags
& FROM_DCE
) ? 0x00 : PS_SENT
);
760 vpkt_hdr
.status
= htolel(packet_status
);
762 /* Write the packet header. */
763 if (!wtap_dump_file_write(wdh
, &vpkt_hdr
, hdr_size
, err
))
766 /* Write the packet data */
767 if (!wtap_dump_file_write(wdh
, pd
, phdr
->caplen
, err
))
770 /* Store the frame offset in the index table. */
771 if (visual
->index_table_index
>= visual
->index_table_size
)
773 /* End of table reached. Reallocate with a larger size */
774 visual
->index_table_size
*= 2;
775 visual
->index_table
= (guint32
*)g_realloc(visual
->index_table
,
776 visual
->index_table_size
* sizeof *visual
->index_table
);
778 visual
->index_table
[visual
->index_table_index
] = htolel(visual
->next_offset
);
780 /* Update the table index and offset for the next frame. */
781 visual
->index_table_index
++;
782 visual
->next_offset
+= (guint32
) hdr_size
+ phdr
->caplen
;
788 /* Finish writing to a dump file.
789 Returns TRUE on success, FALSE on failure. */
790 static gboolean
visual_dump_close(wtap_dumper
*wdh
, int *err
)
792 struct visual_write_info
* visual
= (struct visual_write_info
*)wdh
->priv
;
794 struct visual_file_hdr vfile_hdr
;
798 /* If the visual structure was never allocated then nothing useful
803 /* Write out the frame table at the end of the file. */
804 if (visual
->index_table
)
806 /* Write the index table to the file. */
807 n_to_write
= visual
->index_table_index
* sizeof *visual
->index_table
;
808 if (!wtap_dump_file_write(wdh
, visual
->index_table
, n_to_write
, err
))
810 visual_dump_free(wdh
);
815 /* Write the magic number at the start of the file. */
816 if (wtap_dump_file_seek(wdh
, 0, SEEK_SET
, err
) == -1)
818 magicp
= visual_magic
;
819 magic_size
= sizeof visual_magic
;
820 if (!wtap_dump_file_write(wdh
, magicp
, magic_size
, err
))
822 visual_dump_free(wdh
);
826 /* Initialize the file header with zeroes for the reserved fields. */
827 memset(&vfile_hdr
, '\0', sizeof vfile_hdr
);
828 vfile_hdr
.num_pkts
= htolel(visual
->index_table_index
);
829 vfile_hdr
.start_time
= htolel(visual
->start_time
);
830 vfile_hdr
.max_length
= htoles(65535);
831 vfile_hdr
.file_flags
= htoles(1); /* indexes are present */
832 vfile_hdr
.file_version
= htoles(1);
833 g_strlcpy(vfile_hdr
.description
, "Wireshark file", 64);
835 /* Translate the encapsulation type */
838 case WTAP_ENCAP_ETHERNET
:
839 vfile_hdr
.media_type
= htoles(6);
842 case WTAP_ENCAP_TOKEN_RING
:
843 vfile_hdr
.media_type
= htoles(9);
846 case WTAP_ENCAP_LAPB
:
847 vfile_hdr
.media_type
= htoles(16);
850 case WTAP_ENCAP_PPP
: /* PPP is differentiated from CHDLC in PktHdr */
851 case WTAP_ENCAP_PPP_WITH_PHDR
:
852 case WTAP_ENCAP_CHDLC_WITH_PHDR
:
853 vfile_hdr
.media_type
= htoles(22);
856 case WTAP_ENCAP_FRELAY_WITH_PHDR
:
857 vfile_hdr
.media_type
= htoles(32);
861 /* Write the file header following the magic bytes. */
862 if (!wtap_dump_file_write(wdh
, &vfile_hdr
, sizeof vfile_hdr
, err
))
864 visual_dump_free(wdh
);
868 /* Deallocate the file write data */
869 visual_dump_free(wdh
);
874 /* Free the memory allocated by a visual file writer. */
875 static void visual_dump_free(wtap_dumper
*wdh
)
877 struct visual_write_info
* visual
= (struct visual_write_info
*)wdh
->priv
;
881 /* Free the index table memory. */
882 if (visual
->index_table
)
883 g_free(visual
->index_table
);