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