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