Make "infer_pkt_encap()" take a pointer and length as arguments.
[obnox/wireshark/wip.git] / wiretap / ngsniffer.c
1 /* ngsniffer.c
2  *
3  * $Id: ngsniffer.c,v 1.94 2002/12/20 21:58:46 guy Exp $
4  *
5  * Wiretap Library
6  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
7  *
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.
12  *
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.
17  *
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23 /* The code in ngsniffer.c that decodes the time fields for each packet in the
24  * Sniffer trace originally came from code from TCPVIEW:
25  *
26  * TCPVIEW
27  *
28  * Author:      Martin Hunt
29  *              Networks and Distributed Computing
30  *              Computing & Communications
31  *              University of Washington
32  *              Administration Building, AG-44
33  *              Seattle, WA  98195
34  *              Internet: martinh@cac.washington.edu
35  *
36  *
37  * Copyright 1992 by the University of Washington
38  *
39  * Permission to use, copy, modify, and distribute this software and its
40  * documentation for any purpose and without fee is hereby granted, provided
41  * that the above copyright notice appears in all copies and that both the
42  * above copyright notice and this permission notice appear in supporting
43  * documentation, and that the name of the University of Washington not be
44  * used in advertising or publicity pertaining to distribution of the software
45  * without specific, written prior permission.  This software is made
46  * available "as is", and
47  * THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED,
48  * WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION ALL IMPLIED
49  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND IN
50  * NO EVENT SHALL THE UNIVERSITY OF WASHINGTON BE LIABLE FOR ANY SPECIAL,
51  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
52  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT
53  * (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION
54  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
55  *
56  */
57 #ifdef HAVE_CONFIG_H
58 #include "config.h"
59 #endif
60
61 #include <stdlib.h>
62 #include <errno.h>
63 #include <string.h>
64 #include "wtap-int.h"
65 #include "file_wrappers.h"
66 #include "buffer.h"
67 #include "ngsniffer.h"
68
69 /* Magic number in Sniffer files. */
70 static const char ngsniffer_magic[] = {
71         'T', 'R', 'S', 'N', 'I', 'F', 'F', ' ', 'd', 'a', 't', 'a',
72         ' ', ' ', ' ', ' ', 0x1a
73 };
74
75 /*
76  * Sniffer record types.
77  */
78 #define REC_VERS        1       /* Version record (f_vers) */
79 #define REC_FRAME2      4       /* Frame data (f_frame2) */
80 #define REC_FRAME4      8       /* Frame data (f_frame4) */
81 #define REC_FRAME6      12      /* Frame data (f_frame6) (see below) */
82 #define REC_EOF         3       /* End-of-file record (no data follows) */
83 /*
84  * and now for some unknown header types
85  */
86 #define REC_HEADER1     6       /* Header containing serial numbers? */
87 #define REC_HEADER2     7       /* Header containing ??? */
88 #define REC_V2DESC      8       /* In version 2 sniffer traces contains
89                                  * infos about this capturing session.
90                                  * Collides with REC_FRAME4 */
91 #define REC_HEADER3     13      /* Retransmission counts? */
92 #define REC_HEADER4     14      /* ? */
93 #define REC_HEADER5     15      /* ? */
94 #define REC_HEADER6     16      /* More broadcast/retransmission counts? */
95 #define REC_HEADER7     17      /* ? */
96
97
98 /*
99  * Sniffer version record format.
100  */
101 struct vers_rec {
102         gint16  maj_vers;       /* major version number */
103         gint16  min_vers;       /* minor version number */
104         gint16  time;           /* DOS-format time */
105         gint16  date;           /* DOS-format date */
106         gint8   type;           /* what type of records follow */
107         guint8  network;        /* network type */
108         gint8   format;         /* format version */
109         guint8  timeunit;       /* timestamp units */
110         gint8   cmprs_vers;     /* compression version */
111         gint8   cmprs_level;    /* compression level */
112         gint16  rsvd[2];        /* reserved */
113 };
114
115 /*
116  * Sniffer type 2 data record format - followed by frame data.
117  */
118 struct frame2_rec {
119         guint16 time_low;       /* low part of time stamp */
120         guint16 time_med;       /* middle part of time stamp */
121         guint16 time_high;      /* high part of time stamp */
122         gint16  size;           /* number of bytes of data */
123         guint8  fs;             /* frame error status bits */
124         guint8  flags;          /* buffer flags */
125         gint16  true_size;      /* size of original frame, in bytes */
126         gint16  rsvd;           /* reserved */
127 };
128
129 /*
130  * Sniffer type 4 data record format - followed by frame data.
131  *
132  * XXX - the manual says that the "flags" field holds "buffer flags;
133  * BF_xxxx", but doesn't say what the BF_xxxx flags are.
134  *
135  * XXX - the manual also says there's an 8-byte "ATMTimeStamp" driver
136  * time stamp at the end of "ATMSaveInfo", but, from an ATM Sniffer capture
137  * file I've looked at, that appears not to be the case.
138  */
139
140 /*
141  * Fields from the AAL5 trailer for the frame, if it's an AAL5 frame
142  * rather than a cell.
143  */
144 typedef struct _ATM_AAL5Trailer {
145         guint16 aal5t_u2u;      /* user-to-user indicator */
146         guint16 aal5t_len;      /* length of the packet */
147         guint32 aal5t_chksum; /* checksum for AAL5 packet */
148 } ATM_AAL5Trailer;
149
150 typedef struct _ATMTimeStamp {
151         guint32 msw;    /* most significant word */
152         guint32 lsw;    /* least significant word */
153 } ATMTimeStamp;
154
155 typedef struct _ATMSaveInfo {
156         guint32 StatusWord;     /* status word from driver */
157         ATM_AAL5Trailer Trailer; /* AAL5 trailer */
158         guint8  AppTrafType;    /* traffic type */
159         guint8  AppHLType;      /* protocol type */
160         guint16 AppReserved;    /* reserved */
161         guint16 Vpi;            /* virtual path identifier */
162         guint16 Vci;            /* virtual circuit identifier */
163         guint16 channel;        /* link: 0 for DCE, 1 for DTE */
164         guint16 cells;          /* number of cells */
165         guint32 AppVal1;        /* type-dependent */
166         guint32 AppVal2;        /* type-dependent */
167 } ATMSaveInfo;
168
169 /*
170  * Bits in StatusWord.
171  */
172 #define SW_ERRMASK              0x0F    /* Error mask: */
173 #define SW_RX_FIFO_UNDERRUN     0x01    /* Receive FIFO underrun */
174 #define SW_RX_FIFO_OVERRUN      0x02    /* Receive FIFO overrun */
175 #define SW_RX_PKT_TOO_LONG      0x03    /* Received packet > max size */
176 #define SW_CRC_ERROR            0x04    /* CRC error */
177 #define SW_USER_ABORTED_RX      0x05    /* User aborted receive */
178 #define SW_BUF_LEN_TOO_LONG     0x06    /* buffer len > max buf */
179 #define SW_INTERNAL_T1_ERROR    0x07    /* Internal T1 error */
180 #define SW_RX_CHANNEL_DEACTIV8  0x08    /* Rx channel deactivate */
181
182 #define SW_ERROR                0x80    /* Error indicator */
183 #define SW_CONGESTION           0x40    /* Congestion indicator */
184 #define SW_CLP                  0x20    /* Cell loss priority indicator */
185 #define SW_RAW_CELL             0x100   /* RAW cell indicator */
186 #define SW_OAM_CELL             0x200   /* OAM cell indicator */
187
188 /*
189  * Bits in AppTrafType.
190  *
191  * For AAL types other than AAL5, the packet data is presumably for a
192  * single cell, not a reassembled frame, as the ATM Sniffer manual says
193  * it dosn't reassemble cells other than AAL5 cells.
194  */
195 #define ATT_AALTYPE             0x0F    /* AAL type: */
196 #define ATT_AAL_UNKNOWN         0x00    /* Unknown AAL */
197 #define ATT_AAL1                0x01    /* AAL1 */
198 #define ATT_AAL3_4              0x02    /* AAL3/4 */
199 #define ATT_AAL5                0x03    /* AAL5 */
200 #define ATT_AAL_USER            0x04    /* User AAL */
201 #define ATT_AAL_SIGNALLING      0x05    /* Signaling AAL */
202 #define ATT_OAMCELL             0x06    /* OAM cell */
203
204 #define ATT_HLTYPE              0xF0    /* Higher-layer type: */
205 #define ATT_HL_UNKNOWN          0x00    /* unknown */
206 #define ATT_HL_LLCMX            0x10    /* LLC multiplexed (probably RFC 1483) */
207 #define ATT_HL_VCMX             0x20    /* VC multiplexed (probably RFC 1483) */
208 #define ATT_HL_LANE             0x30    /* LAN Emulation */
209 #define ATT_HL_ILMI             0x40    /* ILMI */
210 #define ATT_HL_FRMR             0x50    /* Frame Relay */
211 #define ATT_HL_SPANS            0x60    /* FORE SPANS */
212 #define ATT_HL_IPSILON          0x70    /* Ipsilon */
213
214 /*
215  * Values for AppHLType; the interpretation depends on the ATT_HLTYPE
216  * bits in AppTrafType.
217  */
218 #define AHLT_UNKNOWN            0x0
219 #define AHLT_VCMX_802_3_FCS     0x1     /* VCMX: 802.3 FCS */
220 #define AHLT_LANE_LE_CTRL       0x1     /* LANE: LE Ctrl */
221 #define AHLT_IPSILON_FT0        0x1     /* Ipsilon: Flow Type 0 */
222 #define AHLT_VCMX_802_4_FCS     0x2     /* VCMX: 802.4 FCS */
223 #define AHLT_LANE_802_3         0x2     /* LANE: 802.3 */
224 #define AHLT_IPSILON_FT1        0x2     /* Ipsilon: Flow Type 1 */
225 #define AHLT_VCMX_802_5_FCS     0x3     /* VCMX: 802.5 FCS */
226 #define AHLT_LANE_802_5         0x3     /* LANE: 802.5 */
227 #define AHLT_IPSILON_FT2        0x3     /* Ipsilon: Flow Type 2 */
228 #define AHLT_VCMX_FDDI_FCS      0x4     /* VCMX: FDDI FCS */
229 #define AHLT_LANE_802_3_MC      0x4     /* LANE: 802.3 multicast */
230 #define AHLT_VCMX_802_6_FCS     0x5     /* VCMX: 802.6 FCS */
231 #define AHLT_LANE_802_5_MC      0x5     /* LANE: 802.5 multicast */
232 #define AHLT_VCMX_802_3         0x7     /* VCMX: 802.3 */
233 #define AHLT_VCMX_802_4         0x8     /* VCMX: 802.4 */
234 #define AHLT_VCMX_802_5         0x9     /* VCMX: 802.5 */
235 #define AHLT_VCMX_FDDI          0xa     /* VCMX: FDDI */
236 #define AHLT_VCMX_802_6         0xb     /* VCMX: 802.6 */
237 #define AHLT_VCMX_FRAGMENTS     0xc     /* VCMX: Fragments */
238 #define AHLT_VCMX_BPDU          0xe     /* VCMX: BPDU */
239
240 struct frame4_rec {
241         guint16 time_low;       /* low part of time stamp */
242         guint16 time_med;       /* middle part of time stamp */
243         gint8   time_high;      /* high part of time stamp */
244         gint8   time_day;       /* time in days since start of capture */
245         gint16  size;           /* number of bytes of data */
246         gint8   fs;             /* frame error status bits */
247         gint8   flags;          /* buffer flags */
248         gint16  true_size;      /* size of original frame, in bytes */
249         gint16  rsvd3;          /* reserved */
250         gint16  atm_pad;        /* pad to 4-byte boundary */
251         ATMSaveInfo atm_info;   /* ATM-specific stuff */
252 };
253
254 /*
255  * XXX - I have a version 5.50 file with a bunch of token ring
256  * records listed as type "12".  The record format below was
257  * derived from frame4_rec and a bit of experimentation.
258  * - Gerald
259  */
260 struct frame6_rec {
261         guint16 time_low;       /* low part of time stamp */
262         guint16 time_med;       /* middle part of time stamp */
263         gint8   time_high;      /* high part of time stamp */
264         gint8   time_day;       /* time in days since start of capture */
265         gint16  size;           /* number of bytes of data */
266         gint8   fs;             /* frame error status bits */
267         gint8   flags;          /* buffer flags */
268         gint16  true_size;      /* size of original frame, in bytes */
269         guint8  chemical_x[22]; /* ? */
270 };
271
272 /*
273  * Network type values in type 7 records.
274  *
275  * Note: captures with a major version number of 2 appear to have
276  * type 7 records with text in them (at least one I have does); captures
277  * with a major version number of 5 appear not to have type 7 records
278  * at all (at least one I have doesn't), but do appear to put
279  * non-zero values in the "rsvd" field of the version header (at least
280  * one I have does) - at least some other captures with smaller version
281  * numbers appear to put 0 there, so *maybe* that's where the network
282  * (sub)type is hidden.
283  *
284  * The semantics of these network types is inferred from the Sniffer
285  * documentation, as they correspond to types described in the UI;
286  * in particular, see
287  *
288  *      http://download.nai.com/products/media/sniffer/support/sdos/operation.pdf
289  *
290  * starting at page 3-10 (56 of 496).
291  */
292 #define NET_SDLC        0       /* Probably "SDLC then SNA" */
293 #define NET_HDLC        1       /* Used for X.25; is it used for other
294                                    things as well, or is it "HDLC then
295                                    X.25", as referred to by the document
296                                    cited above, and only used for X.25? */
297 #define NET_FRAME_RELAY 2
298 #define NET_ROUTER      3       /* Probably "Router/Bridge", for various
299                                    point-to-point protocols for use between
300                                    bridges and routers, including PPP as well
301                                    as various proprietary protocols; also
302                                    used for ISDN, for reasons not obvious
303                                    to me, given that a Sniffer knows
304                                    whether it's using a WAN or an ISDN pod */
305 #define NET_PPP         4       /* "Asynchronous", which includes SLIP too */
306 #define NET_SMDS        5       /* Not mentioned in the document, but
307                                    that's a document for version 5.50 of
308                                    the Sniffer, and that version might use
309                                    version 5 in the file format and thus
310                                    might not be using type 7 records */
311
312 /* values for V.timeunit */
313 #define NUM_NGSNIFF_TIMEUNITS 7
314 static double Usec[] = { 15.0, 0.838096, 15.0, 0.5, 2.0, 1.0, 0.1 };
315
316 static int process_header_records(wtap *wth, int *err, gint16 version,
317     gboolean *is_router);
318 static int process_rec_header2_v2(wtap *wth, unsigned char *buffer,
319     guint16 length, int *err);
320 static int process_rec_header2_v4(wtap *wth, unsigned char *buffer,
321     guint16 length, gboolean *is_router, int *err);
322 static gboolean ngsniffer_read(wtap *wth, int *err, long *data_offset);
323 static gboolean ngsniffer_seek_read(wtap *wth, long seek_off,
324     union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size,
325     int *err);
326 static int ngsniffer_read_rec_header(wtap *wth, gboolean is_random,
327     guint16 *typep, guint16 *lengthp, int *err);
328 static gboolean ngsniffer_read_frame2(wtap *wth, gboolean is_random,
329     struct frame2_rec *frame2, int *err);
330 static int set_pseudo_header_frame2(wtap *wth,
331     union wtap_pseudo_header *pseudo_header, struct frame2_rec *frame2);
332 static gboolean ngsniffer_read_frame4(wtap *wth, gboolean is_random,
333     struct frame4_rec *frame4, int *err);
334 static void set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
335     struct frame4_rec *frame4);
336 static gboolean ngsniffer_read_frame6(wtap *wth, gboolean is_random,
337     struct frame6_rec *frame6, int *err);
338 static void set_pseudo_header_frame6(union wtap_pseudo_header *pseudo_header,
339     struct frame6_rec *frame6);
340 static gboolean ngsniffer_read_rec_data(wtap *wth, gboolean is_random,
341     guchar *pd, int length, int *err);
342 static int infer_pkt_encap(const guint8 *pd, int len);
343 static void fix_pseudo_header(int, union wtap_pseudo_header *pseudo_header);
344 static void ngsniffer_sequential_close(wtap *wth);
345 static void ngsniffer_close(wtap *wth);
346 static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
347         const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
348 static gboolean ngsniffer_dump_close(wtap_dumper *wdh, int *err);
349 static int SnifferDecompress( unsigned char * inbuf, size_t inlen,
350         unsigned char * outbuf, size_t outlen, int *err );
351 static int ng_file_read(void *buffer, size_t elementsize, size_t numelements,
352     wtap *wth, gboolean is_random, int *err);
353 static int read_blob(FILE_T infile, ngsniffer_comp_stream_t *comp_stream,
354     int *err);
355 static long ng_file_seek_seq(wtap *wth, long offset, int whence, int *err);
356 static long ng_file_seek_rand(wtap *wth, long offset, int whence, int *err);
357
358 int ngsniffer_open(wtap *wth, int *err)
359 {
360         int bytes_read;
361         char magic[sizeof ngsniffer_magic];
362         char record_type[2];
363         char record_length[4]; /* only the first 2 bytes are length,
364                                   the last 2 are "reserved" and are thrown away */
365         guint16 type, length;
366         struct vers_rec version;
367         guint16 start_date;
368         guint16 start_time;
369         static const int sniffer_encap[] = {
370                 WTAP_ENCAP_TOKEN_RING,
371                 WTAP_ENCAP_ETHERNET,
372                 WTAP_ENCAP_ARCNET,
373                 WTAP_ENCAP_UNKNOWN,     /* StarLAN */
374                 WTAP_ENCAP_UNKNOWN,     /* PC Network broadband */
375                 WTAP_ENCAP_UNKNOWN,     /* LocalTalk */
376                 WTAP_ENCAP_UNKNOWN,     /* Znet */
377                 WTAP_ENCAP_PER_PACKET,  /* Internetwork analyzer (synchronous) */
378                 WTAP_ENCAP_PER_PACKET,  /* Internetwork analyzer (asynchronous) */
379                 WTAP_ENCAP_FDDI_BITSWAPPED,
380                 WTAP_ENCAP_ATM_SNIFFER
381         };
382         #define NUM_NGSNIFF_ENCAPS (sizeof sniffer_encap / sizeof sniffer_encap[0])
383         gboolean is_router;
384         struct tm tm;
385
386         /* Read in the string that should be at the start of a Sniffer file */
387         errno = WTAP_ERR_CANT_READ;
388         bytes_read = file_read(magic, 1, sizeof magic, wth->fh);
389         if (bytes_read != sizeof magic) {
390                 *err = file_error(wth->fh);
391                 if (*err != 0)
392                         return -1;
393                 return 0;
394         }
395         wth->data_offset += sizeof magic;
396
397         if (memcmp(magic, ngsniffer_magic, sizeof ngsniffer_magic)) {
398                 return 0;
399         }
400
401         /*
402          * Read the first record, which the manual says is a version
403          * record.
404          */
405         errno = WTAP_ERR_CANT_READ;
406         bytes_read = file_read(record_type, 1, 2, wth->fh);
407         bytes_read += file_read(record_length, 1, 4, wth->fh);
408         if (bytes_read != 6) {
409                 *err = file_error(wth->fh);
410                 if (*err != 0)
411                         return -1;
412                 return 0;
413         }
414         wth->data_offset += 6;
415
416         type = pletohs(record_type);
417         length = pletohs(record_length);
418
419         if (type != REC_VERS) {
420                 g_message("ngsniffer: Sniffer file doesn't start with a version record");
421                 *err = WTAP_ERR_BAD_RECORD;
422                 return -1;
423         }
424
425         errno = WTAP_ERR_CANT_READ;
426         bytes_read = file_read(&version, 1, sizeof version, wth->fh);
427         if (bytes_read != sizeof version) {
428                 *err = file_error(wth->fh);
429                 if (*err != 0)
430                         return -1;
431                 return 0;
432         }
433         wth->data_offset += sizeof version;
434
435         /* Check the data link type. */
436         if (version.network >= NUM_NGSNIFF_ENCAPS
437             || sniffer_encap[version.network] == WTAP_ENCAP_UNKNOWN) {
438                 g_message("ngsniffer: network type %u unknown or unsupported",
439                     version.network);
440                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
441                 return -1;
442         }
443
444         /* Check the time unit */
445         if (version.timeunit >= NUM_NGSNIFF_TIMEUNITS) {
446                 g_message("ngsniffer: Unknown timeunit %u", version.timeunit);
447                 *err = WTAP_ERR_UNSUPPORTED;
448                 return -1;
449         }
450
451         /* compressed or uncompressed Sniffer file? */
452         if (version.format != 1) {
453                 wth->file_type = WTAP_FILE_NGSNIFFER_COMPRESSED;
454
455         } else {
456                 wth->file_type = WTAP_FILE_NGSNIFFER_UNCOMPRESSED;
457         }
458
459         /* Set encap type before reading header records because the
460          * header record may change encap type.
461          */
462         wth->file_encap = sniffer_encap[version.network];
463
464         /*
465          * We don't know how to handle the remaining header record types,
466          * so we just skip them - except for REC_HEADER2 records, which
467          * we look at, for "Internetwork analyzer" captures, to attempt to
468          * determine what the link-layer encapsulation is.
469          */
470         if (process_header_records(wth, err, pletohs(&version.maj_vers),
471             &is_router) < 0)
472                 return -1;
473
474         /*
475          * Now, if we have a random stream open, position it to the same
476          * location, which should be the beginning of the real data, and
477          * should be the beginning of the compressed data.
478          *
479          * XXX - will we see any records other than REC_FRAME2, REC_FRAME4,
480          * or REC_EOF after this?  If not, we can get rid of the loop in
481          * "ngsniffer_read()".
482          */
483         if (wth->random_fh != NULL) {
484                 if (file_seek(wth->random_fh, wth->data_offset, SEEK_SET, err) == -1)
485                         return -1;
486         }
487
488         /* This is a ngsniffer file */
489         wth->capture.ngsniffer = g_malloc(sizeof(ngsniffer_t));
490
491         /* We haven't allocated any uncompression buffers yet. */
492         wth->capture.ngsniffer->seq.buf = NULL;
493         wth->capture.ngsniffer->rand.buf = NULL;
494
495         /* Set the current file offset; the offset in the compressed file
496            and in the uncompressed data stream currently the same. */
497         wth->capture.ngsniffer->seq.uncomp_offset = wth->data_offset;
498         wth->capture.ngsniffer->seq.comp_offset = wth->data_offset;
499         wth->capture.ngsniffer->rand.uncomp_offset = wth->data_offset;
500         wth->capture.ngsniffer->rand.comp_offset = wth->data_offset;
501
502         /* We don't yet have any list of compressed blobs. */
503         wth->capture.ngsniffer->first_blob = NULL;
504         wth->capture.ngsniffer->last_blob = NULL;
505         wth->capture.ngsniffer->current_blob = NULL;
506
507         wth->subtype_read = ngsniffer_read;
508         wth->subtype_seek_read = ngsniffer_seek_read;
509         wth->subtype_sequential_close = ngsniffer_sequential_close;
510         wth->subtype_close = ngsniffer_close;
511         wth->snapshot_length = 0;       /* not available in header, only in frame */
512         wth->capture.ngsniffer->timeunit = Usec[version.timeunit];
513         wth->capture.ngsniffer->is_atm =
514             (wth->file_encap == WTAP_ENCAP_ATM_SNIFFER);
515         wth->capture.ngsniffer->is_router = is_router;
516
517         /* Get capture start time */
518         start_time = pletohs(&version.time);
519         start_date = pletohs(&version.date);
520         tm.tm_year = ((start_date&0xfe00)>>9) + 1980 - 1900;
521         tm.tm_mon = ((start_date&0x1e0)>>5) - 1;
522         tm.tm_mday = (start_date&0x1f);
523         /* The time does not appear to act as an offset; only the date
524         tm.tm_hour = (start_time&0xf800)>>11;
525         tm.tm_min = (start_time&0x7e0)>>5;
526         tm.tm_sec = (start_time&0x1f)<<1;*/
527         tm.tm_hour = 0;
528         tm.tm_min = 0;
529         tm.tm_sec = 0;
530         tm.tm_isdst = -1;
531         wth->capture.ngsniffer->start = mktime(&tm);
532         /*
533          * XXX - what if "secs" is -1?  Unlikely,
534          * but if the capture was done in a time
535          * zone that switches between standard and
536          * summer time sometime other than when we
537          * do, and thus the time was one that doesn't
538          * exist here because a switch from standard
539          * to summer time zips over it, it could
540          * happen.
541          *
542          * On the other hand, if the capture was done
543          * in a different time zone, this won't work
544          * right anyway; unfortunately, the time zone
545          * isn't stored in the capture file.
546          */
547
548         return 1;
549 }
550
551 static int
552 process_header_records(wtap *wth, int *err, gint16 version, gboolean *is_router)
553 {
554         int bytes_read;
555         char record_type[2];
556         char record_length[4]; /* only the first 2 bytes are length,
557                                   the last 2 are "reserved" and are thrown away */
558         guint16 type, length;
559         int bytes_to_read;
560         unsigned char buffer[256];
561
562         *is_router = FALSE;
563         for (;;) {
564                 errno = WTAP_ERR_CANT_READ;
565                 bytes_read = file_read(record_type, 1, 2, wth->fh);
566                 if (bytes_read != 2) {
567                         *err = file_error(wth->fh);
568                         if (*err != 0)
569                                 return -1;
570                         if (bytes_read != 0) {
571                                 *err = WTAP_ERR_SHORT_READ;
572                                 return -1;
573                         }
574                         return 0;       /* EOF */
575                 }
576
577                 type = pletohs(record_type);
578                 if ((type != REC_HEADER1) && (type != REC_HEADER2)
579                         && (type != REC_HEADER3) && (type != REC_HEADER4)
580                         && (type != REC_HEADER5) && (type != REC_HEADER6)
581                         && (type != REC_HEADER7)
582                         && ((type != REC_V2DESC) || (version > 2)) ) {
583                         /*
584                          * Well, this is either some unknown header type
585                          * (we ignore this case), an uncompressed data
586                          * frame or the length of a compressed blob
587                          * which implies data. Seek backwards over the
588                          * two bytes we read, and return.
589                          */
590                         if (file_seek(wth->fh, -2, SEEK_CUR, err) == -1)
591                                 return -1;
592                         return 0;
593                 }
594
595                 errno = WTAP_ERR_CANT_READ;
596                 bytes_read = file_read(record_length, 1, 4, wth->fh);
597                 if (bytes_read != 4) {
598                         *err = file_error(wth->fh);
599                         if (*err == 0)
600                                 *err = WTAP_ERR_SHORT_READ;
601                         return -1;
602                 }
603                 wth->data_offset += 6;
604
605                 length = pletohs(record_length);
606
607                 /*
608                  * Do we not yet know the encapsulation type (i.e., is
609                  * this is an "Internetwork analyzer" capture?), and
610                  * is this a REC_HEADER2 record?
611                  *
612                  * If so, it appears to specify the particular type
613                  * of network we're on.
614                  *
615                  * If so, the 5th byte of the record appears to specify
616                  * the particular type of network we're on.
617                  */
618                 if (wth->file_encap == WTAP_ENCAP_PER_PACKET &&
619                     type == REC_HEADER2) {
620                         /*
621                          * Yes, get the first up-to-256 bytes of the
622                          * record data.
623                          */
624                         bytes_to_read = MIN(length, sizeof buffer);
625                         bytes_read = file_read(buffer, 1, bytes_to_read,
626                                 wth->fh);
627                         if (bytes_read != bytes_to_read) {
628                                 *err = file_error(wth->fh);
629                                 if (*err == 0) {
630                                         *err = WTAP_ERR_SHORT_READ;
631                                         return -1;
632                                 }
633                         }
634
635                         switch (version) {
636
637                         case 2:
638                                 if (process_rec_header2_v2(wth, buffer,
639                                     length, err) < 0)
640                                         return -1;
641                                 break;
642
643                         case 4:
644                                 if (process_rec_header2_v4(wth, buffer,
645                                     length, is_router, err) < 0)
646                                         return -1;
647                                 break;
648                         }
649
650                         /*
651                          * Skip the rest of the record.
652                          */
653                         if (length > sizeof buffer) {
654                                 if (file_seek(wth->fh, length - sizeof buffer,
655                                     SEEK_CUR, err) == -1)
656                                         return -1;
657                         }
658
659                 } else {
660                         /* Nope, just skip over the data. */
661                         if (file_seek(wth->fh, length, SEEK_CUR, err) == -1)
662                                 return -1;
663                 }
664                 wth->data_offset += length;
665         }
666 }
667
668 static int
669 process_rec_header2_v2(wtap *wth, unsigned char *buffer, guint16 length,
670     int *err)
671 {
672         static const char x_25_str[] = "HDLC\nX.25\n";
673
674         /*
675          * There appears to be a string in a REC_HEADER2 record, with
676          * a list of protocols.  In one X.25 capture I've seen, the
677          * string was "HDLC\nX.25\nCLNP\nISO_TP\nSESS\nPRES\nVTP\nACSE".
678          * Presumably CLNP and everything else is per-packet, but
679          * we assume "HDLC\nX.25\n" indicates that it's an X.25 capture.
680          */
681         if (length < sizeof x_25_str - 1) {
682                 /*
683                  * There's not enough data to compare.
684                  */
685                 g_message("ngsniffer: WAN capture has too-short protocol list");
686                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
687                 return -1;
688         }
689
690         if (strncmp(buffer, x_25_str, sizeof x_25_str - 1) == 0) {
691                 /*
692                  * X.25.
693                  */
694                 wth->file_encap = WTAP_ENCAP_LAPB;
695         } else {
696                 g_message("ngsniffer: WAN capture protocol string %.*s unknown",
697                     length, buffer);
698                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
699                 return -1;
700         }
701         return 0;
702 }
703
704 static int
705 process_rec_header2_v4(wtap *wth, unsigned char *buffer, guint16 length,
706     gboolean *is_router, int *err)
707 {
708         /*
709          * The 5th byte of the REC_HEADER2 record appears to be a
710          * network type.
711          */
712         if (length < 5) {
713                 /*
714                  * There is no 5th byte; give up.
715                  */
716                 g_message("ngsniffer: WAN capture has no network subtype");
717                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
718                 return -1;
719         }
720
721         /*
722          * The X.25 captures I've seen have a type of NET_HDLC, and the
723          * Sniffer documentation seems to imply that it's used for
724          * X.25, although it could be used for other purposes as well.
725          *
726          * NET_ROUTER is used for all sorts of point-to-point protocols,
727          * including ISDN.  It appears, from the documentation, that the
728          * Sniffer attempts to infer the particular protocol by looking
729          * at the traffic; it's not clear whether it stores in the file
730          * an indication of the protocol it inferred was being used.
731          *
732          * For now, we interpret NET_HDLC as X.25 (LAPB) and NET_ROUTER
733          * as "per-packet encapsulation".  We remember that we saw
734          * NET_ROUTER, though, as it appears that we can infer whether
735          * a packet is PPP or ISDN based on the channel number subfield
736          * of the frame error status bits - if it's 0, it's PPP, otherwise
737          * it's ISDN and the channel number indicates which channel it is.
738          */
739         switch (buffer[4]) {
740
741         case NET_HDLC:
742                 wth->file_encap = WTAP_ENCAP_LAPB;
743                 break;
744
745         case NET_FRAME_RELAY:
746                 wth->file_encap = WTAP_ENCAP_FRELAY;
747                 break;
748
749         case NET_ROUTER:
750                 wth->file_encap = WTAP_ENCAP_PER_PACKET;
751                 *is_router = TRUE;
752                 break;
753
754         case NET_PPP:
755                 wth->file_encap = WTAP_ENCAP_PPP_WITH_PHDR;
756                 break;
757
758         default:
759                 /*
760                  * Reject these until we can figure them out.
761                  */
762                 g_message("ngsniffer: WAN network subtype %u unknown or unsupported",
763                     buffer[4]);
764                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
765                 return -1;
766         }
767         return 0;
768 }
769
770 /* Read the next packet */
771 static gboolean ngsniffer_read(wtap *wth, int *err, long *data_offset)
772 {
773         int     ret;
774         guint16 type, length;
775         struct frame2_rec frame2;
776         struct frame4_rec frame4;
777         struct frame6_rec frame6;
778         double  t;
779         guint16 time_low, time_med, time_high, true_size, size;
780         guchar  *pd;
781         int pkt_encap = wth->file_encap;
782
783         for (;;) {
784                 /*
785                  * Read the record header.
786                  */
787                 *data_offset = wth->data_offset;
788                 ret = ngsniffer_read_rec_header(wth, FALSE, &type, &length,
789                     err);
790                 if (ret <= 0) {
791                         /* Read error or EOF */
792                         return FALSE;
793                 }
794                 wth->data_offset += 6;
795
796                 switch (type) {
797
798                 case REC_FRAME2:
799                         if (wth->capture.ngsniffer->is_atm) {
800                                 /*
801                                  * We shouldn't get a frame2 record in
802                                  * an ATM capture.
803                                  */
804                                 g_message("ngsniffer: REC_FRAME2 record in an ATM Sniffer file");
805                                 *err = WTAP_ERR_BAD_RECORD;
806                                 return FALSE;
807                         }
808
809                         /* Read the f_frame2_struct */
810                         if (!ngsniffer_read_frame2(wth, FALSE, &frame2, err)) {
811                                 /* Read error */
812                                 return FALSE;
813                         }
814                         wth->data_offset += sizeof frame2;
815                         time_low = pletohs(&frame2.time_low);
816                         time_med = pletohs(&frame2.time_med);
817                         time_high = pletohs(&frame2.time_high);
818                         size = pletohs(&frame2.size);
819                         true_size = pletohs(&frame2.true_size);
820
821                         length -= sizeof frame2;        /* we already read that much */
822
823                         t = (double)time_low+(double)(time_med)*65536.0 +
824                             (double)time_high*4294967296.0;
825
826                         pkt_encap = set_pseudo_header_frame2(wth,
827                             &wth->pseudo_header, &frame2);
828                         goto found;
829
830                 case REC_FRAME4:
831                         if (!wth->capture.ngsniffer->is_atm) {
832                                 /*
833                                  * We shouldn't get a frame2 record in
834                                  * a non-ATM capture.
835                                  */
836                                 g_message("ngsniffer: REC_FRAME4 record in a non-ATM Sniffer file");
837                                 *err = WTAP_ERR_BAD_RECORD;
838                                 return FALSE;
839                         }
840
841                         /* Read the f_frame4_struct */
842                         if (!ngsniffer_read_frame4(wth, FALSE, &frame4, err)) {
843                                 /* Read error */
844                                 return FALSE;
845                         }
846                         wth->data_offset += sizeof frame4;
847                         time_low = pletohs(&frame4.time_low);
848                         time_med = pletohs(&frame4.time_med);
849                         time_high = frame4.time_high;
850                         size = pletohs(&frame4.size);
851                         true_size = pletohs(&frame4.true_size);
852
853                         length -= sizeof frame4;        /* we already read that much */
854
855                         /*
856                          * XXX - use the "time_day" field?  Is that for captures
857                          * that take a *really* long time?
858                          */
859                         t = (double)time_low+(double)(time_med)*65536.0 +
860                             (double)time_high*4294967296.0;
861
862                         set_pseudo_header_frame4(&wth->pseudo_header, &frame4);
863                         goto found;
864
865                 case REC_FRAME6:
866                         /* XXX - Is this test valid? */
867                         if (wth->capture.ngsniffer->is_atm) {
868                                 g_message("ngsniffer: REC_FRAME6 record in an ATM Sniffer file");
869                                 *err = WTAP_ERR_BAD_RECORD;
870                                 return FALSE;
871                         }
872
873                         /* Read the f_frame6_struct */
874                         if (!ngsniffer_read_frame6(wth, FALSE, &frame6, err)) {
875                                 /* Read error */
876                                 return FALSE;
877                         }
878                         wth->data_offset += sizeof frame6;
879                         time_low = pletohs(&frame6.time_low);
880                         time_med = pletohs(&frame6.time_med);
881                         time_high = frame6.time_high;
882                         size = pletohs(&frame6.size);
883                         true_size = pletohs(&frame6.true_size);
884
885                         length -= sizeof frame6;        /* we already read that much */
886
887                         /*
888                          * XXX - use the "time_day" field?  Is that for captures
889                          * that take a *really* long time?
890                          */
891                         t = (double)time_low+(double)(time_med)*65536.0 +
892                             (double)time_high*4294967296.0;
893
894                         set_pseudo_header_frame6(&wth->pseudo_header, &frame6);
895                         goto found;
896
897                 case REC_EOF:
898                         /*
899                          * End of file.  Return an EOF indication.
900                          */
901                         *err = 0;       /* EOF, not error */
902                         return FALSE;
903
904                 default:
905                         break;  /* unknown type, skip it */
906                 }
907
908                 /*
909                  * Well, we don't know what it is, or we know what
910                  * it is but can't handle it.  Skip past the data
911                  * portion, and keep looping.
912                  */
913                 if (ng_file_seek_seq(wth, length, SEEK_CUR, err) == -1)
914                         return FALSE;
915                 wth->data_offset += length;
916         }
917
918 found:
919         /*
920          * OK, is the frame data size greater than than what's left of the
921          * record?
922          */
923         if (size > length) {
924                 /*
925                  * Yes - treat this as an error.
926                  */
927                 g_message("ngsniffer: Record length is less than packet size");
928                 *err = WTAP_ERR_BAD_RECORD;
929                 return FALSE;
930         }
931
932         wth->phdr.len = true_size ? true_size : size;
933         wth->phdr.caplen = size;
934
935         /*
936          * Read the packet data.
937          */
938         buffer_assure_space(wth->frame_buffer, length);
939         pd = buffer_start_ptr(wth->frame_buffer);
940         if (!ngsniffer_read_rec_data(wth, FALSE, pd, length, err))
941                 return FALSE;   /* Read error */
942         wth->data_offset += length;
943
944         wth->phdr.pkt_encap = pkt_encap;
945         if (pkt_encap == WTAP_ENCAP_PER_PACKET) {
946                 /*
947                  * Infer the packet type from the first byte.
948                  */
949                 wth->phdr.pkt_encap = infer_pkt_encap(pd, length);
950
951                 /*
952                  * Fix up the pseudo-header; we may have set
953                  * "x25.flags", but, for some traffic, we should
954                  * set "isdn.uton" instead, and set the channel
955                  * number.
956                  */
957                 fix_pseudo_header(wth->phdr.pkt_encap, &wth->pseudo_header);
958         }
959
960         t = t/1000000.0 * wth->capture.ngsniffer->timeunit; /* t = # of secs */
961         t += wth->capture.ngsniffer->start;
962         wth->phdr.ts.tv_sec = (long)t;
963         wth->phdr.ts.tv_usec = (unsigned long)((t-(double)(wth->phdr.ts.tv_sec))
964                         *1.0e6);
965         return TRUE;
966 }
967
968 static gboolean ngsniffer_seek_read(wtap *wth, long seek_off,
969     union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size,
970     int *err)
971 {
972         int     ret;
973         guint16 type, length;
974         struct frame2_rec frame2;
975         struct frame4_rec frame4;
976         struct frame6_rec frame6;
977         int     pkt_encap = wth->file_encap;
978
979         if (ng_file_seek_rand(wth, seek_off, SEEK_SET, err) == -1)
980                 return FALSE;
981
982         ret = ngsniffer_read_rec_header(wth, TRUE, &type, &length, err);
983         if (ret <= 0) {
984                 /* Read error or EOF */
985                 if (ret == 0) {
986                         /* EOF means "short read" in random-access mode */
987                         *err = WTAP_ERR_SHORT_READ;
988                 }
989                 return FALSE;
990         }
991
992         switch (type) {
993
994         case REC_FRAME2:
995                 /* Read the f_frame2_struct */
996                 if (!ngsniffer_read_frame2(wth, TRUE, &frame2, err)) {
997                         /* Read error */
998                         return FALSE;
999                 }
1000
1001                 length -= sizeof frame2;        /* we already read that much */
1002
1003                 pkt_encap = set_pseudo_header_frame2(wth, pseudo_header,
1004                     &frame2);
1005                 break;
1006
1007         case REC_FRAME4:
1008                 /* Read the f_frame4_struct */
1009                 if (!ngsniffer_read_frame4(wth, TRUE, &frame4, err)) {
1010                         /* Read error */
1011                         return FALSE;
1012                 }
1013
1014                 length -= sizeof frame4;        /* we already read that much */
1015
1016                 set_pseudo_header_frame4(pseudo_header, &frame4);
1017                 break;
1018
1019         case REC_FRAME6:
1020                 /* Read the f_frame6_struct */
1021                 if (!ngsniffer_read_frame6(wth, TRUE, &frame6, err)) {
1022                         /* Read error */
1023                         return FALSE;
1024                 }
1025
1026                 length -= sizeof frame6;        /* we already read that much */
1027
1028                 set_pseudo_header_frame6(pseudo_header, &frame6);
1029                 break;
1030
1031         default:
1032                 /*
1033                  * "Can't happen".
1034                  */
1035                 g_assert_not_reached();
1036                 return FALSE;
1037         }
1038
1039         /*
1040          * Got the pseudo-header (if any), now get the data.
1041          */
1042         if (!ngsniffer_read_rec_data(wth, TRUE, pd, packet_size, err))
1043                 return FALSE;
1044
1045         if (pkt_encap == WTAP_ENCAP_PER_PACKET) {
1046                 /*
1047                  * Infer the packet type from the first two bytes.
1048                  */
1049                 pkt_encap = infer_pkt_encap(pd, packet_size);
1050
1051                 /*
1052                  * Fix up the pseudo-header; we may have set
1053                  * "x25.flags", but, for some traffic, we should
1054                  * set "isdn.uton" instead, and set the channel
1055                  * number.
1056                  */
1057                 fix_pseudo_header(pkt_encap, pseudo_header);
1058         }
1059
1060         return TRUE;
1061 }
1062
1063 static int ngsniffer_read_rec_header(wtap *wth, gboolean is_random,
1064     guint16 *typep, guint16 *lengthp, int *err)
1065 {
1066         int     bytes_read;
1067         char    record_type[2];
1068         char    record_length[4]; /* only 1st 2 bytes are length */
1069
1070         /*
1071          * Read the record header.
1072          */
1073         bytes_read = ng_file_read(record_type, 1, 2, wth, is_random, err);
1074         if (bytes_read != 2) {
1075                 if (*err != 0)
1076                         return -1;
1077                 if (bytes_read != 0) {
1078                         *err = WTAP_ERR_SHORT_READ;
1079                         return -1;
1080                 }
1081                 return 0;
1082         }
1083         bytes_read = ng_file_read(record_length, 1, 4, wth, is_random, err);
1084         if (bytes_read != 4) {
1085                 if (*err == 0)
1086                         *err = WTAP_ERR_SHORT_READ;
1087                 return -1;
1088         }
1089
1090         *typep = pletohs(record_type);
1091         *lengthp = pletohs(record_length);
1092         return 1;       /* success */
1093 }
1094
1095 static gboolean ngsniffer_read_frame2(wtap *wth, gboolean is_random,
1096     struct frame2_rec *frame2, int *err)
1097 {
1098         int bytes_read;
1099
1100         /* Read the f_frame2_struct */
1101         bytes_read = ng_file_read(frame2, 1, sizeof *frame2, wth, is_random,
1102             err);
1103         if (bytes_read != sizeof *frame2) {
1104                 if (*err == 0)
1105                         *err = WTAP_ERR_SHORT_READ;
1106                 return FALSE;
1107         }
1108         return TRUE;
1109 }
1110
1111 static int set_pseudo_header_frame2(wtap *wth,
1112     union wtap_pseudo_header *pseudo_header, struct frame2_rec *frame2)
1113 {
1114         int pkt_encap;
1115
1116         /*
1117          * In one PPP "Internetwork analyzer" capture:
1118          *
1119          *      The only bit seen in "frame2.fs" is the 0x80 bit, which
1120          *      probably indicates the packet's direction; all other
1121          *      bits were zero.  The Expert Sniffer Network Analyzer
1122          *      5.50 Operations manual says that bit is the FS_DTE bit
1123          *      for async/PPP data.  The other bits are error bits
1124          *      plus bits indicating whether the frame is PPP or SLIP,
1125          *      but the PPP bit isn't set.
1126          *
1127          *      All bits in "frame2.flags" were zero.
1128          *
1129          * In one X.25 "Internetwork analyzer" capture:
1130          *
1131          *      The only bit seen in "frame2.fs" is the 0x80 bit, which
1132          *      probably indicates the packet's direction; all other
1133          *      bits were zero.
1134          *
1135          *      "frame2.flags" was always 0x18; however, the Sniffer
1136          *      manual says that just means that a display filter was
1137          *      calculated for the frame, and it should be displayed,
1138          *      so perhaps that's just a quirk of that particular capture.
1139          *
1140          * In one Ethernet capture:
1141          *
1142          *      "frame2.fs" was always 0; the Sniffer manual says they're
1143          *      error bits of various sorts.
1144          *
1145          *      "frame2.flags" was either 0 or 0x18, with no obvious
1146          *      correlation with anything.  See previous comment
1147          *      about display filters.
1148          *
1149          * In one Token Ring capture:
1150          *
1151          *      "frame2.fs" was either 0 or 0xcc; the Sniffer manual says
1152          *      nothing about those bits for Token Ring captures.
1153          *
1154          *      "frame2.flags" was either 0 or 0x18, with no obvious
1155          *      correlation with anything.  See previous comment
1156          *      about display filters.
1157          *
1158          * In some PPP and ISDN captures, with subtype NET_ROUTER,
1159          * the 0x18 bits in "frame2.fs" are 0 for frames in a PPP
1160          * capture and non-zero for frames in an ISDN capture, specifying
1161          * the channel number in the fashion described in the Sniffer
1162          * manual.
1163          */
1164         if (wth->file_encap == WTAP_ENCAP_PER_PACKET &&
1165             wth->capture.ngsniffer->is_router) {
1166                 if ((frame2->fs & 0x18) == 0)
1167                         pkt_encap = WTAP_ENCAP_PPP_WITH_PHDR;
1168                 else
1169                         pkt_encap = WTAP_ENCAP_ISDN;
1170         } else
1171                 pkt_encap = wth->file_encap;
1172
1173         switch (pkt_encap) {
1174
1175         case WTAP_ENCAP_PPP_WITH_PHDR:
1176                 pseudo_header->p2p.sent = (frame2->fs & 0x80) ? TRUE : FALSE;
1177                 break;
1178
1179         case WTAP_ENCAP_LAPB:
1180         case WTAP_ENCAP_FRELAY:
1181         case WTAP_ENCAP_PER_PACKET:
1182                 pseudo_header->x25.flags = (frame2->fs & 0x80) ? 0x00 : FROM_DCE;
1183                 break;
1184
1185         case WTAP_ENCAP_ISDN:
1186                 pseudo_header->isdn.uton = (frame2->fs & 0x80) ? FALSE : TRUE;
1187                 switch (frame2->fs & 0x18) {
1188
1189                 case 0x18:
1190                         pseudo_header->isdn.channel = 0;        /* D-channel */
1191                         break;
1192
1193                 case 0x08:
1194                         pseudo_header->isdn.channel = 1;        /* B1-channel */
1195                         break;
1196
1197                 case 0x10:
1198                         pseudo_header->isdn.channel = 2;        /* B1-channel */
1199                         break;
1200
1201                 default:
1202                         pseudo_header->isdn.channel = 30;       /* XXX */
1203                         break;
1204                 }
1205         }
1206         return pkt_encap;
1207 }
1208
1209 static gboolean ngsniffer_read_frame4(wtap *wth, gboolean is_random,
1210     struct frame4_rec *frame4, int *err)
1211 {
1212         int bytes_read;
1213
1214         /* Read the f_frame4_struct */
1215         bytes_read = ng_file_read(frame4, 1, sizeof *frame4, wth, is_random,
1216             err);
1217         if (bytes_read != sizeof *frame4) {
1218                 if (*err == 0)
1219                         *err = WTAP_ERR_SHORT_READ;
1220                 return FALSE;
1221         }
1222         return TRUE;
1223 }
1224
1225 static void set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
1226     struct frame4_rec *frame4)
1227 {
1228         guint8 aal_type, hl_type;
1229         guint16 vpi, vci;
1230
1231         aal_type = frame4->atm_info.AppTrafType & ATT_AALTYPE;
1232         hl_type = frame4->atm_info.AppTrafType & ATT_HLTYPE;
1233         vpi = pletohs(&frame4->atm_info.Vpi);
1234         vci = pletohs(&frame4->atm_info.Vci);
1235
1236         switch (aal_type) {
1237
1238         case ATT_AAL_UNKNOWN:
1239                 /*
1240                  * Map ATT_AAL_UNKNOWN on VPI 0, VCI 5 to ATT_AAL_SIGNALLING,
1241                  * as that's the VPCI used for signalling.
1242                  *
1243                  * XXX - is this necessary, or will frames to 0/5 always
1244                  * have ATT_AAL_SIGNALLING?
1245                  */
1246                 if (vpi == 0 && vci == 5)
1247                         pseudo_header->atm.aal = AAL_SIGNALLING;
1248                 else
1249                         pseudo_header->atm.aal = AAL_UNKNOWN;
1250                 pseudo_header->atm.type = TRAF_UNKNOWN;
1251                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1252                 break;
1253
1254         case ATT_AAL1:
1255                 pseudo_header->atm.aal = AAL_1;
1256                 pseudo_header->atm.type = TRAF_UNKNOWN;
1257                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1258                 break;
1259
1260         case ATT_AAL3_4:
1261                 pseudo_header->atm.aal = AAL_3_4;
1262                 pseudo_header->atm.type = TRAF_UNKNOWN;
1263                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1264                 break;
1265
1266         case ATT_AAL5:
1267                 pseudo_header->atm.aal = AAL_5;
1268                 switch (hl_type) {
1269
1270                 case ATT_HL_UNKNOWN:
1271                         pseudo_header->atm.type = TRAF_UNKNOWN;
1272                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1273                         break;
1274
1275                 case ATT_HL_LLCMX:
1276                         pseudo_header->atm.type = TRAF_LLCMX;
1277                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1278                         break;
1279
1280                 case ATT_HL_VCMX:
1281                         pseudo_header->atm.type = TRAF_VCMX;
1282                         switch (frame4->atm_info.AppHLType) {
1283
1284                         case AHLT_UNKNOWN:
1285                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1286                                 break;
1287
1288                         case AHLT_VCMX_802_3_FCS:
1289                                 pseudo_header->atm.subtype =
1290                                     TRAF_ST_VCMX_802_3_FCS;
1291                                 break;
1292
1293                         case AHLT_VCMX_802_4_FCS:
1294                                 pseudo_header->atm.subtype =
1295                                     TRAF_ST_VCMX_802_4_FCS;
1296                                 break;
1297
1298                         case AHLT_VCMX_802_5_FCS:
1299                                 pseudo_header->atm.subtype =
1300                                     TRAF_ST_VCMX_802_5_FCS;
1301                                 break;
1302
1303                         case AHLT_VCMX_FDDI_FCS:
1304                                 pseudo_header->atm.subtype =
1305                                     TRAF_ST_VCMX_FDDI_FCS;
1306                                 break;
1307
1308                         case AHLT_VCMX_802_6_FCS:
1309                                 pseudo_header->atm.subtype =
1310                                     TRAF_ST_VCMX_802_6_FCS;
1311                                 break;
1312
1313                         case AHLT_VCMX_802_3:
1314                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_3;
1315                                 break;
1316
1317                         case AHLT_VCMX_802_4:
1318                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_4;
1319                                 break;
1320
1321                         case AHLT_VCMX_802_5:
1322                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_5;
1323                                 break;
1324
1325                         case AHLT_VCMX_FDDI:
1326                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_FDDI;
1327                                 break;
1328
1329                         case AHLT_VCMX_802_6:
1330                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_6;
1331                                 break;
1332
1333                         case AHLT_VCMX_FRAGMENTS:
1334                                 pseudo_header->atm.subtype =
1335                                     TRAF_ST_VCMX_FRAGMENTS;
1336                                 break;
1337
1338                         case AHLT_VCMX_BPDU:
1339                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_BPDU;
1340                                 break;
1341
1342                         default:
1343                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1344                                 break;
1345                         }
1346                         break;
1347
1348                 case ATT_HL_LANE:
1349                         pseudo_header->atm.type = TRAF_LANE;
1350                         switch (frame4->atm_info.AppHLType) {
1351
1352                         case AHLT_UNKNOWN:
1353                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1354                                 break;
1355
1356                         case AHLT_LANE_LE_CTRL:
1357                                 pseudo_header->atm.subtype =
1358                                     TRAF_ST_LANE_LE_CTRL;
1359                                 break;
1360
1361                         case AHLT_LANE_802_3:
1362                                 pseudo_header->atm.subtype = TRAF_ST_LANE_802_3;
1363                                 break;
1364
1365                         case AHLT_LANE_802_5:
1366                                 pseudo_header->atm.subtype = TRAF_ST_LANE_802_5;
1367                                 break;
1368
1369                         case AHLT_LANE_802_3_MC:
1370                                 pseudo_header->atm.subtype =
1371                                     TRAF_ST_LANE_802_3_MC;
1372                                 break;
1373
1374                         case AHLT_LANE_802_5_MC:
1375                                 pseudo_header->atm.subtype =
1376                                     TRAF_ST_LANE_802_5_MC;
1377                                 break;
1378
1379                         default:
1380                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1381                                 break;
1382                         }
1383                         break;
1384
1385                 case ATT_HL_ILMI:
1386                         pseudo_header->atm.type = TRAF_ILMI;
1387                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1388                         break;
1389
1390                 case ATT_HL_FRMR:
1391                         pseudo_header->atm.type = TRAF_FR;
1392                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1393                         break;
1394
1395                 case ATT_HL_SPANS:
1396                         pseudo_header->atm.type = TRAF_SPANS;
1397                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1398                         break;
1399
1400                 case ATT_HL_IPSILON:
1401                         pseudo_header->atm.type = TRAF_IPSILON;
1402                         switch (frame4->atm_info.AppHLType) {
1403
1404                         case AHLT_UNKNOWN:
1405                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1406                                 break;
1407
1408                         case AHLT_IPSILON_FT0:
1409                                 pseudo_header->atm.subtype =
1410                                     TRAF_ST_IPSILON_FT0;
1411                                 break;
1412
1413                         case AHLT_IPSILON_FT1:
1414                                 pseudo_header->atm.subtype =
1415                                     TRAF_ST_IPSILON_FT1;
1416                                 break;
1417
1418                         case AHLT_IPSILON_FT2:
1419                                 pseudo_header->atm.subtype =
1420                                     TRAF_ST_IPSILON_FT2;
1421                                 break;
1422
1423                         default:
1424                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1425                                 break;
1426                         }
1427                         break;
1428
1429                 default:
1430                         pseudo_header->atm.type = TRAF_UNKNOWN;
1431                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1432                         break;
1433                 }
1434                 break;
1435
1436         case ATT_AAL_USER:
1437                 pseudo_header->atm.aal = AAL_USER;
1438                 pseudo_header->atm.type = TRAF_UNKNOWN;
1439                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1440                 break;
1441
1442         case ATT_AAL_SIGNALLING:
1443                 pseudo_header->atm.aal = AAL_SIGNALLING;
1444                 pseudo_header->atm.type = TRAF_UNKNOWN;
1445                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1446                 break;
1447
1448         case ATT_OAMCELL:
1449                 pseudo_header->atm.aal = AAL_OAMCELL;
1450                 pseudo_header->atm.type = TRAF_UNKNOWN;
1451                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1452                 break;
1453
1454         default:
1455                 pseudo_header->atm.aal = AAL_UNKNOWN;
1456                 pseudo_header->atm.type = TRAF_UNKNOWN;
1457                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1458                 break;
1459         }
1460         pseudo_header->atm.vpi = vpi;
1461         pseudo_header->atm.vci = vci;
1462         pseudo_header->atm.channel = pletohs(&frame4->atm_info.channel);
1463         pseudo_header->atm.cells = pletohs(&frame4->atm_info.cells);
1464         pseudo_header->atm.aal5t_u2u = pletohs(&frame4->atm_info.Trailer.aal5t_u2u);
1465         pseudo_header->atm.aal5t_len = pletohs(&frame4->atm_info.Trailer.aal5t_len);
1466         pseudo_header->atm.aal5t_chksum = pletohl(&frame4->atm_info.Trailer.aal5t_chksum);
1467 }
1468
1469 static gboolean ngsniffer_read_frame6(wtap *wth, gboolean is_random,
1470     struct frame6_rec *frame6, int *err)
1471 {
1472         int bytes_read;
1473
1474         /* Read the f_frame6_struct */
1475         bytes_read = ng_file_read(frame6, 1, sizeof *frame6, wth, is_random,
1476             err);
1477         if (bytes_read != sizeof *frame6) {
1478                 if (*err == 0)
1479                         *err = WTAP_ERR_SHORT_READ;
1480                 return FALSE;
1481         }
1482         return TRUE;
1483 }
1484
1485 static void set_pseudo_header_frame6(
1486         union wtap_pseudo_header *pseudo_header _U_,
1487         struct frame6_rec *frame6 _U_)
1488 {
1489         /* XXX - Once the frame format is divined, something will most likely go here */
1490 }
1491
1492 static gboolean ngsniffer_read_rec_data(wtap *wth, gboolean is_random,
1493     guchar *pd, int length, int *err)
1494 {
1495         int     bytes_read;
1496
1497         bytes_read = ng_file_read(pd, 1, length, wth, is_random, err);
1498
1499         if (bytes_read != length) {
1500                 if (*err == 0)
1501                         *err = WTAP_ERR_SHORT_READ;
1502                 return FALSE;
1503         }
1504         return TRUE;
1505 }
1506
1507 /*
1508  * OK, this capture is from an "Internetwork analyzer", and we either
1509  * didn't see a type 7 record or it had a network type such as NET_HDLC
1510  * that doesn't tell us which *particular* HDLC derivative this is;
1511  * let's look at the first few bytes of the packet, a pointer to which
1512  * was passed to us as an argument, and see whether it looks like PPP,
1513  * Frame Relay, Wellfleet HDLC, Cisco HDLC, or LAPB - or, if it's none
1514  * of those, assume it's LAPD.
1515  *
1516  * (XXX - are there any "Internetwork analyzer" captures that don't
1517  * have type 7 records?  If so, is there some other field that will
1518  * tell us what type of capture it is?)
1519  */
1520 static int infer_pkt_encap(const guint8 *pd, int len)
1521 {
1522         if (len <= 0) {
1523                 /*
1524                  * Nothing to infer, but it doesn't matter how you
1525                  * dissect an empty packet.  Let's just say PPP.
1526                  */
1527                 return WTAP_ENCAP_PPP_WITH_PHDR;
1528         }
1529
1530         switch (pd[0]) {
1531
1532         case 0xFF:
1533                 /*
1534                  * PPP.  (XXX - check for 0xFF 0x03?)
1535                  */
1536                 return WTAP_ENCAP_PPP_WITH_PHDR;
1537
1538         case 0x34:
1539         case 0x28:
1540                 /*
1541                  * Frame Relay.
1542                  *
1543                  * XXX - in version 4 captures, wouldn't this just have
1544                  * a capture subtype of NET_FRAME_RELAY?  Or is this
1545                  * here only to handle other versions of the capture
1546                  * file, where we might just not yet have found where
1547                  * the subtype is specified in the capture?
1548                  */
1549                 return WTAP_ENCAP_FRELAY;
1550         }
1551
1552         if (len >= 2) {
1553                 if (pd[0] == 0x07 && pd[1] == 0x03) {
1554                         /*
1555                          * Wellfleet HDLC.
1556                          */
1557                         return WTAP_ENCAP_WFLEET_HDLC;
1558                 } else if ((pd[0] == 0x08 && pd[1] == 0x00) ||
1559                            (pd[0] == 0x8F && pd[1] == 0x00)) {
1560                         /*
1561                          * Cisco HDLC.
1562                          */
1563                         return WTAP_ENCAP_CHDLC;
1564                 }
1565         }
1566
1567         if (pd[0] & 1) {
1568                 /*
1569                  * LAPB.
1570                  */
1571                 return WTAP_ENCAP_LAPB;
1572         } else {
1573                 /*
1574                  * LAPD.
1575                  * We report it as WTAP_ENCAP_ISDN.
1576                  *
1577                  * XXX - is there something buried in the header to tell us
1578                  * whether the capture was taken with an ISDN pod?
1579                  *
1580                  * Or is this here just because some ISDN captures run
1581                  * LAPB/X.25 over the B channel(s), so we check for
1582                  * LAPB even in NET_ROUTER captures?  If so, we should
1583                  * perhaps move that heuristic up to the ISDN dissector,
1584                  * so that we can infer LAPB traffic in *all* ISDN
1585                  * captures, not just DOS Sniffer ISDN captures?
1586                  */
1587                 return WTAP_ENCAP_ISDN;
1588         }
1589 }
1590
1591 static void fix_pseudo_header(int encap,
1592     union wtap_pseudo_header *pseudo_header)
1593 {
1594         switch (encap) {
1595
1596         case WTAP_ENCAP_ISDN:
1597                 if (pseudo_header->x25.flags == 0x00)
1598                         pseudo_header->isdn.uton = FALSE;
1599                 else
1600                         pseudo_header->isdn.uton = TRUE;
1601
1602                 /*
1603                  * XXX - this is currently a per-packet encapsulation
1604                  * type, and we can't determine whether a capture is
1605                  * an ISDN capture before seeing any packets, and
1606                  * B-channel PPP packets look like PPP packets and
1607                  * are given WTAP_ENCAP_PPP_WITH_PHDR, not
1608                  * WTAP_ENCAP_ISDN, so we assume this is a D-channel
1609                  * packet and thus give it a channel number of 0.
1610                  */
1611                 pseudo_header->isdn.channel = 0;
1612                 break;
1613         }
1614 }
1615
1616 /* Throw away the buffers used by the sequential I/O stream, but not
1617    those used by the random I/O stream. */
1618 static void ngsniffer_sequential_close(wtap *wth)
1619 {
1620         if (wth->capture.ngsniffer->seq.buf != NULL) {
1621                 g_free(wth->capture.ngsniffer->seq.buf);
1622                 wth->capture.ngsniffer->seq.buf = NULL;
1623         }
1624 }
1625
1626 static void free_blob(gpointer data, gpointer user_data _U_)
1627 {
1628         g_free(data);
1629 }
1630
1631 /* Close stuff used by the random I/O stream, if any, and free up any
1632    private data structures.  (If there's a "sequential_close" routine
1633    for a capture file type, it'll be called before the "close" routine
1634    is called, so we don't have to free the sequential buffer here.) */
1635 static void ngsniffer_close(wtap *wth)
1636 {
1637         if (wth->capture.ngsniffer->rand.buf != NULL)
1638                 g_free(wth->capture.ngsniffer->rand.buf);
1639         if (wth->capture.ngsniffer->first_blob != NULL) {
1640                 g_list_foreach(wth->capture.ngsniffer->first_blob, free_blob, NULL);
1641                 g_list_free(wth->capture.ngsniffer->first_blob);
1642         }
1643         g_free(wth->capture.ngsniffer);
1644 }
1645
1646 static const int wtap_encap[] = {
1647     -1,         /* WTAP_ENCAP_UNKNOWN -> unsupported */
1648     1,          /* WTAP_ENCAP_ETHERNET */
1649     0,          /* WTAP_ENCAP_TOKEN_RING */
1650     -1,         /* WTAP_ENCAP_SLIP -> unsupported */
1651     7,          /* WTAP_ENCAP_PPP -> Internetwork analyzer (synchronous) FIXME ! */
1652     9,          /* WTAP_ENCAP_FDDI */
1653     9,          /* WTAP_ENCAP_FDDI_BITSWAPPED */
1654     -1,         /* WTAP_ENCAP_RAW_IP -> unsupported */
1655     2,          /* WTAP_ENCAP_ARCNET */
1656     -1,         /* WTAP_ENCAP_ATM_RFC1483 */
1657     -1,         /* WTAP_ENCAP_LINUX_ATM_CLIP */
1658     7,          /* WTAP_ENCAP_LAPB -> Internetwork analyzer (synchronous) */
1659     -1,         /* WTAP_ENCAP_ATM_SNIFFER */
1660     -1,         /* WTAP_ENCAP_NULL -> unsupported */
1661     -1,         /* WTAP_ENCAP_ASCEND -> unsupported */
1662     -1,         /* WTAP_ENCAP_ISDN -> unsupported */
1663     -1,         /* WTAP_ENCAP_IP_OVER_FC -> unsupported */
1664     7,          /* WTAP_ENCAP_PPP_WITH_PHDR -> Internetwork analyzer (synchronous) FIXME ! */
1665 };
1666 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
1667
1668 /* Returns 0 if we could write the specified encapsulation type,
1669    an error indication otherwise. */
1670 int ngsniffer_dump_can_write_encap(int encap)
1671 {
1672     /* Per-packet encapsulations aren't supported. */
1673     if (encap == WTAP_ENCAP_PER_PACKET)
1674         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
1675
1676     if (encap < 0 || (unsigned)encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
1677         return WTAP_ERR_UNSUPPORTED_ENCAP;
1678
1679     return 0;
1680 }
1681
1682 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
1683    failure */
1684 gboolean ngsniffer_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err)
1685 {
1686     size_t nwritten;
1687     char buf[6] = {REC_VERS, 0x00, 0x12, 0x00, 0x00, 0x00}; /* version record */
1688
1689     /* This is a sniffer file */
1690     wdh->subtype_write = ngsniffer_dump;
1691     wdh->subtype_close = ngsniffer_dump_close;
1692
1693     wdh->dump.ngsniffer = g_malloc(sizeof(ngsniffer_dump_t));
1694     wdh->dump.ngsniffer->first_frame = TRUE;
1695     wdh->dump.ngsniffer->start = 0;
1696
1697     /* Write the file header. */
1698     nwritten = fwrite(ngsniffer_magic, 1, sizeof ngsniffer_magic, wdh->fh);
1699     if (nwritten != sizeof ngsniffer_magic) {
1700         if (nwritten == 0 && ferror(wdh->fh))
1701             *err = errno;
1702         else
1703             *err = WTAP_ERR_SHORT_WRITE;
1704         return FALSE;
1705     }
1706     nwritten = fwrite(buf, 1, 6, wdh->fh);
1707     if (nwritten != 6) {
1708         if (nwritten == 0 && ferror(wdh->fh))
1709             *err = errno;
1710         else
1711             *err = WTAP_ERR_SHORT_WRITE;
1712         return FALSE;
1713     }
1714
1715     return TRUE;
1716 }
1717
1718 /* Write a record for a packet to a dump file.
1719    Returns TRUE on success, FALSE on failure. */
1720 static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1721     const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
1722 {
1723     ngsniffer_dump_t *priv = wdh->dump.ngsniffer;
1724     struct frame2_rec rec_hdr;
1725     size_t nwritten;
1726     char buf[6];
1727     double t;
1728     guint16 t_low, t_med, t_high;
1729     struct vers_rec version;
1730     gint16 maj_vers, min_vers;
1731     guint16 start_date;
1732     struct tm *tm;
1733
1734     /* Sniffer files have a capture start date in the file header, and
1735        have times relative to the beginning of that day in the packet
1736        headers; pick the date of the first packet as the capture start
1737        date. */
1738     if (priv->first_frame) {
1739         priv->first_frame=FALSE;
1740         tm = localtime(&phdr->ts.tv_sec);
1741         if (tm != NULL) {
1742           start_date = (tm->tm_year - (1980 - 1900)) << 9;
1743           start_date |= (tm->tm_mon + 1) << 5;
1744           start_date |= tm->tm_mday;
1745           /* record the start date, not the start time */
1746           priv->start = phdr->ts.tv_sec - (3600*tm->tm_hour + 60*tm->tm_min + tm->tm_sec);
1747         } else {
1748           start_date = 0;
1749           priv->start = 0;
1750         }
1751
1752         /* "sniffer" version ? */
1753         maj_vers = 4;
1754         min_vers = 0;
1755         version.maj_vers = htoles(maj_vers);
1756         version.min_vers = htoles(min_vers);
1757         version.time = 0;
1758         version.date = htoles(start_date);
1759         version.type = 4;
1760         version.network = wtap_encap[wdh->encap];
1761         version.format = 1;
1762         version.timeunit = 1; /* 0.838096 */
1763         version.cmprs_vers = 0;
1764         version.cmprs_level = 0;
1765         version.rsvd[0] = 0;
1766         version.rsvd[1] = 0;
1767         nwritten = fwrite(&version, 1, sizeof version, wdh->fh);
1768         if (nwritten != sizeof version) {
1769             if (nwritten == 0 && ferror(wdh->fh))
1770                 *err = errno;
1771             else
1772                 *err = WTAP_ERR_SHORT_WRITE;
1773             return FALSE;
1774         }
1775     }
1776
1777     buf[0] = REC_FRAME2;
1778     buf[1] = 0x00;
1779     buf[2] = (char)((phdr->caplen + sizeof(struct frame2_rec))%256);
1780     buf[3] = (char)((phdr->caplen + sizeof(struct frame2_rec))/256);
1781     buf[4] = 0x00;
1782     buf[5] = 0x00;
1783     nwritten = fwrite(buf, 1, 6, wdh->fh);
1784     if (nwritten != 6) {
1785         if (nwritten == 0 && ferror(wdh->fh))
1786             *err = errno;
1787         else
1788             *err = WTAP_ERR_SHORT_WRITE;
1789         return FALSE;
1790     }
1791     t = (double)phdr->ts.tv_sec + (double)phdr->ts.tv_usec/1.0e6; /* # of secs */
1792     t = (t - priv->start)*1.0e6 / Usec[1]; /* timeunit = 1 */
1793     t_low = (guint16)(t-(double)((guint32)(t/65536.0))*65536.0);
1794     t_med = (guint16)((guint32)(t/65536.0) % 65536);
1795     t_high = (guint16)(t/4294967296.0);
1796     rec_hdr.time_low = htoles(t_low);
1797     rec_hdr.time_med = htoles(t_med);
1798     rec_hdr.time_high = htoles(t_high);
1799     rec_hdr.size = htoles(phdr->caplen);
1800     if (wdh->encap == WTAP_ENCAP_LAPB || wdh->encap == WTAP_ENCAP_PPP_WITH_PHDR)
1801         rec_hdr.fs = (pseudo_header->x25.flags & FROM_DCE) ? 0x00 : 0x80;
1802     else
1803         rec_hdr.fs = 0;
1804     rec_hdr.flags = 0;
1805     rec_hdr.true_size = phdr->len != phdr->caplen ? htoles(phdr->len) : 0;
1806     rec_hdr.rsvd = 0;
1807     nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, wdh->fh);
1808     if (nwritten != sizeof rec_hdr) {
1809         if (nwritten == 0 && ferror(wdh->fh))
1810             *err = errno;
1811         else
1812             *err = WTAP_ERR_SHORT_WRITE;
1813         return FALSE;
1814     }
1815     nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
1816     if (nwritten != phdr->caplen) {
1817         if (nwritten == 0 && ferror(wdh->fh))
1818             *err = errno;
1819         else
1820             *err = WTAP_ERR_SHORT_WRITE;
1821         return FALSE;
1822     }
1823     return TRUE;
1824 }
1825
1826 /* Finish writing to a dump file.
1827    Returns TRUE on success, FALSE on failure. */
1828 static gboolean ngsniffer_dump_close(wtap_dumper *wdh, int *err)
1829 {
1830     /* EOF record */
1831     char buf[6] = {REC_EOF, 0x00, 0x00, 0x00, 0x00, 0x00};
1832     size_t nwritten;
1833
1834     nwritten = fwrite(buf, 1, 6, wdh->fh);
1835     if (nwritten != 6) {
1836         if (err != NULL) {
1837             if (nwritten == 0 && ferror(wdh->fh))
1838                 *err = errno;
1839             else
1840                 *err = WTAP_ERR_SHORT_WRITE;
1841         }
1842         return FALSE;
1843     }
1844     return TRUE;
1845 }
1846
1847 /*
1848    SnifferDecompress() decompresses a blob of compressed data from a
1849          Sniffer(R) capture file.
1850
1851    This function is Copyright (c) 1999-2999 Tim Farley
1852
1853    Parameters
1854       inbuf - buffer of compressed bytes from file, not including
1855          the preceding length word
1856       inlen - length of inbuf in bytes
1857       outbuf - decompressed contents, could contain a partial Sniffer
1858          record at the end.
1859       outlen - length of outbuf.
1860
1861    Return value is the number of bytes in outbuf on return.
1862 */
1863 static int
1864 SnifferDecompress( unsigned char * inbuf, size_t inlen,
1865                        unsigned char * outbuf, size_t outlen, int *err )
1866 {
1867    unsigned char * pin = inbuf;
1868    unsigned char * pout = outbuf;
1869    unsigned char * pin_end = pin + inlen;
1870    unsigned char * pout_end = pout + outlen;
1871    unsigned int bit_mask;  /* one bit is set in this, to mask with bit_value */
1872    unsigned int bit_value = 0; /* cache the last 16 coding bits we retrieved */
1873    unsigned int code_type; /* encoding type, from high 4 bits of byte */
1874    unsigned int code_low;  /* other 4 bits from encoding byte */
1875    int length;             /* length of RLE sequence or repeated string */
1876    int offset;             /* offset of string to repeat */
1877
1878    bit_mask  = 0;  /* don't have any bits yet */
1879    while (1)
1880    {
1881       /* Shift down the bit mask we use to see whats encoded */
1882       bit_mask = bit_mask >> 1;
1883
1884       /* If there are no bits left, time to get another 16 bits */
1885       if ( 0 == bit_mask )
1886       {
1887          bit_mask  = 0x8000;  /* start with the high bit */
1888          bit_value = pletohs(pin);   /* get the next 16 bits */
1889          pin += 2;          /* skip over what we just grabbed */
1890          if ( pin >= pin_end )
1891          {
1892             *err = WTAP_ERR_UNC_TRUNCATED;       /* data was oddly truncated */
1893             return ( -1 );
1894          }
1895       }
1896
1897       /* Use the bits in bit_value to see what's encoded and what is raw data */
1898       if ( !(bit_mask & bit_value) )
1899       {
1900          /* bit not set - raw byte we just copy */
1901          *(pout++) = *(pin++);
1902       }
1903       else
1904       {
1905          /* bit set - next item is encoded.  Peel off high nybble
1906             of next byte to see the encoding type.  Set aside low
1907             nybble while we are at it */
1908          code_type = (unsigned int) ((*pin) >> 4 ) & 0xF;
1909          code_low  = (unsigned int) ((*pin) & 0xF );
1910          pin++;   /* increment over the code byte we just retrieved */
1911          if ( pin >= pin_end )
1912          {
1913             *err = WTAP_ERR_UNC_TRUNCATED;       /* data was oddly truncated */
1914             return ( -1 );
1915          }
1916
1917          /* Based on the code type, decode the compressed string */
1918          switch ( code_type )
1919          {
1920             case 0  :   /* RLE short runs */
1921                 /*
1922                     Run length is the low nybble of the first code byte.
1923                     Byte to repeat immediately follows.
1924                     Total code size: 2 bytes.
1925                 */
1926                 length = code_low + 3;
1927                 /* If length would put us past end of output, avoid overflow */
1928                 if ( pout + length > pout_end )
1929                 {
1930                     *err = WTAP_ERR_UNC_OVERFLOW;
1931                     return ( -1 );
1932                 }
1933
1934                 /* generate the repeated series of bytes */
1935                 memset( pout, *pin++, length );
1936                 pout += length;
1937                 break;
1938             case 1  :   /* RLE long runs */
1939                 /*
1940                     Low 4 bits of run length is the low nybble of the
1941                     first code byte, upper 8 bits of run length is in
1942                     the next byte.
1943                     Byte to repeat immediately follows.
1944                     Total code size: 3 bytes.
1945                 */
1946                 length = code_low + ((unsigned int)(*pin++) << 4) + 19;
1947                 /* If we are already at end of input, there is no byte
1948                    to repeat */
1949                 if ( pin >= pin_end )
1950                 {
1951                     *err = WTAP_ERR_UNC_TRUNCATED;       /* data was oddly truncated */
1952                     return ( -1 );
1953                 }
1954                 /* If length would put us past end of output, avoid overflow */
1955                 if ( pout + length > pout_end )
1956                 {
1957                     *err = WTAP_ERR_UNC_OVERFLOW;
1958                     return ( -1 );
1959                 }
1960
1961                 /* generate the repeated series of bytes */
1962                 memset( pout, *pin++, length );
1963                 pout += length;
1964                 break;
1965             case 2  :   /* LZ77 long strings */
1966                 /*
1967                     Low 4 bits of offset to string is the low nybble of the
1968                     first code byte, upper 8 bits of offset is in
1969                     the next byte.
1970                     Length of string immediately follows.
1971                     Total code size: 3 bytes.
1972                 */
1973                 offset = code_low + ((unsigned int)(*pin++) << 4) + 3;
1974                 /* If we are already at end of input, there is no byte
1975                    to repeat */
1976                 if ( pin >= pin_end )
1977                 {
1978                     *err = WTAP_ERR_UNC_TRUNCATED;       /* data was oddly truncated */
1979                     return ( -1 );
1980                 }
1981                 /* Check if offset would put us back past begin of buffer */
1982                 if ( pout - offset < outbuf )
1983                 {
1984                     *err = WTAP_ERR_UNC_BAD_OFFSET;
1985                     return ( -1 );
1986                 }
1987
1988                 /* get length from next byte, make sure it won't overrun buf */
1989                 length = (unsigned int)(*pin++) + 16;
1990                 if ( pout + length > pout_end )
1991                 {
1992                     *err = WTAP_ERR_UNC_OVERFLOW;
1993                     return ( -1 );
1994                 }
1995
1996                 /* Copy the string from previous text to output position,
1997                    advance output pointer */
1998                 memcpy( pout, pout - offset, length );
1999                 pout += length;
2000                 break;
2001             default :   /* (3 to 15): LZ77 short strings */
2002                 /*
2003                     Low 4 bits of offset to string is the low nybble of the
2004                     first code byte, upper 8 bits of offset is in
2005                     the next byte.
2006                     Length of string to repeat is overloaded into code_type.
2007                     Total code size: 2 bytes.
2008                 */
2009                 offset = code_low + ((unsigned int)(*pin++) << 4) + 3;
2010                 /* Check if offset would put us back past begin of buffer */
2011                 if ( pout - offset < outbuf )
2012                 {
2013                     *err = WTAP_ERR_UNC_BAD_OFFSET;
2014                     return ( -1 );
2015                 }
2016
2017                 /* get length from code_type, make sure it won't overrun buf */
2018                 length = code_type;
2019                 if ( pout + length > pout_end )
2020                 {
2021                     *err = WTAP_ERR_UNC_OVERFLOW;
2022                     return ( -1 );
2023                 }
2024
2025                 /* Copy the string from previous text to output position,
2026                    advance output pointer */
2027                 memcpy( pout, pout - offset, length );
2028                 pout += length;
2029                 break;
2030          }
2031       }
2032
2033       /* If we've consumed all the input, we are done */
2034       if ( pin >= pin_end )
2035          break;
2036    }
2037
2038    return ( pout - outbuf );  /* return length of expanded text */
2039 }
2040
2041 /*
2042  * XXX - is there any guarantee that this is big enough to hold the
2043  * uncompressed data from any blob?
2044  */
2045 #define OUTBUF_SIZE     65536
2046
2047 /* Information about a compressed blob; we save the offset in the
2048    underlying compressed file, and the offset in the uncompressed data
2049    stream, of the blob. */
2050 typedef struct {
2051         long    blob_comp_offset;
2052         long    blob_uncomp_offset;
2053 } blob_info_t;
2054
2055 static int
2056 ng_file_read(void *buffer, size_t elementsize, size_t numelements, wtap *wth,
2057     gboolean is_random, int *err)
2058 {
2059     FILE_T infile;
2060     ngsniffer_comp_stream_t *comp_stream;
2061     int copybytes = elementsize * numelements; /* bytes left to be copied */
2062     int copied_bytes = 0; /* bytes already copied */
2063     unsigned char *outbuffer = buffer; /* where to write next decompressed data */
2064     blob_info_t *blob;
2065     int bytes_to_copy;
2066     int bytes_left;
2067
2068     if (is_random) {
2069         infile = wth->random_fh;
2070         comp_stream = &wth->capture.ngsniffer->rand;
2071     } else {
2072         infile = wth->fh;
2073         comp_stream = &wth->capture.ngsniffer->seq;
2074     }
2075
2076     if (wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED) {
2077         errno = WTAP_ERR_CANT_READ;
2078         copied_bytes = file_read(buffer, 1, copybytes, infile);
2079         if (copied_bytes != copybytes)
2080             *err = file_error(infile);
2081         return copied_bytes;
2082     }
2083
2084     /* Allocate the stream buffer if it hasn't already been allocated. */
2085     if (comp_stream->buf == NULL) {
2086         comp_stream->buf = g_malloc(OUTBUF_SIZE);
2087
2088         if (is_random) {
2089             /* This is the first read of the random file, so we're at
2090                the beginning of the sequence of blobs in the file
2091                (as we've not done any random reads yet to move the
2092                current position in the random stream); set the
2093                current blob to be the first blob. */
2094             wth->capture.ngsniffer->current_blob =
2095                 wth->capture.ngsniffer->first_blob;
2096         } else {
2097             /* This is the first sequential read; if we also have a
2098                random stream open, allocate the first element for the
2099                list of blobs, and make it the last element as well. */
2100             if (wth->random_fh != NULL) {
2101                 g_assert(wth->capture.ngsniffer->first_blob == NULL);
2102                 blob = g_malloc(sizeof (blob_info_t));
2103                 blob->blob_comp_offset = comp_stream->comp_offset;
2104                 blob->blob_uncomp_offset = comp_stream->uncomp_offset;
2105                 wth->capture.ngsniffer->first_blob =
2106                         g_list_append(wth->capture.ngsniffer->first_blob, blob);
2107                 wth->capture.ngsniffer->last_blob =
2108                         wth->capture.ngsniffer->first_blob;
2109             }
2110         }
2111
2112         /* Now read the first blob into the buffer. */
2113         if (read_blob(infile, comp_stream, err) < 0)
2114             return -1;
2115     }
2116     while (copybytes > 0) {
2117         bytes_left = comp_stream->nbytes - comp_stream->nextout;
2118         if (bytes_left == 0) {
2119             /* There's no decompressed stuff left to copy from the current
2120                blob; get the next blob. */
2121
2122             if (is_random) {
2123                 /* Move to the next blob in the list. */
2124                 wth->capture.ngsniffer->current_blob =
2125                         g_list_next(wth->capture.ngsniffer->current_blob);
2126                 blob = wth->capture.ngsniffer->current_blob->data;
2127             } else {
2128                 /* If we also have a random stream open, add a new element,
2129                    for this blob, to the list of blobs; we know the list is
2130                    non-empty, as we initialized it on the first sequential
2131                    read, so we just add the new element at the end, and
2132                    adjust the pointer to the last element to refer to it. */
2133                 if (wth->random_fh != NULL) {
2134                     blob = g_malloc(sizeof (blob_info_t));
2135                     blob->blob_comp_offset = comp_stream->comp_offset;
2136                     blob->blob_uncomp_offset = comp_stream->uncomp_offset;
2137                     wth->capture.ngsniffer->last_blob =
2138                         g_list_append(wth->capture.ngsniffer->last_blob, blob);
2139                 }
2140             }
2141
2142             if (read_blob(infile, comp_stream, err) < 0)
2143                 return -1;
2144             bytes_left = comp_stream->nbytes - comp_stream->nextout;
2145         }
2146
2147         bytes_to_copy = copybytes;
2148         if (bytes_to_copy > bytes_left)
2149             bytes_to_copy = bytes_left;
2150         memcpy(outbuffer, &comp_stream->buf[comp_stream->nextout],
2151                 bytes_to_copy);
2152         copybytes -= bytes_to_copy;
2153         copied_bytes += bytes_to_copy;
2154         outbuffer += bytes_to_copy;
2155         comp_stream->nextout += bytes_to_copy;
2156         comp_stream->uncomp_offset += bytes_to_copy;
2157     }
2158     return copied_bytes;
2159 }
2160
2161 /* Read a blob from a compressed stream.
2162    Return -1 and set "*err" on error, otherwise return 0. */
2163 static int
2164 read_blob(FILE_T infile, ngsniffer_comp_stream_t *comp_stream, int *err)
2165 {
2166     size_t in_len;
2167     size_t read_len;
2168     unsigned short blob_len;
2169     gint16 blob_len_host;
2170     gboolean uncompressed;
2171     unsigned char file_inbuf[65536];
2172     int out_len;
2173
2174     /* Read one 16-bit word which is length of next compressed blob */
2175     errno = WTAP_ERR_CANT_READ;
2176     read_len = file_read(&blob_len, 1, 2, infile);
2177     if (2 != read_len) {
2178         *err = file_error(infile);
2179         return -1;
2180     }
2181     comp_stream->comp_offset += 2;
2182     blob_len_host = pletohs(&blob_len);
2183
2184     /* Compressed or uncompressed? */
2185     if (blob_len_host < 0) {
2186         /* Uncompressed blob; blob length is absolute value of the number. */
2187         in_len = -blob_len_host;
2188         uncompressed = TRUE;
2189     } else {
2190         in_len = blob_len_host;
2191         uncompressed = FALSE;
2192     }
2193
2194     /* Read the blob */
2195     errno = WTAP_ERR_CANT_READ;
2196     read_len = file_read(file_inbuf, 1, in_len, infile);
2197     if (in_len != read_len) {
2198         *err = file_error(infile);
2199         return -1;
2200     }
2201     comp_stream->comp_offset += in_len;
2202
2203     if (uncompressed) {
2204         memcpy(comp_stream->buf, file_inbuf, in_len);
2205         out_len = in_len;
2206     } else {
2207         /* Decompress the blob */
2208         out_len = SnifferDecompress(file_inbuf, in_len,
2209                                 comp_stream->buf, OUTBUF_SIZE, err);
2210         if (out_len < 0)
2211             return -1;
2212     }
2213     comp_stream->nextout = 0;
2214     comp_stream->nbytes = out_len;
2215     return 0;
2216 }
2217
2218 /* Seek in the sequential data stream; we can only seek forward, and we
2219    do it on compressed files by skipping forward. */
2220 static long
2221 ng_file_seek_seq(wtap *wth, long offset, int whence, int *err)
2222 {
2223     long delta;
2224     char buf[65536];
2225     long amount_to_read;
2226
2227     if (wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED)
2228         return file_seek(wth->fh, offset, whence, err);
2229
2230     switch (whence) {
2231
2232     case SEEK_SET:
2233         break;          /* "offset" is the target offset */
2234
2235     case SEEK_CUR:
2236         offset += wth->capture.ngsniffer->seq.uncomp_offset;
2237         break;          /* "offset" is relative to the current offset */
2238
2239     case SEEK_END:
2240         g_assert_not_reached(); /* "offset" is relative to the end of the file... */
2241         break;          /* ...but we don't know where that is. */
2242     }
2243
2244     delta = offset - wth->capture.ngsniffer->seq.uncomp_offset;
2245     g_assert(delta >= 0);
2246
2247     /* Ok, now read and discard "delta" bytes. */
2248     while (delta != 0) {
2249         amount_to_read = delta;
2250         if ((unsigned long)amount_to_read > sizeof buf)
2251             amount_to_read = sizeof buf;
2252         if (ng_file_read(buf, 1, amount_to_read, wth, FALSE, err) < 0)
2253             return -1;  /* error */
2254         delta -= amount_to_read;
2255     }
2256     return offset;
2257 }
2258
2259 /* Seek in the random data stream.
2260
2261    On compressed files, we see whether we're seeking to a position within
2262    the blob we currently have in memory and, if not, we find in the list
2263    of blobs the last blob that starts at or before the position to which
2264    we're seeking, and read that blob in.  We can then move to the appropriate
2265    position within the blob we have in memory (whether it's the blob we
2266    already had in memory or, if necessary, the one we read in). */
2267 static long
2268 ng_file_seek_rand(wtap *wth, long offset, int whence, int *err)
2269 {
2270     ngsniffer_t *ngsniffer;
2271     long delta;
2272     GList *new, *next;
2273     blob_info_t *next_blob, *new_blob;
2274
2275     if (wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED)
2276         return file_seek(wth->random_fh, offset, whence, err);
2277
2278     ngsniffer = wth->capture.ngsniffer;
2279
2280     switch (whence) {
2281
2282     case SEEK_SET:
2283         break;          /* "offset" is the target offset */
2284
2285     case SEEK_CUR:
2286         offset += ngsniffer->rand.uncomp_offset;
2287         break;          /* "offset" is relative to the current offset */
2288
2289     case SEEK_END:
2290         g_assert_not_reached(); /* "offset" is relative to the end of the file... */
2291         break;          /* ...but we don't know where that is. */
2292     }
2293
2294     delta = offset - ngsniffer->rand.uncomp_offset;
2295
2296     /* Is the place to which we're seeking within the current buffer, or
2297        will we have to read a different blob into the buffer? */
2298     new = NULL;
2299     if (delta > 0) {
2300         /* We're going forwards.
2301            Is the place to which we're seeking within the current buffer? */
2302         if ((size_t)(ngsniffer->rand.nextout + delta) >= ngsniffer->rand.nbytes) {
2303             /* No.  Search for a blob that contains the target offset in
2304                the uncompressed byte stream, starting with the blob
2305                following the current blob. */
2306             new = g_list_next(ngsniffer->current_blob);
2307             for (;;) {
2308                 next = g_list_next(new);
2309                 if (next == NULL) {
2310                     /* No more blobs; the current one is it. */
2311                     break;
2312                 }
2313
2314                 next_blob = next->data;
2315                 /* Does the next blob start after the target offset?
2316                    If so, the current blob is the one we want. */
2317                 if (next_blob->blob_uncomp_offset > offset)
2318                     break;
2319
2320                 new = next;
2321             }
2322         }
2323     } else if (delta < 0) {
2324         /* We're going backwards.
2325            Is the place to which we're seeking within the current buffer? */
2326         if (ngsniffer->rand.nextout + delta < 0) {
2327             /* No.  Search for a blob that contains the target offset in
2328                the uncompressed byte stream, starting with the blob
2329                preceding the current blob. */
2330             new = g_list_previous(ngsniffer->current_blob);
2331             for (;;) {
2332                 /* Does this blob start at or before the target offset?
2333                    If so, the current blob is the one we want. */
2334                 new_blob = new->data;
2335                 if (new_blob->blob_uncomp_offset <= offset)
2336                     break;
2337
2338                 /* It doesn't - skip to the previous blob. */
2339                 new = g_list_previous(new);
2340             }
2341         }
2342     }
2343
2344     if (new != NULL) {
2345         /* The place to which we're seeking isn't in the current buffer;
2346            move to a new blob. */
2347         new_blob = new->data;
2348
2349         /* Seek in the compressed file to the offset in the compressed file
2350            of the beginning of that blob. */
2351         if (file_seek(wth->random_fh, new_blob->blob_comp_offset, SEEK_SET, err) == -1)
2352             return -1;
2353
2354         /* Make the blob we found the current one. */
2355         ngsniffer->current_blob = new;
2356
2357         /* Now set the current offsets to the offsets of the beginning
2358            of the blob. */
2359         ngsniffer->rand.uncomp_offset = new_blob->blob_uncomp_offset;
2360         ngsniffer->rand.comp_offset = new_blob->blob_comp_offset;
2361
2362         /* Now fill the buffer. */
2363         if (read_blob(wth->random_fh, &ngsniffer->rand, err) < 0)
2364             return -1;
2365
2366         /* Set "delta" to the amount to move within this blob; it had
2367            better be >= 0, and < the amount of uncompressed data in
2368            the blob, as otherwise it'd mean we need to seek before
2369            the beginning or after the end of this blob. */
2370         delta = offset - ngsniffer->rand.uncomp_offset;
2371         g_assert(delta >= 0 && (unsigned long)delta < ngsniffer->rand.nbytes);
2372     }
2373
2374     /* OK, the place to which we're seeking is in the buffer; adjust
2375        "ngsniffer->rand.nextout" to point to the place to which
2376        we're seeking, and adjust "ngsniffer->rand.uncomp_offset" to be
2377        the destination offset. */
2378     ngsniffer->rand.nextout += delta;
2379     ngsniffer->rand.uncomp_offset += delta;
2380
2381     return offset;
2382 }