2 * File read and write routines for Visual Networks cap files.
3 * Copyright (c) 2001, Tom Nisbet tnisbet@visualnetworks.com
6 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
8 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include "file_wrappers.h"
19 * A Visual Networks traffic capture file contains three sections. The
20 * first is a 192 octet file header. This is followed by the captured
21 * packet header, and for ATM captures, there is an additional atm packet header.
22 * The data follows the packet header. The last section is the packet index block.
23 * The index block contains one 4 octet pointer for each captured packet.
24 * The first packet index is (4 * num_pkts) octets from the end of the file
25 * and the last index is in the last four octets of the file.
27 * All integer and time values are stored in little-endian format, except for
28 * the ATM Packet Header, which is stored in network byte order.
33 * [ Packet Header 1 ] [(opt) ATM Packet Header] [ Data ]
35 * [ Packet Header n ] [(opt) ATM Packet Header] [ Data ]
38 * [ Index Block 1 ] ... [ Index Block n ]
41 /* Capture file header, INCLUDING the magic number, is 192 bytes. */
42 #define CAPTUREFILE_HEADER_SIZE 192
44 /* Magic number for Visual Networks traffic capture files. */
45 static const char visual_magic[] = {
50 /* Visual File Header (minus magic number). */
51 /* This structure is used to extract information */
52 struct visual_file_hdr
54 guint32 num_pkts; /* Number of packets in the file */
55 guint32 start_time; /* Capture start time in PC format */
56 guint16 media_type; /* IANA ifType of packet source */
57 guint16 max_length; /* Max allowable stored packet length */
58 guint16 file_flags; /* File type flags */
59 /* Bit 0 indicates indexes present */
60 guint16 file_version; /* Version number of this file format */
61 guint32 media_speed; /* ifSpeed of packet source in bits/sec. */
62 guint16 media_param; /* Media-specific extra parameter. */
63 char RESERVED_[102]; /* MUST BE ALL ZEROS FOR FUTURE COMPATABILITY */
64 char description[64]; /* File description (null terminated) */
68 /* Packet status bits */
71 #define PS_ERRORED 0x04
72 #define PS_1ST_AFTER_DROP 0x08
73 #define PS_APPROX_ORDER 0x10
75 #define PS_ABORTED 0x80
77 /* Visual Packet Header */
78 /* This structure is used to extract information */
81 guint32 ts_delta; /* Time stamp - msecs since start of capture */
82 guint16 orig_len; /* Actual length of packet */
83 guint16 incl_len; /* Number of octets captured in file */
84 guint32 status; /* Packet status flags (media specific) */
85 guint8 encap_hint; /* Encapsulation type hint */
86 guint8 encap_skip; /* Number of bytes to skip before decoding */
87 char RESERVED_[6]; /* RESERVED - must be zero */
90 /* Optional Visual ATM Packet Header */
91 /* This structure is used to extract information */
94 guint16 vpi; /* 4 bits of zeros; 12 bits of ATM VPI */
95 guint16 vci; /* ATM VCI */
96 guint8 info; /* 4 bits version; 3 bits unused-zero; 1 bit direction */
97 guint8 category; /* indicates type of traffic. 4 bits of status + 4 bits of type */
98 guint16 cell_count; /* number of cells that make up this pdu */
99 guint32 data_length; /* PDU data length for AAL-5 PDUs, all others - cellcount * 48 */
100 guint32 ts_secs; /* seonds value of sysUpTime when the last cell of this PDU was captured */
101 guint32 ts_nsec; /* nanoseonds value of sysUpTime when the last cell of this PDU was captured */
105 /* visual_atm_hdr info bit definitions */
106 #define FROM_NETWORK 0x01
107 #define ATM_VER_MASK 0xf0 /* Not currently displayed */
109 /* visual_atm_hdr category definitions */
110 /* High nibble - not currently displayed */
111 #define VN_INCOMPLETE 0x40
112 #define VN_BAD_CRC 0x80
113 #define VN_CAT_STAT_MASK 0xf0
115 #define VN_UNKNOWN 0x00
118 #define VN_AAL34 0x03
124 #define VN_CAT_TYPE_MASK 0x0f
127 /* Additional information for reading Visual files */
128 struct visual_read_info
130 guint32 num_pkts; /* Number of pkts in the file */
131 guint32 current_pkt; /* Next packet to be read */
132 time_t start_time; /* Capture start time in seconds */
136 /* Additional information for writing Visual files */
137 struct visual_write_info
139 time_t start_time; /* Capture start time in seconds */
140 int index_table_index; /* Index of the next index entry */
141 int index_table_size; /* Allocated size of the index table */
142 guint32 * index_table; /* File offsets for the packets */
143 guint32 next_offset; /* Offset of next packet */
147 /* Local functions to handle file reads and writes */
148 static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
149 gint64 *data_offset);
150 static gboolean visual_seek_read(wtap *wth, gint64 seek_off,
151 wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
152 static gboolean visual_read_packet(wtap *wth, FILE_T fh,
153 wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
154 static gboolean visual_dump(wtap_dumper *wdh, const wtap_rec *rec,
155 const guint8 *pd, int *err, gchar **err_info);
156 static gboolean visual_dump_finish(wtap_dumper *wdh, int *err);
157 static void visual_dump_free(wtap_dumper *wdh);
160 /* Open a file for reading */
161 wtap_open_return_val visual_open(wtap *wth, int *err, gchar **err_info)
163 char magic[sizeof visual_magic];
164 struct visual_file_hdr vfile_hdr;
165 struct visual_read_info * visual;
168 /* Check the magic string at the start of the file */
169 if (!wtap_read_bytes(wth->fh, magic, sizeof magic, err, err_info))
171 if (*err != WTAP_ERR_SHORT_READ)
172 return WTAP_OPEN_ERROR;
173 return WTAP_OPEN_NOT_MINE;
175 if (memcmp(magic, visual_magic, sizeof visual_magic) != 0)
177 return WTAP_OPEN_NOT_MINE;
180 /* Read the rest of the file header. */
181 if (!wtap_read_bytes(wth->fh, &vfile_hdr, sizeof vfile_hdr, err, err_info))
183 return WTAP_OPEN_ERROR;
186 /* Verify the file version is known */
187 vfile_hdr.file_version = pletoh16(&vfile_hdr.file_version);
188 if (vfile_hdr.file_version != 1)
190 *err = WTAP_ERR_UNSUPPORTED;
191 *err_info = g_strdup_printf("visual: file version %u unsupported", vfile_hdr.file_version);
192 return WTAP_OPEN_ERROR;
195 /* Translate the encapsulation type; these values are SNMP ifType
196 values, as found in http://www.iana.org/assignments/smi-numbers.
198 Note that a file with media type 22 ("propPointToPointSerial") may
199 contain Cisco HDLC or PPP over HDLC. This will get sorted out after
200 the first packet is read.
202 XXX - should we use WTAP_ENCAP_PER_PACKET for that? */
203 switch (pletoh16(&vfile_hdr.media_type))
205 case 6: /* ethernet-csmacd */
206 encap = WTAP_ENCAP_ETHERNET;
209 case 9: /* IEEE802.5 */
210 encap = WTAP_ENCAP_TOKEN_RING;
214 encap = WTAP_ENCAP_LAPB;
217 case 22: /* propPointToPointSerial */
219 encap = WTAP_ENCAP_CHDLC_WITH_PHDR;
222 case 32: /* frame-relay */
223 encap = WTAP_ENCAP_FRELAY_WITH_PHDR;
227 encap = WTAP_ENCAP_ATM_PDUS;
231 *err = WTAP_ERR_UNSUPPORTED;
232 *err_info = g_strdup_printf("visual: network type %u unknown or unsupported",
233 vfile_hdr.media_type);
234 return WTAP_OPEN_ERROR;
237 /* Fill in the wiretap struct with data from the file header */
238 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS;
239 wth->file_encap = encap;
240 wth->snapshot_length = pletoh16(&vfile_hdr.max_length);
242 /* Set up the pointers to the handlers for this file type */
243 wth->subtype_read = visual_read;
244 wth->subtype_seek_read = visual_seek_read;
245 wth->file_tsprec = WTAP_TSPREC_MSEC;
247 /* Add Visual-specific information to the wiretap struct for later use. */
248 visual = (struct visual_read_info *)g_malloc(sizeof(struct visual_read_info));
249 wth->priv = (void *)visual;
250 visual->num_pkts = pletoh32(&vfile_hdr.num_pkts);
251 visual->start_time = pletoh32(&vfile_hdr.start_time);
252 visual->current_pkt = 1;
254 return WTAP_OPEN_MINE;
258 /* Read the next available packet from the file. This is called
259 in a loop to sequentially read the entire file one time. After
260 the file has been read once, any Future access to the packets is
261 done through seek_read. */
262 static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
265 struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
267 /* Check for the end of the packet data. Note that a check for file EOF
268 will not work because there are index values stored after the last
270 if (visual->current_pkt > visual->num_pkts)
272 *err = 0; /* it's just an EOF, not an error */
275 visual->current_pkt++;
277 *data_offset = file_tell(wth->fh);
279 return visual_read_packet(wth, wth->fh, &wth->rec, wth->rec_data,
283 /* Read packet header and data for random access. */
284 static gboolean visual_seek_read(wtap *wth, gint64 seek_off,
285 wtap_rec *rec, Buffer *buf, int *err, gchar **err_info)
287 /* Seek to the packet header */
288 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
291 /* Read the packet. */
292 if (!visual_read_packet(wth, wth->random_fh, rec, buf, err, err_info)) {
294 *err = WTAP_ERR_SHORT_READ;
301 visual_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
302 Buffer *buf, int *err, gchar **err_info)
304 struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
305 struct visual_pkt_hdr vpkt_hdr;
307 struct visual_atm_hdr vatm_hdr;
309 guint32 packet_status;
312 /* Read the packet header. */
313 if (!wtap_read_bytes_or_eof(fh, &vpkt_hdr, (unsigned int)sizeof vpkt_hdr, err, err_info))
318 /* Get the included length of data. This includes extra headers + payload */
319 packet_size = pletoh16(&vpkt_hdr.incl_len);
321 rec->rec_type = REC_TYPE_PACKET;
322 rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
324 /* Set the packet time and length. */
325 relmsecs = pletoh32(&vpkt_hdr.ts_delta);
326 rec->ts.secs = visual->start_time + relmsecs/1000;
327 rec->ts.nsecs = (relmsecs % 1000)*1000000;
329 rec->rec_header.packet_header.len = pletoh16(&vpkt_hdr.orig_len);
331 packet_status = pletoh32(&vpkt_hdr.status);
333 /* Do encapsulation-specific processing.
335 Most Visual capture types include the FCS in the original length
336 value, but don't include the FCS as part of the payload or captured
337 length. This is different from the model used in most other capture
338 file formats, including pcap and pcapng in cases where the FCS isn't
339 captured (which are the typical cases), and causes the RTP audio
340 payload save to fail since then captured len != orig len.
342 We adjust the original length to remove the FCS bytes we counted based
343 on the file encapsualtion type. The only downside to this fix is
344 throughput calculations will be slightly lower as it won't include
345 the FCS bytes. However, as noted, that problem also exists with
346 other capture formats.
348 We also set status flags. The only status currently supported for
349 all encapsulations is direction. This either goes in the p2p or the
350 X.25 pseudo header. It would probably be better to move this up
352 switch (wth->file_encap)
354 case WTAP_ENCAP_ETHERNET:
355 /* Ethernet has a 4-byte FCS. */
356 if (rec->rec_header.packet_header.len < 4)
358 *err = WTAP_ERR_BAD_FILE;
359 *err_info = g_strdup_printf("visual: Ethernet packet has %u-byte original packet, less than the FCS length",
360 rec->rec_header.packet_header.len);
363 rec->rec_header.packet_header.len -= 4;
365 /* XXX - the above implies that there's never an FCS; should this
366 set the FCS length to 0? */
367 rec->rec_header.packet_header.pseudo_header.eth.fcs_len = -1;
370 case WTAP_ENCAP_CHDLC_WITH_PHDR:
371 /* This has a 2-byte FCS. */
372 if (rec->rec_header.packet_header.len < 2)
374 *err = WTAP_ERR_BAD_FILE;
375 *err_info = g_strdup_printf("visual: Cisco HDLC packet has %u-byte original packet, less than the FCS length",
376 rec->rec_header.packet_header.len);
379 rec->rec_header.packet_header.len -= 2;
381 rec->rec_header.packet_header.pseudo_header.p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
384 case WTAP_ENCAP_PPP_WITH_PHDR:
386 XXX - true? Note that PPP can negotiate no FCS, a 2-byte FCS,
388 rec->rec_header.packet_header.pseudo_header.p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
391 case WTAP_ENCAP_FRELAY_WITH_PHDR:
392 /* This has a 2-byte FCS. */
393 if (rec->rec_header.packet_header.len < 2)
395 *err = WTAP_ERR_BAD_FILE;
396 *err_info = g_strdup_printf("visual: Frame Relay packet has %u-byte original packet, less than the FCS length",
397 rec->rec_header.packet_header.len);
400 rec->rec_header.packet_header.len -= 2;
402 rec->rec_header.packet_header.pseudo_header.dte_dce.flags =
403 (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
406 case WTAP_ENCAP_LAPB:
407 /* This has a 2-byte FCS. */
408 if (rec->rec_header.packet_header.len < 2)
410 *err = WTAP_ERR_BAD_FILE;
411 *err_info = g_strdup_printf("visual: Frame Relay packet has %u-byte original packet, less than the FCS length",
412 rec->rec_header.packet_header.len);
415 rec->rec_header.packet_header.len -= 2;
417 rec->rec_header.packet_header.pseudo_header.dte_dce.flags =
418 (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
421 case WTAP_ENCAP_ATM_PDUS:
422 /* ATM original length doesn't include any FCS. Do nothing to
425 ATM packets have an additional packet header; read and
427 if (!wtap_read_bytes(fh, &vatm_hdr, (unsigned int)sizeof vatm_hdr, err, err_info))
432 /* Remove ATM header from length of included bytes in capture, as
433 this header was appended by the processor doing the packet
434 reassembly, and was not transmitted across the wire */
435 packet_size -= (guint32)sizeof vatm_hdr;
438 rec->rec_header.packet_header.pseudo_header.atm.type = TRAF_UNKNOWN;
439 rec->rec_header.packet_header.pseudo_header.atm.subtype = TRAF_ST_UNKNOWN;
440 rec->rec_header.packet_header.pseudo_header.atm.aal5t_len = 0;
442 /* Next two items not supported. Defaulting to zero */
443 rec->rec_header.packet_header.pseudo_header.atm.aal5t_u2u = 0;
444 rec->rec_header.packet_header.pseudo_header.atm.aal5t_chksum = 0;
446 /* Flags appear only to convey that packet is a raw cell. Set to 0 */
447 rec->rec_header.packet_header.pseudo_header.atm.flags = 0;
449 /* Not supported. Defaulting to zero */
450 rec->rec_header.packet_header.pseudo_header.atm.aal2_cid = 0;
452 switch(vatm_hdr.category & VN_CAT_TYPE_MASK )
455 rec->rec_header.packet_header.pseudo_header.atm.aal = AAL_1;
459 rec->rec_header.packet_header.pseudo_header.atm.aal = AAL_2;
463 rec->rec_header.packet_header.pseudo_header.atm.aal = AAL_3_4;
467 rec->rec_header.packet_header.pseudo_header.atm.aal = AAL_5;
468 rec->rec_header.packet_header.pseudo_header.atm.type = TRAF_LLCMX;
469 rec->rec_header.packet_header.pseudo_header.atm.aal5t_len = pntoh32(&vatm_hdr.data_length);
473 /* Marking next 3 as OAM versus unknown */
477 rec->rec_header.packet_header.pseudo_header.atm.aal = AAL_OAMCELL;
482 rec->rec_header.packet_header.pseudo_header.atm.aal = AAL_UNKNOWN;
485 rec->rec_header.packet_header.pseudo_header.atm.vpi = pntoh16(&vatm_hdr.vpi) & 0x0FFF;
486 rec->rec_header.packet_header.pseudo_header.atm.vci = pntoh16(&vatm_hdr.vci);
487 rec->rec_header.packet_header.pseudo_header.atm.cells = pntoh16(&vatm_hdr.cell_count);
489 /* Using bit value of 1 (DCE -> DTE) to indicate From Network */
490 rec->rec_header.packet_header.pseudo_header.atm.channel = vatm_hdr.info & FROM_NETWORK;
493 /* Not sure about token ring. Just leaving alone for now. */
494 case WTAP_ENCAP_TOKEN_RING:
499 rec->rec_header.packet_header.caplen = packet_size;
501 /* Check for too-large packet. */
502 if (packet_size > WTAP_MAX_PACKET_SIZE_STANDARD)
504 /* Probably a corrupt capture file; don't blow up trying
505 to allocate space for an immensely-large packet. */
506 *err = WTAP_ERR_BAD_FILE;
507 *err_info = g_strdup_printf("visual: File has %u-byte packet, bigger than maximum of %u",
508 packet_size, WTAP_MAX_PACKET_SIZE_STANDARD);
512 /* Read the packet data */
513 if (!wtap_read_packet_bytes(fh, buf, packet_size, err, err_info))
516 if (wth->file_encap == WTAP_ENCAP_CHDLC_WITH_PHDR)
518 /* Fill in the encapsulation. Visual files have a media type in the
519 file header and an encapsulation type in each packet header. Files
520 with a media type of HDLC can be either Cisco EtherType or PPP.
522 The encapsulation hint values we've seen are:
524 2 - seen in an Ethernet capture
525 13 - seen in a PPP capture; possibly also seen in Cisco HDLC
527 14 - seen in a PPP capture; probably seen only for PPP.
529 According to bug 2005, the collection probe can be configured
530 for PPP, in which case the encapsulation hint is 14, or can
531 be configured for auto-detect, in which case the encapsulation
532 hint is 13, and the encapsulation must be guessed from the
533 packet contents. Auto-detect is the default. */
534 pd = ws_buffer_start_ptr(buf);
536 /* If PPP is specified in the encap hint, then use that */
537 if (vpkt_hdr.encap_hint == 14)
539 /* But first we need to examine the first three octets to
540 try to determine the proper encapsulation, see RFC 2364. */
541 if (packet_size >= 3 &&
542 (0xfe == pd[0]) && (0xfe == pd[1]) && (0x03 == pd[2]))
544 /* It is actually LLC encapsulated PPP */
545 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_ATM_RFC1483;
549 /* It is actually PPP */
550 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
555 /* Otherwise, we need to examine the first two octets to
556 try to determine the encapsulation. */
557 if (packet_size >= 2 && (0xff == pd[0]) && (0x03 == pd[1]))
559 /* It is actually PPP */
560 rec->rec_header.packet_header.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
568 /* Check for media types that may be written in Visual file format.
569 Returns 0 if the specified encapsulation type is supported,
570 an error indication otherwise. */
571 int visual_dump_can_write_encap(int encap)
573 /* Per-packet encapsulations aren't supported. */
574 if (encap == WTAP_ENCAP_PER_PACKET)
575 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
577 /* Check for supported encapsulation types */
580 case WTAP_ENCAP_ETHERNET:
581 case WTAP_ENCAP_TOKEN_RING:
582 case WTAP_ENCAP_LAPB:
583 case WTAP_ENCAP_CHDLC_WITH_PHDR:
584 case WTAP_ENCAP_FRELAY_WITH_PHDR:
586 case WTAP_ENCAP_PPP_WITH_PHDR:
590 return WTAP_ERR_UNWRITABLE_ENCAP;
594 /* Open a file for writing.
595 Returns TRUE on success, FALSE on failure; sets "*err" to an
596 error code on failure */
597 gboolean visual_dump_open(wtap_dumper *wdh, int *err)
599 struct visual_write_info *visual;
601 /* Set the write routines for a visual file. */
602 wdh->subtype_write = visual_dump;
603 wdh->subtype_finish = visual_dump_finish;
605 /* Create a struct to hold file information for the duration
607 visual = (struct visual_write_info *)g_malloc(sizeof(struct visual_write_info));
608 wdh->priv = (void *)visual;
609 visual->index_table_index = 0;
610 visual->index_table_size = 1024;
611 visual->index_table = 0;
612 visual->next_offset = CAPTUREFILE_HEADER_SIZE;
614 /* All of the fields in the file header aren't known yet so
615 just skip over it for now. It will be created after all
616 of the packets have been written. */
617 if (wtap_dump_file_seek(wdh, CAPTUREFILE_HEADER_SIZE, SEEK_SET, err) == -1)
624 /* Write a packet to a Visual dump file.
625 Returns TRUE on success, FALSE on failure. */
626 static gboolean visual_dump(wtap_dumper *wdh, const wtap_rec *rec,
627 const guint8 *pd, int *err, gchar **err_info _U_)
629 const union wtap_pseudo_header *pseudo_header = &rec->rec_header.packet_header.pseudo_header;
630 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
631 struct visual_pkt_hdr vpkt_hdr;
632 size_t hdr_size = sizeof vpkt_hdr;
634 guint32 packet_status;
636 /* We can only write packet records. */
637 if (rec->rec_type != REC_TYPE_PACKET) {
638 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
642 /* Don't write anything we're not willing to read. */
643 if (rec->rec_header.packet_header.caplen > WTAP_MAX_PACKET_SIZE_STANDARD) {
644 *err = WTAP_ERR_PACKET_TOO_LARGE;
648 /* If the visual structure was never allocated then nothing useful
653 /* Zero out unused and reserved fields in the packet header. */
654 memset(&vpkt_hdr, 0, hdr_size);
656 /* Visual UpTime capture files have a capture start time in the
657 file header. Each packet has a capture time (in msec) relative
658 to the file start time. Use the time of the first packet as the
660 if (visual->index_table_index == 0)
662 /* This is the first packet. Save its start time as the file time. */
663 visual->start_time = rec->ts.secs;
665 /* Initialize the index table */
666 visual->index_table = (guint32 *)g_malloc(1024 * sizeof *visual->index_table);
667 visual->index_table_size = 1024;
670 /* Calculate milliseconds since capture start. */
671 delta_msec = rec->ts.nsecs / 1000000;
672 delta_msec += (guint32)((rec->ts.secs - visual->start_time) * 1000);
673 vpkt_hdr.ts_delta = GUINT32_TO_LE(delta_msec);
675 /* Fill in the length fields. */
676 vpkt_hdr.orig_len = GUINT16_TO_LE(rec->rec_header.packet_header.len);
677 vpkt_hdr.incl_len = GUINT16_TO_LE(rec->rec_header.packet_header.caplen);
679 /* Fill in the encapsulation hint for the file's media type. */
682 case WTAP_ENCAP_ETHERNET: /* Ethernet */
683 vpkt_hdr.encap_hint = 2;
685 case WTAP_ENCAP_TOKEN_RING: /* Token Ring */
686 vpkt_hdr.encap_hint = 3;
688 case WTAP_ENCAP_PPP: /* PPP */
689 case WTAP_ENCAP_PPP_WITH_PHDR:
690 vpkt_hdr.encap_hint = 14;
692 case WTAP_ENCAP_CHDLC_WITH_PHDR: /* HDLC Router */
693 vpkt_hdr.encap_hint = 13;
695 case WTAP_ENCAP_FRELAY_WITH_PHDR: /* Frame Relay Auto-detect */
696 vpkt_hdr.encap_hint = 12;
698 case WTAP_ENCAP_LAPB: /* Unknown */
700 vpkt_hdr.encap_hint = 1;
704 /* Set status flags. The only status currently supported for all
705 encapsulations is direction. This either goes in the p2p or the
706 X.25 pseudo header. It would probably be better to move this up
711 case WTAP_ENCAP_CHDLC_WITH_PHDR:
712 packet_status |= (pseudo_header->p2p.sent ? PS_SENT : 0x00);
715 case WTAP_ENCAP_FRELAY_WITH_PHDR:
716 case WTAP_ENCAP_LAPB:
718 ((pseudo_header->dte_dce.flags & FROM_DCE) ? 0x00 : PS_SENT);
721 vpkt_hdr.status = GUINT32_TO_LE(packet_status);
723 /* Write the packet header. */
724 if (!wtap_dump_file_write(wdh, &vpkt_hdr, hdr_size, err))
727 /* Write the packet data */
728 if (!wtap_dump_file_write(wdh, pd, rec->rec_header.packet_header.caplen, err))
731 /* Store the frame offset in the index table. */
732 if (visual->index_table_index >= visual->index_table_size)
734 /* End of table reached. Reallocate with a larger size */
735 visual->index_table_size *= 2;
736 visual->index_table = (guint32 *)g_realloc(visual->index_table,
737 visual->index_table_size * sizeof *visual->index_table);
739 visual->index_table[visual->index_table_index] = GUINT32_TO_LE(visual->next_offset);
741 /* Update the table index and offset for the next frame. */
742 visual->index_table_index++;
743 visual->next_offset += (guint32) hdr_size + rec->rec_header.packet_header.caplen;
749 /* Finish writing to a dump file.
750 Returns TRUE on success, FALSE on failure. */
751 static gboolean visual_dump_finish(wtap_dumper *wdh, int *err)
753 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
755 struct visual_file_hdr vfile_hdr;
759 /* If the visual structure was never allocated then nothing useful
764 /* Write out the frame table at the end of the file. */
765 if (visual->index_table)
767 /* Write the index table to the file. */
768 n_to_write = visual->index_table_index * sizeof *visual->index_table;
769 if (!wtap_dump_file_write(wdh, visual->index_table, n_to_write, err))
771 visual_dump_free(wdh);
776 /* Write the magic number at the start of the file. */
777 if (wtap_dump_file_seek(wdh, 0, SEEK_SET, err) == -1)
779 magicp = visual_magic;
780 magic_size = sizeof visual_magic;
781 if (!wtap_dump_file_write(wdh, magicp, magic_size, err))
783 visual_dump_free(wdh);
787 /* Initialize the file header with zeroes for the reserved fields. */
788 memset(&vfile_hdr, '\0', sizeof vfile_hdr);
789 vfile_hdr.num_pkts = GUINT32_TO_LE(visual->index_table_index);
790 vfile_hdr.start_time = GUINT32_TO_LE(visual->start_time);
791 vfile_hdr.max_length = GUINT16_TO_LE(65535);
792 vfile_hdr.file_flags = GUINT16_TO_LE(1); /* indexes are present */
793 vfile_hdr.file_version = GUINT16_TO_LE(1);
794 g_strlcpy(vfile_hdr.description, "Wireshark file", 64);
796 /* Translate the encapsulation type */
799 case WTAP_ENCAP_ETHERNET:
800 vfile_hdr.media_type = GUINT16_TO_LE(6);
803 case WTAP_ENCAP_TOKEN_RING:
804 vfile_hdr.media_type = GUINT16_TO_LE(9);
807 case WTAP_ENCAP_LAPB:
808 vfile_hdr.media_type = GUINT16_TO_LE(16);
811 case WTAP_ENCAP_PPP: /* PPP is differentiated from CHDLC in PktHdr */
812 case WTAP_ENCAP_PPP_WITH_PHDR:
813 case WTAP_ENCAP_CHDLC_WITH_PHDR:
814 vfile_hdr.media_type = GUINT16_TO_LE(22);
817 case WTAP_ENCAP_FRELAY_WITH_PHDR:
818 vfile_hdr.media_type = GUINT16_TO_LE(32);
822 /* Write the file header following the magic bytes. */
823 if (!wtap_dump_file_write(wdh, &vfile_hdr, sizeof vfile_hdr, err))
825 visual_dump_free(wdh);
829 /* Deallocate the file write data */
830 visual_dump_free(wdh);
835 /* Free the memory allocated by a visual file writer. */
836 static void visual_dump_free(wtap_dumper *wdh)
838 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
842 /* Free the index table memory. */
843 g_free(visual->index_table);
848 * Editor modelines - http://www.wireshark.org/tools/modelines.html
853 * indent-tabs-mode: nil
856 * vi: set shiftwidth=4 tabstop=8 expandtab:
857 * :indentSize=4:tabSize=8:noTabs=true: