Move the definitions of LANalyzer records to lanalyzer.c.
[obnox/wireshark/wip.git] / wiretap / visual.c
1 /* visual.c
2  * File read and write routines for Visual Networks cap files.
3  * Copyright (c) 2001, Tom Nisbet  tnisbet@visualnetworks.com
4  *
5  * $Id$
6  *
7  * Wiretap Library
8  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 #include <errno.h>
29 #include <string.h>
30 #include "wtap-int.h"
31 #include "file_wrappers.h"
32 #include "buffer.h"
33 #include "visual.h"
34
35 /*
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.
43  *
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.
46  *
47  * [ File Header ] 
48  * 
49  *
50  * [ Packet Header 1 ] [(opt) ATM Packet Header] [ Data ]
51  * ...
52  * [ Packet Header n ] [(opt) ATM Packet Header] [ Data ]
53  *
54  *
55  * [ Index Block 1 ] ... [ Index Block n ]
56  */
57
58 /* Capture file header, INCLUDING the magic number, is 192 bytes. */
59 #define CAPTUREFILE_HEADER_SIZE 192
60
61 /* Magic number for Visual Networks traffic capture files. */
62 static const char visual_magic[] = {
63     5, 'V', 'N', 'F'
64 };
65
66
67 /* Visual File Header (minus magic number). */
68 /* This structure is used to extract information */
69 struct visual_file_hdr
70 {
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) */
82 };
83
84
85 /* Packet status bits */
86 #define PS_LONG             0x01
87 #define PS_SHORT            0x02
88 #define PS_ERRORED          0x04
89 #define PS_1ST_AFTER_DROP   0x08
90 #define PS_APPROX_ORDER     0x10
91 #define PS_SENT             0x40
92 #define PS_ABORTED          0x80
93
94 /* Visual Packet Header */
95 /* This structure is used to extract information */
96 struct visual_pkt_hdr
97 {
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 */
105 };
106
107 /* Optional Visual ATM Packet Header */
108 /* This structure is used to extract information */
109 struct visual_atm_hdr
110 {
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 */
119
120 };
121
122 /* visual_atm_hdr info bit definitions */
123 #define FROM_NETWORK       0x01
124 #define ATM_VER_MASK       0xf0  /* Not currently displayed */
125
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
131 /* Low nibble */
132 #define VN_UNKNOWN         0x00
133 #define VN_AAL1            0x01
134 #define VN_AAL2            0x02
135 #define VN_AAL34           0x03
136 #define VN_O191            0x04
137 #define VN_AAL5            0x05
138 #define VN_OAM             0x0a
139 #define VN_RM              0x0b
140 #define VN_IDLE            0x0c
141 #define VN_CAT_TYPE_MASK   0x0f
142
143
144 /* Additional information for reading Visual files */
145 struct visual_read_info
146 {
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 */
150 };
151
152
153 /* Additional information for writing Visual files */
154 struct visual_write_info
155 {
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 */
161 };
162
163
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);
176
177
178 /* Open a file for reading */
179 int visual_open(wtap *wth, int *err, gchar **err_info)
180 {
181     int bytes_read;
182     char magic[sizeof visual_magic];
183     struct visual_file_hdr vfile_hdr;
184     struct visual_read_info * visual;
185     int encap;
186
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)
191     {
192         *err = file_error(wth->fh, err_info);
193         if (*err != 0)
194             return -1;
195         return 0;
196     }
197     if (memcmp(magic, visual_magic, sizeof visual_magic) != 0)
198     {
199         return 0;
200     }
201
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)
206     {
207         *err = file_error(wth->fh, err_info);
208         if (*err != 0)
209             return -1;
210         return 0;
211     }
212
213     /* Verify the file version is known */
214     vfile_hdr.file_version = pletohs(&vfile_hdr.file_version);
215     if (vfile_hdr.file_version != 1)
216     {
217         *err = WTAP_ERR_UNSUPPORTED;
218         *err_info = g_strdup_printf("visual: file version %u unsupported", vfile_hdr.file_version);
219         return -1;
220     }
221
222     /* Translate the encapsulation type; these values are SNMP ifType
223        values, as found in http://www.iana.org/assignments/smi-numbers.
224
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.
228
229        XXX - should we use WTAP_ENCAP_PER_PACKET for that? */
230     switch (pletohs(&vfile_hdr.media_type))
231     {
232     case  6:    /* ethernet-csmacd */
233         encap = WTAP_ENCAP_ETHERNET;
234         break;
235
236     case  9:    /* IEEE802.5 */
237         encap = WTAP_ENCAP_TOKEN_RING;
238         break;
239
240     case 16:    /* lapb */
241         encap = WTAP_ENCAP_LAPB;
242         break;
243
244     case 22:    /* propPointToPointSerial */
245     case 118:   /* HDLC */
246         encap = WTAP_ENCAP_CHDLC_WITH_PHDR;
247         break;
248
249     case 32:    /* frame-relay */
250         encap = WTAP_ENCAP_FRELAY_WITH_PHDR;
251         break;
252
253     case 37:    /* ATM */
254        encap = WTAP_ENCAP_ATM_PDUS;
255        break;
256
257     default:
258         *err = WTAP_ERR_UNSUPPORTED_ENCAP;
259         *err_info = g_strdup_printf("visual: network type %u unknown or unsupported",
260                                      vfile_hdr.media_type);
261         return -1;
262     }
263
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);
268
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;
272
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;
277
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;
284
285     return 1;
286 }
287
288
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,
294     gint64 *data_offset)
295 {
296     struct visual_read_info *visual = (struct visual_read_info *)wth->priv;
297     guint32 packet_size = 0;
298     int bytes_read;
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);
303     time_t  secs;
304     guint32 usecs;
305     double  t;
306
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
309        packet's data. */
310     if (visual->current_pkt > visual->num_pkts)
311     {
312         *err = 0;   /* it's just an EOF, not an error */
313         return FALSE;
314     }
315     visual->current_pkt++;
316
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)
321     {
322         *err = file_error(wth->fh, err_info);
323         if (*err == 0 && bytes_read != 0)
324         {
325             *err = WTAP_ERR_SHORT_READ;
326         }
327         return FALSE;
328     }
329     wth->data_offset += phdr_size;
330
331     /* Get the included length of data. This includes extra headers + payload */
332     packet_size = pletohs(&vpkt_hdr.incl_len);
333
334     /* Check for additional ATM packet header */
335     if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
336     {
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)
341        {
342            *err = file_error(wth->fh, err_info);
343            if (*err == 0 && bytes_read != 0)
344            {
345                *err = WTAP_ERR_SHORT_READ;
346            }
347            return FALSE;
348        }
349        wth->data_offset += ahdr_size;
350        
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;
355     }
356
357     /* Read the packet data. */
358     if (packet_size > WTAP_MAX_PACKET_SIZE)
359     {
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);
365         return FALSE;
366     }
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);
372
373     if (bytes_read != (int) packet_size)
374     {
375         *err = file_error(wth->fh, err_info);
376         if (*err == 0)
377             *err = WTAP_ERR_SHORT_READ;
378         return FALSE;
379     }
380     wth->data_offset += packet_size;
381
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;
389     
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.
395     *
396     * Only downside to this fix is throughput calculations will be slightly lower
397     * as they won't include the FCS bytes.
398     */
399
400     wth->phdr.caplen = packet_size;
401     wth->phdr.len = pletohs(&vpkt_hdr.orig_len);
402
403     switch (wth->file_encap)
404     {
405     case WTAP_ENCAP_ETHERNET:
406        wth->phdr.len -= 4;
407        break;
408     
409     case WTAP_ENCAP_FRELAY_WITH_PHDR:
410     case WTAP_ENCAP_CHDLC_WITH_PHDR:
411     case WTAP_ENCAP_LAPB:
412        wth->phdr.len -= 2;
413        break;
414
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:
419     default:
420        break;
421     }
422
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);
429         return FALSE;
430     }
431
432     /* Sanity check */
433     if (wth->phdr.len < wth->phdr.caplen)
434     {
435        wth->phdr.len = wth->phdr.caplen;
436     }
437
438     /* Set the pseudo_header. */
439     visual_set_pseudo_header(wth->file_encap, &vpkt_hdr, &vatm_hdr, &wth->pseudo_header);
440
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.
444
445        The encapsulation hint values we've seen are:
446
447          2 - seen in an Ethernet capture
448          13 - seen in a PPP capture; possibly also seen in Cisco HDLC
449               captures
450          14 - seen in a PPP capture; probably seen only for PPP */
451     if (wth->file_encap == WTAP_ENCAP_CHDLC_WITH_PHDR)
452     {
453         /* If PPP is specified in the encap hint, then use that */
454         if (vpkt_hdr.encap_hint == 14)
455         {
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]))
460             {
461                 /* It is actually LLC encapsulated PPP */
462                 wth->phdr.pkt_encap = WTAP_ENCAP_ATM_RFC1483;
463             }
464             else
465             {
466                 /* It is actually PPP */
467                 wth->phdr.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
468             }
469         }
470         else
471         {
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]))
476             {
477                 /* It is actually PPP */
478                 wth->phdr.pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
479             }
480         }
481     }
482     return TRUE;
483 }
484
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)
491 {
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);
496     int bytes_read;
497     int header_size;
498
499     /* Get the size of the visual packet header to skip */
500     header_size = sizeof(struct visual_pkt_hdr);
501
502     /* If ATM capture, need to skip over visual ATM packet header too */
503     if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
504     {
505        header_size += (int)sizeof(struct visual_atm_hdr);
506     }
507     
508     /* Seek to the packet header */
509     if (file_seek(wth->random_fh, seek_off - header_size,
510                   SEEK_SET, err) == -1)
511         return FALSE;
512
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);
518         if (*err == 0)
519             *err = WTAP_ERR_SHORT_READ;
520         return FALSE;
521     }
522     
523     /* Check for additional ATM packet header */
524     if (wth->file_encap == WTAP_ENCAP_ATM_PDUS)
525     {
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)
530        {
531            *err = file_error(wth->fh, err_info);
532            if (*err == 0 && bytes_read != 0)
533            {
534                *err = WTAP_ERR_SHORT_READ;
535            }
536            return FALSE;
537        }
538     }
539
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) {
544         if (*err == 0)
545             *err = WTAP_ERR_SHORT_READ;
546         return FALSE;
547     }
548
549     /* Set the pseudo_header. */
550     visual_set_pseudo_header(wth->file_encap, &vpkt_hdr, &vatm_hdr, pseudo_header);
551
552     return TRUE;
553 }
554
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)
557 {
558     guint32 packet_status;
559
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
563        into the phdr. */
564     packet_status = pletohl(&vpkt_hdr->status);
565     switch (encap)
566     {
567     case WTAP_ENCAP_ETHERNET:
568         /* XXX - is there an FCS in the frame? */
569         pseudo_header->eth.fcs_len = -1;
570         break;
571
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;
575         break;
576
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;
581         break;
582
583     case WTAP_ENCAP_ATM_PDUS:
584        /* Set defaults */
585        pseudo_header->atm.type = TRAF_UNKNOWN;
586        pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
587        pseudo_header->atm.aal5t_len = 0;
588
589        /* Next two items not supported. Defaulting to zero */
590        pseudo_header->atm.aal5t_u2u = 0;
591        pseudo_header->atm.aal5t_chksum = 0;
592        
593        /* Flags appear only to convey that packet is a raw cell. Set to 0 */
594        pseudo_header->atm.flags = 0; 
595        
596        /* Not supported. Defaulting to zero */
597        pseudo_header->atm.aal2_cid = 0;
598
599        switch(vatm_hdr->category & VN_CAT_TYPE_MASK )
600        {
601        case VN_AAL1:
602           pseudo_header->atm.aal = AAL_1;
603           break;
604
605        case VN_AAL2:
606           pseudo_header->atm.aal = AAL_2;
607           break;
608        
609        case VN_AAL34:
610           pseudo_header->atm.aal = AAL_3_4;
611           break;
612        
613        case VN_AAL5:
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);
617           break;
618        
619        case VN_OAM:
620        /* Marking next 3 as OAM versus unknown */
621        case VN_O191:
622        case VN_IDLE:
623        case VN_RM:
624           pseudo_header->atm.aal = AAL_OAMCELL;
625           break;
626
627        case VN_UNKNOWN:
628        default:
629           pseudo_header->atm.aal = AAL_UNKNOWN;
630           break;
631
632        }
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);
636        
637        /* Using bit value of 1 (DCE -> DTE) to indicate From Network */
638        pseudo_header->atm.channel = vatm_hdr->info & FROM_NETWORK;
639        
640        break;
641     }
642 }
643
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)
648 {
649     /* Per-packet encapsulations aren't supported. */
650     if (encap == WTAP_ENCAP_PER_PACKET)
651         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
652
653     /* Check for supported encapsulation types */
654     switch (encap)
655     {
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:
661     case WTAP_ENCAP_PPP:
662     case WTAP_ENCAP_PPP_WITH_PHDR:
663         return 0;
664     }
665
666     return WTAP_ERR_UNSUPPORTED_ENCAP;
667 }
668
669
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)
674 {
675     struct visual_write_info *visual;
676
677     /* Set the write routines for a visual file. */
678     wdh->subtype_write = visual_dump;
679     wdh->subtype_close = visual_dump_close;
680
681     /* Create a struct to hold file information for the duration
682        of the write */
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;
689
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) {
694         *err = errno;
695         return FALSE;
696     }
697
698     return TRUE;
699 }
700
701
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)
706 {
707     struct visual_write_info * visual = wdh->priv;
708     struct visual_pkt_hdr vpkt_hdr;
709     size_t hdr_size = sizeof vpkt_hdr;
710     unsigned delta_msec;
711     guint32 packet_status;
712
713     /* If the visual structure was never allocated then nothing useful
714        can be done. */
715     if (visual == 0)
716         return FALSE;
717
718     /* Zero out unused and reserved fields in the packet header. */
719     memset(&vpkt_hdr, 0, hdr_size);
720
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
724        file start time. */
725     if (visual->index_table_index == 0)
726     {
727         /* This is the first packet.  Save its start time as the file time. */
728         visual->start_time = (guint32) phdr->ts.secs;
729
730         /* Initialize the index table */
731         visual->index_table = g_malloc(1024 * sizeof *visual->index_table);
732         visual->index_table_size = 1024;
733     }
734
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);
739
740     /* Fill in the length fields. */
741     vpkt_hdr.orig_len = htoles(phdr->len);
742     vpkt_hdr.incl_len = htoles(phdr->caplen);
743
744     /* Fill in the encapsulation hint for the file's media type. */
745     switch (wdh->encap)
746     {
747     case WTAP_ENCAP_ETHERNET:   /* Ethernet */
748         vpkt_hdr.encap_hint = 2;
749         break;
750     case WTAP_ENCAP_TOKEN_RING: /* Token Ring */
751         vpkt_hdr.encap_hint = 3;
752         break;
753     case WTAP_ENCAP_PPP:        /* PPP */
754     case WTAP_ENCAP_PPP_WITH_PHDR:
755         vpkt_hdr.encap_hint = 14;
756         break;
757     case WTAP_ENCAP_CHDLC_WITH_PHDR:      /* HDLC Router */
758         vpkt_hdr.encap_hint = 13;
759         break;
760     case WTAP_ENCAP_FRELAY_WITH_PHDR:     /* Frame Relay Auto-detect */
761         vpkt_hdr.encap_hint = 12;
762         break;
763     case WTAP_ENCAP_LAPB:       /* Unknown */
764     default:
765         vpkt_hdr.encap_hint = 1;
766         break;
767     }
768
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
772        into the phdr. */
773     packet_status = 0;
774     switch (wdh->encap)
775     {
776     case WTAP_ENCAP_CHDLC_WITH_PHDR:
777         packet_status |= (pseudo_header->p2p.sent ? PS_SENT : 0x00);
778         break;
779
780     case WTAP_ENCAP_FRELAY_WITH_PHDR:
781     case WTAP_ENCAP_LAPB:
782         packet_status |=
783             ((pseudo_header->x25.flags & FROM_DCE) ? 0x00 : PS_SENT);
784         break;
785     }
786     vpkt_hdr.status = htolel(packet_status);
787
788     /* Write the packet header. */
789     if (!wtap_dump_file_write(wdh, &vpkt_hdr, hdr_size, err))
790         return FALSE;
791
792     /* Write the packet data */
793     if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
794         return FALSE;
795
796     /* Store the frame offset in the index table. */
797     if (visual->index_table_index >= visual->index_table_size)
798     {
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);
803     }
804     visual->index_table[visual->index_table_index] = htolel(visual->next_offset);
805
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;
809
810     return TRUE;
811 }
812
813
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)
817 {
818     struct visual_write_info * visual = wdh->priv;
819     size_t n_to_write;
820     struct visual_file_hdr vfile_hdr;
821     const char *magicp;
822     size_t magic_size;
823
824     /* If the visual structure was never allocated then nothing useful
825        can be done. */
826     if (visual == 0)
827         return FALSE;
828
829     /* Write out the frame table at the end of the file. */
830     if (visual->index_table)
831     {
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))
835         {
836             visual_dump_free(wdh);
837             return FALSE;
838         }
839     }
840
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))
846     {
847         visual_dump_free(wdh);
848         return FALSE;
849     }
850
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);
859
860     /* Translate the encapsulation type */
861     switch (wdh->encap)
862     {
863     case WTAP_ENCAP_ETHERNET:
864         vfile_hdr.media_type = htoles(6);
865         break;
866
867     case WTAP_ENCAP_TOKEN_RING:
868         vfile_hdr.media_type = htoles(9);
869         break;
870
871     case WTAP_ENCAP_LAPB:
872         vfile_hdr.media_type = htoles(16);
873         break;
874
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);
879         break;
880
881     case WTAP_ENCAP_FRELAY_WITH_PHDR:
882         vfile_hdr.media_type = htoles(32);
883         break;
884     }
885
886     /* Write the file header following the magic bytes. */
887     if (!wtap_dump_file_write(wdh, &vfile_hdr, sizeof vfile_hdr, err))
888     {
889         visual_dump_free(wdh);
890         return FALSE;
891     }
892
893     /* Deallocate the file write data */
894     visual_dump_free(wdh);
895     return TRUE;
896 }
897
898
899 /* Free the memory allocated by a visual file writer. */
900 static void visual_dump_free(wtap_dumper *wdh)
901 {
902     struct visual_write_info * visual = wdh->priv;
903
904     if (visual)
905     {
906         /* Free the index table memory. */
907         if (visual->index_table)
908             g_free(visual->index_table);
909     }
910 }