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