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