2 * File read and write routines for Visual Networks cap files.
3 * Copyright (c) 2001, Tom Nisbet tnisbet@visualnetworks.com
8 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #include "file_wrappers.h"
36 * A Visual Networks traffic capture file contains three sections. The
37 * first is a 192 octet file header. This is followed by the captured
38 * packet header, and for ATM captures, there is an additional atm packet header.
39 * The data follows the packet header. The last section is the packet index block.
40 * The index block contains one 4 octet pointer for each captured packet.
41 * The first packet index is (4 * num_pkts) octets from the end of the file
42 * and the last index is in the last four octets of the file.
44 * All integer and time values are stored in little-endian format, except for
45 * the ATM Packet Header, which is stored in network byte order.
50 * [ Packet Header 1 ] [(opt) ATM Packet Header] [ Data ]
52 * [ Packet Header n ] [(opt) ATM Packet Header] [ Data ]
55 * [ Index Block 1 ] ... [ Index Block n ]
58 /* Capture file header, INCLUDING the magic number, is 192 bytes. */
59 #define CAPTUREFILE_HEADER_SIZE 192
61 /* Magic number for Visual Networks traffic capture files. */
62 static const char visual_magic[] = {
67 /* Visual File Header (minus magic number). */
68 /* This structure is used to extract information */
69 struct visual_file_hdr
71 guint32 num_pkts; /* Number of packets in the file */
72 guint32 start_time; /* Capture start time in PC format */
73 guint16 media_type; /* IANA ifType of packet source */
74 guint16 max_length; /* Max allowable stored packet length */
75 guint16 file_flags; /* File type flags */
76 /* Bit 0 indicates indexes present */
77 guint16 file_version; /* Version number of this file format */
78 guint32 media_speed; /* ifSpeed of packet source in bits/sec. */
79 guint16 media_param; /* Media-specific extra parameter. */
80 char RESERVED_[102]; /* MUST BE ALL ZEROS FOR FUTURE COMPATABILITY */
81 char description[64]; /* File description (null terminated) */
85 /* Packet status bits */
88 #define PS_ERRORED 0x04
89 #define PS_1ST_AFTER_DROP 0x08
90 #define PS_APPROX_ORDER 0x10
92 #define PS_ABORTED 0x80
94 /* Visual Packet Header */
95 /* This structure is used to extract information */
98 guint32 ts_delta; /* Time stamp - msecs since start of capture */
99 guint16 orig_len; /* Actual length of packet */
100 guint16 incl_len; /* Number of octets captured in file */
101 guint32 status; /* Packet status flags (media specific) */
102 guint8 encap_hint; /* Encapsulation type hint */
103 guint8 encap_skip; /* Number of bytes to skip before decoding */
104 char RESERVED_[6]; /* RESERVED - must be zero */
107 /* Optional Visual ATM Packet Header */
108 /* This structure is used to extract information */
109 struct visual_atm_hdr
111 guint16 vpi; /* 4 bits of zeros; 12 bits of ATM VPI */
112 guint16 vci; /* ATM VCI */
113 guint8 info; /* 4 bits version; 3 bits unused-zero; 1 bit direction */
114 guint8 category; /* indicates type of traffic. 4 bits of status + 4 bits of type */
115 guint16 cell_count; /* number of cells that make up this pdu */
116 guint32 data_length; /* PDU data length for AAL-5 PDUs, all others - cellcount * 48 */
117 guint32 ts_secs; /* seonds value of sysUpTime when the last cell of this PDU was captured */
118 guint32 ts_nsec; /* nanoseonds value of sysUpTime when the last cell of this PDU was captured */
122 /* visual_atm_hdr info bit definitions */
123 #define FROM_NETWORK 0x01
124 #define ATM_VER_MASK 0xf0 /* Not currently displayed */
126 /* visual_atm_hdr category definitions */
127 /* High nibble - not currently displayed */
128 #define VN_INCOMPLETE 0x40
129 #define VN_BAD_CRC 0x80
130 #define VN_CAT_STAT_MASK 0xf0
132 #define VN_UNKNOWN 0x00
135 #define VN_AAL34 0x03
141 #define VN_CAT_TYPE_MASK 0x0f
144 /* Additional information for reading Visual files */
145 struct visual_read_info
147 guint32 num_pkts; /* Number of pkts in the file */
148 guint32 current_pkt; /* Next packet to be read */
149 double start_time; /* Capture start time in microseconds */
153 /* Additional information for writing Visual files */
154 struct visual_write_info
156 unsigned start_time; /* Capture start time in seconds */
157 int index_table_index; /* Index of the next index entry */
158 int index_table_size; /* Allocated size of the index table */
159 guint32 * index_table; /* File offsets for the packets */
160 guint32 next_offset; /* Offset of next packet */
164 /* Local functions to handle file reads and writes */
165 static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
166 gint64 *data_offset);
167 static gboolean visual_seek_read(wtap *wth, gint64 seek_off,
168 union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size,
169 int *err, gchar **err_info);
170 static void visual_set_pseudo_header(int encap, struct visual_pkt_hdr *vpkt_hdr,
171 struct visual_atm_hdr *vatm_hdr, union wtap_pseudo_header *pseudo_header);
172 static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
173 const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
174 static gboolean visual_dump_close(wtap_dumper *wdh, int *err);
175 static void visual_dump_free(wtap_dumper *wdh);
178 /* Open a file for reading */
179 int visual_open(wtap *wth, int *err, gchar **err_info)
182 char magic[sizeof visual_magic];
183 struct visual_file_hdr vfile_hdr;
184 struct visual_read_info * visual;
187 /* Check the magic string at the start of the file */
188 errno = WTAP_ERR_CANT_READ;
189 bytes_read = file_read(magic, sizeof magic, wth->fh);
190 if (bytes_read != sizeof magic)
192 *err = file_error(wth->fh, err_info);
197 if (memcmp(magic, visual_magic, sizeof visual_magic) != 0)
202 /* Read the rest of the file header. */
203 errno = WTAP_ERR_CANT_READ;
204 bytes_read = file_read(&vfile_hdr, sizeof vfile_hdr, wth->fh);
205 if (bytes_read != sizeof vfile_hdr)
207 *err = file_error(wth->fh, err_info);
213 /* Verify the file version is known */
214 vfile_hdr.file_version = pletohs(&vfile_hdr.file_version);
215 if (vfile_hdr.file_version != 1)
217 *err = WTAP_ERR_UNSUPPORTED;
218 *err_info = g_strdup_printf("visual: file version %u unsupported", vfile_hdr.file_version);
222 /* Translate the encapsulation type; these values are SNMP ifType
223 values, as found in http://www.iana.org/assignments/smi-numbers.
225 Note that a file with media type 22 ("propPointToPointSerial") may
226 contain Cisco HDLC or PPP over HDLC. This will get sorted out after
227 the first packet is read.
229 XXX - should we use WTAP_ENCAP_PER_PACKET for that? */
230 switch (pletohs(&vfile_hdr.media_type))
232 case 6: /* ethernet-csmacd */
233 encap = WTAP_ENCAP_ETHERNET;
236 case 9: /* IEEE802.5 */
237 encap = WTAP_ENCAP_TOKEN_RING;
241 encap = WTAP_ENCAP_LAPB;
244 case 22: /* propPointToPointSerial */
246 encap = WTAP_ENCAP_CHDLC_WITH_PHDR;
249 case 32: /* frame-relay */
250 encap = WTAP_ENCAP_FRELAY_WITH_PHDR;
254 encap = WTAP_ENCAP_ATM_PDUS;
258 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
259 *err_info = g_strdup_printf("visual: network type %u unknown or unsupported",
260 vfile_hdr.media_type);
264 /* Fill in the wiretap struct with data from the file header */
265 wth->file_type = WTAP_FILE_VISUAL_NETWORKS;
266 wth->file_encap = encap;
267 wth->snapshot_length = pletohs(&vfile_hdr.max_length);
269 /* Save the pointer to the beginning of the packet data so
270 that the later seek_reads work correctly. */
271 wth->data_offset = CAPTUREFILE_HEADER_SIZE;
273 /* Set up the pointers to the handlers for this file type */
274 wth->subtype_read = visual_read;
275 wth->subtype_seek_read = visual_seek_read;
276 wth->tsprecision = WTAP_FILE_TSPREC_USEC;
278 /* Add Visual-specific information to the wiretap struct for later use. */
279 visual = (struct visual_read_info *)g_malloc(sizeof(struct visual_read_info));
280 wth->priv = (void *)visual;
281 visual->num_pkts = pletohl(&vfile_hdr.num_pkts);
282 visual->start_time = ((double) pletohl(&vfile_hdr.start_time)) * 1000000;
283 visual->current_pkt = 1;
289 /* Read the next available packet from the file. This is called
290 in a loop to sequentially read the entire file one time. After
291 the file has been read once, any Future access to the packets is
292 done through seek_read. */
293 static gboolean visual_read(wtap *wth, int *err, gchar **err_info,
296 struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
297 guint32 packet_size = 0;
299 struct visual_pkt_hdr vpkt_hdr;
300 struct visual_atm_hdr vatm_hdr;
301 int phdr_size = sizeof(vpkt_hdr);
302 int ahdr_size = sizeof(vatm_hdr);
307 /* Check for the end of the packet data. Note that a check for file EOF
308 will not work because there are index values stored after the last
310 if (visual->current_pkt > visual->num_pkts)
312 *err = 0; /* it's just an EOF, not an error */
315 visual->current_pkt++;
317 /* Read the packet header. */
318 errno = WTAP_ERR_CANT_READ;
319 bytes_read = file_read(&vpkt_hdr, phdr_size, wth->fh);
320 if (bytes_read != phdr_size)
322 *err = file_error(wth->fh, err_info);
323 if (*err == 0 && bytes_read != 0)
325 *err = WTAP_ERR_SHORT_READ;
329 wth->data_offset += phdr_size;
331 /* Get the included length of data. This includes extra headers + payload */
332 packet_size = pletohs(&vpkt_hdr.incl_len);
334 /* Check for additional ATM packet header */
335 if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
337 /* Read the atm packet header. */
338 errno = WTAP_ERR_CANT_READ;
339 bytes_read = file_read(&vatm_hdr, ahdr_size, wth->fh);
340 if (bytes_read != ahdr_size)
342 *err = file_error(wth->fh, err_info);
343 if (*err == 0 && bytes_read != 0)
345 *err = WTAP_ERR_SHORT_READ;
349 wth->data_offset += ahdr_size;
351 /* Remove ATM header from length of included bytes in capture, as
352 this header was appended by the processor doing the packet reassembly,
353 and was not transmitted across the wire */
354 packet_size -= ahdr_size;
357 /* Read the packet data. */
358 if (packet_size > WTAP_MAX_PACKET_SIZE)
360 /* Probably a corrupt capture file; don't blow up trying
361 to allocate space for an immensely-large packet. */
362 *err = WTAP_ERR_BAD_RECORD;
363 *err_info = g_strdup_printf("visual: File has %u-byte packet, bigger than maximum of %u",
364 packet_size, WTAP_MAX_PACKET_SIZE);
367 buffer_assure_space(wth->frame_buffer, packet_size);
368 *data_offset = wth->data_offset;
369 errno = WTAP_ERR_CANT_READ;
370 bytes_read = file_read(buffer_start_ptr(wth->frame_buffer),
371 packet_size, wth->fh);
373 if (bytes_read != (int) packet_size)
375 *err = file_error(wth->fh, err_info);
377 *err = WTAP_ERR_SHORT_READ;
380 wth->data_offset += packet_size;
382 /* Set the packet time and length. */
383 t = visual->start_time;
384 t += ((double)pletohl(&vpkt_hdr.ts_delta))*1000;
385 secs = (time_t)(t/1000000);
386 usecs = (guint32)(t - secs*1000000);
387 wth->phdr.ts.secs = secs;
388 wth->phdr.ts.nsecs = usecs * 1000;
390 /* Most visual capture types include FCS checks in the original length value, but
391 * but don't include the FCS as part of the payload or captured length.
392 * This causes the RTP audio payload save to fail since then captured len != orig len.
393 * Adjusting the original length to remove the FCS bytes we counted based
394 * on the file encapsualtion type.
396 * Only downside to this fix is throughput calculations will be slightly lower
397 * as they won't include the FCS bytes.
400 wth->phdr.caplen = packet_size;
401 wth->phdr.len = pletohs(&vpkt_hdr.orig_len);
403 switch (wth->file_encap)
405 case WTAP_ENCAP_ETHERNET:
409 case WTAP_ENCAP_FRELAY_WITH_PHDR:
410 case WTAP_ENCAP_CHDLC_WITH_PHDR:
411 case WTAP_ENCAP_LAPB:
415 /* ATM original length doesn't include any FCS. Do nothing. */
416 case WTAP_ENCAP_ATM_PDUS:
417 /* Not sure about token ring. Just leaving alone for now. */
418 case WTAP_ENCAP_TOKEN_RING:
423 if (wth->phdr.len > WTAP_MAX_PACKET_SIZE) {
424 /* Check if wth->phdr.len is sane, small values of wth.phdr.len before
425 the case loop above can cause integer underflows */
426 *err = WTAP_ERR_BAD_RECORD;
427 *err_info = g_strdup_printf("visual: File has %u-byte original packet, bigger than maximum of %u",
428 wth->phdr.len, WTAP_MAX_PACKET_SIZE);
433 if (wth->phdr.len < wth->phdr.caplen)
435 wth->phdr.len = wth->phdr.caplen;
438 /* Set the pseudo_header. */
439 visual_set_pseudo_header(wth->file_encap, &vpkt_hdr, &vatm_hdr, &wth->pseudo_header);
441 /* Fill in the encapsulation. Visual files have a media type in the
442 file header and an encapsulation type in each packet header. Files
443 with a media type of HDLC can be either Cisco EtherType or PPP.
445 The encapsulation hint values we've seen are:
447 2 - seen in an Ethernet capture
448 13 - seen in a PPP capture; possibly also seen in Cisco HDLC
450 14 - seen in a PPP capture; probably seen only for PPP */
451 if (wth->file_encap == WTAP_ENCAP_CHDLC_WITH_PHDR)
453 /* If PPP is specified in the encap hint, then use that */
454 if (vpkt_hdr.encap_hint == 14)
456 /* But first we need to examine the first three octets to
457 try to determine the proper encapsulation, see RFC 2364. */
458 guint8 *buf = buffer_start_ptr(wth->frame_buffer);
459 if ((0xfe == buf[0]) && (0xfe == buf[1]) && (0x03 == buf[2]))
461 /* It is actually LLC encapsulated PPP */
462 wth->phdr.pkt_encap = WTAP_ENCAP_ATM_RFC1483;
466 /* It is actually PPP */
467 wth->phdr.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
472 /* Otherwise, we need to examine the first two octets to
473 try to determine the encapsulation. */
474 guint8 *buf = buffer_start_ptr(wth->frame_buffer);
475 if ((0xff == buf[0]) && (0x03 == buf[1]))
477 /* It is actually PPP */
478 wth->phdr.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
485 /* Read packet data for random access.
486 This gets the packet data and rebuilds the pseudo header so that
487 the direction flag works. */
488 static gboolean visual_seek_read (wtap *wth, gint64 seek_off,
489 union wtap_pseudo_header *pseudo_header, guint8 *pd, int len,
490 int *err, gchar **err_info)
492 struct visual_pkt_hdr vpkt_hdr;
493 struct visual_atm_hdr vatm_hdr;
494 int phdr_size = sizeof(vpkt_hdr);
495 int ahdr_size = sizeof(vatm_hdr);
499 /* Get the size of the visual packet header to skip */
500 header_size = sizeof(struct visual_pkt_hdr);
502 /* If ATM capture, need to skip over visual ATM packet header too */
503 if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
505 header_size += (int)sizeof(struct visual_atm_hdr);
508 /* Seek to the packet header */
509 if (file_seek(wth->random_fh, seek_off - header_size,
510 SEEK_SET, err) == -1)
513 /* Read the packet header to get the status flags. */
514 errno = WTAP_ERR_CANT_READ;
515 bytes_read = file_read(&vpkt_hdr, phdr_size, wth->random_fh);
516 if (bytes_read != phdr_size) {
517 *err = file_error(wth->random_fh, err_info);
519 *err = WTAP_ERR_SHORT_READ;
523 /* Check for additional ATM packet header */
524 if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
526 /* Read the atm packet header */
527 errno = WTAP_ERR_CANT_READ;
528 bytes_read = file_read(&vatm_hdr, ahdr_size, wth->random_fh);
529 if (bytes_read != ahdr_size)
531 *err = file_error(wth->fh, err_info);
532 if (*err == 0 && bytes_read != 0)
534 *err = WTAP_ERR_SHORT_READ;
540 /* Read the packet data. */
541 errno = WTAP_ERR_CANT_READ;
542 bytes_read = file_read(pd, len, wth->random_fh);
543 if (bytes_read != len) {
545 *err = WTAP_ERR_SHORT_READ;
549 /* Set the pseudo_header. */
550 visual_set_pseudo_header(wth->file_encap, &vpkt_hdr, &vatm_hdr, pseudo_header);
555 static void visual_set_pseudo_header(int encap, struct visual_pkt_hdr *vpkt_hdr,
556 struct visual_atm_hdr *vatm_hdr, union wtap_pseudo_header *pseudo_header)
558 guint32 packet_status;
560 /* Set status flags. The only status currently supported for all
561 encapsulations is direction. This either goes in the p2p or the
562 X.25 pseudo header. It would probably be better to move this up
564 packet_status = pletohl(&vpkt_hdr->status);
567 case WTAP_ENCAP_ETHERNET:
568 /* XXX - is there an FCS in the frame? */
569 pseudo_header->eth.fcs_len = -1;
572 case WTAP_ENCAP_CHDLC_WITH_PHDR:
573 case WTAP_ENCAP_PPP_WITH_PHDR:
574 pseudo_header->p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
577 case WTAP_ENCAP_FRELAY_WITH_PHDR:
578 case WTAP_ENCAP_LAPB:
579 pseudo_header->x25.flags =
580 (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
583 case WTAP_ENCAP_ATM_PDUS:
585 pseudo_header->atm.type = TRAF_UNKNOWN;
586 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
587 pseudo_header->atm.aal5t_len = 0;
589 /* Next two items not supported. Defaulting to zero */
590 pseudo_header->atm.aal5t_u2u = 0;
591 pseudo_header->atm.aal5t_chksum = 0;
593 /* Flags appear only to convey that packet is a raw cell. Set to 0 */
594 pseudo_header->atm.flags = 0;
596 /* Not supported. Defaulting to zero */
597 pseudo_header->atm.aal2_cid = 0;
599 switch(vatm_hdr->category & VN_CAT_TYPE_MASK )
602 pseudo_header->atm.aal = AAL_1;
606 pseudo_header->atm.aal = AAL_2;
610 pseudo_header->atm.aal = AAL_3_4;
614 pseudo_header->atm.aal = AAL_5;
615 pseudo_header->atm.type = TRAF_LLCMX;
616 pseudo_header->atm.aal5t_len = pntohl(&vatm_hdr->data_length);
620 /* Marking next 3 as OAM versus unknown */
624 pseudo_header->atm.aal = AAL_OAMCELL;
629 pseudo_header->atm.aal = AAL_UNKNOWN;
633 pseudo_header->atm.vpi = pntohs(&vatm_hdr->vpi) & 0x0FFF;
634 pseudo_header->atm.vci = pntohs(&vatm_hdr->vci);
635 pseudo_header->atm.cells = pntohs(&vatm_hdr->cell_count);
637 /* Using bit value of 1 (DCE -> DTE) to indicate From Network */
638 pseudo_header->atm.channel = vatm_hdr->info & FROM_NETWORK;
644 /* Check for media types that may be written in Visual file format.
645 Returns 0 if the specified encapsulation type is supported,
646 an error indication otherwise. */
647 int visual_dump_can_write_encap(int encap)
649 /* Per-packet encapsulations aren't supported. */
650 if (encap == WTAP_ENCAP_PER_PACKET)
651 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
653 /* Check for supported encapsulation types */
656 case WTAP_ENCAP_ETHERNET:
657 case WTAP_ENCAP_TOKEN_RING:
658 case WTAP_ENCAP_LAPB:
659 case WTAP_ENCAP_CHDLC_WITH_PHDR:
660 case WTAP_ENCAP_FRELAY_WITH_PHDR:
662 case WTAP_ENCAP_PPP_WITH_PHDR:
666 return WTAP_ERR_UNSUPPORTED_ENCAP;
670 /* Open a file for writing.
671 Returns TRUE on success, FALSE on failure; sets "*err" to an
672 error code on failure */
673 gboolean visual_dump_open(wtap_dumper *wdh, int *err)
675 struct visual_write_info *visual;
677 /* Set the write routines for a visual file. */
678 wdh->subtype_write = visual_dump;
679 wdh->subtype_close = visual_dump_close;
681 /* Create a struct to hold file information for the duration
683 visual = (struct visual_write_info *)g_malloc(sizeof(struct visual_write_info));
684 wdh->priv = (void *)visual;
685 visual->index_table_index = 0;
686 visual->index_table_size = 1024;
687 visual->index_table = 0;
688 visual->next_offset = CAPTUREFILE_HEADER_SIZE;
690 /* All of the fields in the file header aren't known yet so
691 just skip over it for now. It will be created after all
692 of the packets have been written. */
693 if (fseek(wdh->fh, CAPTUREFILE_HEADER_SIZE, SEEK_SET) == -1) {
702 /* Write a packet to a Visual dump file.
703 Returns TRUE on success, FALSE on failure. */
704 static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
705 const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
707 struct visual_write_info * visual = wdh->priv;
708 struct visual_pkt_hdr vpkt_hdr;
709 size_t hdr_size = sizeof vpkt_hdr;
711 guint32 packet_status;
713 /* If the visual structure was never allocated then nothing useful
718 /* Zero out unused and reserved fields in the packet header. */
719 memset(&vpkt_hdr, 0, hdr_size);
721 /* Visual UpTime capture files have a capture start time in the
722 file header. Each packet has a capture time (in msec) relative
723 to the file start time. Use the time of the first packet as the
725 if (visual->index_table_index == 0)
727 /* This is the first packet. Save its start time as the file time. */
728 visual->start_time = (guint32) phdr->ts.secs;
730 /* Initialize the index table */
731 visual->index_table = g_malloc(1024 * sizeof *visual->index_table);
732 visual->index_table_size = 1024;
735 /* Calculate milliseconds since capture start. */
736 delta_msec = phdr->ts.nsecs / 1000000;
737 delta_msec += ( (guint32) phdr->ts.secs - visual->start_time) * 1000;
738 vpkt_hdr.ts_delta = htolel(delta_msec);
740 /* Fill in the length fields. */
741 vpkt_hdr.orig_len = htoles(phdr->len);
742 vpkt_hdr.incl_len = htoles(phdr->caplen);
744 /* Fill in the encapsulation hint for the file's media type. */
747 case WTAP_ENCAP_ETHERNET: /* Ethernet */
748 vpkt_hdr.encap_hint = 2;
750 case WTAP_ENCAP_TOKEN_RING: /* Token Ring */
751 vpkt_hdr.encap_hint = 3;
753 case WTAP_ENCAP_PPP: /* PPP */
754 case WTAP_ENCAP_PPP_WITH_PHDR:
755 vpkt_hdr.encap_hint = 14;
757 case WTAP_ENCAP_CHDLC_WITH_PHDR: /* HDLC Router */
758 vpkt_hdr.encap_hint = 13;
760 case WTAP_ENCAP_FRELAY_WITH_PHDR: /* Frame Relay Auto-detect */
761 vpkt_hdr.encap_hint = 12;
763 case WTAP_ENCAP_LAPB: /* Unknown */
765 vpkt_hdr.encap_hint = 1;
769 /* Set status flags. The only status currently supported for all
770 encapsulations is direction. This either goes in the p2p or the
771 X.25 pseudo header. It would probably be better to move this up
776 case WTAP_ENCAP_CHDLC_WITH_PHDR:
777 packet_status |= (pseudo_header->p2p.sent ? PS_SENT : 0x00);
780 case WTAP_ENCAP_FRELAY_WITH_PHDR:
781 case WTAP_ENCAP_LAPB:
783 ((pseudo_header->x25.flags & FROM_DCE) ? 0x00 : PS_SENT);
786 vpkt_hdr.status = htolel(packet_status);
788 /* Write the packet header. */
789 if (!wtap_dump_file_write(wdh, &vpkt_hdr, hdr_size, err))
792 /* Write the packet data */
793 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
796 /* Store the frame offset in the index table. */
797 if (visual->index_table_index >= visual->index_table_size)
799 /* End of table reached. Reallocate with a larger size */
800 visual->index_table_size *= 2;
801 visual->index_table = g_realloc(visual->index_table,
802 visual->index_table_size * sizeof *visual->index_table);
804 visual->index_table[visual->index_table_index] = htolel(visual->next_offset);
806 /* Update the table index and offset for the next frame. */
807 visual->index_table_index++;
808 visual->next_offset += (guint32) hdr_size + phdr->caplen;
814 /* Finish writing to a dump file.
815 Returns TRUE on success, FALSE on failure. */
816 static gboolean visual_dump_close(wtap_dumper *wdh, int *err)
818 struct visual_write_info * visual = wdh->priv;
820 struct visual_file_hdr vfile_hdr;
824 /* If the visual structure was never allocated then nothing useful
829 /* Write out the frame table at the end of the file. */
830 if (visual->index_table)
832 /* Write the index table to the file. */
833 n_to_write = visual->index_table_index * sizeof *visual->index_table;
834 if (!wtap_dump_file_write(wdh, visual->index_table, n_to_write, err))
836 visual_dump_free(wdh);
841 /* Write the magic number at the start of the file. */
842 fseek(wdh->fh, 0, SEEK_SET);
843 magicp = visual_magic;
844 magic_size = sizeof visual_magic;
845 if (!wtap_dump_file_write(wdh, magicp, magic_size, err))
847 visual_dump_free(wdh);
851 /* Initialize the file header with zeroes for the reserved fields. */
852 memset(&vfile_hdr, '\0', sizeof vfile_hdr);
853 vfile_hdr.num_pkts = htolel(visual->index_table_index);
854 vfile_hdr.start_time = htolel(visual->start_time);
855 vfile_hdr.max_length = htoles(65535);
856 vfile_hdr.file_flags = htoles(1); /* indexes are present */
857 vfile_hdr.file_version = htoles(1);
858 g_strlcpy(vfile_hdr.description, "Wireshark file", 64);
860 /* Translate the encapsulation type */
863 case WTAP_ENCAP_ETHERNET:
864 vfile_hdr.media_type = htoles(6);
867 case WTAP_ENCAP_TOKEN_RING:
868 vfile_hdr.media_type = htoles(9);
871 case WTAP_ENCAP_LAPB:
872 vfile_hdr.media_type = htoles(16);
875 case WTAP_ENCAP_PPP: /* PPP is differentiated from CHDLC in PktHdr */
876 case WTAP_ENCAP_PPP_WITH_PHDR:
877 case WTAP_ENCAP_CHDLC_WITH_PHDR:
878 vfile_hdr.media_type = htoles(22);
881 case WTAP_ENCAP_FRELAY_WITH_PHDR:
882 vfile_hdr.media_type = htoles(32);
886 /* Write the file header following the magic bytes. */
887 if (!wtap_dump_file_write(wdh, &vfile_hdr, sizeof vfile_hdr, err))
889 visual_dump_free(wdh);
893 /* Deallocate the file write data */
894 visual_dump_free(wdh);
899 /* Free the memory allocated by a visual file writer. */
900 static void visual_dump_free(wtap_dumper *wdh)
902 struct visual_write_info * visual = wdh->priv;
906 /* Free the index table memory. */
907 if (visual->index_table)
908 g_free(visual->index_table);