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