The Sniffer file formats include a file to identify raw cells; export
[obnox/wireshark/wip.git] / wiretap / ngsniffer.c
1 /* ngsniffer.c
2  *
3  * $Id: ngsniffer.c,v 1.104 2003/01/10 04:04:41 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, gint16 version,
357     gboolean *is_router);
358 static int process_rec_header2_v2(wtap *wth, unsigned char *buffer,
359     guint16 length, int *err);
360 static int process_rec_header2_v45(wtap *wth, unsigned char *buffer,
361     guint16 length, gboolean *is_router, int *err);
362 static gboolean ngsniffer_read(wtap *wth, int *err, long *data_offset);
363 static gboolean ngsniffer_seek_read(wtap *wth, long seek_off,
364     union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size,
365     int *err);
366 static int ngsniffer_read_rec_header(wtap *wth, gboolean is_random,
367     guint16 *typep, guint16 *lengthp, int *err);
368 static gboolean ngsniffer_read_frame2(wtap *wth, gboolean is_random,
369     struct frame2_rec *frame2, int *err);
370 static int set_pseudo_header_frame2(wtap *wth,
371     union wtap_pseudo_header *pseudo_header, struct frame2_rec *frame2);
372 static gboolean ngsniffer_read_frame4(wtap *wth, gboolean is_random,
373     struct frame4_rec *frame4, int *err);
374 static void set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
375     struct frame4_rec *frame4);
376 static gboolean ngsniffer_read_frame6(wtap *wth, gboolean is_random,
377     struct frame6_rec *frame6, int *err);
378 static void set_pseudo_header_frame6(union wtap_pseudo_header *pseudo_header,
379     struct frame6_rec *frame6);
380 static gboolean ngsniffer_read_rec_data(wtap *wth, gboolean is_random,
381     guchar *pd, int length, int *err);
382 static int infer_pkt_encap(const guint8 *pd, int len);
383 static int fix_pseudo_header(int encap, const guint8 *pd, int len,
384     union wtap_pseudo_header *pseudo_header);
385 static void ngsniffer_sequential_close(wtap *wth);
386 static void ngsniffer_close(wtap *wth);
387 static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
388         const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err);
389 static gboolean ngsniffer_dump_close(wtap_dumper *wdh, int *err);
390 static int SnifferDecompress( unsigned char * inbuf, size_t inlen,
391         unsigned char * outbuf, size_t outlen, int *err );
392 static int ng_file_read(void *buffer, size_t elementsize, size_t numelements,
393     wtap *wth, gboolean is_random, int *err);
394 static int read_blob(FILE_T infile, ngsniffer_comp_stream_t *comp_stream,
395     int *err);
396 static long ng_file_seek_seq(wtap *wth, long offset, int whence, int *err);
397 static long ng_file_seek_rand(wtap *wth, long offset, int whence, int *err);
398
399 int ngsniffer_open(wtap *wth, int *err)
400 {
401         int bytes_read;
402         char magic[sizeof ngsniffer_magic];
403         char record_type[2];
404         char record_length[4]; /* only the first 2 bytes are length,
405                                   the last 2 are "reserved" and are thrown away */
406         guint16 type, length;
407         struct vers_rec version;
408         guint16 maj_vers;
409         guint16 start_date;
410         guint16 start_time;
411         static const int sniffer_encap[] = {
412                 WTAP_ENCAP_TOKEN_RING,
413                 WTAP_ENCAP_ETHERNET,
414                 WTAP_ENCAP_ARCNET,
415                 WTAP_ENCAP_UNKNOWN,     /* StarLAN */
416                 WTAP_ENCAP_UNKNOWN,     /* PC Network broadband */
417                 WTAP_ENCAP_UNKNOWN,     /* LocalTalk */
418                 WTAP_ENCAP_UNKNOWN,     /* Znet */
419                 WTAP_ENCAP_PER_PACKET,  /* Internetwork analyzer (synchronous) */
420                 WTAP_ENCAP_PER_PACKET,  /* Internetwork analyzer (asynchronous) */
421                 WTAP_ENCAP_FDDI_BITSWAPPED,
422                 WTAP_ENCAP_ATM_PDUS
423         };
424         #define NUM_NGSNIFF_ENCAPS (sizeof sniffer_encap / sizeof sniffer_encap[0])
425         gboolean is_router;
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                 g_message("ngsniffer: Sniffer file doesn't start with a version record");
463                 *err = WTAP_ERR_BAD_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                 g_message("ngsniffer: network type %u unknown or unsupported",
481                     version.network);
482                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
483                 return -1;
484         }
485
486         /* Check the time unit */
487         if (version.timeunit >= NUM_NGSNIFF_TIMEUNITS) {
488                 g_message("ngsniffer: Unknown timeunit %u", version.timeunit);
489                 *err = WTAP_ERR_UNSUPPORTED;
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         maj_vers = pletohs(&version.maj_vers);
513         if (process_header_records(wth, err, maj_vers, &is_router) < 0)
514                 return -1;
515
516         /*
517          * Now, if we have a random stream open, position it to the same
518          * location, which should be the beginning of the real data, and
519          * should be the beginning of the compressed data.
520          *
521          * XXX - will we see any records other than REC_FRAME2, REC_FRAME4,
522          * or REC_EOF after this?  If not, we can get rid of the loop in
523          * "ngsniffer_read()".
524          */
525         if (wth->random_fh != NULL) {
526                 if (file_seek(wth->random_fh, wth->data_offset, SEEK_SET, err) == -1)
527                         return -1;
528         }
529
530         /* This is a ngsniffer file */
531         wth->capture.ngsniffer = g_malloc(sizeof(ngsniffer_t));
532         wth->capture.ngsniffer->maj_vers = maj_vers;
533         wth->capture.ngsniffer->min_vers = pletohs(&version.min_vers);
534
535         /* We haven't allocated any uncompression buffers yet. */
536         wth->capture.ngsniffer->seq.buf = NULL;
537         wth->capture.ngsniffer->rand.buf = NULL;
538
539         /* Set the current file offset; the offset in the compressed file
540            and in the uncompressed data stream currently the same. */
541         wth->capture.ngsniffer->seq.uncomp_offset = wth->data_offset;
542         wth->capture.ngsniffer->seq.comp_offset = wth->data_offset;
543         wth->capture.ngsniffer->rand.uncomp_offset = wth->data_offset;
544         wth->capture.ngsniffer->rand.comp_offset = wth->data_offset;
545
546         /* We don't yet have any list of compressed blobs. */
547         wth->capture.ngsniffer->first_blob = NULL;
548         wth->capture.ngsniffer->last_blob = NULL;
549         wth->capture.ngsniffer->current_blob = NULL;
550
551         wth->subtype_read = ngsniffer_read;
552         wth->subtype_seek_read = ngsniffer_seek_read;
553         wth->subtype_sequential_close = ngsniffer_sequential_close;
554         wth->subtype_close = ngsniffer_close;
555         wth->snapshot_length = 0;       /* not available in header, only in frame */
556         wth->capture.ngsniffer->timeunit = Usec[version.timeunit];
557         wth->capture.ngsniffer->is_atm =
558             (wth->file_encap == WTAP_ENCAP_ATM_PDUS);
559         wth->capture.ngsniffer->is_router = is_router;
560
561         /* Get capture start time */
562         start_time = pletohs(&version.time);
563         start_date = pletohs(&version.date);
564         tm.tm_year = ((start_date&0xfe00)>>9) + 1980 - 1900;
565         tm.tm_mon = ((start_date&0x1e0)>>5) - 1;
566         tm.tm_mday = (start_date&0x1f);
567         /* The time does not appear to act as an offset; only the date
568         tm.tm_hour = (start_time&0xf800)>>11;
569         tm.tm_min = (start_time&0x7e0)>>5;
570         tm.tm_sec = (start_time&0x1f)<<1;*/
571         tm.tm_hour = 0;
572         tm.tm_min = 0;
573         tm.tm_sec = 0;
574         tm.tm_isdst = -1;
575         wth->capture.ngsniffer->start = mktime(&tm);
576         /*
577          * XXX - what if "secs" is -1?  Unlikely,
578          * but if the capture was done in a time
579          * zone that switches between standard and
580          * summer time sometime other than when we
581          * do, and thus the time was one that doesn't
582          * exist here because a switch from standard
583          * to summer time zips over it, it could
584          * happen.
585          *
586          * On the other hand, if the capture was done
587          * in a different time zone, this won't work
588          * right anyway; unfortunately, the time zone
589          * isn't stored in the capture file.
590          */
591
592         return 1;
593 }
594
595 static int
596 process_header_records(wtap *wth, int *err, gint16 version, gboolean *is_router)
597 {
598         int bytes_read;
599         char record_type[2];
600         char record_length[4]; /* only the first 2 bytes are length,
601                                   the last 2 are "reserved" and are thrown away */
602         guint16 type, length;
603         int bytes_to_read;
604         unsigned char buffer[256];
605
606         *is_router = FALSE;
607         for (;;) {
608                 errno = WTAP_ERR_CANT_READ;
609                 bytes_read = file_read(record_type, 1, 2, wth->fh);
610                 if (bytes_read != 2) {
611                         *err = file_error(wth->fh);
612                         if (*err != 0)
613                                 return -1;
614                         if (bytes_read != 0) {
615                                 *err = WTAP_ERR_SHORT_READ;
616                                 return -1;
617                         }
618                         return 0;       /* EOF */
619                 }
620
621                 type = pletohs(record_type);
622                 if ((type != REC_HEADER1) && (type != REC_HEADER2)
623                         && (type != REC_HEADER3) && (type != REC_HEADER4)
624                         && (type != REC_HEADER5) && (type != REC_HEADER6)
625                         && (type != REC_HEADER7)
626                         && ((type != REC_V2DESC) || (version > 2)) ) {
627                         /*
628                          * Well, this is either some unknown header type
629                          * (we ignore this case), an uncompressed data
630                          * frame or the length of a compressed blob
631                          * which implies data. Seek backwards over the
632                          * two bytes we read, and return.
633                          */
634                         if (file_seek(wth->fh, -2, SEEK_CUR, err) == -1)
635                                 return -1;
636                         return 0;
637                 }
638
639                 errno = WTAP_ERR_CANT_READ;
640                 bytes_read = file_read(record_length, 1, 4, wth->fh);
641                 if (bytes_read != 4) {
642                         *err = file_error(wth->fh);
643                         if (*err == 0)
644                                 *err = WTAP_ERR_SHORT_READ;
645                         return -1;
646                 }
647                 wth->data_offset += 6;
648
649                 length = pletohs(record_length);
650
651                 /*
652                  * Do we not yet know the encapsulation type (i.e., is
653                  * this is an "Internetwork analyzer" capture?), and
654                  * is this a REC_HEADER2 record?
655                  *
656                  * If so, it appears to specify the particular type
657                  * of network we're on.
658                  */
659                 if (wth->file_encap == WTAP_ENCAP_PER_PACKET &&
660                     type == REC_HEADER2) {
661                         /*
662                          * Yes, get the first up-to-256 bytes of the
663                          * record data.
664                          */
665                         bytes_to_read = MIN(length, sizeof buffer);
666                         bytes_read = file_read(buffer, 1, bytes_to_read,
667                                 wth->fh);
668                         if (bytes_read != bytes_to_read) {
669                                 *err = file_error(wth->fh);
670                                 if (*err == 0) {
671                                         *err = WTAP_ERR_SHORT_READ;
672                                         return -1;
673                                 }
674                         }
675
676                         switch (version) {
677
678                         case 2:
679                                 if (process_rec_header2_v2(wth, buffer,
680                                     length, err) < 0)
681                                         return -1;
682                                 break;
683
684                         case 4:
685                         case 5:
686                                 if (process_rec_header2_v45(wth, buffer,
687                                     length, is_router, err) < 0)
688                                         return -1;
689                                 break;
690                         }
691
692                         /*
693                          * Skip the rest of the record.
694                          */
695                         if (length > sizeof buffer) {
696                                 if (file_seek(wth->fh, length - sizeof buffer,
697                                     SEEK_CUR, err) == -1)
698                                         return -1;
699                         }
700
701                 } else {
702                         /* Nope, just skip over the data. */
703                         if (file_seek(wth->fh, length, SEEK_CUR, err) == -1)
704                                 return -1;
705                 }
706                 wth->data_offset += length;
707         }
708 }
709
710 static int
711 process_rec_header2_v2(wtap *wth, unsigned char *buffer, guint16 length,
712     int *err)
713 {
714         static const char x_25_str[] = "HDLC\nX.25\n";
715
716         /*
717          * There appears to be a string in a REC_HEADER2 record, with
718          * a list of protocols.  In one X.25 capture I've seen, the
719          * string was "HDLC\nX.25\nCLNP\nISO_TP\nSESS\nPRES\nVTP\nACSE".
720          * Presumably CLNP and everything else is per-packet, but
721          * we assume "HDLC\nX.25\n" indicates that it's an X.25 capture.
722          */
723         if (length < sizeof x_25_str - 1) {
724                 /*
725                  * There's not enough data to compare.
726                  */
727                 g_message("ngsniffer: WAN capture has too-short protocol list");
728                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
729                 return -1;
730         }
731
732         if (strncmp(buffer, x_25_str, sizeof x_25_str - 1) == 0) {
733                 /*
734                  * X.25.
735                  */
736                 wth->file_encap = WTAP_ENCAP_LAPB;
737         } else {
738                 g_message("ngsniffer: WAN capture protocol string %.*s unknown",
739                     length, buffer);
740                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
741                 return -1;
742         }
743         return 0;
744 }
745
746 static int
747 process_rec_header2_v45(wtap *wth, unsigned char *buffer, guint16 length,
748     gboolean *is_router, int *err)
749 {
750         /*
751          * The 5th byte of the REC_HEADER2 record appears to be a
752          * network type.
753          */
754         if (length < 5) {
755                 /*
756                  * There is no 5th byte; give up.
757                  */
758                 g_message("ngsniffer: WAN capture has no network subtype");
759                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
760                 return -1;
761         }
762
763         /*
764          * The X.25 captures I've seen have a type of NET_HDLC, and the
765          * Sniffer documentation seems to imply that it's used for
766          * X.25, although it could be used for other purposes as well.
767          *
768          * NET_ROUTER is used for all sorts of point-to-point protocols,
769          * including ISDN.  It appears, from the documentation, that the
770          * Sniffer attempts to infer the particular protocol by looking
771          * at the traffic; it's not clear whether it stores in the file
772          * an indication of the protocol it inferred was being used.
773          *
774          * Unfortunately, it also appears that NET_HDLC is used for
775          * stuff other than X.25 as well, so we can't just interpret
776          * it unconditionally as X.25.
777          *
778          * For now, we interpret both NET_HDLC and NET_ROUTER as "per-packet
779          * encapsulation".  We remember that we saw NET_ROUTER, though,
780          * as it appears that we can infer whether a packet is PPP or
781          * ISDN based on the channel number subfield of the frame error
782          * status bits - if it's 0, it's PPP, otherwise it's ISDN and
783          * the channel number indicates which channel it is.  We assume
784          * NET_HDLC isn't used for ISDN.
785          */
786         switch (buffer[4]) {
787
788         case NET_SDLC:
789                 wth->file_encap = WTAP_ENCAP_SDLC;
790                 break;
791
792         case NET_HDLC:
793                 wth->file_encap = WTAP_ENCAP_PER_PACKET;
794                 break;
795
796         case NET_FRAME_RELAY:
797                 wth->file_encap = WTAP_ENCAP_FRELAY;
798                 break;
799
800         case NET_ROUTER:
801                 wth->file_encap = WTAP_ENCAP_PER_PACKET;
802                 *is_router = TRUE;
803                 break;
804
805         case NET_PPP:
806                 wth->file_encap = WTAP_ENCAP_PPP_WITH_PHDR;
807                 break;
808
809         default:
810                 /*
811                  * Reject these until we can figure them out.
812                  */
813                 g_message("ngsniffer: WAN network subtype %u unknown or unsupported",
814                     buffer[4]);
815                 *err = WTAP_ERR_UNSUPPORTED_ENCAP;
816                 return -1;
817         }
818         return 0;
819 }
820
821 /* Read the next packet */
822 static gboolean ngsniffer_read(wtap *wth, int *err, long *data_offset)
823 {
824         int     ret;
825         guint16 type, length;
826         struct frame2_rec frame2;
827         struct frame4_rec frame4;
828         struct frame6_rec frame6;
829         double  t;
830         guint16 time_low, time_med, time_high, true_size, size;
831         guchar  *pd;
832         int pkt_encap = wth->file_encap;
833
834         for (;;) {
835                 /*
836                  * Read the record header.
837                  */
838                 *data_offset = wth->data_offset;
839                 ret = ngsniffer_read_rec_header(wth, FALSE, &type, &length,
840                     err);
841                 if (ret <= 0) {
842                         /* Read error or EOF */
843                         return FALSE;
844                 }
845                 wth->data_offset += 6;
846
847                 switch (type) {
848
849                 case REC_FRAME2:
850                         if (wth->capture.ngsniffer->is_atm) {
851                                 /*
852                                  * We shouldn't get a frame2 record in
853                                  * an ATM capture.
854                                  */
855                                 g_message("ngsniffer: REC_FRAME2 record in an ATM Sniffer file");
856                                 *err = WTAP_ERR_BAD_RECORD;
857                                 return FALSE;
858                         }
859
860                         /* Read the f_frame2_struct */
861                         if (!ngsniffer_read_frame2(wth, FALSE, &frame2, err)) {
862                                 /* Read error */
863                                 return FALSE;
864                         }
865                         wth->data_offset += sizeof frame2;
866                         time_low = pletohs(&frame2.time_low);
867                         time_med = pletohs(&frame2.time_med);
868                         time_high = pletohs(&frame2.time_high);
869                         size = pletohs(&frame2.size);
870                         true_size = pletohs(&frame2.true_size);
871
872                         length -= sizeof frame2;        /* we already read that much */
873
874                         t = (double)time_low+(double)(time_med)*65536.0 +
875                             (double)time_high*4294967296.0;
876
877                         pkt_encap = set_pseudo_header_frame2(wth,
878                             &wth->pseudo_header, &frame2);
879                         goto found;
880
881                 case REC_FRAME4:
882                         if (!wth->capture.ngsniffer->is_atm) {
883                                 /*
884                                  * We shouldn't get a frame2 record in
885                                  * a non-ATM capture.
886                                  */
887                                 g_message("ngsniffer: REC_FRAME4 record in a non-ATM Sniffer file");
888                                 *err = WTAP_ERR_BAD_RECORD;
889                                 return FALSE;
890                         }
891
892                         /* Read the f_frame4_struct */
893                         if (!ngsniffer_read_frame4(wth, FALSE, &frame4, err)) {
894                                 /* Read error */
895                                 return FALSE;
896                         }
897                         wth->data_offset += sizeof frame4;
898                         time_low = pletohs(&frame4.time_low);
899                         time_med = pletohs(&frame4.time_med);
900                         time_high = frame4.time_high;
901                         size = pletohs(&frame4.size);
902                         true_size = pletohs(&frame4.true_size);
903
904                         /*
905                          * XXX - it looks as if version 4 captures have
906                          * a bogus record length, based on the assumption
907                          * that the record is a frame2 record.
908                          */
909                         if (wth->capture.ngsniffer->maj_vers >= 5)
910                                 length -= sizeof frame4;        /* we already read that much */
911                         else {
912                                 if (wth->capture.ngsniffer->min_vers >= 95)
913                                         length -= sizeof frame2;
914                                 else
915                                         length -= sizeof frame4;
916                         }
917
918                         /*
919                          * XXX - use the "time_day" field?  Is that for captures
920                          * that take a *really* long time?
921                          */
922                         t = (double)time_low+(double)(time_med)*65536.0 +
923                             (double)time_high*4294967296.0;
924
925                         set_pseudo_header_frame4(&wth->pseudo_header, &frame4);
926                         goto found;
927
928                 case REC_FRAME6:
929                         /* Read the f_frame6_struct */
930                         if (!ngsniffer_read_frame6(wth, FALSE, &frame6, err)) {
931                                 /* Read error */
932                                 return FALSE;
933                         }
934                         wth->data_offset += sizeof frame6;
935                         time_low = pletohs(&frame6.time_low);
936                         time_med = pletohs(&frame6.time_med);
937                         time_high = frame6.time_high;
938                         size = pletohs(&frame6.size);
939                         true_size = pletohs(&frame6.true_size);
940
941                         length -= sizeof frame6;        /* we already read that much */
942
943                         /*
944                          * XXX - use the "time_day" field?  Is that for captures
945                          * that take a *really* long time?
946                          */
947                         t = (double)time_low+(double)(time_med)*65536.0 +
948                             (double)time_high*4294967296.0;
949
950                         set_pseudo_header_frame6(&wth->pseudo_header, &frame6);
951                         goto found;
952
953                 case REC_EOF:
954                         /*
955                          * End of file.  Return an EOF indication.
956                          */
957                         *err = 0;       /* EOF, not error */
958                         return FALSE;
959
960                 default:
961                         break;  /* unknown type, skip it */
962                 }
963
964                 /*
965                  * Well, we don't know what it is, or we know what
966                  * it is but can't handle it.  Skip past the data
967                  * portion, and keep looping.
968                  */
969                 if (ng_file_seek_seq(wth, length, SEEK_CUR, err) == -1)
970                         return FALSE;
971                 wth->data_offset += length;
972         }
973
974 found:
975         /*
976          * OK, is the frame data size greater than than what's left of the
977          * record?
978          */
979         if (size > length) {
980                 /*
981                  * Yes - treat this as an error.
982                  */
983                 g_message("ngsniffer: Record length is less than packet size");
984                 *err = WTAP_ERR_BAD_RECORD;
985                 return FALSE;
986         }
987
988         wth->phdr.len = true_size ? true_size : size;
989         wth->phdr.caplen = size;
990
991         /*
992          * Read the packet data.
993          */
994         buffer_assure_space(wth->frame_buffer, length);
995         pd = buffer_start_ptr(wth->frame_buffer);
996         if (!ngsniffer_read_rec_data(wth, FALSE, pd, length, err))
997                 return FALSE;   /* Read error */
998         wth->data_offset += length;
999
1000         pkt_encap = fix_pseudo_header(pkt_encap, pd, length,
1001             &wth->pseudo_header);
1002         wth->phdr.pkt_encap = pkt_encap;
1003
1004         t = t/1000000.0 * wth->capture.ngsniffer->timeunit; /* t = # of secs */
1005         t += wth->capture.ngsniffer->start;
1006         wth->phdr.ts.tv_sec = (long)t;
1007         wth->phdr.ts.tv_usec = (unsigned long)((t-(double)(wth->phdr.ts.tv_sec))
1008                         *1.0e6);
1009         return TRUE;
1010 }
1011
1012 static gboolean ngsniffer_seek_read(wtap *wth, long seek_off,
1013     union wtap_pseudo_header *pseudo_header, guchar *pd, int packet_size,
1014     int *err)
1015 {
1016         int     ret;
1017         guint16 type, length;
1018         struct frame2_rec frame2;
1019         struct frame4_rec frame4;
1020         struct frame6_rec frame6;
1021         int     pkt_encap = wth->file_encap;
1022
1023         if (ng_file_seek_rand(wth, seek_off, SEEK_SET, err) == -1)
1024                 return FALSE;
1025
1026         ret = ngsniffer_read_rec_header(wth, TRUE, &type, &length, err);
1027         if (ret <= 0) {
1028                 /* Read error or EOF */
1029                 if (ret == 0) {
1030                         /* EOF means "short read" in random-access mode */
1031                         *err = WTAP_ERR_SHORT_READ;
1032                 }
1033                 return FALSE;
1034         }
1035
1036         switch (type) {
1037
1038         case REC_FRAME2:
1039                 /* Read the f_frame2_struct */
1040                 if (!ngsniffer_read_frame2(wth, TRUE, &frame2, err)) {
1041                         /* Read error */
1042                         return FALSE;
1043                 }
1044
1045                 length -= sizeof frame2;        /* we already read that much */
1046
1047                 pkt_encap = set_pseudo_header_frame2(wth, pseudo_header,
1048                     &frame2);
1049                 break;
1050
1051         case REC_FRAME4:
1052                 /* Read the f_frame4_struct */
1053                 if (!ngsniffer_read_frame4(wth, TRUE, &frame4, err)) {
1054                         /* Read error */
1055                         return FALSE;
1056                 }
1057
1058                 length -= sizeof frame4;        /* we already read that much */
1059
1060                 set_pseudo_header_frame4(pseudo_header, &frame4);
1061                 break;
1062
1063         case REC_FRAME6:
1064                 /* Read the f_frame6_struct */
1065                 if (!ngsniffer_read_frame6(wth, TRUE, &frame6, err)) {
1066                         /* Read error */
1067                         return FALSE;
1068                 }
1069
1070                 length -= sizeof frame6;        /* we already read that much */
1071
1072                 set_pseudo_header_frame6(pseudo_header, &frame6);
1073                 break;
1074
1075         default:
1076                 /*
1077                  * "Can't happen".
1078                  */
1079                 g_assert_not_reached();
1080                 return FALSE;
1081         }
1082
1083         /*
1084          * Got the pseudo-header (if any), now get the data.
1085          */
1086         if (!ngsniffer_read_rec_data(wth, TRUE, pd, packet_size, err))
1087                 return FALSE;
1088
1089         fix_pseudo_header(pkt_encap, pd, packet_size, pseudo_header);
1090
1091         return TRUE;
1092 }
1093
1094 static int ngsniffer_read_rec_header(wtap *wth, gboolean is_random,
1095     guint16 *typep, guint16 *lengthp, int *err)
1096 {
1097         int     bytes_read;
1098         char    record_type[2];
1099         char    record_length[4]; /* only 1st 2 bytes are length */
1100
1101         /*
1102          * Read the record header.
1103          */
1104         bytes_read = ng_file_read(record_type, 1, 2, wth, is_random, err);
1105         if (bytes_read != 2) {
1106                 if (*err != 0)
1107                         return -1;
1108                 if (bytes_read != 0) {
1109                         *err = WTAP_ERR_SHORT_READ;
1110                         return -1;
1111                 }
1112                 return 0;
1113         }
1114         bytes_read = ng_file_read(record_length, 1, 4, wth, is_random, err);
1115         if (bytes_read != 4) {
1116                 if (*err == 0)
1117                         *err = WTAP_ERR_SHORT_READ;
1118                 return -1;
1119         }
1120
1121         *typep = pletohs(record_type);
1122         *lengthp = pletohs(record_length);
1123         return 1;       /* success */
1124 }
1125
1126 static gboolean ngsniffer_read_frame2(wtap *wth, gboolean is_random,
1127     struct frame2_rec *frame2, int *err)
1128 {
1129         int bytes_read;
1130
1131         /* Read the f_frame2_struct */
1132         bytes_read = ng_file_read(frame2, 1, sizeof *frame2, wth, is_random,
1133             err);
1134         if (bytes_read != sizeof *frame2) {
1135                 if (*err == 0)
1136                         *err = WTAP_ERR_SHORT_READ;
1137                 return FALSE;
1138         }
1139         return TRUE;
1140 }
1141
1142 static int set_pseudo_header_frame2(wtap *wth,
1143     union wtap_pseudo_header *pseudo_header, struct frame2_rec *frame2)
1144 {
1145         int pkt_encap;
1146
1147         /*
1148          * In one PPP "Internetwork analyzer" capture:
1149          *
1150          *      The only bit seen in "frame2.fs" is the 0x80 bit, which
1151          *      probably indicates the packet's direction; all other
1152          *      bits were zero.  The Expert Sniffer Network Analyzer
1153          *      5.50 Operations manual says that bit is the FS_DTE bit
1154          *      for async/PPP data.  The other bits are error bits
1155          *      plus bits indicating whether the frame is PPP or SLIP,
1156          *      but the PPP bit isn't set.
1157          *
1158          *      All bits in "frame2.flags" were zero.
1159          *
1160          * In one X.25 "Internetwork analyzer" capture:
1161          *
1162          *      The only bit seen in "frame2.fs" is the 0x80 bit, which
1163          *      probably indicates the packet's direction; all other
1164          *      bits were zero.
1165          *
1166          *      "frame2.flags" was always 0x18; however, the Sniffer
1167          *      manual says that just means that a display filter was
1168          *      calculated for the frame, and it should be displayed,
1169          *      so perhaps that's just a quirk of that particular capture.
1170          *
1171          * In one Ethernet capture:
1172          *
1173          *      "frame2.fs" was always 0; the Sniffer manual says they're
1174          *      error bits of various sorts.
1175          *
1176          *      "frame2.flags" was either 0 or 0x18, with no obvious
1177          *      correlation with anything.  See previous comment
1178          *      about display filters.
1179          *
1180          * In one Token Ring capture:
1181          *
1182          *      "frame2.fs" was either 0 or 0xcc; the Sniffer manual says
1183          *      nothing about those bits for Token Ring captures.
1184          *
1185          *      "frame2.flags" was either 0 or 0x18, with no obvious
1186          *      correlation with anything.  See previous comment
1187          *      about display filters.
1188          *
1189          * In some NET_ROUTER captures, the 0x18 bits in "frame2.fs" are
1190          * 0 for frames in a non-ISDN capture and non-zero for frames in
1191          * an ISDN capture, specifying the channel number in the fashion
1192          * described in the Sniffer manual, so we use that to distinguish
1193          * between ISDN frames and non-ISDN frames.
1194          */
1195         if (wth->file_encap == WTAP_ENCAP_PER_PACKET &&
1196             wth->capture.ngsniffer->is_router &&
1197             (frame2->fs & 0x18) != 0)
1198                 pkt_encap = WTAP_ENCAP_ISDN;
1199         else
1200                 pkt_encap = wth->file_encap;
1201
1202         switch (pkt_encap) {
1203
1204         case WTAP_ENCAP_PPP_WITH_PHDR:
1205                 pseudo_header->p2p.sent = (frame2->fs & 0x80) ? TRUE : FALSE;
1206                 break;
1207
1208         case WTAP_ENCAP_LAPB:
1209         case WTAP_ENCAP_FRELAY:
1210         case WTAP_ENCAP_PER_PACKET:
1211                 pseudo_header->x25.flags = (frame2->fs & 0x80) ? 0x00 : FROM_DCE;
1212                 break;
1213
1214         case WTAP_ENCAP_ISDN:
1215                 pseudo_header->isdn.uton = (frame2->fs & 0x80) ? FALSE : TRUE;
1216                 switch (frame2->fs & 0x18) {
1217
1218                 case 0x18:
1219                         pseudo_header->isdn.channel = 0;        /* D-channel */
1220                         break;
1221
1222                 case 0x08:
1223                         pseudo_header->isdn.channel = 1;        /* B1-channel */
1224                         break;
1225
1226                 case 0x10:
1227                         pseudo_header->isdn.channel = 2;        /* B1-channel */
1228                         break;
1229
1230                 default:
1231                         pseudo_header->isdn.channel = 30;       /* XXX */
1232                         break;
1233                 }
1234         }
1235         return pkt_encap;
1236 }
1237
1238 static gboolean ngsniffer_read_frame4(wtap *wth, gboolean is_random,
1239     struct frame4_rec *frame4, int *err)
1240 {
1241         int bytes_read;
1242
1243         /* Read the f_frame4_struct */
1244         bytes_read = ng_file_read(frame4, 1, sizeof *frame4, wth, is_random,
1245             err);
1246         if (bytes_read != sizeof *frame4) {
1247                 if (*err == 0)
1248                         *err = WTAP_ERR_SHORT_READ;
1249                 return FALSE;
1250         }
1251         return TRUE;
1252 }
1253
1254 static void set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
1255     struct frame4_rec *frame4)
1256 {
1257         guint32 StatusWord;
1258         guint8 aal_type, hl_type;
1259         guint16 vpi, vci;
1260
1261         /*
1262          * Map flags from frame4.atm_info.StatusWord.
1263          */
1264         pseudo_header->atm.flags = 0;
1265         StatusWord = pletohl(&frame4->atm_info.StatusWord);
1266         if (StatusWord & SW_RAW_CELL)
1267                 pseudo_header->atm.flags |= ATM_RAW_CELL;
1268
1269         aal_type = frame4->atm_info.AppTrafType & ATT_AALTYPE;
1270         hl_type = frame4->atm_info.AppTrafType & ATT_HLTYPE;
1271         vpi = pletohs(&frame4->atm_info.Vpi);
1272         vci = pletohs(&frame4->atm_info.Vci);
1273
1274         switch (aal_type) {
1275
1276         case ATT_AAL_UNKNOWN:
1277                 /*
1278                  * Map ATT_AAL_UNKNOWN on VPI 0, VCI 5 to ATT_AAL_SIGNALLING,
1279                  * as that's the VPCI used for signalling.
1280                  *
1281                  * XXX - is this necessary, or will frames to 0/5 always
1282                  * have ATT_AAL_SIGNALLING?
1283                  */
1284                 if (vpi == 0 && vci == 5)
1285                         pseudo_header->atm.aal = AAL_SIGNALLING;
1286                 else
1287                         pseudo_header->atm.aal = AAL_UNKNOWN;
1288                 pseudo_header->atm.type = TRAF_UNKNOWN;
1289                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1290                 break;
1291
1292         case ATT_AAL1:
1293                 pseudo_header->atm.aal = AAL_1;
1294                 pseudo_header->atm.type = TRAF_UNKNOWN;
1295                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1296                 break;
1297
1298         case ATT_AAL3_4:
1299                 pseudo_header->atm.aal = AAL_3_4;
1300                 pseudo_header->atm.type = TRAF_UNKNOWN;
1301                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1302                 break;
1303
1304         case ATT_AAL5:
1305                 pseudo_header->atm.aal = AAL_5;
1306                 switch (hl_type) {
1307
1308                 case ATT_HL_UNKNOWN:
1309                         pseudo_header->atm.type = TRAF_UNKNOWN;
1310                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1311                         break;
1312
1313                 case ATT_HL_LLCMX:
1314                         pseudo_header->atm.type = TRAF_LLCMX;
1315                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1316                         break;
1317
1318                 case ATT_HL_VCMX:
1319                         pseudo_header->atm.type = TRAF_VCMX;
1320                         switch (frame4->atm_info.AppHLType) {
1321
1322                         case AHLT_UNKNOWN:
1323                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1324                                 break;
1325
1326                         case AHLT_VCMX_802_3_FCS:
1327                                 pseudo_header->atm.subtype =
1328                                     TRAF_ST_VCMX_802_3_FCS;
1329                                 break;
1330
1331                         case AHLT_VCMX_802_4_FCS:
1332                                 pseudo_header->atm.subtype =
1333                                     TRAF_ST_VCMX_802_4_FCS;
1334                                 break;
1335
1336                         case AHLT_VCMX_802_5_FCS:
1337                                 pseudo_header->atm.subtype =
1338                                     TRAF_ST_VCMX_802_5_FCS;
1339                                 break;
1340
1341                         case AHLT_VCMX_FDDI_FCS:
1342                                 pseudo_header->atm.subtype =
1343                                     TRAF_ST_VCMX_FDDI_FCS;
1344                                 break;
1345
1346                         case AHLT_VCMX_802_6_FCS:
1347                                 pseudo_header->atm.subtype =
1348                                     TRAF_ST_VCMX_802_6_FCS;
1349                                 break;
1350
1351                         case AHLT_VCMX_802_3:
1352                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_3;
1353                                 break;
1354
1355                         case AHLT_VCMX_802_4:
1356                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_4;
1357                                 break;
1358
1359                         case AHLT_VCMX_802_5:
1360                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_5;
1361                                 break;
1362
1363                         case AHLT_VCMX_FDDI:
1364                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_FDDI;
1365                                 break;
1366
1367                         case AHLT_VCMX_802_6:
1368                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_6;
1369                                 break;
1370
1371                         case AHLT_VCMX_FRAGMENTS:
1372                                 pseudo_header->atm.subtype =
1373                                     TRAF_ST_VCMX_FRAGMENTS;
1374                                 break;
1375
1376                         case AHLT_VCMX_BPDU:
1377                                 pseudo_header->atm.subtype = TRAF_ST_VCMX_BPDU;
1378                                 break;
1379
1380                         default:
1381                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1382                                 break;
1383                         }
1384                         break;
1385
1386                 case ATT_HL_LANE:
1387                         pseudo_header->atm.type = TRAF_LANE;
1388                         switch (frame4->atm_info.AppHLType) {
1389
1390                         case AHLT_UNKNOWN:
1391                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1392                                 break;
1393
1394                         case AHLT_LANE_LE_CTRL:
1395                                 pseudo_header->atm.subtype =
1396                                     TRAF_ST_LANE_LE_CTRL;
1397                                 break;
1398
1399                         case AHLT_LANE_802_3:
1400                                 pseudo_header->atm.subtype = TRAF_ST_LANE_802_3;
1401                                 break;
1402
1403                         case AHLT_LANE_802_5:
1404                                 pseudo_header->atm.subtype = TRAF_ST_LANE_802_5;
1405                                 break;
1406
1407                         case AHLT_LANE_802_3_MC:
1408                                 pseudo_header->atm.subtype =
1409                                     TRAF_ST_LANE_802_3_MC;
1410                                 break;
1411
1412                         case AHLT_LANE_802_5_MC:
1413                                 pseudo_header->atm.subtype =
1414                                     TRAF_ST_LANE_802_5_MC;
1415                                 break;
1416
1417                         default:
1418                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1419                                 break;
1420                         }
1421                         break;
1422
1423                 case ATT_HL_ILMI:
1424                         pseudo_header->atm.type = TRAF_ILMI;
1425                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1426                         break;
1427
1428                 case ATT_HL_FRMR:
1429                         pseudo_header->atm.type = TRAF_FR;
1430                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1431                         break;
1432
1433                 case ATT_HL_SPANS:
1434                         pseudo_header->atm.type = TRAF_SPANS;
1435                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1436                         break;
1437
1438                 case ATT_HL_IPSILON:
1439                         pseudo_header->atm.type = TRAF_IPSILON;
1440                         switch (frame4->atm_info.AppHLType) {
1441
1442                         case AHLT_UNKNOWN:
1443                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1444                                 break;
1445
1446                         case AHLT_IPSILON_FT0:
1447                                 pseudo_header->atm.subtype =
1448                                     TRAF_ST_IPSILON_FT0;
1449                                 break;
1450
1451                         case AHLT_IPSILON_FT1:
1452                                 pseudo_header->atm.subtype =
1453                                     TRAF_ST_IPSILON_FT1;
1454                                 break;
1455
1456                         case AHLT_IPSILON_FT2:
1457                                 pseudo_header->atm.subtype =
1458                                     TRAF_ST_IPSILON_FT2;
1459                                 break;
1460
1461                         default:
1462                                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1463                                 break;
1464                         }
1465                         break;
1466
1467                 default:
1468                         pseudo_header->atm.type = TRAF_UNKNOWN;
1469                         pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1470                         break;
1471                 }
1472                 break;
1473
1474         case ATT_AAL_USER:
1475                 pseudo_header->atm.aal = AAL_USER;
1476                 pseudo_header->atm.type = TRAF_UNKNOWN;
1477                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1478                 break;
1479
1480         case ATT_AAL_SIGNALLING:
1481                 pseudo_header->atm.aal = AAL_SIGNALLING;
1482                 pseudo_header->atm.type = TRAF_UNKNOWN;
1483                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1484                 break;
1485
1486         case ATT_OAMCELL:
1487                 pseudo_header->atm.aal = AAL_OAMCELL;
1488                 pseudo_header->atm.type = TRAF_UNKNOWN;
1489                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1490                 break;
1491
1492         default:
1493                 pseudo_header->atm.aal = AAL_UNKNOWN;
1494                 pseudo_header->atm.type = TRAF_UNKNOWN;
1495                 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1496                 break;
1497         }
1498         pseudo_header->atm.vpi = vpi;
1499         pseudo_header->atm.vci = vci;
1500         pseudo_header->atm.channel = pletohs(&frame4->atm_info.channel);
1501         pseudo_header->atm.cells = pletohs(&frame4->atm_info.cells);
1502         pseudo_header->atm.aal5t_u2u = pletohs(&frame4->atm_info.Trailer.aal5t_u2u);
1503         pseudo_header->atm.aal5t_len = pletohs(&frame4->atm_info.Trailer.aal5t_len);
1504         pseudo_header->atm.aal5t_chksum = pntohl(&frame4->atm_info.Trailer.aal5t_chksum);
1505 }
1506
1507 static gboolean ngsniffer_read_frame6(wtap *wth, gboolean is_random,
1508     struct frame6_rec *frame6, int *err)
1509 {
1510         int bytes_read;
1511
1512         /* Read the f_frame6_struct */
1513         bytes_read = ng_file_read(frame6, 1, sizeof *frame6, wth, is_random,
1514             err);
1515         if (bytes_read != sizeof *frame6) {
1516                 if (*err == 0)
1517                         *err = WTAP_ERR_SHORT_READ;
1518                 return FALSE;
1519         }
1520         return TRUE;
1521 }
1522
1523 static void set_pseudo_header_frame6(
1524         union wtap_pseudo_header *pseudo_header _U_,
1525         struct frame6_rec *frame6 _U_)
1526 {
1527         /* XXX - Once the frame format is divined, something will most likely go here */
1528 }
1529
1530 static gboolean ngsniffer_read_rec_data(wtap *wth, gboolean is_random,
1531     guchar *pd, int length, int *err)
1532 {
1533         int     bytes_read;
1534
1535         bytes_read = ng_file_read(pd, 1, length, wth, is_random, err);
1536
1537         if (bytes_read != length) {
1538                 if (*err == 0)
1539                         *err = WTAP_ERR_SHORT_READ;
1540                 return FALSE;
1541         }
1542         return TRUE;
1543 }
1544
1545 /*
1546  * OK, this capture is from an "Internetwork analyzer", and we either
1547  * didn't see a type 7 record or it had a network type such as NET_HDLC
1548  * that doesn't tell us which *particular* HDLC derivative this is;
1549  * let's look at the first few bytes of the packet, a pointer to which
1550  * was passed to us as an argument, and see whether it looks like PPP,
1551  * Frame Relay, Wellfleet HDLC, Cisco HDLC, or LAPB - or, if it's none
1552  * of those, assume it's LAPD.
1553  *
1554  * (XXX - are there any "Internetwork analyzer" captures that don't
1555  * have type 7 records?  If so, is there some other field that will
1556  * tell us what type of capture it is?)
1557  */
1558 static int infer_pkt_encap(const guint8 *pd, int len)
1559 {
1560         if (len <= 0) {
1561                 /*
1562                  * Nothing to infer, but it doesn't matter how you
1563                  * dissect an empty packet.  Let's just say PPP.
1564                  */
1565                 return WTAP_ENCAP_PPP_WITH_PHDR;
1566         }
1567
1568         switch (pd[0]) {
1569
1570         case 0xFF:
1571                 /*
1572                  * PPP.  (XXX - check for 0xFF 0x03?)
1573                  */
1574                 return WTAP_ENCAP_PPP_WITH_PHDR;
1575
1576         case 0x34:
1577         case 0x28:
1578                 /*
1579                  * Frame Relay.
1580                  *
1581                  * XXX - in version 4 and 5 captures, wouldn't this just
1582                  * have a capture subtype of NET_FRAME_RELAY?  Or is this
1583                  * here only to handle other versions of the capture
1584                  * file, where we might just not yet have found where
1585                  * the subtype is specified in the capture?
1586                  */
1587                 return WTAP_ENCAP_FRELAY;
1588         }
1589
1590         if (len >= 2) {
1591                 if (pd[0] == 0x07 && pd[1] == 0x03) {
1592                         /*
1593                          * Wellfleet HDLC.
1594                          */
1595                         return WTAP_ENCAP_WFLEET_HDLC;
1596                 } else if ((pd[0] == 0x0F && pd[1] == 0x00) ||
1597                            (pd[0] == 0x8F && pd[1] == 0x00)) {
1598                         /*
1599                          * Cisco HDLC.
1600                          */
1601                         return WTAP_ENCAP_CHDLC;
1602                 }
1603         }
1604
1605         if (pd[0] & 1) {
1606                 /*
1607                  * LAPB.
1608                  */
1609                 return WTAP_ENCAP_LAPB;
1610         } else {
1611                 /*
1612                  * LAPD.
1613                  * We report it as WTAP_ENCAP_ISDN.
1614                  *
1615                  * XXX - is there something buried in the header to tell us
1616                  * whether the capture was taken with an ISDN pod?
1617                  *
1618                  * Or is this here just because some ISDN captures run
1619                  * LAPB/X.25 over the B channel(s), so we check for
1620                  * LAPB even in NET_ROUTER captures?  If so, we should
1621                  * perhaps move that heuristic up to the ISDN dissector,
1622                  * so that we can infer LAPB traffic in *all* ISDN
1623                  * captures, not just DOS Sniffer ISDN captures?
1624                  */
1625                 return WTAP_ENCAP_ISDN;
1626         }
1627 }
1628
1629 static int fix_pseudo_header(int encap, const guint8 *pd, int len,
1630     union wtap_pseudo_header *pseudo_header)
1631 {
1632         switch (encap) {
1633
1634         case WTAP_ENCAP_PER_PACKET:
1635                 /*
1636                  * Infer the packet type from the first two bytes.
1637                  */
1638                 encap = infer_pkt_encap(pd, len);
1639
1640                 /*
1641                  * Fix up the pseudo-header to match the new
1642                  * encapsulation type.
1643                  */
1644                 switch (encap) {
1645
1646                 case WTAP_ENCAP_WFLEET_HDLC:
1647                 case WTAP_ENCAP_CHDLC:
1648                 case WTAP_ENCAP_PPP_WITH_PHDR:
1649                         if (pseudo_header->x25.flags == 0)
1650                                 pseudo_header->p2p.sent = TRUE;
1651                         else
1652                                 pseudo_header->p2p.sent = FALSE;
1653                         break;
1654
1655                 case WTAP_ENCAP_ISDN:
1656                         if (pseudo_header->x25.flags == 0x00)
1657                                 pseudo_header->isdn.uton = FALSE;
1658                         else
1659                                 pseudo_header->isdn.uton = TRUE;
1660
1661                         /*
1662                          * XXX - this is currently a per-packet
1663                          * encapsulation type, and we can't determine
1664                          * whether a capture is an ISDN capture before
1665                          * seeing any packets, and B-channel PPP packets
1666                          * look like PPP packets and are given
1667                          * WTAP_ENCAP_PPP_WITH_PHDR, not WTAP_ENCAP_ISDN,
1668                          * so we assume this is a D-channel packet and
1669                          * thus give it a channel number of 0.
1670                          */
1671                         pseudo_header->isdn.channel = 0;
1672                         break;
1673                 }
1674                 break;
1675
1676         case WTAP_ENCAP_ATM_PDUS:
1677                 /*
1678                  * If the Windows Sniffer writes out one of its ATM
1679                  * capture files in DOS Sniffer format, it doesn't
1680                  * distinguish between LE Control and LANE encapsulated
1681                  * LAN frames, so we fix that up here.
1682                  */
1683                 if (pseudo_header->atm.type == TRAF_LANE && len >= 2 &&
1684                     pd[0] == 0xff && pd[1] == 0x00)
1685                         pseudo_header->atm.subtype = TRAF_ST_LANE_LE_CTRL;
1686                 break;
1687         }
1688         return encap;
1689 }
1690
1691 /* Throw away the buffers used by the sequential I/O stream, but not
1692    those used by the random I/O stream. */
1693 static void ngsniffer_sequential_close(wtap *wth)
1694 {
1695         if (wth->capture.ngsniffer->seq.buf != NULL) {
1696                 g_free(wth->capture.ngsniffer->seq.buf);
1697                 wth->capture.ngsniffer->seq.buf = NULL;
1698         }
1699 }
1700
1701 static void free_blob(gpointer data, gpointer user_data _U_)
1702 {
1703         g_free(data);
1704 }
1705
1706 /* Close stuff used by the random I/O stream, if any, and free up any
1707    private data structures.  (If there's a "sequential_close" routine
1708    for a capture file type, it'll be called before the "close" routine
1709    is called, so we don't have to free the sequential buffer here.) */
1710 static void ngsniffer_close(wtap *wth)
1711 {
1712         if (wth->capture.ngsniffer->rand.buf != NULL)
1713                 g_free(wth->capture.ngsniffer->rand.buf);
1714         if (wth->capture.ngsniffer->first_blob != NULL) {
1715                 g_list_foreach(wth->capture.ngsniffer->first_blob, free_blob, NULL);
1716                 g_list_free(wth->capture.ngsniffer->first_blob);
1717         }
1718         g_free(wth->capture.ngsniffer);
1719 }
1720
1721 static const int wtap_encap[] = {
1722     -1,         /* WTAP_ENCAP_UNKNOWN -> unsupported */
1723     1,          /* WTAP_ENCAP_ETHERNET */
1724     0,          /* WTAP_ENCAP_TOKEN_RING */
1725     -1,         /* WTAP_ENCAP_SLIP -> unsupported */
1726     7,          /* WTAP_ENCAP_PPP -> Internetwork analyzer (synchronous) FIXME ! */
1727     9,          /* WTAP_ENCAP_FDDI */
1728     9,          /* WTAP_ENCAP_FDDI_BITSWAPPED */
1729     -1,         /* WTAP_ENCAP_RAW_IP -> unsupported */
1730     2,          /* WTAP_ENCAP_ARCNET */
1731     -1,         /* WTAP_ENCAP_ATM_RFC1483 */
1732     -1,         /* WTAP_ENCAP_LINUX_ATM_CLIP */
1733     7,          /* WTAP_ENCAP_LAPB -> Internetwork analyzer (synchronous) */
1734     -1,         /* WTAP_ENCAP_ATM_PDUS */
1735     -1,         /* WTAP_ENCAP_NULL -> unsupported */
1736     -1,         /* WTAP_ENCAP_ASCEND -> unsupported */
1737     -1,         /* WTAP_ENCAP_ISDN -> unsupported */
1738     -1,         /* WTAP_ENCAP_IP_OVER_FC -> unsupported */
1739     7,          /* WTAP_ENCAP_PPP_WITH_PHDR -> Internetwork analyzer (synchronous) FIXME ! */
1740 };
1741 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
1742
1743 /* Returns 0 if we could write the specified encapsulation type,
1744    an error indication otherwise. */
1745 int ngsniffer_dump_can_write_encap(int encap)
1746 {
1747     /* Per-packet encapsulations aren't supported. */
1748     if (encap == WTAP_ENCAP_PER_PACKET)
1749         return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
1750
1751     if (encap < 0 || (unsigned)encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
1752         return WTAP_ERR_UNSUPPORTED_ENCAP;
1753
1754     return 0;
1755 }
1756
1757 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
1758    failure */
1759 gboolean ngsniffer_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err)
1760 {
1761     size_t nwritten;
1762     char buf[6] = {REC_VERS, 0x00, 0x12, 0x00, 0x00, 0x00}; /* version record */
1763
1764     /* This is a sniffer file */
1765     wdh->subtype_write = ngsniffer_dump;
1766     wdh->subtype_close = ngsniffer_dump_close;
1767
1768     wdh->dump.ngsniffer = g_malloc(sizeof(ngsniffer_dump_t));
1769     wdh->dump.ngsniffer->first_frame = TRUE;
1770     wdh->dump.ngsniffer->start = 0;
1771
1772     /* Write the file header. */
1773     nwritten = fwrite(ngsniffer_magic, 1, sizeof ngsniffer_magic, wdh->fh);
1774     if (nwritten != sizeof ngsniffer_magic) {
1775         if (nwritten == 0 && ferror(wdh->fh))
1776             *err = errno;
1777         else
1778             *err = WTAP_ERR_SHORT_WRITE;
1779         return FALSE;
1780     }
1781     nwritten = fwrite(buf, 1, 6, wdh->fh);
1782     if (nwritten != 6) {
1783         if (nwritten == 0 && ferror(wdh->fh))
1784             *err = errno;
1785         else
1786             *err = WTAP_ERR_SHORT_WRITE;
1787         return FALSE;
1788     }
1789
1790     return TRUE;
1791 }
1792
1793 /* Write a record for a packet to a dump file.
1794    Returns TRUE on success, FALSE on failure. */
1795 static gboolean ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
1796     const union wtap_pseudo_header *pseudo_header, const guchar *pd, int *err)
1797 {
1798     ngsniffer_dump_t *priv = wdh->dump.ngsniffer;
1799     struct frame2_rec rec_hdr;
1800     size_t nwritten;
1801     char buf[6];
1802     double t;
1803     guint16 t_low, t_med, t_high;
1804     struct vers_rec version;
1805     gint16 maj_vers, min_vers;
1806     guint16 start_date;
1807     struct tm *tm;
1808
1809     /* Sniffer files have a capture start date in the file header, and
1810        have times relative to the beginning of that day in the packet
1811        headers; pick the date of the first packet as the capture start
1812        date. */
1813     if (priv->first_frame) {
1814         priv->first_frame=FALSE;
1815         tm = localtime(&phdr->ts.tv_sec);
1816         if (tm != NULL) {
1817           start_date = (tm->tm_year - (1980 - 1900)) << 9;
1818           start_date |= (tm->tm_mon + 1) << 5;
1819           start_date |= tm->tm_mday;
1820           /* record the start date, not the start time */
1821           priv->start = phdr->ts.tv_sec - (3600*tm->tm_hour + 60*tm->tm_min + tm->tm_sec);
1822         } else {
1823           start_date = 0;
1824           priv->start = 0;
1825         }
1826
1827         /* "sniffer" version ? */
1828         maj_vers = 4;
1829         min_vers = 0;
1830         version.maj_vers = htoles(maj_vers);
1831         version.min_vers = htoles(min_vers);
1832         version.time = 0;
1833         version.date = htoles(start_date);
1834         version.type = 4;
1835         version.network = wtap_encap[wdh->encap];
1836         version.format = 1;
1837         version.timeunit = 1; /* 0.838096 */
1838         version.cmprs_vers = 0;
1839         version.cmprs_level = 0;
1840         version.rsvd[0] = 0;
1841         version.rsvd[1] = 0;
1842         nwritten = fwrite(&version, 1, sizeof version, wdh->fh);
1843         if (nwritten != sizeof version) {
1844             if (nwritten == 0 && ferror(wdh->fh))
1845                 *err = errno;
1846             else
1847                 *err = WTAP_ERR_SHORT_WRITE;
1848             return FALSE;
1849         }
1850     }
1851
1852     buf[0] = REC_FRAME2;
1853     buf[1] = 0x00;
1854     buf[2] = (char)((phdr->caplen + sizeof(struct frame2_rec))%256);
1855     buf[3] = (char)((phdr->caplen + sizeof(struct frame2_rec))/256);
1856     buf[4] = 0x00;
1857     buf[5] = 0x00;
1858     nwritten = fwrite(buf, 1, 6, wdh->fh);
1859     if (nwritten != 6) {
1860         if (nwritten == 0 && ferror(wdh->fh))
1861             *err = errno;
1862         else
1863             *err = WTAP_ERR_SHORT_WRITE;
1864         return FALSE;
1865     }
1866     t = (double)phdr->ts.tv_sec + (double)phdr->ts.tv_usec/1.0e6; /* # of secs */
1867     t = (t - priv->start)*1.0e6 / Usec[1]; /* timeunit = 1 */
1868     t_low = (guint16)(t-(double)((guint32)(t/65536.0))*65536.0);
1869     t_med = (guint16)((guint32)(t/65536.0) % 65536);
1870     t_high = (guint16)(t/4294967296.0);
1871     rec_hdr.time_low = htoles(t_low);
1872     rec_hdr.time_med = htoles(t_med);
1873     rec_hdr.time_high = htoles(t_high);
1874     rec_hdr.size = htoles(phdr->caplen);
1875     if (wdh->encap == WTAP_ENCAP_LAPB || wdh->encap == WTAP_ENCAP_PPP_WITH_PHDR)
1876         rec_hdr.fs = (pseudo_header->x25.flags & FROM_DCE) ? 0x00 : 0x80;
1877     else
1878         rec_hdr.fs = 0;
1879     rec_hdr.flags = 0;
1880     rec_hdr.true_size = phdr->len != phdr->caplen ? htoles(phdr->len) : 0;
1881     rec_hdr.rsvd = 0;
1882     nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, wdh->fh);
1883     if (nwritten != sizeof rec_hdr) {
1884         if (nwritten == 0 && ferror(wdh->fh))
1885             *err = errno;
1886         else
1887             *err = WTAP_ERR_SHORT_WRITE;
1888         return FALSE;
1889     }
1890     nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
1891     if (nwritten != phdr->caplen) {
1892         if (nwritten == 0 && ferror(wdh->fh))
1893             *err = errno;
1894         else
1895             *err = WTAP_ERR_SHORT_WRITE;
1896         return FALSE;
1897     }
1898     return TRUE;
1899 }
1900
1901 /* Finish writing to a dump file.
1902    Returns TRUE on success, FALSE on failure. */
1903 static gboolean ngsniffer_dump_close(wtap_dumper *wdh, int *err)
1904 {
1905     /* EOF record */
1906     char buf[6] = {REC_EOF, 0x00, 0x00, 0x00, 0x00, 0x00};
1907     size_t nwritten;
1908
1909     nwritten = fwrite(buf, 1, 6, wdh->fh);
1910     if (nwritten != 6) {
1911         if (err != NULL) {
1912             if (nwritten == 0 && ferror(wdh->fh))
1913                 *err = errno;
1914             else
1915                 *err = WTAP_ERR_SHORT_WRITE;
1916         }
1917         return FALSE;
1918     }
1919     return TRUE;
1920 }
1921
1922 /*
1923    SnifferDecompress() decompresses a blob of compressed data from a
1924          Sniffer(R) capture file.
1925
1926    This function is Copyright (c) 1999-2999 Tim Farley
1927
1928    Parameters
1929       inbuf - buffer of compressed bytes from file, not including
1930          the preceding length word
1931       inlen - length of inbuf in bytes
1932       outbuf - decompressed contents, could contain a partial Sniffer
1933          record at the end.
1934       outlen - length of outbuf.
1935
1936    Return value is the number of bytes in outbuf on return.
1937 */
1938 static int
1939 SnifferDecompress( unsigned char * inbuf, size_t inlen,
1940                        unsigned char * outbuf, size_t outlen, int *err )
1941 {
1942    unsigned char * pin = inbuf;
1943    unsigned char * pout = outbuf;
1944    unsigned char * pin_end = pin + inlen;
1945    unsigned char * pout_end = pout + outlen;
1946    unsigned int bit_mask;  /* one bit is set in this, to mask with bit_value */
1947    unsigned int bit_value = 0; /* cache the last 16 coding bits we retrieved */
1948    unsigned int code_type; /* encoding type, from high 4 bits of byte */
1949    unsigned int code_low;  /* other 4 bits from encoding byte */
1950    int length;             /* length of RLE sequence or repeated string */
1951    int offset;             /* offset of string to repeat */
1952
1953    bit_mask  = 0;  /* don't have any bits yet */
1954    while (1)
1955    {
1956       /* Shift down the bit mask we use to see whats encoded */
1957       bit_mask = bit_mask >> 1;
1958
1959       /* If there are no bits left, time to get another 16 bits */
1960       if ( 0 == bit_mask )
1961       {
1962          bit_mask  = 0x8000;  /* start with the high bit */
1963          bit_value = pletohs(pin);   /* get the next 16 bits */
1964          pin += 2;          /* skip over what we just grabbed */
1965          if ( pin >= pin_end )
1966          {
1967             *err = WTAP_ERR_UNC_TRUNCATED;       /* data was oddly truncated */
1968             return ( -1 );
1969          }
1970       }
1971
1972       /* Use the bits in bit_value to see what's encoded and what is raw data */
1973       if ( !(bit_mask & bit_value) )
1974       {
1975          /* bit not set - raw byte we just copy */
1976          *(pout++) = *(pin++);
1977       }
1978       else
1979       {
1980          /* bit set - next item is encoded.  Peel off high nybble
1981             of next byte to see the encoding type.  Set aside low
1982             nybble while we are at it */
1983          code_type = (unsigned int) ((*pin) >> 4 ) & 0xF;
1984          code_low  = (unsigned int) ((*pin) & 0xF );
1985          pin++;   /* increment over the code byte we just retrieved */
1986          if ( pin >= pin_end )
1987          {
1988             *err = WTAP_ERR_UNC_TRUNCATED;       /* data was oddly truncated */
1989             return ( -1 );
1990          }
1991
1992          /* Based on the code type, decode the compressed string */
1993          switch ( code_type )
1994          {
1995             case 0  :   /* RLE short runs */
1996                 /*
1997                     Run length is the low nybble of the first code byte.
1998                     Byte to repeat immediately follows.
1999                     Total code size: 2 bytes.
2000                 */
2001                 length = code_low + 3;
2002                 /* If length would put us past end of output, avoid overflow */
2003                 if ( pout + length > pout_end )
2004                 {
2005                     *err = WTAP_ERR_UNC_OVERFLOW;
2006                     return ( -1 );
2007                 }
2008
2009                 /* generate the repeated series of bytes */
2010                 memset( pout, *pin++, length );
2011                 pout += length;
2012                 break;
2013             case 1  :   /* RLE long runs */
2014                 /*
2015                     Low 4 bits of run length is the low nybble of the
2016                     first code byte, upper 8 bits of run length is in
2017                     the next byte.
2018                     Byte to repeat immediately follows.
2019                     Total code size: 3 bytes.
2020                 */
2021                 length = code_low + ((unsigned int)(*pin++) << 4) + 19;
2022                 /* If we are already at end of input, there is no byte
2023                    to repeat */
2024                 if ( pin >= pin_end )
2025                 {
2026                     *err = WTAP_ERR_UNC_TRUNCATED;       /* data was oddly truncated */
2027                     return ( -1 );
2028                 }
2029                 /* If length would put us past end of output, avoid overflow */
2030                 if ( pout + length > pout_end )
2031                 {
2032                     *err = WTAP_ERR_UNC_OVERFLOW;
2033                     return ( -1 );
2034                 }
2035
2036                 /* generate the repeated series of bytes */
2037                 memset( pout, *pin++, length );
2038                 pout += length;
2039                 break;
2040             case 2  :   /* LZ77 long strings */
2041                 /*
2042                     Low 4 bits of offset to string is the low nybble of the
2043                     first code byte, upper 8 bits of offset is in
2044                     the next byte.
2045                     Length of string immediately follows.
2046                     Total code size: 3 bytes.
2047                 */
2048                 offset = code_low + ((unsigned int)(*pin++) << 4) + 3;
2049                 /* If we are already at end of input, there is no byte
2050                    to repeat */
2051                 if ( pin >= pin_end )
2052                 {
2053                     *err = WTAP_ERR_UNC_TRUNCATED;       /* data was oddly truncated */
2054                     return ( -1 );
2055                 }
2056                 /* Check if offset would put us back past begin of buffer */
2057                 if ( pout - offset < outbuf )
2058                 {
2059                     *err = WTAP_ERR_UNC_BAD_OFFSET;
2060                     return ( -1 );
2061                 }
2062
2063                 /* get length from next byte, make sure it won't overrun buf */
2064                 length = (unsigned int)(*pin++) + 16;
2065                 if ( pout + length > pout_end )
2066                 {
2067                     *err = WTAP_ERR_UNC_OVERFLOW;
2068                     return ( -1 );
2069                 }
2070
2071                 /* Copy the string from previous text to output position,
2072                    advance output pointer */
2073                 memcpy( pout, pout - offset, length );
2074                 pout += length;
2075                 break;
2076             default :   /* (3 to 15): LZ77 short strings */
2077                 /*
2078                     Low 4 bits of offset to string is the low nybble of the
2079                     first code byte, upper 8 bits of offset is in
2080                     the next byte.
2081                     Length of string to repeat is overloaded into code_type.
2082                     Total code size: 2 bytes.
2083                 */
2084                 offset = code_low + ((unsigned int)(*pin++) << 4) + 3;
2085                 /* Check if offset would put us back past begin of buffer */
2086                 if ( pout - offset < outbuf )
2087                 {
2088                     *err = WTAP_ERR_UNC_BAD_OFFSET;
2089                     return ( -1 );
2090                 }
2091
2092                 /* get length from code_type, make sure it won't overrun buf */
2093                 length = code_type;
2094                 if ( pout + length > pout_end )
2095                 {
2096                     *err = WTAP_ERR_UNC_OVERFLOW;
2097                     return ( -1 );
2098                 }
2099
2100                 /* Copy the string from previous text to output position,
2101                    advance output pointer */
2102                 memcpy( pout, pout - offset, length );
2103                 pout += length;
2104                 break;
2105          }
2106       }
2107
2108       /* If we've consumed all the input, we are done */
2109       if ( pin >= pin_end )
2110          break;
2111    }
2112
2113    return ( pout - outbuf );  /* return length of expanded text */
2114 }
2115
2116 /*
2117  * XXX - is there any guarantee that this is big enough to hold the
2118  * uncompressed data from any blob?
2119  */
2120 #define OUTBUF_SIZE     65536
2121
2122 /* Information about a compressed blob; we save the offset in the
2123    underlying compressed file, and the offset in the uncompressed data
2124    stream, of the blob. */
2125 typedef struct {
2126         long    blob_comp_offset;
2127         long    blob_uncomp_offset;
2128 } blob_info_t;
2129
2130 static int
2131 ng_file_read(void *buffer, size_t elementsize, size_t numelements, wtap *wth,
2132     gboolean is_random, int *err)
2133 {
2134     FILE_T infile;
2135     ngsniffer_comp_stream_t *comp_stream;
2136     int copybytes = elementsize * numelements; /* bytes left to be copied */
2137     int copied_bytes = 0; /* bytes already copied */
2138     unsigned char *outbuffer = buffer; /* where to write next decompressed data */
2139     blob_info_t *blob;
2140     int bytes_to_copy;
2141     int bytes_left;
2142
2143     if (is_random) {
2144         infile = wth->random_fh;
2145         comp_stream = &wth->capture.ngsniffer->rand;
2146     } else {
2147         infile = wth->fh;
2148         comp_stream = &wth->capture.ngsniffer->seq;
2149     }
2150
2151     if (wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED) {
2152         errno = WTAP_ERR_CANT_READ;
2153         copied_bytes = file_read(buffer, 1, copybytes, infile);
2154         if (copied_bytes != copybytes)
2155             *err = file_error(infile);
2156         return copied_bytes;
2157     }
2158
2159     /* Allocate the stream buffer if it hasn't already been allocated. */
2160     if (comp_stream->buf == NULL) {
2161         comp_stream->buf = g_malloc(OUTBUF_SIZE);
2162
2163         if (is_random) {
2164             /* This is the first read of the random file, so we're at
2165                the beginning of the sequence of blobs in the file
2166                (as we've not done any random reads yet to move the
2167                current position in the random stream); set the
2168                current blob to be the first blob. */
2169             wth->capture.ngsniffer->current_blob =
2170                 wth->capture.ngsniffer->first_blob;
2171         } else {
2172             /* This is the first sequential read; if we also have a
2173                random stream open, allocate the first element for the
2174                list of blobs, and make it the last element as well. */
2175             if (wth->random_fh != NULL) {
2176                 g_assert(wth->capture.ngsniffer->first_blob == NULL);
2177                 blob = g_malloc(sizeof (blob_info_t));
2178                 blob->blob_comp_offset = comp_stream->comp_offset;
2179                 blob->blob_uncomp_offset = comp_stream->uncomp_offset;
2180                 wth->capture.ngsniffer->first_blob =
2181                         g_list_append(wth->capture.ngsniffer->first_blob, blob);
2182                 wth->capture.ngsniffer->last_blob =
2183                         wth->capture.ngsniffer->first_blob;
2184             }
2185         }
2186
2187         /* Now read the first blob into the buffer. */
2188         if (read_blob(infile, comp_stream, err) < 0)
2189             return -1;
2190     }
2191     while (copybytes > 0) {
2192         bytes_left = comp_stream->nbytes - comp_stream->nextout;
2193         if (bytes_left == 0) {
2194             /* There's no decompressed stuff left to copy from the current
2195                blob; get the next blob. */
2196
2197             if (is_random) {
2198                 /* Move to the next blob in the list. */
2199                 wth->capture.ngsniffer->current_blob =
2200                         g_list_next(wth->capture.ngsniffer->current_blob);
2201                 blob = wth->capture.ngsniffer->current_blob->data;
2202             } else {
2203                 /* If we also have a random stream open, add a new element,
2204                    for this blob, to the list of blobs; we know the list is
2205                    non-empty, as we initialized it on the first sequential
2206                    read, so we just add the new element at the end, and
2207                    adjust the pointer to the last element to refer to it. */
2208                 if (wth->random_fh != NULL) {
2209                     blob = g_malloc(sizeof (blob_info_t));
2210                     blob->blob_comp_offset = comp_stream->comp_offset;
2211                     blob->blob_uncomp_offset = comp_stream->uncomp_offset;
2212                     wth->capture.ngsniffer->last_blob =
2213                         g_list_append(wth->capture.ngsniffer->last_blob, blob);
2214                 }
2215             }
2216
2217             if (read_blob(infile, comp_stream, err) < 0)
2218                 return -1;
2219             bytes_left = comp_stream->nbytes - comp_stream->nextout;
2220         }
2221
2222         bytes_to_copy = copybytes;
2223         if (bytes_to_copy > bytes_left)
2224             bytes_to_copy = bytes_left;
2225         memcpy(outbuffer, &comp_stream->buf[comp_stream->nextout],
2226                 bytes_to_copy);
2227         copybytes -= bytes_to_copy;
2228         copied_bytes += bytes_to_copy;
2229         outbuffer += bytes_to_copy;
2230         comp_stream->nextout += bytes_to_copy;
2231         comp_stream->uncomp_offset += bytes_to_copy;
2232     }
2233     return copied_bytes;
2234 }
2235
2236 /* Read a blob from a compressed stream.
2237    Return -1 and set "*err" on error, otherwise return 0. */
2238 static int
2239 read_blob(FILE_T infile, ngsniffer_comp_stream_t *comp_stream, int *err)
2240 {
2241     size_t in_len;
2242     size_t read_len;
2243     unsigned short blob_len;
2244     gint16 blob_len_host;
2245     gboolean uncompressed;
2246     unsigned char file_inbuf[65536];
2247     int out_len;
2248
2249     /* Read one 16-bit word which is length of next compressed blob */
2250     errno = WTAP_ERR_CANT_READ;
2251     read_len = file_read(&blob_len, 1, 2, infile);
2252     if (2 != read_len) {
2253         *err = file_error(infile);
2254         return -1;
2255     }
2256     comp_stream->comp_offset += 2;
2257     blob_len_host = pletohs(&blob_len);
2258
2259     /* Compressed or uncompressed? */
2260     if (blob_len_host < 0) {
2261         /* Uncompressed blob; blob length is absolute value of the number. */
2262         in_len = -blob_len_host;
2263         uncompressed = TRUE;
2264     } else {
2265         in_len = blob_len_host;
2266         uncompressed = FALSE;
2267     }
2268
2269     /* Read the blob */
2270     errno = WTAP_ERR_CANT_READ;
2271     read_len = file_read(file_inbuf, 1, in_len, infile);
2272     if (in_len != read_len) {
2273         *err = file_error(infile);
2274         return -1;
2275     }
2276     comp_stream->comp_offset += in_len;
2277
2278     if (uncompressed) {
2279         memcpy(comp_stream->buf, file_inbuf, in_len);
2280         out_len = in_len;
2281     } else {
2282         /* Decompress the blob */
2283         out_len = SnifferDecompress(file_inbuf, in_len,
2284                                 comp_stream->buf, OUTBUF_SIZE, err);
2285         if (out_len < 0)
2286             return -1;
2287     }
2288     comp_stream->nextout = 0;
2289     comp_stream->nbytes = out_len;
2290     return 0;
2291 }
2292
2293 /* Seek in the sequential data stream; we can only seek forward, and we
2294    do it on compressed files by skipping forward. */
2295 static long
2296 ng_file_seek_seq(wtap *wth, long offset, int whence, int *err)
2297 {
2298     long delta;
2299     char buf[65536];
2300     long amount_to_read;
2301
2302     if (wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED)
2303         return file_seek(wth->fh, offset, whence, err);
2304
2305     switch (whence) {
2306
2307     case SEEK_SET:
2308         break;          /* "offset" is the target offset */
2309
2310     case SEEK_CUR:
2311         offset += wth->capture.ngsniffer->seq.uncomp_offset;
2312         break;          /* "offset" is relative to the current offset */
2313
2314     case SEEK_END:
2315         g_assert_not_reached(); /* "offset" is relative to the end of the file... */
2316         break;          /* ...but we don't know where that is. */
2317     }
2318
2319     delta = offset - wth->capture.ngsniffer->seq.uncomp_offset;
2320     g_assert(delta >= 0);
2321
2322     /* Ok, now read and discard "delta" bytes. */
2323     while (delta != 0) {
2324         amount_to_read = delta;
2325         if ((unsigned long)amount_to_read > sizeof buf)
2326             amount_to_read = sizeof buf;
2327         if (ng_file_read(buf, 1, amount_to_read, wth, FALSE, err) < 0)
2328             return -1;  /* error */
2329         delta -= amount_to_read;
2330     }
2331     return offset;
2332 }
2333
2334 /* Seek in the random data stream.
2335
2336    On compressed files, we see whether we're seeking to a position within
2337    the blob we currently have in memory and, if not, we find in the list
2338    of blobs the last blob that starts at or before the position to which
2339    we're seeking, and read that blob in.  We can then move to the appropriate
2340    position within the blob we have in memory (whether it's the blob we
2341    already had in memory or, if necessary, the one we read in). */
2342 static long
2343 ng_file_seek_rand(wtap *wth, long offset, int whence, int *err)
2344 {
2345     ngsniffer_t *ngsniffer;
2346     long delta;
2347     GList *new, *next;
2348     blob_info_t *next_blob, *new_blob;
2349
2350     if (wth->file_type == WTAP_FILE_NGSNIFFER_UNCOMPRESSED)
2351         return file_seek(wth->random_fh, offset, whence, err);
2352
2353     ngsniffer = wth->capture.ngsniffer;
2354
2355     switch (whence) {
2356
2357     case SEEK_SET:
2358         break;          /* "offset" is the target offset */
2359
2360     case SEEK_CUR:
2361         offset += ngsniffer->rand.uncomp_offset;
2362         break;          /* "offset" is relative to the current offset */
2363
2364     case SEEK_END:
2365         g_assert_not_reached(); /* "offset" is relative to the end of the file... */
2366         break;          /* ...but we don't know where that is. */
2367     }
2368
2369     delta = offset - ngsniffer->rand.uncomp_offset;
2370
2371     /* Is the place to which we're seeking within the current buffer, or
2372        will we have to read a different blob into the buffer? */
2373     new = NULL;
2374     if (delta > 0) {
2375         /* We're going forwards.
2376            Is the place to which we're seeking within the current buffer? */
2377         if ((size_t)(ngsniffer->rand.nextout + delta) >= ngsniffer->rand.nbytes) {
2378             /* No.  Search for a blob that contains the target offset in
2379                the uncompressed byte stream, starting with the blob
2380                following the current blob. */
2381             new = g_list_next(ngsniffer->current_blob);
2382             for (;;) {
2383                 next = g_list_next(new);
2384                 if (next == NULL) {
2385                     /* No more blobs; the current one is it. */
2386                     break;
2387                 }
2388
2389                 next_blob = next->data;
2390                 /* Does the next blob start after the target offset?
2391                    If so, the current blob is the one we want. */
2392                 if (next_blob->blob_uncomp_offset > offset)
2393                     break;
2394
2395                 new = next;
2396             }
2397         }
2398     } else if (delta < 0) {
2399         /* We're going backwards.
2400            Is the place to which we're seeking within the current buffer? */
2401         if (ngsniffer->rand.nextout + delta < 0) {
2402             /* No.  Search for a blob that contains the target offset in
2403                the uncompressed byte stream, starting with the blob
2404                preceding the current blob. */
2405             new = g_list_previous(ngsniffer->current_blob);
2406             for (;;) {
2407                 /* Does this blob start at or before the target offset?
2408                    If so, the current blob is the one we want. */
2409                 new_blob = new->data;
2410                 if (new_blob->blob_uncomp_offset <= offset)
2411                     break;
2412
2413                 /* It doesn't - skip to the previous blob. */
2414                 new = g_list_previous(new);
2415             }
2416         }
2417     }
2418
2419     if (new != NULL) {
2420         /* The place to which we're seeking isn't in the current buffer;
2421            move to a new blob. */
2422         new_blob = new->data;
2423
2424         /* Seek in the compressed file to the offset in the compressed file
2425            of the beginning of that blob. */
2426         if (file_seek(wth->random_fh, new_blob->blob_comp_offset, SEEK_SET, err) == -1)
2427             return -1;
2428
2429         /* Make the blob we found the current one. */
2430         ngsniffer->current_blob = new;
2431
2432         /* Now set the current offsets to the offsets of the beginning
2433            of the blob. */
2434         ngsniffer->rand.uncomp_offset = new_blob->blob_uncomp_offset;
2435         ngsniffer->rand.comp_offset = new_blob->blob_comp_offset;
2436
2437         /* Now fill the buffer. */
2438         if (read_blob(wth->random_fh, &ngsniffer->rand, err) < 0)
2439             return -1;
2440
2441         /* Set "delta" to the amount to move within this blob; it had
2442            better be >= 0, and < the amount of uncompressed data in
2443            the blob, as otherwise it'd mean we need to seek before
2444            the beginning or after the end of this blob. */
2445         delta = offset - ngsniffer->rand.uncomp_offset;
2446         g_assert(delta >= 0 && (unsigned long)delta < ngsniffer->rand.nbytes);
2447     }
2448
2449     /* OK, the place to which we're seeking is in the buffer; adjust
2450        "ngsniffer->rand.nextout" to point to the place to which
2451        we're seeking, and adjust "ngsniffer->rand.uncomp_offset" to be
2452        the destination offset. */
2453     ngsniffer->rand.nextout += delta;
2454     ngsniffer->rand.uncomp_offset += delta;
2455
2456     return offset;
2457 }