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 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "file_wrappers.h"
31 * A Visual Networks traffic capture file contains three sections. The
32 * first is a 192 octet file header. This is followed by the captured
33 * packet header, and for ATM captures, there is an additional atm packet header.
34 * The data follows the packet header. The last section is the packet index block.
35 * The index block contains one 4 octet pointer for each captured packet.
36 * The first packet index is (4 * num_pkts) octets from the end of the file
37 * and the last index is in the last four octets of the file.
39 * All integer and time values are stored in little-endian format, except for
40 * the ATM Packet Header, which is stored in network byte order.
45 * [ Packet Header 1 ] [(opt) ATM Packet Header] [ Data ]
47 * [ Packet Header n ] [(opt) ATM Packet Header] [ Data ]
50 * [ Index Block 1 ] ... [ Index Block n ]
53 /* Capture file header, INCLUDING the magic number, is 192 bytes. */
54 #define CAPTUREFILE_HEADER_SIZE 192
56 /* Magic number for Visual Networks traffic capture files. */
57 static const char visual_magic[] = {
62 /* Visual File Header (minus magic number). */
63 /* This structure is used to extract information */
64 struct visual_file_hdr
66 guint32 num_pkts; /* Number of packets in the file */
67 guint32 start_time; /* Capture start time in PC format */
68 guint16 media_type; /* IANA ifType of packet source */
69 guint16 max_length; /* Max allowable stored packet length */
70 guint16 file_flags; /* File type flags */
71 /* Bit 0 indicates indexes present */
72 guint16 file_version; /* Version number of this file format */
73 guint32 media_speed; /* ifSpeed of packet source in bits/sec. */
74 guint16 media_param; /* Media-specific extra parameter. */
75 char RESERVED_[102]; /* MUST BE ALL ZEROS FOR FUTURE COMPATABILITY */
76 char description[64]; /* File description (null terminated) */
80 /* Packet status bits */
83 #define PS_ERRORED 0x04
84 #define PS_1ST_AFTER_DROP 0x08
85 #define PS_APPROX_ORDER 0x10
87 #define PS_ABORTED 0x80
89 /* Visual Packet Header */
90 /* This structure is used to extract information */
93 guint32 ts_delta; /* Time stamp - msecs since start of capture */
94 guint16 orig_len; /* Actual length of packet */
95 guint16 incl_len; /* Number of octets captured in file */
96 guint32 status; /* Packet status flags (media specific) */
97 guint8 encap_hint; /* Encapsulation type hint */
98 guint8 encap_skip; /* Number of bytes to skip before decoding */
99 char RESERVED_[6]; /* RESERVED - must be zero */
102 /* Optional Visual ATM Packet Header */
103 /* This structure is used to extract information */
104 struct visual_atm_hdr
106 guint16 vpi; /* 4 bits of zeros; 12 bits of ATM VPI */
107 guint16 vci; /* ATM VCI */
108 guint8 info; /* 4 bits version; 3 bits unused-zero; 1 bit direction */
109 guint8 category; /* indicates type of traffic. 4 bits of status + 4 bits of type */
110 guint16 cell_count; /* number of cells that make up this pdu */
111 guint32 data_length; /* PDU data length for AAL-5 PDUs, all others - cellcount * 48 */
112 guint32 ts_secs; /* seonds value of sysUpTime when the last cell of this PDU was captured */
113 guint32 ts_nsec; /* nanoseonds value of sysUpTime when the last cell of this PDU was captured */
117 /* visual_atm_hdr info bit definitions */
118 #define FROM_NETWORK 0x01
119 #define ATM_VER_MASK 0xf0 /* Not currently displayed */
121 /* visual_atm_hdr category definitions */
122 /* High nibble - not currently displayed */
123 #define VN_INCOMPLETE 0x40
124 #define VN_BAD_CRC 0x80
125 #define VN_CAT_STAT_MASK 0xf0
127 #define VN_UNKNOWN 0x00
130 #define VN_AAL34 0x03
136 #define VN_CAT_TYPE_MASK 0x0f
139 /* Additional information for reading Visual files */
140 struct visual_read_info
142 guint32 num_pkts; /* Number of pkts in the file */
143 guint32 current_pkt; /* Next packet to be read */
144 time_t start_time; /* Capture start time in seconds */
148 /* Additional information for writing Visual files */
149 struct visual_write_info
151 time_t start_time; /* Capture start time in seconds */
152 int index_table_index; /* Index of the next index entry */
153 int index_table_size; /* Allocated size of the index table */
154 guint32 * index_table; /* File offsets for the packets */
155 guint32 next_offset; /* Offset of next packet */
159 /* Local functions to handle file reads and writes */
160 static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
161 gint64 *data_offset);
162 static gboolean visual_seek_read(wtap *wth, gint64 seek_off,
163 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
164 static gboolean visual_read_packet(wtap *wth, FILE_T fh,
165 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
166 static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
167 const guint8 *pd, int *err, gchar **err_info);
168 static gboolean visual_dump_close(wtap_dumper *wdh, int *err);
169 static void visual_dump_free(wtap_dumper *wdh);
172 /* Open a file for reading */
173 wtap_open_return_val visual_open(wtap *wth, int *err, gchar **err_info)
175 char magic[sizeof visual_magic];
176 struct visual_file_hdr vfile_hdr;
177 struct visual_read_info * visual;
180 /* Check the magic string at the start of the file */
181 if (!wtap_read_bytes(wth->fh, magic, sizeof magic, err, err_info))
183 if (*err != WTAP_ERR_SHORT_READ)
184 return WTAP_OPEN_ERROR;
185 return WTAP_OPEN_NOT_MINE;
187 if (memcmp(magic, visual_magic, sizeof visual_magic) != 0)
189 return WTAP_OPEN_NOT_MINE;
192 /* Read the rest of the file header. */
193 if (!wtap_read_bytes(wth->fh, &vfile_hdr, sizeof vfile_hdr, err, err_info))
195 return WTAP_OPEN_ERROR;
198 /* Verify the file version is known */
199 vfile_hdr.file_version = pletoh16(&vfile_hdr.file_version);
200 if (vfile_hdr.file_version != 1)
202 *err = WTAP_ERR_UNSUPPORTED;
203 *err_info = g_strdup_printf("visual: file version %u unsupported", vfile_hdr.file_version);
204 return WTAP_OPEN_ERROR;
207 /* Translate the encapsulation type; these values are SNMP ifType
208 values, as found in http://www.iana.org/assignments/smi-numbers.
210 Note that a file with media type 22 ("propPointToPointSerial") may
211 contain Cisco HDLC or PPP over HDLC. This will get sorted out after
212 the first packet is read.
214 XXX - should we use WTAP_ENCAP_PER_PACKET for that? */
215 switch (pletoh16(&vfile_hdr.media_type))
217 case 6: /* ethernet-csmacd */
218 encap = WTAP_ENCAP_ETHERNET;
221 case 9: /* IEEE802.5 */
222 encap = WTAP_ENCAP_TOKEN_RING;
226 encap = WTAP_ENCAP_LAPB;
229 case 22: /* propPointToPointSerial */
231 encap = WTAP_ENCAP_CHDLC_WITH_PHDR;
234 case 32: /* frame-relay */
235 encap = WTAP_ENCAP_FRELAY_WITH_PHDR;
239 encap = WTAP_ENCAP_ATM_PDUS;
243 *err = WTAP_ERR_UNSUPPORTED;
244 *err_info = g_strdup_printf("visual: network type %u unknown or unsupported",
245 vfile_hdr.media_type);
246 return WTAP_OPEN_ERROR;
249 /* Fill in the wiretap struct with data from the file header */
250 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_VISUAL_NETWORKS;
251 wth->file_encap = encap;
252 wth->snapshot_length = pletoh16(&vfile_hdr.max_length);
254 /* Set up the pointers to the handlers for this file type */
255 wth->subtype_read = visual_read;
256 wth->subtype_seek_read = visual_seek_read;
257 wth->file_tsprec = WTAP_TSPREC_MSEC;
259 /* Add Visual-specific information to the wiretap struct for later use. */
260 visual = (struct visual_read_info *)g_malloc(sizeof(struct visual_read_info));
261 wth->priv = (void *)visual;
262 visual->num_pkts = pletoh32(&vfile_hdr.num_pkts);
263 visual->start_time = pletoh32(&vfile_hdr.start_time);
264 visual->current_pkt = 1;
266 return WTAP_OPEN_MINE;
270 /* Read the next available packet from the file. This is called
271 in a loop to sequentially read the entire file one time. After
272 the file has been read once, any Future access to the packets is
273 done through seek_read. */
274 static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
277 struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
279 /* Check for the end of the packet data. Note that a check for file EOF
280 will not work because there are index values stored after the last
282 if (visual->current_pkt > visual->num_pkts)
284 *err = 0; /* it's just an EOF, not an error */
287 visual->current_pkt++;
289 *data_offset = file_tell(wth->fh);
291 return visual_read_packet(wth, wth->fh, &wth->phdr, wth->frame_buffer,
295 /* Read packet header and data for random access. */
296 static gboolean visual_seek_read(wtap *wth, gint64 seek_off,
297 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
299 /* Seek to the packet header */
300 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
303 /* Read the packet. */
304 if (!visual_read_packet(wth, wth->random_fh, phdr, buf, err, err_info)) {
306 *err = WTAP_ERR_SHORT_READ;
313 visual_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
314 Buffer *buf, int *err, gchar **err_info)
316 struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
317 struct visual_pkt_hdr vpkt_hdr;
319 struct visual_atm_hdr vatm_hdr;
321 guint32 packet_status;
324 /* Read the packet header. */
325 if (!wtap_read_bytes_or_eof(fh, &vpkt_hdr, (unsigned int)sizeof vpkt_hdr, err, err_info))
330 /* Get the included length of data. This includes extra headers + payload */
331 packet_size = pletoh16(&vpkt_hdr.incl_len);
333 phdr->rec_type = REC_TYPE_PACKET;
334 phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
336 /* Set the packet time and length. */
337 relmsecs = pletoh32(&vpkt_hdr.ts_delta);
338 phdr->ts.secs = visual->start_time + relmsecs/1000;
339 phdr->ts.nsecs = (relmsecs % 1000)*1000000;
341 phdr->len = pletoh16(&vpkt_hdr.orig_len);
343 packet_status = pletoh32(&vpkt_hdr.status);
345 /* Do encapsulation-specific processing.
347 Most Visual capture types include the FCS in the original length
348 value, but don't include the FCS as part of the payload or captured
349 length. This is different from the model used in most other capture
350 file formats, including pcap and pcap-ng in cases where the FCS isn't
351 captured (which are the typical cases), and causes the RTP audio
352 payload save to fail since then captured len != orig len.
354 We adjust the original length to remove the FCS bytes we counted based
355 on the file encapsualtion type. The only downside to this fix is
356 throughput calculations will be slightly lower as it won't include
357 the FCS bytes. However, as noted, that problem also exists with
358 other capture formats.
360 We also set status flags. The only status currently supported for
361 all encapsulations is direction. This either goes in the p2p or the
362 X.25 pseudo header. It would probably be better to move this up
364 switch (wth->file_encap)
366 case WTAP_ENCAP_ETHERNET:
367 /* Ethernet has a 4-byte FCS. */
370 *err = WTAP_ERR_BAD_FILE;
371 *err_info = g_strdup_printf("visual: Ethernet packet has %u-byte original packet, less than the FCS length",
377 /* XXX - the above implies that there's never an FCS; should this
378 set the FCS length to 0? */
379 phdr->pseudo_header.eth.fcs_len = -1;
382 case WTAP_ENCAP_CHDLC_WITH_PHDR:
383 /* This has a 2-byte FCS. */
386 *err = WTAP_ERR_BAD_FILE;
387 *err_info = g_strdup_printf("visual: Cisco HDLC packet has %u-byte original packet, less than the FCS length",
393 phdr->pseudo_header.p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
396 case WTAP_ENCAP_PPP_WITH_PHDR:
398 XXX - true? Note that PPP can negotiate no FCS, a 2-byte FCS,
400 phdr->pseudo_header.p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
403 case WTAP_ENCAP_FRELAY_WITH_PHDR:
404 /* This has a 2-byte FCS. */
407 *err = WTAP_ERR_BAD_FILE;
408 *err_info = g_strdup_printf("visual: Frame Relay packet has %u-byte original packet, less than the FCS length",
414 phdr->pseudo_header.x25.flags =
415 (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
418 case WTAP_ENCAP_LAPB:
419 /* This has a 2-byte FCS. */
422 *err = WTAP_ERR_BAD_FILE;
423 *err_info = g_strdup_printf("visual: Frame Relay packet has %u-byte original packet, less than the FCS length",
429 phdr->pseudo_header.x25.flags =
430 (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
433 case WTAP_ENCAP_ATM_PDUS:
434 /* ATM original length doesn't include any FCS. Do nothing to
437 ATM packets have an additional packet header; read and
439 if (!wtap_read_bytes(fh, &vatm_hdr, (unsigned int)sizeof vatm_hdr, err, err_info))
444 /* Remove ATM header from length of included bytes in capture, as
445 this header was appended by the processor doing the packet
446 reassembly, and was not transmitted across the wire */
447 packet_size -= (guint32)sizeof vatm_hdr;
450 phdr->pseudo_header.atm.type = TRAF_UNKNOWN;
451 phdr->pseudo_header.atm.subtype = TRAF_ST_UNKNOWN;
452 phdr->pseudo_header.atm.aal5t_len = 0;
454 /* Next two items not supported. Defaulting to zero */
455 phdr->pseudo_header.atm.aal5t_u2u = 0;
456 phdr->pseudo_header.atm.aal5t_chksum = 0;
458 /* Flags appear only to convey that packet is a raw cell. Set to 0 */
459 phdr->pseudo_header.atm.flags = 0;
461 /* Not supported. Defaulting to zero */
462 phdr->pseudo_header.atm.aal2_cid = 0;
464 switch(vatm_hdr.category & VN_CAT_TYPE_MASK )
467 phdr->pseudo_header.atm.aal = AAL_1;
471 phdr->pseudo_header.atm.aal = AAL_2;
475 phdr->pseudo_header.atm.aal = AAL_3_4;
479 phdr->pseudo_header.atm.aal = AAL_5;
480 phdr->pseudo_header.atm.type = TRAF_LLCMX;
481 phdr->pseudo_header.atm.aal5t_len = pntoh32(&vatm_hdr.data_length);
485 /* Marking next 3 as OAM versus unknown */
489 phdr->pseudo_header.atm.aal = AAL_OAMCELL;
494 phdr->pseudo_header.atm.aal = AAL_UNKNOWN;
497 phdr->pseudo_header.atm.vpi = pntoh16(&vatm_hdr.vpi) & 0x0FFF;
498 phdr->pseudo_header.atm.vci = pntoh16(&vatm_hdr.vci);
499 phdr->pseudo_header.atm.cells = pntoh16(&vatm_hdr.cell_count);
501 /* Using bit value of 1 (DCE -> DTE) to indicate From Network */
502 phdr->pseudo_header.atm.channel = vatm_hdr.info & FROM_NETWORK;
505 /* Not sure about token ring. Just leaving alone for now. */
506 case WTAP_ENCAP_TOKEN_RING:
511 phdr->caplen = packet_size;
513 /* Check for too-large packet. */
514 if (packet_size > WTAP_MAX_PACKET_SIZE)
516 /* Probably a corrupt capture file; don't blow up trying
517 to allocate space for an immensely-large packet. */
518 *err = WTAP_ERR_BAD_FILE;
519 *err_info = g_strdup_printf("visual: File has %u-byte packet, bigger than maximum of %u",
520 packet_size, WTAP_MAX_PACKET_SIZE);
524 /* Read the packet data */
525 if (!wtap_read_packet_bytes(fh, buf, packet_size, err, err_info))
528 if (wth->file_encap == WTAP_ENCAP_CHDLC_WITH_PHDR)
530 /* Fill in the encapsulation. Visual files have a media type in the
531 file header and an encapsulation type in each packet header. Files
532 with a media type of HDLC can be either Cisco EtherType or PPP.
534 The encapsulation hint values we've seen are:
536 2 - seen in an Ethernet capture
537 13 - seen in a PPP capture; possibly also seen in Cisco HDLC
539 14 - seen in a PPP capture; probably seen only for PPP.
541 According to bug 2005, the collection probe can be configured
542 for PPP, in which case the encapsulation hint is 14, or can
543 be configured for auto-detect, in which case the encapsulation
544 hint is 13, and the encapsulation must be guessed from the
545 packet contents. Auto-detect is the default. */
546 pd = ws_buffer_start_ptr(buf);
548 /* If PPP is specified in the encap hint, then use that */
549 if (vpkt_hdr.encap_hint == 14)
551 /* But first we need to examine the first three octets to
552 try to determine the proper encapsulation, see RFC 2364. */
553 if (packet_size >= 3 &&
554 (0xfe == pd[0]) && (0xfe == pd[1]) && (0x03 == pd[2]))
556 /* It is actually LLC encapsulated PPP */
557 phdr->pkt_encap = WTAP_ENCAP_ATM_RFC1483;
561 /* It is actually PPP */
562 phdr->pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
567 /* Otherwise, we need to examine the first two octets to
568 try to determine the encapsulation. */
569 if (packet_size >= 2 && (0xff == pd[0]) && (0x03 == pd[1]))
571 /* It is actually PPP */
572 phdr->pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
580 /* Check for media types that may be written in Visual file format.
581 Returns 0 if the specified encapsulation type is supported,
582 an error indication otherwise. */
583 int visual_dump_can_write_encap(int encap)
585 /* Per-packet encapsulations aren't supported. */
586 if (encap == WTAP_ENCAP_PER_PACKET)
587 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
589 /* Check for supported encapsulation types */
592 case WTAP_ENCAP_ETHERNET:
593 case WTAP_ENCAP_TOKEN_RING:
594 case WTAP_ENCAP_LAPB:
595 case WTAP_ENCAP_CHDLC_WITH_PHDR:
596 case WTAP_ENCAP_FRELAY_WITH_PHDR:
598 case WTAP_ENCAP_PPP_WITH_PHDR:
602 return WTAP_ERR_UNWRITABLE_ENCAP;
606 /* Open a file for writing.
607 Returns TRUE on success, FALSE on failure; sets "*err" to an
608 error code on failure */
609 gboolean visual_dump_open(wtap_dumper *wdh, int *err)
611 struct visual_write_info *visual;
613 /* Set the write routines for a visual file. */
614 wdh->subtype_write = visual_dump;
615 wdh->subtype_close = visual_dump_close;
617 /* Create a struct to hold file information for the duration
619 visual = (struct visual_write_info *)g_malloc(sizeof(struct visual_write_info));
620 wdh->priv = (void *)visual;
621 visual->index_table_index = 0;
622 visual->index_table_size = 1024;
623 visual->index_table = 0;
624 visual->next_offset = CAPTUREFILE_HEADER_SIZE;
626 /* All of the fields in the file header aren't known yet so
627 just skip over it for now. It will be created after all
628 of the packets have been written. */
629 if (wtap_dump_file_seek(wdh, CAPTUREFILE_HEADER_SIZE, SEEK_SET, err) == -1)
636 /* Write a packet to a Visual dump file.
637 Returns TRUE on success, FALSE on failure. */
638 static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
639 const guint8 *pd, int *err, gchar **err_info _U_)
641 const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header;
642 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
643 struct visual_pkt_hdr vpkt_hdr;
644 size_t hdr_size = sizeof vpkt_hdr;
646 guint32 packet_status;
648 /* We can only write packet records. */
649 if (phdr->rec_type != REC_TYPE_PACKET) {
650 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
654 /* Don't write anything we're not willing to read. */
655 if (phdr->caplen > WTAP_MAX_PACKET_SIZE) {
656 *err = WTAP_ERR_PACKET_TOO_LARGE;
660 /* If the visual structure was never allocated then nothing useful
665 /* Zero out unused and reserved fields in the packet header. */
666 memset(&vpkt_hdr, 0, hdr_size);
668 /* Visual UpTime capture files have a capture start time in the
669 file header. Each packet has a capture time (in msec) relative
670 to the file start time. Use the time of the first packet as the
672 if (visual->index_table_index == 0)
674 /* This is the first packet. Save its start time as the file time. */
675 visual->start_time = phdr->ts.secs;
677 /* Initialize the index table */
678 visual->index_table = (guint32 *)g_malloc(1024 * sizeof *visual->index_table);
679 visual->index_table_size = 1024;
682 /* Calculate milliseconds since capture start. */
683 delta_msec = phdr->ts.nsecs / 1000000;
684 delta_msec += (guint32)((phdr->ts.secs - visual->start_time) * 1000);
685 vpkt_hdr.ts_delta = GUINT32_TO_LE(delta_msec);
687 /* Fill in the length fields. */
688 vpkt_hdr.orig_len = GUINT16_TO_LE(phdr->len);
689 vpkt_hdr.incl_len = GUINT16_TO_LE(phdr->caplen);
691 /* Fill in the encapsulation hint for the file's media type. */
694 case WTAP_ENCAP_ETHERNET: /* Ethernet */
695 vpkt_hdr.encap_hint = 2;
697 case WTAP_ENCAP_TOKEN_RING: /* Token Ring */
698 vpkt_hdr.encap_hint = 3;
700 case WTAP_ENCAP_PPP: /* PPP */
701 case WTAP_ENCAP_PPP_WITH_PHDR:
702 vpkt_hdr.encap_hint = 14;
704 case WTAP_ENCAP_CHDLC_WITH_PHDR: /* HDLC Router */
705 vpkt_hdr.encap_hint = 13;
707 case WTAP_ENCAP_FRELAY_WITH_PHDR: /* Frame Relay Auto-detect */
708 vpkt_hdr.encap_hint = 12;
710 case WTAP_ENCAP_LAPB: /* Unknown */
712 vpkt_hdr.encap_hint = 1;
716 /* Set status flags. The only status currently supported for all
717 encapsulations is direction. This either goes in the p2p or the
718 X.25 pseudo header. It would probably be better to move this up
723 case WTAP_ENCAP_CHDLC_WITH_PHDR:
724 packet_status |= (pseudo_header->p2p.sent ? PS_SENT : 0x00);
727 case WTAP_ENCAP_FRELAY_WITH_PHDR:
728 case WTAP_ENCAP_LAPB:
730 ((pseudo_header->x25.flags & FROM_DCE) ? 0x00 : PS_SENT);
733 vpkt_hdr.status = GUINT32_TO_LE(packet_status);
735 /* Write the packet header. */
736 if (!wtap_dump_file_write(wdh, &vpkt_hdr, hdr_size, err))
739 /* Write the packet data */
740 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
743 /* Store the frame offset in the index table. */
744 if (visual->index_table_index >= visual->index_table_size)
746 /* End of table reached. Reallocate with a larger size */
747 visual->index_table_size *= 2;
748 visual->index_table = (guint32 *)g_realloc(visual->index_table,
749 visual->index_table_size * sizeof *visual->index_table);
751 visual->index_table[visual->index_table_index] = GUINT32_TO_LE(visual->next_offset);
753 /* Update the table index and offset for the next frame. */
754 visual->index_table_index++;
755 visual->next_offset += (guint32) hdr_size + phdr->caplen;
761 /* Finish writing to a dump file.
762 Returns TRUE on success, FALSE on failure. */
763 static gboolean visual_dump_close(wtap_dumper *wdh, int *err)
765 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
767 struct visual_file_hdr vfile_hdr;
771 /* If the visual structure was never allocated then nothing useful
776 /* Write out the frame table at the end of the file. */
777 if (visual->index_table)
779 /* Write the index table to the file. */
780 n_to_write = visual->index_table_index * sizeof *visual->index_table;
781 if (!wtap_dump_file_write(wdh, visual->index_table, n_to_write, err))
783 visual_dump_free(wdh);
788 /* Write the magic number at the start of the file. */
789 if (wtap_dump_file_seek(wdh, 0, SEEK_SET, err) == -1)
791 magicp = visual_magic;
792 magic_size = sizeof visual_magic;
793 if (!wtap_dump_file_write(wdh, magicp, magic_size, err))
795 visual_dump_free(wdh);
799 /* Initialize the file header with zeroes for the reserved fields. */
800 memset(&vfile_hdr, '\0', sizeof vfile_hdr);
801 vfile_hdr.num_pkts = GUINT32_TO_LE(visual->index_table_index);
802 vfile_hdr.start_time = GUINT32_TO_LE(visual->start_time);
803 vfile_hdr.max_length = GUINT16_TO_LE(65535);
804 vfile_hdr.file_flags = GUINT16_TO_LE(1); /* indexes are present */
805 vfile_hdr.file_version = GUINT16_TO_LE(1);
806 g_strlcpy(vfile_hdr.description, "Wireshark file", 64);
808 /* Translate the encapsulation type */
811 case WTAP_ENCAP_ETHERNET:
812 vfile_hdr.media_type = GUINT16_TO_LE(6);
815 case WTAP_ENCAP_TOKEN_RING:
816 vfile_hdr.media_type = GUINT16_TO_LE(9);
819 case WTAP_ENCAP_LAPB:
820 vfile_hdr.media_type = GUINT16_TO_LE(16);
823 case WTAP_ENCAP_PPP: /* PPP is differentiated from CHDLC in PktHdr */
824 case WTAP_ENCAP_PPP_WITH_PHDR:
825 case WTAP_ENCAP_CHDLC_WITH_PHDR:
826 vfile_hdr.media_type = GUINT16_TO_LE(22);
829 case WTAP_ENCAP_FRELAY_WITH_PHDR:
830 vfile_hdr.media_type = GUINT16_TO_LE(32);
834 /* Write the file header following the magic bytes. */
835 if (!wtap_dump_file_write(wdh, &vfile_hdr, sizeof vfile_hdr, err))
837 visual_dump_free(wdh);
841 /* Deallocate the file write data */
842 visual_dump_free(wdh);
847 /* Free the memory allocated by a visual file writer. */
848 static void visual_dump_free(wtap_dumper *wdh)
850 struct visual_write_info * visual = (struct visual_write_info *)wdh->priv;
854 /* Free the index table memory. */
855 if (visual->index_table)
856 g_free(visual->index_table);
861 * Editor modelines - http://www.wireshark.org/tools/modelines.html
866 * indent-tabs-mode: nil
869 * vi: set shiftwidth=4 tabstop=8 expandtab:
870 * :indentSize=4:tabSize=8:noTabs=true: