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