4 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
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.
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.
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.
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:
27 * Networks and Distributed Computing
28 * Computing & Communications
29 * University of Washington
30 * Administration Building, AG-44
32 * Internet: martinh@cac.washington.edu
35 * Copyright 1992 by the University of Washington
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.
60 #include "file_wrappers.h"
61 #include "ngsniffer.h"
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
70 * Sniffer record types.
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) */
78 * and now for some unknown header types
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 /* ? */
105 * Sniffer version record format.
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 */
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 */
136 * Sniffer type 2 data record format - followed by frame data.
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*:
144 * ISDN channel information for ISDN;
146 * PPP vs. SLIP information for Async.
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
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.)
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".
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).
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 */
197 * The bits differ for different link-layer types.
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 */
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 */
220 * Internetwork analyzer (synchronous and asynchronous).
222 #define FS_WAN_DTE 0x80 /* DTE->DCE frame */
225 * Internetwork analyzer (synchronous).
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 */
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?
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 */
250 * Sniffer type 4 data record format - followed by frame data.
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.
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.
263 * Fields from the AAL5 trailer for the frame, if it's an AAL5 frame
264 * rather than a cell.
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 */
272 typedef struct _ATMTimeStamp {
273 guint32 msw; /* most significant word */
274 guint32 lsw; /* least significant word */
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 */
292 * Bits in StatusWord.
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 */
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 */
311 * Bits in AppTrafType.
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.
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 */
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 */
337 * Values for AppHLType; the interpretation depends on the ATT_HLTYPE
338 * bits in AppTrafType.
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 */
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 */
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.
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]; /* ? */
395 * Network type values in some type 7 records.
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).
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
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.
413 * The semantics of these network types is inferred from the Sniffer
414 * documentation, as they correspond to types described in the UI;
417 * http://www.mcafee.com/common/media/sniffer/support/sdos/operation.pdf
419 * starting at page 3-10 (56 of 496).
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?
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 */
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.
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?
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 */
465 #define NUM_NGSNIFF_TIMEUNITS (sizeof Psec / sizeof Psec[0])
467 /* Information for a compressed Sniffer data stream. */
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;
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 */
490 * DOS date to "struct tm" conversion values.
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)
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,
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,
541 static gboolean ng_file_seek_rand(wtap *wth, gint64 offset, int *err,
545 ngsniffer_open(wtap *wth, int *err, gchar **err_info)
547 char magic[sizeof ngsniffer_magic];
549 char record_length[4]; /* only the first 2 bytes are length,
550 the last 2 are "reserved" and are thrown away */
552 struct vers_rec version;
558 static const int sniffer_encap[] = {
559 WTAP_ENCAP_TOKEN_RING,
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,
571 #define NUM_NGSNIFF_ENCAPS (sizeof sniffer_encap / sizeof sniffer_encap[0])
573 gint64 current_offset;
574 ngsniffer_t *ngsniffer;
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;
583 if (memcmp(magic, ngsniffer_magic, sizeof ngsniffer_magic)) {
584 return WTAP_OPEN_NOT_MINE;
588 * Read the first record, which the manual says is a version
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;
596 type = pletoh16(record_type);
598 if (type != REC_VERS) {
599 *err = WTAP_ERR_BAD_FILE;
600 *err_info = g_strdup_printf("ngsniffer: Sniffer file doesn't start with a version record");
601 return WTAP_OPEN_ERROR;
604 if (!wtap_read_bytes(wth->fh, &version, sizeof version, err, err_info))
605 return WTAP_OPEN_ERROR;
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",
613 return WTAP_OPEN_ERROR;
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;
623 /* compressed or uncompressed Sniffer file? */
624 if (version.format != 1) {
625 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_COMPRESSED;
627 wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_UNCOMPRESSED;
630 /* Set encap type before reading header records because the
631 * header record may change encap type.
633 wth->file_encap = sniffer_encap[version.network];
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.
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?
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) {
656 * Well, we haven't determined the internetwork analyzer
663 * ... and this is a version 1 capture; look
664 * at the first "rsvd" word.
666 switch (pletoh16(&version.rsvd[0])) {
670 wth->file_encap = WTAP_ENCAP_ISDN;
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.
683 wth->file_encap = WTAP_ENCAP_FRELAY_WITH_PHDR;
688 current_offset = file_tell(wth->fh);
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.
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()".
699 if (wth->random_fh != NULL) {
700 if (file_seek(wth->random_fh, current_offset, SEEK_SET, err) == -1)
701 return WTAP_OPEN_ERROR;
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);
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;
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;
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;
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;
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);
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
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;
759 ngsniffer->start = mktime(&tm);
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
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.
776 wth->file_tsprec = WTAP_TSPREC_NSEC; /* XXX */
778 return WTAP_OPEN_MINE;
782 process_header_records(wtap *wth, int *err, gchar **err_info, gint16 maj_vers,
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;
790 unsigned char buffer[256];
793 if (!wtap_read_bytes_or_eof(wth->fh, record_type, 2, err, err_info)) {
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)) ) {
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.
812 if (file_seek(wth->fh, -2, SEEK_CUR, err) == -1)
817 if (!wtap_read_bytes(wth->fh, record_length, 4,
821 rec_length_remaining = pletoh16(record_length);
824 * Is this is an "Internetwork analyzer" capture, and
825 * is this a REC_HEADER2 record?
827 * If so, it appears to specify the particular type
828 * of network we're on.
830 * XXX - handle sync and async differently? (E.g.,
831 * does this apply only to sync?)
833 if ((network == NETWORK_SYNCHRO || network == NETWORK_ASYNC) &&
834 rec_type == REC_HEADER2) {
836 * Yes, get the first up-to-256 bytes of the
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))
847 if (process_rec_header2_v2(wth, buffer,
848 rec_length_remaining, err, err_info) < 0)
855 if (process_rec_header2_v145(wth, buffer,
856 rec_length_remaining, maj_vers, err, err_info) < 0)
862 * Skip the rest of the record.
864 if (rec_length_remaining > sizeof buffer) {
865 if (file_seek(wth->fh, rec_length_remaining - sizeof buffer,
866 SEEK_CUR, err) == -1)
870 /* Nope, just skip over the data. */
871 if (file_seek(wth->fh, rec_length_remaining, SEEK_CUR, err) == -1)
878 process_rec_header2_v2(wtap *wth, unsigned char *buffer, guint16 length,
879 int *err, gchar **err_info)
881 static const char x_25_str[] = "HDLC\nX.25\n";
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.
890 if (length < sizeof x_25_str - 1) {
892 * There's not enough data to compare.
894 *err = WTAP_ERR_UNSUPPORTED;
895 *err_info = g_strdup_printf("ngsniffer: WAN capture has too-short protocol list");
899 if (strncmp((char *)buffer, x_25_str, sizeof x_25_str - 1) == 0) {
903 wth->file_encap = WTAP_ENCAP_LAPB;
905 *err = WTAP_ERR_UNSUPPORTED;
906 *err_info = g_strdup_printf("ngsniffer: WAN capture protocol string %.*s unknown",
914 process_rec_header2_v145(wtap *wth, unsigned char *buffer, guint16 length,
915 gint16 maj_vers, int *err, gchar **err_info)
918 * The 5th byte of the REC_HEADER2 record appears to be a
923 * There is no 5th byte; give up.
925 *err = WTAP_ERR_UNSUPPORTED;
926 *err_info = g_strdup("ngsniffer: WAN capture has no network subtype");
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.
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.
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.
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.
956 wth->file_encap = WTAP_ENCAP_SDLC;
960 wth->file_encap = WTAP_ENCAP_PER_PACKET;
963 case NET_FRAME_RELAY:
964 wth->file_encap = WTAP_ENCAP_FRELAY_WITH_PHDR;
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.)
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.
981 wth->file_encap = WTAP_ENCAP_PER_PACKET;
985 if (buffer[1] == 0xfa)
986 wth->file_encap = WTAP_ENCAP_ISDN;
992 * There is no 5th byte; give up.
994 *err = WTAP_ERR_UNSUPPORTED;
995 *err_info = g_strdup("ngsniffer: WAN bridge/router capture has no ISDN flag");
998 if (buffer[6] == 0x01)
999 wth->file_encap = WTAP_ENCAP_ISDN;
1005 wth->file_encap = WTAP_ENCAP_PPP_WITH_PHDR;
1010 * Reject these until we can figure them out.
1012 *err = WTAP_ERR_UNSUPPORTED;
1013 *err_info = g_strdup_printf("ngsniffer: WAN network subtype %u unknown or unsupported",
1020 /* Read the next packet */
1022 ngsniffer_read(wtap *wth, int *err, gchar **err_info, gint64 *data_offset)
1024 ngsniffer_t *ngsniffer;
1028 ngsniffer = (ngsniffer_t *)wth->priv;
1031 * We use the uncompressed offset, as that's what
1032 * we need to use for compressed files.
1034 *data_offset = ngsniffer->seq.uncomp_offset;
1037 * Process the record.
1039 ret = ngsniffer_process_record(wth, FALSE, &padding,
1040 &wth->phdr, wth->frame_buffer, err, err_info);
1042 /* Read error or short read */
1047 * ret is the record type.
1056 * Skip any extra data in the record.
1059 if (!ng_file_skip_seq(wth, padding, err,
1067 * End of file. Return an EOF indication.
1069 *err = 0; /* EOF, not error */
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,
1080 if (!ng_file_skip_seq(wth, padding, err,
1090 ngsniffer_seek_read(wtap *wth, gint64 seek_off,
1091 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
1095 if (!ng_file_seek_rand(wth, seek_off, err, err_info))
1098 ret = ngsniffer_process_record(wth, TRUE, NULL, phdr, buf, err, err_info);
1100 /* Read error or short read */
1105 * ret is the record type.
1119 g_assert_not_reached();
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.
1132 ngsniffer_process_record(wtap *wth, gboolean is_random, guint *padding,
1133 struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
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;
1147 * Read the record header.
1149 if (!ng_read_bytes_or_eof(wth, record_type, 2, is_random, err, err_info)) {
1154 if (!ng_read_bytes(wth, record_length, 4, is_random, err, err_info))
1157 rec_type = pletoh16(record_type);
1158 rec_length_remaining = pletoh16(record_length);
1160 ngsniffer = (ngsniffer_t *)wth->priv;
1164 if (ngsniffer->network == NETWORK_ATM) {
1166 * We shouldn't get a frame2 record in
1169 *err = WTAP_ERR_BAD_FILE;
1170 *err_info = g_strdup("ngsniffer: REC_FRAME2 record in an ATM Sniffer file");
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");
1181 /* Read the f_frame2_struct */
1182 if (!ng_read_bytes(wth, &frame2, (unsigned int)sizeof frame2,
1183 is_random, err, err_info))
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);
1192 rec_length_remaining -= (guint)sizeof frame2; /* we already read that much */
1194 set_pseudo_header_frame2(wth, &phdr->pseudo_header, &frame2);
1198 if (ngsniffer->network != NETWORK_ATM) {
1200 * We shouldn't get a frame2 record in
1201 * a non-ATM capture.
1203 *err = WTAP_ERR_BAD_FILE;
1204 *err_info = g_strdup("ngsniffer: REC_FRAME4 record in a non-ATM Sniffer file");
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).
1215 if (ngsniffer->maj_vers < 5 && ngsniffer->min_vers >= 95)
1216 rec_length_remaining += (guint)(sizeof frame4 - sizeof frame2);
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");
1225 /* Read the f_frame4_struct */
1226 if (!ng_read_bytes(wth, &frame4, (unsigned int)sizeof frame4,
1227 is_random, err, err_info))
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);
1236 rec_length_remaining -= (guint)sizeof frame4; /* we already read that much */
1238 set_pseudo_header_frame4(&phdr->pseudo_header, &frame4);
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");
1249 /* Read the f_frame6_struct */
1250 if (!ng_read_bytes(wth, &frame6, (unsigned int)sizeof frame6,
1251 is_random, err, err_info))
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);
1260 rec_length_remaining -= (guint)sizeof frame6; /* we already read that much */
1262 set_pseudo_header_frame6(wth, &phdr->pseudo_header, &frame6);
1267 * End of file. Return an EOF indication.
1269 *err = 0; /* EOF, not error */
1274 * Unknown record type, or type that's not an EOF or
1277 if (padding != NULL) {
1279 * Treat the entire record as padding, so we
1282 *padding = rec_length_remaining;
1284 return rec_type; /* unknown type */
1288 * This is a packet record.
1290 * Is the frame data size greater than than what's left of the
1293 if (size > rec_length_remaining) {
1295 * Yes - treat this as an error.
1297 *err = WTAP_ERR_BAD_FILE;
1298 *err_info = g_strdup("ngsniffer: Record length is less than packet size");
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
1307 if (padding != NULL) {
1309 * Padding, if the frame data size is less than what's
1310 * left of the record.
1312 *padding = rec_length_remaining - size;
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;
1321 * Read the packet data.
1323 ws_buffer_assure_space(buf, size);
1324 if (!ng_read_bytes(wth, ws_buffer_start_ptr(buf), size, is_random,
1328 phdr->pkt_encap = fix_pseudo_header(wth->file_encap,
1329 buf, size, &phdr->pseudo_header);
1332 * 40-bit time stamp, in units of timeunit picoseconds.
1334 t = (((guint64)time_high)<<32) | (((guint64)time_med) << 16) | time_low;
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
1341 t *= ngsniffer->timeunit;
1344 * Convert to seconds and picoseconds.
1346 tsecs = t/G_GUINT64_CONSTANT(1000000000000);
1347 tpsecs = t - tsecs*G_GUINT64_CONSTANT(1000000000000);
1350 * Add in the time_day value (86400 seconds/day).
1352 tsecs += time_day*86400;
1355 * Add in the capture start time.
1357 tsecs += ngsniffer->start;
1359 phdr->ts.secs = (time_t)tsecs;
1360 phdr->ts.nsecs = (int)(tpsecs/1000); /* psecs to nsecs */
1362 return rec_type; /* success */
1366 set_pseudo_header_frame2(wtap *wth, union wtap_pseudo_header *pseudo_header,
1367 struct frame2_rec *frame2)
1370 * In one PPP "Internetwork analyzer" capture:
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.
1380 * All bits in "frame2.flags" were zero.
1382 * In one X.25 "Internetwork analyzer" capture:
1384 * The only bit seen in "frame2.fs" is the 0x80 bit, which
1385 * probably indicates the packet's direction; all other
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.
1393 * In one Ethernet capture:
1395 * "frame2.fs" was always 0; the Sniffer manual says they're
1396 * error bits of various sorts.
1398 * "frame2.flags" was either 0 or 0x18, with no obvious
1399 * correlation with anything. See previous comment
1400 * about display filters.
1402 * In one Token Ring capture:
1404 * "frame2.fs" was either 0 or 0xcc; the Sniffer manual says
1405 * nothing about those bits for Token Ring captures.
1407 * "frame2.flags" was either 0 or 0x18, with no obvious
1408 * correlation with anything. See previous comment
1409 * about display filters.
1411 switch (wth->file_encap) {
1413 case WTAP_ENCAP_ETHERNET:
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?
1421 pseudo_header->eth.fcs_len = 0;
1424 case WTAP_ENCAP_PPP_WITH_PHDR:
1425 case WTAP_ENCAP_SDLC:
1426 pseudo_header->p2p.sent = (frame2->fs & FS_WAN_DTE) ? TRUE : FALSE;
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;
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) {
1439 case FS_ISDN_CHAN_D:
1440 pseudo_header->isdn.channel = 0; /* D-channel */
1443 case FS_ISDN_CHAN_B1:
1444 pseudo_header->isdn.channel = 1; /* B1-channel */
1447 case FS_ISDN_CHAN_B2:
1448 pseudo_header->isdn.channel = 2; /* B2-channel */
1452 pseudo_header->isdn.channel = 30; /* XXX */
1459 set_pseudo_header_frame4(union wtap_pseudo_header *pseudo_header,
1460 struct frame4_rec *frame4)
1463 guint8 aal_type, hl_type;
1467 * Map flags from frame4.atm_info.StatusWord.
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;
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);
1481 case ATT_AAL_UNKNOWN:
1483 * Map ATT_AAL_UNKNOWN on VPI 0, VCI 5 to ATT_AAL_SIGNALLING,
1484 * as that's the VPCI used for signalling.
1486 * XXX - is this necessary, or will frames to 0/5 always
1487 * have ATT_AAL_SIGNALLING?
1489 if (vpi == 0 && vci == 5)
1490 pseudo_header->atm.aal = AAL_SIGNALLING;
1492 pseudo_header->atm.aal = AAL_UNKNOWN;
1493 pseudo_header->atm.type = TRAF_UNKNOWN;
1494 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1498 pseudo_header->atm.aal = AAL_1;
1499 pseudo_header->atm.type = TRAF_UNKNOWN;
1500 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1504 pseudo_header->atm.aal = AAL_3_4;
1505 pseudo_header->atm.type = TRAF_UNKNOWN;
1506 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1510 pseudo_header->atm.aal = AAL_5;
1513 case ATT_HL_UNKNOWN:
1514 pseudo_header->atm.type = TRAF_UNKNOWN;
1515 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1519 pseudo_header->atm.type = TRAF_LLCMX;
1520 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1524 pseudo_header->atm.type = TRAF_VCMX;
1525 switch (frame4->atm_info.AppHLType) {
1528 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1531 case AHLT_VCMX_802_3_FCS:
1532 pseudo_header->atm.subtype =
1533 TRAF_ST_VCMX_802_3_FCS;
1536 case AHLT_VCMX_802_4_FCS:
1537 pseudo_header->atm.subtype =
1538 TRAF_ST_VCMX_802_4_FCS;
1541 case AHLT_VCMX_802_5_FCS:
1542 pseudo_header->atm.subtype =
1543 TRAF_ST_VCMX_802_5_FCS;
1546 case AHLT_VCMX_FDDI_FCS:
1547 pseudo_header->atm.subtype =
1548 TRAF_ST_VCMX_FDDI_FCS;
1551 case AHLT_VCMX_802_6_FCS:
1552 pseudo_header->atm.subtype =
1553 TRAF_ST_VCMX_802_6_FCS;
1556 case AHLT_VCMX_802_3:
1557 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_3;
1560 case AHLT_VCMX_802_4:
1561 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_4;
1564 case AHLT_VCMX_802_5:
1565 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_5;
1568 case AHLT_VCMX_FDDI:
1569 pseudo_header->atm.subtype = TRAF_ST_VCMX_FDDI;
1572 case AHLT_VCMX_802_6:
1573 pseudo_header->atm.subtype = TRAF_ST_VCMX_802_6;
1576 case AHLT_VCMX_FRAGMENTS:
1577 pseudo_header->atm.subtype =
1578 TRAF_ST_VCMX_FRAGMENTS;
1581 case AHLT_VCMX_BPDU:
1582 pseudo_header->atm.subtype = TRAF_ST_VCMX_BPDU;
1586 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1592 pseudo_header->atm.type = TRAF_LANE;
1593 switch (frame4->atm_info.AppHLType) {
1596 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1599 case AHLT_LANE_LE_CTRL:
1600 pseudo_header->atm.subtype =
1601 TRAF_ST_LANE_LE_CTRL;
1604 case AHLT_LANE_802_3:
1605 pseudo_header->atm.subtype = TRAF_ST_LANE_802_3;
1608 case AHLT_LANE_802_5:
1609 pseudo_header->atm.subtype = TRAF_ST_LANE_802_5;
1612 case AHLT_LANE_802_3_MC:
1613 pseudo_header->atm.subtype =
1614 TRAF_ST_LANE_802_3_MC;
1617 case AHLT_LANE_802_5_MC:
1618 pseudo_header->atm.subtype =
1619 TRAF_ST_LANE_802_5_MC;
1623 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1629 pseudo_header->atm.type = TRAF_ILMI;
1630 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1634 pseudo_header->atm.type = TRAF_FR;
1635 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1639 pseudo_header->atm.type = TRAF_SPANS;
1640 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1643 case ATT_HL_IPSILON:
1644 pseudo_header->atm.type = TRAF_IPSILON;
1645 switch (frame4->atm_info.AppHLType) {
1648 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1651 case AHLT_IPSILON_FT0:
1652 pseudo_header->atm.subtype =
1653 TRAF_ST_IPSILON_FT0;
1656 case AHLT_IPSILON_FT1:
1657 pseudo_header->atm.subtype =
1658 TRAF_ST_IPSILON_FT1;
1661 case AHLT_IPSILON_FT2:
1662 pseudo_header->atm.subtype =
1663 TRAF_ST_IPSILON_FT2;
1667 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1673 pseudo_header->atm.type = TRAF_UNKNOWN;
1674 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1680 pseudo_header->atm.aal = AAL_USER;
1681 pseudo_header->atm.type = TRAF_UNKNOWN;
1682 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
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;
1692 pseudo_header->atm.aal = AAL_OAMCELL;
1693 pseudo_header->atm.type = TRAF_UNKNOWN;
1694 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
1698 pseudo_header->atm.aal = AAL_UNKNOWN;
1699 pseudo_header->atm.type = TRAF_UNKNOWN;
1700 pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
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);
1713 set_pseudo_header_frame6(wtap *wth, union wtap_pseudo_header *pseudo_header,
1714 struct frame6_rec *frame6 _U_)
1716 /* XXX - Once the frame format is divined, something will most likely go here */
1718 switch (wth->file_encap) {
1720 case WTAP_ENCAP_ETHERNET:
1721 /* XXX - is there an FCS? */
1722 pseudo_header->eth.fcs_len = -1;
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.
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?)
1741 infer_pkt_encap(const guint8 *pd, int len)
1747 * Nothing to infer, but it doesn't matter how you
1748 * dissect an empty packet. Let's just say PPP.
1750 return WTAP_ENCAP_PPP_WITH_PHDR;
1753 if (pd[0] == 0xFF) {
1755 * PPP. (XXX - check for 0xFF 0x03?)
1757 return WTAP_ENCAP_PPP_WITH_PHDR;
1761 if (pd[0] == 0x07 && pd[1] == 0x03) {
1765 return WTAP_ENCAP_WFLEET_HDLC;
1766 } else if ((pd[0] == 0x0F && pd[1] == 0x00) ||
1767 (pd[0] == 0x8F && pd[1] == 0x00)) {
1771 return WTAP_ENCAP_CHDLC_WITH_PHDR;
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.
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?
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.
1796 for (i = 0; i < len && (pd[i] & 0x01) == 0; i++)
1798 i++; /* advance to the byte after the last DLCI byte */
1803 return WTAP_ENCAP_LAPB;
1806 return WTAP_ENCAP_FRELAY_WITH_PHDR;
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.
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
1818 return WTAP_ENCAP_LAPB;
1822 fix_pseudo_header(int encap, Buffer *buf, int len,
1823 union wtap_pseudo_header *pseudo_header)
1827 pd = ws_buffer_start_ptr(buf);
1830 case WTAP_ENCAP_PER_PACKET:
1832 * Infer the packet type from the first two bytes.
1834 encap = infer_pkt_encap(pd, len);
1837 * Fix up the pseudo-header to match the new
1838 * encapsulation type.
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;
1848 pseudo_header->p2p.sent = FALSE;
1851 case WTAP_ENCAP_ISDN:
1852 if (pseudo_header->x25.flags == 0x00)
1853 pseudo_header->isdn.uton = FALSE;
1855 pseudo_header->isdn.uton = TRUE;
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.
1867 pseudo_header->isdn.channel = 0;
1872 case WTAP_ENCAP_ATM_PDUS:
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.
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
1885 if (pseudo_header->atm.type == TRAF_LANE && len >= 2) {
1886 if (pd[0] == 0xff && pd[1] == 0x00) {
1888 * This must be LE Control.
1890 pseudo_header->atm.subtype =
1891 TRAF_ST_LANE_LE_CTRL;
1894 * This can't be LE Control.
1896 if (pseudo_header->atm.subtype ==
1897 TRAF_ST_LANE_LE_CTRL) {
1899 * XXX - Ethernet or Token Ring?
1901 pseudo_header->atm.subtype =
1911 /* Throw away the buffers used by the sequential I/O stream, but not
1912 those used by the random I/O stream. */
1914 ngsniffer_sequential_close(wtap *wth)
1916 ngsniffer_t *ngsniffer;
1918 ngsniffer = (ngsniffer_t *)wth->priv;
1919 if (ngsniffer->seq.buf != NULL) {
1920 g_free(ngsniffer->seq.buf);
1921 ngsniffer->seq.buf = NULL;
1926 free_blob(gpointer data, gpointer user_data _U_)
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.) */
1936 ngsniffer_close(wtap *wth)
1938 ngsniffer_t *ngsniffer;
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);
1950 gboolean first_frame;
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 ! */
1975 #define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
1977 /* Returns 0 if we could write the specified encapsulation type,
1978 an error indication otherwise. */
1980 ngsniffer_dump_can_write_encap(int encap)
1982 /* Per-packet encapsulations aren't supported. */
1983 if (encap == WTAP_ENCAP_PER_PACKET)
1984 return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
1986 if (encap < 0 || (unsigned)encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
1987 return WTAP_ERR_UNWRITABLE_ENCAP;
1992 /* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
1995 ngsniffer_dump_open(wtap_dumper *wdh, int *err)
1997 ngsniffer_dump_t *ngsniffer;
1998 char buf[6] = {REC_VERS, 0x00, 0x12, 0x00, 0x00, 0x00}; /* version record */
2000 /* This is a sniffer file */
2001 wdh->subtype_write = ngsniffer_dump;
2002 wdh->subtype_finish = ngsniffer_dump_finish;
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;
2009 /* Write the file header. */
2010 if (!wtap_dump_file_write(wdh, ngsniffer_magic, sizeof ngsniffer_magic,
2013 if (!wtap_dump_file_write(wdh, buf, 6, err))
2019 /* Write a record for a packet to a dump file.
2020 Returns TRUE on success, FALSE on failure. */
2022 ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
2023 const guint8 *pd, int *err, gchar **err_info _U_)
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;
2031 guint16 t_low, t_med;
2033 struct vers_rec version;
2034 gint16 maj_vers, min_vers;
2038 /* We can only write packet records. */
2039 if (phdr->rec_type != REC_TYPE_PACKET) {
2040 *err = WTAP_ERR_UNWRITABLE_REC_TYPE;
2044 /* The captured length field is 16 bits, so there's a hard
2046 if (phdr->caplen > 65535) {
2047 *err = WTAP_ERR_PACKET_TOO_LARGE;
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
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);
2066 ngsniffer->start = 0;
2069 /* "sniffer" version ? */
2072 version.maj_vers = GUINT16_TO_LE(maj_vers);
2073 version.min_vers = GUINT16_TO_LE(min_vers);
2075 version.date = GUINT16_TO_LE(start_date);
2077 version.network = wtap_encap[wdh->encap];
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))
2088 buf[0] = REC_FRAME2;
2090 buf[2] = (char)((phdr->caplen + sizeof(struct frame2_rec))%256);
2091 buf[3] = (char)((phdr->caplen + sizeof(struct frame2_rec))/256);
2094 if (!wtap_dump_file_write(wdh, buf, 6, err))
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 */
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) {
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;
2120 case WTAP_ENCAP_PPP_WITH_PHDR:
2121 case WTAP_ENCAP_SDLC:
2122 rec_hdr.fs = pseudo_header->p2p.sent ? 0x00 : FS_WAN_DTE;
2125 case WTAP_ENCAP_ISDN:
2126 rec_hdr.fs = pseudo_header->isdn.uton ? FS_WAN_DTE : 0x00;
2127 switch (pseudo_header->isdn.channel) {
2129 case 0: /* D-channel */
2130 rec_hdr.fs |= FS_ISDN_CHAN_D;
2133 case 1: /* B1-channel */
2134 rec_hdr.fs |= FS_ISDN_CHAN_B1;
2137 case 2: /* B2-channel */
2138 rec_hdr.fs |= FS_ISDN_CHAN_B2;
2148 rec_hdr.true_size = phdr->len != phdr->caplen ? GUINT16_TO_LE(phdr->len) : 0;
2150 if (!wtap_dump_file_write(wdh, &rec_hdr, sizeof rec_hdr, err))
2152 if (!wtap_dump_file_write(wdh, pd, phdr->caplen, err))
2157 /* Finish writing to a dump file.
2158 Returns TRUE on success, FALSE on failure. */
2160 ngsniffer_dump_finish(wtap_dumper *wdh, int *err)
2163 char buf[6] = {REC_EOF, 0x00, 0x00, 0x00, 0x00, 0x00};
2165 if (!wtap_dump_file_write(wdh, buf, 6, err))
2171 SnifferDecompress() decompresses a blob of compressed data from a
2172 Sniffer(R) capture file.
2174 This function is Copyright (c) 1999-2999 Tim Farley
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
2182 outlen - length of outbuf.
2183 err - return error code here
2184 err_info - for WTAP_ERR_DECOMPRESS, return descriptive string here
2186 Return value is the number of bytes in outbuf on return.
2190 * Make sure we have at least "length" bytes remaining
2191 * in the input buffer.
2193 #define CHECK_INPUT_POINTER( length ) \
2194 if ( pin + (length - 1) >= pin_end ) \
2196 *err = WTAP_ERR_DECOMPRESS; \
2197 *err_info = g_strdup("ngsniffer: Compressed data item goes past the end of the compressed block"); \
2202 * Make sure the byte containing the high order part of a buffer
2203 * offset is present.
2205 * If it is, then fetch it and combine it with the low-order part.
2207 #define FETCH_OFFSET_HIGH \
2208 CHECK_INPUT_POINTER( 1 ); \
2209 offset = code_low + ((unsigned int)(*pin++) << 4) + 3;
2212 * Make sure the output buffer is big enough to get "length"
2213 * bytes added to it.
2215 #define CHECK_OUTPUT_LENGTH( length ) \
2216 if ( pout + length > pout_end ) \
2218 *err = WTAP_ERR_UNC_OVERFLOW; \
2223 * Make sure we have another byte to fetch, and then fetch it and
2224 * append it to the buffer "length" times.
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 ); \
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.
2238 * Then append the string from the specified offset, with the
2239 * specified length, to the output buffer.
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 ) \
2247 *err = WTAP_ERR_DECOMPRESS; \
2248 *err_info = g_strdup("ngsniffer: LZ77 compressed data has bad offset to string"); \
2251 /* Check if offset would cause us to copy on top of ourselves */ \
2252 if ( pout - offset + length > pout ) \
2254 *err = WTAP_ERR_DECOMPRESS; \
2255 *err_info = g_strdup("ngsniffer: LZ77 compressed data has bad offset to string"); \
2258 /* Copy the string from previous text to output position, \
2259 advance output pointer */ \
2260 memcpy( pout, pout - offset, length ); \
2264 SnifferDecompress(unsigned char *inbuf, size_t inlen, unsigned char *outbuf,
2265 size_t outlen, int *err, gchar **err_info)
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 */
2278 if (inlen > G_MAXUINT16) {
2282 bit_mask = 0; /* don't have any bits yet */
2283 /* Process until we've consumed all the input */
2284 while (pin < pin_end)
2286 /* Shift down the bit mask we use to see what's encoded */
2287 bit_mask = bit_mask >> 1;
2289 /* If there are no bits left, time to get another 16 bits */
2290 if ( 0 == bit_mask )
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 */
2301 /* Use the bits in bit_value to see what's encoded and what is raw data */
2302 if ( !(bit_mask & bit_value) )
2304 /* bit not set - raw byte we just copy */
2306 /* If length would put us past end of output, avoid overflow */
2307 CHECK_OUTPUT_LENGTH( 1 );
2308 *(pout++) = *(pin++);
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 */
2319 /* Based on the code type, decode the compressed string */
2320 switch ( code_type )
2322 case 0 : /* RLE short runs */
2324 Run length is the low nybble of the first code byte.
2325 Byte to repeat immediately follows.
2326 Total code size: 2 bytes.
2328 length = code_low + 3;
2330 /* check the length and then, if it's OK,
2331 generate the repeated series of bytes */
2332 APPEND_RLE_BYTE( length );
2334 case 1 : /* RLE long runs */
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
2339 Byte to repeat immediately follows.
2340 Total code size: 3 bytes.
2342 CHECK_INPUT_POINTER( 1 );
2343 length = code_low + ((unsigned int)(*pin++) << 4) + 19;
2345 /* check the length and then, if it's OK,
2346 generate the repeated series of bytes */
2347 APPEND_RLE_BYTE( length );
2349 case 2 : /* LZ77 long strings */
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
2354 Length of string immediately follows.
2355 Total code size: 3 bytes.
2359 /* get length from next byte, make sure it won't overrun buf */
2360 CHECK_INPUT_POINTER( 1 );
2361 length = (unsigned int)(*pin++) + 16;
2363 /* check the offset and length and then, if
2364 they're OK, copy the data */
2365 APPEND_LZW_STRING( offset, length );
2367 default : /* (3 to 15): LZ77 short strings */
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
2372 Length of string to repeat is overloaded into code_type.
2373 Total code size: 2 bytes.
2377 /* get length from code_type */
2380 /* check the offset and length and then, if
2381 they're OK, copy the data */
2382 APPEND_LZW_STRING( offset, length );
2388 return (int) ( pout - outbuf ); /* return length of expanded text */
2392 * XXX - is there any guarantee that 65535 bytes is big enough to hold the
2393 * uncompressed data from any blob?
2395 #define OUTBUF_SIZE 65536
2396 #define INBUF_SIZE 65536
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. */
2402 gint64 blob_comp_offset;
2403 gint64 blob_uncomp_offset;
2407 ng_read_bytes_or_eof(wtap *wth, void *buffer, unsigned int nbytes, gboolean is_random,
2408 int *err, gchar **err_info)
2410 ngsniffer_t *ngsniffer;
2412 ngsniffer_comp_stream_t *comp_stream;
2413 unsigned char *outbuffer = (unsigned char *)buffer; /* where to write next decompressed data */
2415 unsigned int bytes_to_copy;
2416 unsigned int bytes_left;
2418 ngsniffer = (ngsniffer_t *)wth->priv;
2420 infile = wth->random_fh;
2421 comp_stream = &ngsniffer->rand;
2424 comp_stream = &ngsniffer->seq;
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))
2430 comp_stream->uncomp_offset += nbytes;
2431 comp_stream->comp_offset += nbytes;
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);
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;
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,
2457 ngsniffer->last_blob = ngsniffer->first_blob;
2461 /* Now read the first blob into the buffer. */
2462 if (!read_blob(infile, comp_stream, err, err_info))
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. */
2472 /* Move to the next blob in the list. */
2473 ngsniffer->current_blob = g_list_next(ngsniffer->current_blob);
2474 if (!ngsniffer->current_blob) {
2476 * XXX - this "can't happen"; we should have a
2477 * blob for every byte in the file.
2479 *err = WTAP_ERR_CANT_SEEK;
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,
2497 if (!read_blob(infile, comp_stream, err, err_info))
2499 bytes_left = comp_stream->nbytes - comp_stream->nextout;
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],
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;
2516 ng_read_bytes(wtap *wth, void *buffer, unsigned int nbytes, gboolean is_random,
2517 int *err, gchar **err_info)
2519 if (!ng_read_bytes_or_eof(wth, buffer, nbytes, is_random, err, err_info)) {
2521 * In this case, even reading zero bytes, because we're at
2522 * the end of the file, is a short read.
2525 *err = WTAP_ERR_SHORT_READ;
2531 /* Read a blob from a compressed stream.
2532 Return FALSE and set "*err" and "*err_info" on error, otherwise return TRUE. */
2534 read_blob(FILE_T infile, ngsniffer_comp_stream_t *comp_stream, int *err,
2538 unsigned short blob_len;
2539 gint16 blob_len_host;
2540 gboolean uncompressed;
2541 unsigned char *file_inbuf;
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))
2547 comp_stream->comp_offset += 2;
2548 blob_len_host = pletoh16(&blob_len);
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;
2556 in_len = blob_len_host;
2557 uncompressed = FALSE;
2560 file_inbuf = (unsigned char *)g_malloc(INBUF_SIZE);
2563 if (!wtap_read_bytes(infile, file_inbuf, in_len, err, err_info)) {
2567 comp_stream->comp_offset += in_len;
2570 memcpy(comp_stream->buf, file_inbuf, in_len);
2573 /* Decompress the blob */
2574 out_len = SnifferDecompress(file_inbuf, in_len,
2575 comp_stream->buf, OUTBUF_SIZE, err,
2584 comp_stream->nextout = 0;
2585 comp_stream->nbytes = out_len;
2589 /* Skip some number of bytes forward in the sequential stream. */
2591 ng_file_skip_seq(wtap *wth, gint64 delta, int *err, gchar **err_info)
2593 ngsniffer_t *ngsniffer;
2595 unsigned int amount_to_read;
2597 ngsniffer = (ngsniffer_t *)wth->priv;
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);
2604 g_assert(delta >= 0);
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;
2612 amount_to_read = (unsigned int) delta;
2614 if (!ng_read_bytes(wth, buf, amount_to_read, FALSE, err, err_info)) {
2616 return FALSE; /* error */
2619 delta -= amount_to_read;
2626 /* Seek to a given offset in the random data stream.
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). */
2635 ng_file_seek_rand(wtap *wth, gint64 offset, int *err, gchar **err_info)
2637 ngsniffer_t *ngsniffer;
2639 GList *new_list, *next_list;
2640 blob_info_t *next_blob, *new_blob;
2642 ngsniffer = (ngsniffer_t *)wth->priv;
2644 if (wth->file_type_subtype == WTAP_FILE_TYPE_SUBTYPE_NGSNIFFER_UNCOMPRESSED) {
2645 if (file_seek(wth->random_fh, offset, SEEK_SET, err) == -1)
2650 delta = offset - ngsniffer->rand.uncomp_offset;
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? */
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
2666 new_list = ngsniffer->first_blob;
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);
2673 next_list = g_list_next(new_list);
2674 if (next_list == NULL) {
2675 /* No more blobs; the current one is it. */
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)
2685 new_list = next_list;
2687 if (new_list == NULL) {
2689 * We're seeking past the end of what
2690 * we've read so far.
2692 *err = WTAP_ERR_CANT_SEEK;
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
2707 new_list = ngsniffer->last_blob;
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);
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)
2720 /* It doesn't - skip to the previous blob. */
2721 new_list = g_list_previous(new_list);
2723 if (new_list == NULL) {
2725 * XXX - shouldn't happen.
2727 *err = WTAP_ERR_CANT_SEEK;
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;
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)
2744 * Do we have a buffer for the random stream yet?
2746 if (ngsniffer->rand.buf == NULL) {
2748 * No - allocate it, as we'll be reading into it.
2750 ngsniffer->rand.buf = (unsigned char *)g_malloc(OUTBUF_SIZE);
2753 /* Make the blob we found the current one. */
2754 ngsniffer->current_blob = new_list;
2756 /* Now set the current offsets to the offsets of the beginning
2758 ngsniffer->rand.uncomp_offset = new_blob->blob_uncomp_offset;
2759 ngsniffer->rand.comp_offset = new_blob->blob_comp_offset;
2761 /* Now fill the buffer. */
2762 if (!read_blob(wth->random_fh, &ngsniffer->rand, err, err_info))
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);
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;
2784 * Editor modelines - http://www.wireshark.org/tools/modelines.html
2789 * indent-tabs-mode: t
2792 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
2793 * :indentSize=8:tabSize=8:noTabs=false: