HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / wiretap / visual.c
blob12e4c06c8e94e6e3c8fe6593f380773335eb9627
1 /* visual.c
2 * File read and write routines for Visual Networks cap files.
3 * Copyright (c) 2001, Tom Nisbet tnisbet@visualnetworks.com
5 * $Id$
7 * Wiretap Library
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.
25 #include "config.h"
26 #include <errno.h>
27 #include <string.h>
28 #include "wtap-int.h"
29 #include "file_wrappers.h"
30 #include "buffer.h"
31 #include "visual.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.
45 * [ File Header ]
48 * [ Packet Header 1 ] [(opt) ATM Packet Header] [ Data ]
49 * ...
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[] = {
61 5, 'V', 'N', 'F'
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 */
84 #define PS_LONG 0x01
85 #define PS_SHORT 0x02
86 #define PS_ERRORED 0x04
87 #define PS_1ST_AFTER_DROP 0x08
88 #define PS_APPROX_ORDER 0x10
89 #define PS_SENT 0x40
90 #define PS_ABORTED 0x80
92 /* Visual Packet Header */
93 /* This structure is used to extract information */
94 struct visual_pkt_hdr
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
129 /* Low nibble */
130 #define VN_UNKNOWN 0x00
131 #define VN_AAL1 0x01
132 #define VN_AAL2 0x02
133 #define VN_AAL34 0x03
134 #define VN_O191 0x04
135 #define VN_AAL5 0x05
136 #define VN_OAM 0x0a
137 #define VN_RM 0x0b
138 #define VN_IDLE 0x0c
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)
179 int bytes_read;
180 char magic[sizeof visual_magic];
181 struct visual_file_hdr vfile_hdr;
182 struct visual_read_info * visual;
183 int encap;
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)
192 return -1;
193 return 0;
195 if (memcmp(magic, visual_magic, sizeof visual_magic) != 0)
197 return 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);
206 if (*err == 0)
207 *err = WTAP_ERR_SHORT_READ;
208 return -1;
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);
217 return -1;
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;
232 break;
234 case 9: /* IEEE802.5 */
235 encap = WTAP_ENCAP_TOKEN_RING;
236 break;
238 case 16: /* lapb */
239 encap = WTAP_ENCAP_LAPB;
240 break;
242 case 22: /* propPointToPointSerial */
243 case 118: /* HDLC */
244 encap = WTAP_ENCAP_CHDLC_WITH_PHDR;
245 break;
247 case 32: /* frame-relay */
248 encap = WTAP_ENCAP_FRELAY_WITH_PHDR;
249 break;
251 case 37: /* ATM */
252 encap = WTAP_ENCAP_ATM_PDUS;
253 break;
255 default:
256 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
257 *err_info = g_strdup_printf("visual: network type %u unknown or unsupported",
258 vfile_hdr.media_type);
259 return -1;
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;
279 return 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,
288 gint64 *data_offset)
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
294 packet's data. */
295 if (visual->current_pkt > visual->num_pkts)
297 *err = 0; /* it's just an EOF, not an error */
298 return FALSE;
300 visual->current_pkt++;
302 *data_offset = file_tell(wth->fh);
304 return visual_read_packet(wth, wth->fh, &wth->phdr, wth->frame_buffer,
305 err, err_info);
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)
315 return FALSE;
317 /* Read the packet. */
318 if (!visual_read_packet(wth, wth->random_fh, phdr, buf, err, err_info)) {
319 if (*err == 0)
320 *err = WTAP_ERR_SHORT_READ;
321 return FALSE;
323 return TRUE;
326 static gboolean
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;
332 int bytes_read;
333 guint32 packet_size;
334 struct visual_atm_hdr vatm_hdr;
335 double t;
336 time_t secs;
337 guint32 usecs;
338 guint32 packet_status;
339 guint8 *pd;
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;
351 return FALSE;
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
389 into the phdr. */
390 switch (wth->file_encap)
392 case WTAP_ENCAP_ETHERNET:
393 /* Ethernet has a 4-byte FCS. */
394 if (phdr->len < 4)
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",
398 phdr->len);
399 return FALSE;
401 phdr->len -= 4;
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;
406 break;
408 case WTAP_ENCAP_CHDLC_WITH_PHDR:
409 /* This has a 2-byte FCS. */
410 if (phdr->len < 2)
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",
414 phdr->len);
415 return FALSE;
417 phdr->len -= 2;
419 phdr->pseudo_header.p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
420 break;
422 case WTAP_ENCAP_PPP_WITH_PHDR:
423 /* No FCS.
424 XXX - true? Note that PPP can negotiate no FCS, a 2-byte FCS,
425 or a 4-byte FCS. */
426 phdr->pseudo_header.p2p.sent = (packet_status & PS_SENT) ? TRUE : FALSE;
427 break;
429 case WTAP_ENCAP_FRELAY_WITH_PHDR:
430 /* This has a 2-byte FCS. */
431 if (phdr->len < 2)
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",
435 phdr->len);
436 return FALSE;
438 phdr->len -= 2;
440 phdr->pseudo_header.x25.flags =
441 (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
442 break;
444 case WTAP_ENCAP_LAPB:
445 /* This has a 2-byte FCS. */
446 if (phdr->len < 2)
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",
450 phdr->len);
451 return FALSE;
453 phdr->len -= 2;
455 phdr->pseudo_header.x25.flags =
456 (packet_status & PS_SENT) ? 0x00 : FROM_DCE;
457 break;
459 case WTAP_ENCAP_ATM_PDUS:
460 /* ATM original length doesn't include any FCS. Do nothing to
461 the packet length.
463 ATM packets have an additional packet header; read and
464 process it. */
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);
470 if (*err == 0)
472 *err = WTAP_ERR_SHORT_READ;
474 return FALSE;
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;
482 /* Set defaults */
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 )
499 case VN_AAL1:
500 phdr->pseudo_header.atm.aal = AAL_1;
501 break;
503 case VN_AAL2:
504 phdr->pseudo_header.atm.aal = AAL_2;
505 break;
507 case VN_AAL34:
508 phdr->pseudo_header.atm.aal = AAL_3_4;
509 break;
511 case VN_AAL5:
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);
515 break;
517 case VN_OAM:
518 /* Marking next 3 as OAM versus unknown */
519 case VN_O191:
520 case VN_IDLE:
521 case VN_RM:
522 phdr->pseudo_header.atm.aal = AAL_OAMCELL;
523 break;
525 case VN_UNKNOWN:
526 default:
527 phdr->pseudo_header.atm.aal = AAL_UNKNOWN;
528 break;
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;
536 break;
538 /* Not sure about token ring. Just leaving alone for now. */
539 case WTAP_ENCAP_TOKEN_RING:
540 default:
541 break;
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);
554 return FALSE;
557 /* Sanity check */
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))
565 return FALSE;
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
577 captures
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;
598 else
600 /* It is actually PPP */
601 phdr->pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
604 else
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;
616 return TRUE;
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 */
629 switch (encap)
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:
636 case WTAP_ENCAP_PPP:
637 case WTAP_ENCAP_PPP_WITH_PHDR:
638 return 0;
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
657 of the write */
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)
669 return FALSE;
671 return TRUE;
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;
684 guint delta_msec;
685 guint32 packet_status;
687 /* If the visual structure was never allocated then nothing useful
688 can be done. */
689 if (visual == 0)
690 return FALSE;
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
698 file start time. */
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. */
719 switch (wdh->encap)
721 case WTAP_ENCAP_ETHERNET: /* Ethernet */
722 vpkt_hdr.encap_hint = 2;
723 break;
724 case WTAP_ENCAP_TOKEN_RING: /* Token Ring */
725 vpkt_hdr.encap_hint = 3;
726 break;
727 case WTAP_ENCAP_PPP: /* PPP */
728 case WTAP_ENCAP_PPP_WITH_PHDR:
729 vpkt_hdr.encap_hint = 14;
730 break;
731 case WTAP_ENCAP_CHDLC_WITH_PHDR: /* HDLC Router */
732 vpkt_hdr.encap_hint = 13;
733 break;
734 case WTAP_ENCAP_FRELAY_WITH_PHDR: /* Frame Relay Auto-detect */
735 vpkt_hdr.encap_hint = 12;
736 break;
737 case WTAP_ENCAP_LAPB: /* Unknown */
738 default:
739 vpkt_hdr.encap_hint = 1;
740 break;
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
746 into the phdr. */
747 packet_status = 0;
748 switch (wdh->encap)
750 case WTAP_ENCAP_CHDLC_WITH_PHDR:
751 packet_status |= (pseudo_header->p2p.sent ? PS_SENT : 0x00);
752 break;
754 case WTAP_ENCAP_FRELAY_WITH_PHDR:
755 case WTAP_ENCAP_LAPB:
756 packet_status |=
757 ((pseudo_header->x25.flags & FROM_DCE) ? 0x00 : PS_SENT);
758 break;
760 vpkt_hdr.status = htolel(packet_status);
762 /* Write the packet header. */
763 if (!wtap_dump_file_write(wdh, &vpkt_hdr, hdr_size, err))
764 return FALSE;
766 /* Write the packet data */
767 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
768 return FALSE;
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;
784 return TRUE;
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;
793 size_t n_to_write;
794 struct visual_file_hdr vfile_hdr;
795 const char *magicp;
796 size_t magic_size;
798 /* If the visual structure was never allocated then nothing useful
799 can be done. */
800 if (visual == 0)
801 return FALSE;
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);
811 return FALSE;
815 /* Write the magic number at the start of the file. */
816 if (wtap_dump_file_seek(wdh, 0, SEEK_SET, err) == -1)
817 return FALSE;
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);
823 return FALSE;
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 */
836 switch (wdh->encap)
838 case WTAP_ENCAP_ETHERNET:
839 vfile_hdr.media_type = htoles(6);
840 break;
842 case WTAP_ENCAP_TOKEN_RING:
843 vfile_hdr.media_type = htoles(9);
844 break;
846 case WTAP_ENCAP_LAPB:
847 vfile_hdr.media_type = htoles(16);
848 break;
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);
854 break;
856 case WTAP_ENCAP_FRELAY_WITH_PHDR:
857 vfile_hdr.media_type = htoles(32);
858 break;
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);
865 return FALSE;
868 /* Deallocate the file write data */
869 visual_dump_free(wdh);
870 return TRUE;
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;
879 if (visual)
881 /* Free the index table memory. */
882 if (visual->index_table)
883 g_free(visual->index_table);