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