2 * Routines for opening files in what Savvius (formerly WildPackets) calls
3 * the classic file format in the description of their "PeekRdr Sample
4 * Application" (C++ source code to read their capture files, downloading
5 * of which requires a maintenance contract, so it's not free as in beer
6 * and probably not as in speech, either).
8 * As that description says, it's used by AiroPeek and AiroPeek NX prior
9 * to 2.0, EtherPeek prior to 6.0, and EtherPeek NX prior to 3.0. It
10 * was probably also used by TokenPeek.
12 * This handles versions 5, 6, and 7 of that format (the format version
13 * number is what appears in the file, and is distinct from the application
16 * Copyright (c) 2001, Daniel Thompson <d.thompson@gmx.net>
19 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
21 * SPDX-License-Identifier: GPL-2.0-or-later
25 #include "peekclassic.h"
29 #include <wsutil/epochs.h>
30 #include <wsutil/802_11-utils.h>
31 #include <wsutil/ws_assert.h>
34 #include "file_wrappers.h"
38 * This file decoder could not have been written without examining how
39 * tcptrace (http://www.tcptrace.org/) handles EtherPeek files.
43 typedef struct peekclassic_master_header
{
46 } peekclassic_master_header_t
;
47 #define PEEKCLASSIC_MASTER_HDR_SIZE 2
49 /* secondary header (V5,V6,V7) */
50 typedef struct peekclassic_v567_header
{
56 uint32_t mediaType
; /* Media Type Ethernet=0 Token Ring = 1 */
57 uint32_t physMedium
; /* Physical Medium native=0 802.1=1 */
58 uint32_t appVers
; /* App Version Number Maj.Min.Bug.Build */
59 uint32_t linkSpeed
; /* Link Speed Bits/sec */
61 } peekclassic_v567_header_t
;
62 #define PEEKCLASSIC_V567_HDR_SIZE 48
65 typedef struct peekclassic_header
{
66 peekclassic_master_header_t master
;
68 peekclassic_v567_header_t v567
;
70 } peekclassic_header_t
;
73 * Packet header (V5, V6).
75 * NOTE: the time stamp, although it's a 32-bit number, is only aligned
76 * on a 16-bit boundary. (Does this date back to 68K Macs? The 68000
77 * only required 16-bit alignment of 32-bit quantities, as did the 68010,
78 * and the 68020/68030/68040 required no alignment.)
80 * As such, we cannot declare this as a C structure, as compilers on
81 * most platforms will put 2 bytes of padding before the time stamp to
82 * align it on a 32-bit boundary.
84 * So, instead, we #define numbers as the offsets of the fields.
86 #define PEEKCLASSIC_V56_LENGTH_OFFSET 0
87 #define PEEKCLASSIC_V56_SLICE_LENGTH_OFFSET 2
88 #define PEEKCLASSIC_V56_FLAGS_OFFSET 4
89 #define PEEKCLASSIC_V56_STATUS_OFFSET 5
90 #define PEEKCLASSIC_V56_TIMESTAMP_OFFSET 6
91 #define PEEKCLASSIC_V56_DESTNUM_OFFSET 10
92 #define PEEKCLASSIC_V56_SRCNUM_OFFSET 12
93 #define PEEKCLASSIC_V56_PROTONUM_OFFSET 14
94 #define PEEKCLASSIC_V56_PROTOSTR_OFFSET 16
95 #define PEEKCLASSIC_V56_FILTERNUM_OFFSET 24
96 #define PEEKCLASSIC_V56_PKT_SIZE 26
98 /* 64-bit time in micro seconds from the (Mac) epoch */
99 typedef struct peekclassic_utime
{
105 * Packet header (V7).
107 * This doesn't have the same alignment problem, but we do it with
110 #define PEEKCLASSIC_V7_PROTONUM_OFFSET 0
111 #define PEEKCLASSIC_V7_LENGTH_OFFSET 2
112 #define PEEKCLASSIC_V7_SLICE_LENGTH_OFFSET 4
113 #define PEEKCLASSIC_V7_FLAGS_OFFSET 6
114 #define PEEKCLASSIC_V7_STATUS_OFFSET 7
115 #define PEEKCLASSIC_V7_TIMESTAMP_OFFSET 8
116 #define PEEKCLASSIC_V7_PKT_SIZE 16
121 #define FLAGS_CONTROL_FRAME 0x01 /* Frame is a control frame */
122 #define FLAGS_HAS_CRC_ERROR 0x02 /* Frame has a CRC error */
123 #define FLAGS_HAS_FRAME_ERROR 0x04 /* Frame has a frame error */
124 #define FLAGS_ROUTE_INFO 0x08 /* Frame has token ring routing information */
125 #define FLAGS_FRAME_TOO_LONG 0x10 /* Frame too long */
126 #define FLAGS_FRAME_TOO_SHORT 0x20 /* Frame too short (runt) */
127 #define FLAGS_TRIGGER 0x40 /* Trigger packet (?) */
128 #define FLAGS_SNAP 0x80 /* SNAP packet (SNAP header?) */
133 #define STATUS_SELECTED 0x01 /* Selected (in the *Peek GUI?) */
134 #define STATUS_TRUNCATED 0x02 /* Truncated (?) */
135 #define STATUS_APPLEPEEK 0x10 /* ApplePeek packet (?) */
136 #define STATUS_SLICED 0x20 /* Sliced (cut short by snaplen?) */
137 #define STATUS_HIDDEN 0x80 /* Hidden (in the *Peek GUI?) */
140 time_t reference_time
;
143 static bool peekclassic_read_v7(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
,
144 int *err
, char **err_info
, int64_t *data_offset
);
145 static bool peekclassic_seek_read_v7(wtap
*wth
, int64_t seek_off
,
146 wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
);
147 static int peekclassic_read_packet_v7(wtap
*wth
, FILE_T fh
,
148 wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
);
149 static bool peekclassic_read_v56(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
,
150 int *err
, char **err_info
, int64_t *data_offset
);
151 static bool peekclassic_seek_read_v56(wtap
*wth
, int64_t seek_off
,
152 wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
);
153 static bool peekclassic_read_packet_v56(wtap
*wth
, FILE_T fh
,
154 wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
);
156 static int peekclassic_v56_file_type_subtype
= -1;
157 static int peekclassic_v7_file_type_subtype
= -1;
159 void register_peekclassic(void);
161 wtap_open_return_val
peekclassic_open(wtap
*wth
, int *err
, char **err_info
)
163 peekclassic_header_t ep_hdr
;
164 time_t reference_time
;
166 peekclassic_t
*peekclassic
;
168 /* Peek classic files do not start with a magic value large enough
169 * to be unique; hence we use the following algorithm to determine
170 * the type of an unknown file:
171 * - populate the master header and reject file if there is no match
172 * - populate the secondary header and check that the reserved space
173 * is zero, and check some other fields; this isn't perfect,
174 * and we may have to add more checks at some point.
176 ws_assert(sizeof(ep_hdr
.master
) == PEEKCLASSIC_MASTER_HDR_SIZE
);
177 if (!wtap_read_bytes(wth
->fh
, &ep_hdr
.master
,
178 (int)sizeof(ep_hdr
.master
), err
, err_info
)) {
179 if (*err
!= WTAP_ERR_SHORT_READ
)
180 return WTAP_OPEN_ERROR
;
181 return WTAP_OPEN_NOT_MINE
;
185 * It appears that EtherHelp (a free application from WildPackets
186 * that did blind capture, saving to a file, so that you could
187 * give the resulting file to somebody with EtherPeek) saved
188 * captures in EtherPeek format except that it ORed the 0x80
189 * bit on in the version number.
191 * We therefore strip off the 0x80 bit in the version number.
192 * Perhaps there's some reason to care whether the capture
193 * came from EtherHelp; if we discover one, we should check
196 ep_hdr
.master
.version
&= ~0x80;
198 /* switch on the file version */
199 switch (ep_hdr
.master
.version
) {
204 /* get the secondary header */
205 ws_assert(sizeof(ep_hdr
.secondary
.v567
) ==
206 PEEKCLASSIC_V567_HDR_SIZE
);
207 if (!wtap_read_bytes(wth
->fh
, &ep_hdr
.secondary
.v567
,
208 (int)sizeof(ep_hdr
.secondary
.v567
), err
, err_info
)) {
209 if (*err
!= WTAP_ERR_SHORT_READ
)
210 return WTAP_OPEN_ERROR
;
211 return WTAP_OPEN_NOT_MINE
;
214 if ((0 != ep_hdr
.secondary
.v567
.reserved
[0]) ||
215 (0 != ep_hdr
.secondary
.v567
.reserved
[1]) ||
216 (0 != ep_hdr
.secondary
.v567
.reserved
[2])) {
218 return WTAP_OPEN_NOT_MINE
;
222 * Check the mediaType and physMedium fields.
223 * We assume it's not a Peek classic file if
224 * these aren't values we know, rather than
225 * reporting them as invalid Peek classic files,
226 * as, given the lack of a magic number, we need
227 * all the checks we can get.
229 ep_hdr
.secondary
.v567
.mediaType
=
230 g_ntohl(ep_hdr
.secondary
.v567
.mediaType
);
231 ep_hdr
.secondary
.v567
.physMedium
=
232 g_ntohl(ep_hdr
.secondary
.v567
.physMedium
);
234 switch (ep_hdr
.secondary
.v567
.physMedium
) {
238 * "Native" format, presumably meaning
239 * Ethernet or Token Ring.
241 switch (ep_hdr
.secondary
.v567
.mediaType
) {
244 file_encap
= WTAP_ENCAP_ETHERNET
;
248 file_encap
= WTAP_ENCAP_TOKEN_RING
;
253 * Assume this isn't a Peek classic file.
255 return WTAP_OPEN_NOT_MINE
;
260 switch (ep_hdr
.secondary
.v567
.mediaType
) {
264 * 802.11, with a private header giving
265 * some radio information. Presumably
266 * this is from AiroPeek.
268 file_encap
= WTAP_ENCAP_IEEE_802_11_WITH_RADIO
;
273 * Assume this isn't a Peek classic file.
275 return WTAP_OPEN_NOT_MINE
;
281 * Assume this isn't a Peek classic file.
283 return WTAP_OPEN_NOT_MINE
;
288 * Assume this is a V5, V6 or V7 Peek classic file, and
289 * byte swap the rest of the fields in the secondary header.
291 * XXX - we could check the file length if the file were
292 * uncompressed, but it might be compressed.
294 ep_hdr
.secondary
.v567
.filelength
=
295 g_ntohl(ep_hdr
.secondary
.v567
.filelength
);
296 ep_hdr
.secondary
.v567
.numPackets
=
297 g_ntohl(ep_hdr
.secondary
.v567
.numPackets
);
298 ep_hdr
.secondary
.v567
.timeDate
=
299 g_ntohl(ep_hdr
.secondary
.v567
.timeDate
);
300 ep_hdr
.secondary
.v567
.timeStart
=
301 g_ntohl(ep_hdr
.secondary
.v567
.timeStart
);
302 ep_hdr
.secondary
.v567
.timeStop
=
303 g_ntohl(ep_hdr
.secondary
.v567
.timeStop
);
304 ep_hdr
.secondary
.v567
.appVers
=
305 g_ntohl(ep_hdr
.secondary
.v567
.appVers
);
306 ep_hdr
.secondary
.v567
.linkSpeed
=
307 g_ntohl(ep_hdr
.secondary
.v567
.linkSpeed
);
309 /* Get the reference time as a time_t */
310 reference_time
= ep_hdr
.secondary
.v567
.timeDate
- EPOCH_DELTA_1904_01_01_00_00_00_UTC
;
315 * Assume this isn't a Peek classic file.
317 return WTAP_OPEN_NOT_MINE
;
321 * This is a Peek classic file.
323 * At this point we have recognised the file type and have populated
324 * the whole ep_hdr structure in host byte order.
326 peekclassic
= g_new(peekclassic_t
, 1);
327 wth
->priv
= (void *)peekclassic
;
328 peekclassic
->reference_time
= reference_time
;
329 wth
->file_encap
= file_encap
;
330 switch (ep_hdr
.master
.version
) {
334 wth
->file_type_subtype
= peekclassic_v56_file_type_subtype
;
335 wth
->subtype_read
= peekclassic_read_v56
;
336 wth
->subtype_seek_read
= peekclassic_seek_read_v56
;
340 wth
->file_type_subtype
= peekclassic_v7_file_type_subtype
;
341 wth
->subtype_read
= peekclassic_read_v7
;
342 wth
->subtype_seek_read
= peekclassic_seek_read_v7
;
346 /* this is impossible */
347 ws_assert_not_reached();
350 wth
->snapshot_length
= 0; /* not available in header */
351 wth
->file_tsprec
= WTAP_TSPREC_USEC
;
354 * Add an IDB; we don't know how many interfaces were
355 * involved, so we just say one interface, about which
356 * we only know the link-layer type, snapshot length,
357 * and time stamp resolution.
359 wtap_add_generated_idb(wth
);
361 return WTAP_OPEN_MINE
;
364 static bool peekclassic_read_v7(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
,
365 int *err
, char **err_info
, int64_t *data_offset
)
369 *data_offset
= file_tell(wth
->fh
);
371 /* Read the packet. */
372 sliceLength
= peekclassic_read_packet_v7(wth
, wth
->fh
, rec
, buf
,
377 /* Skip extra ignored data at the end of the packet. */
378 if ((uint32_t)sliceLength
> rec
->rec_header
.packet_header
.caplen
) {
379 if (!wtap_read_bytes(wth
->fh
, NULL
, sliceLength
- rec
->rec_header
.packet_header
.caplen
,
384 /* Records are padded to an even length, so if the slice length
385 is odd, read the padding byte. */
386 if (sliceLength
& 0x01) {
387 if (!wtap_read_bytes(wth
->fh
, NULL
, 1, err
, err_info
))
394 static bool peekclassic_seek_read_v7(wtap
*wth
, int64_t seek_off
,
395 wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
)
397 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
400 /* Read the packet. */
401 if (peekclassic_read_packet_v7(wth
, wth
->random_fh
, rec
, buf
,
402 err
, err_info
) == -1) {
404 *err
= WTAP_ERR_SHORT_READ
;
410 #define RADIO_INFO_SIZE 4
412 static int peekclassic_read_packet_v7(wtap
*wth
, FILE_T fh
,
413 wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
)
415 uint8_t ep_pkt
[PEEKCLASSIC_V7_PKT_SIZE
];
420 uint16_t sliceLength
;
427 uint8_t radio_info
[RADIO_INFO_SIZE
];
429 if (!wtap_read_bytes_or_eof(fh
, ep_pkt
, sizeof(ep_pkt
), err
, err_info
))
432 /* Extract the fields from the packet */
434 protoNum
= pntoh16(&ep_pkt
[PEEKCLASSIC_V7_PROTONUM_OFFSET
]);
436 length
= pntoh16(&ep_pkt
[PEEKCLASSIC_V7_LENGTH_OFFSET
]);
437 sliceLength
= pntoh16(&ep_pkt
[PEEKCLASSIC_V7_SLICE_LENGTH_OFFSET
]);
438 flags
= ep_pkt
[PEEKCLASSIC_V7_FLAGS_OFFSET
];
439 status
= ep_pkt
[PEEKCLASSIC_V7_STATUS_OFFSET
];
440 timestamp
= pntoh64(&ep_pkt
[PEEKCLASSIC_V7_TIMESTAMP_OFFSET
]);
442 /* force sliceLength to be the actual length of the packet */
443 if (0 == sliceLength
) {
444 sliceLength
= length
;
447 * The maximum value of sliceLength and length are 65535, which
448 * are less than WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't
449 * need to check them.
452 /* fill in packet header values */
453 rec
->rec_type
= REC_TYPE_PACKET
;
454 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
455 rec
->presence_flags
= WTAP_HAS_TS
|WTAP_HAS_CAP_LEN
;
456 tsecs
= (time_t) (timestamp
/1000000);
457 tusecs
= (uint32_t) (timestamp
- tsecs
*1000000);
458 rec
->ts
.secs
= tsecs
- EPOCH_DELTA_1904_01_01_00_00_00_UTC
;
459 rec
->ts
.nsecs
= tusecs
* 1000;
460 rec
->rec_header
.packet_header
.len
= length
;
461 rec
->rec_header
.packet_header
.caplen
= sliceLength
;
463 if (flags
& FLAGS_HAS_CRC_ERROR
)
464 pack_flags
|= PACK_FLAGS_CRC_ERROR
;
465 if (flags
& FLAGS_FRAME_TOO_LONG
)
466 pack_flags
|= PACK_FLAGS_PACKET_TOO_LONG
;
467 if (flags
& FLAGS_FRAME_TOO_SHORT
)
468 pack_flags
|= PACK_FLAGS_PACKET_TOO_SHORT
;
469 wtap_block_add_uint32_option(rec
->block
, OPT_PKT_FLAGS
, pack_flags
);
471 switch (wth
->file_encap
) {
473 case WTAP_ENCAP_IEEE_802_11_WITH_RADIO
:
474 memset(&rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
, 0, sizeof(rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
));
475 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.fcs_len
= 0; /* no FCS */
476 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.decrypted
= false;
477 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.datapad
= false;
478 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.phy
= PHDR_802_11_PHY_UNKNOWN
;
481 * Now process the radio information pseudo-header.
482 * It's a 4-byte pseudo-header, consisting of:
484 * 1 byte of data rate, in units of 500 kb/s;
486 * 1 byte of channel number;
488 * 1 byte of signal strength as a percentage of
489 * the maximum, i.e. (RXVECTOR RSSI/RXVECTOR RSSI_Max)*100,
490 * or, at least, that's what I infer it is, given what
491 * the WildPackets note "Converting Signal Strength
492 * Percentage to dBm Values" says (it also says that
493 * the conversion the percentage to a dBm value is
494 * an adapter-dependent process, so, as we don't know
495 * what type of adapter was used to do the capture,
496 * we can't do the conversion);
498 * 1 byte of unknown content (padding?).
500 if (rec
->rec_header
.packet_header
.len
< RADIO_INFO_SIZE
|| rec
->rec_header
.packet_header
.caplen
< RADIO_INFO_SIZE
) {
501 *err
= WTAP_ERR_BAD_FILE
;
502 *err_info
= ws_strdup_printf("peekclassic: 802.11 packet has length < 4");
505 rec
->rec_header
.packet_header
.len
-= RADIO_INFO_SIZE
;
506 rec
->rec_header
.packet_header
.caplen
-= RADIO_INFO_SIZE
;
507 sliceLength
-= RADIO_INFO_SIZE
;
509 /* read the pseudo-header */
510 if (!wtap_read_bytes(fh
, radio_info
, RADIO_INFO_SIZE
, err
, err_info
))
513 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.has_data_rate
= true;
514 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.data_rate
= radio_info
[0];
516 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.has_channel
= true;
517 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.channel
= radio_info
[1];
519 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.has_signal_percent
= true;
520 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.signal_percent
= radio_info
[2];
523 * We don't know they PHY, but we do have the data rate;
524 * try to guess it based on the data rate and channel.
526 if (RATE_IS_DSSS(rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.data_rate
)) {
528 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.phy
= PHDR_802_11_PHY_11B
;
529 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.phy_info
.info_11b
.has_short_preamble
= false;
530 } else if (RATE_IS_OFDM(rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.data_rate
)) {
531 /* 11a or 11g, depending on the band. */
532 if (CHAN_IS_BG(rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.channel
)) {
534 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.phy
= PHDR_802_11_PHY_11G
;
535 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.phy_info
.info_11g
.has_mode
= false;
538 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.phy
= PHDR_802_11_PHY_11A
;
539 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.phy_info
.info_11a
.has_channel_type
= false;
540 rec
->rec_header
.packet_header
.pseudo_header
.ieee_802_11
.phy_info
.info_11a
.has_turbo_type
= false;
545 * The last 4 bytes appear to be random data - the length
546 * might include the FCS - so we reduce the length by 4.
548 * Or maybe this is just the same kind of random 4 bytes
549 * of junk at the end you get in Wireless Sniffer
552 if (rec
->rec_header
.packet_header
.len
< 4 || rec
->rec_header
.packet_header
.caplen
< 4) {
553 *err
= WTAP_ERR_BAD_FILE
;
554 *err_info
= ws_strdup_printf("peekclassic: 802.11 packet has length < 8");
557 rec
->rec_header
.packet_header
.len
-= 4;
558 rec
->rec_header
.packet_header
.caplen
-= 4;
561 case WTAP_ENCAP_ETHERNET
:
562 /* XXX - it appears that if the low-order bit of
563 "status" is 0, there's an FCS in this frame,
564 and if it's 1, there's 4 bytes of 0. */
565 rec
->rec_header
.packet_header
.pseudo_header
.eth
.fcs_len
= (status
& 0x01) ? 0 : 4;
569 /* read the packet data */
570 if (!wtap_read_packet_bytes(fh
, buf
, rec
->rec_header
.packet_header
.caplen
, err
, err_info
))
576 static bool peekclassic_read_v56(wtap
*wth
, wtap_rec
*rec
, Buffer
*buf
,
577 int *err
, char **err_info
, int64_t *data_offset
)
579 *data_offset
= file_tell(wth
->fh
);
581 /* read the packet */
582 if (!peekclassic_read_packet_v56(wth
, wth
->fh
, rec
, buf
,
587 * XXX - is the captured packet data padded to a multiple
593 static bool peekclassic_seek_read_v56(wtap
*wth
, int64_t seek_off
,
594 wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
)
596 if (file_seek(wth
->random_fh
, seek_off
, SEEK_SET
, err
) == -1)
599 /* read the packet */
600 if (!peekclassic_read_packet_v56(wth
, wth
->random_fh
, rec
, buf
,
603 *err
= WTAP_ERR_SHORT_READ
;
609 static bool peekclassic_read_packet_v56(wtap
*wth
, FILE_T fh
,
610 wtap_rec
*rec
, Buffer
*buf
, int *err
, char **err_info
)
612 peekclassic_t
*peekclassic
= (peekclassic_t
*)wth
->priv
;
613 uint8_t ep_pkt
[PEEKCLASSIC_V56_PKT_SIZE
];
615 uint16_t sliceLength
;
631 if (!wtap_read_bytes_or_eof(fh
, ep_pkt
, sizeof(ep_pkt
), err
, err_info
))
634 /* Extract the fields from the packet */
635 length
= pntoh16(&ep_pkt
[PEEKCLASSIC_V56_LENGTH_OFFSET
]);
636 sliceLength
= pntoh16(&ep_pkt
[PEEKCLASSIC_V56_SLICE_LENGTH_OFFSET
]);
637 flags
= ep_pkt
[PEEKCLASSIC_V56_FLAGS_OFFSET
];
639 status
= ep_pkt
[PEEKCLASSIC_V56_STATUS_OFFSET
];
641 timestamp
= pntoh32(&ep_pkt
[PEEKCLASSIC_V56_TIMESTAMP_OFFSET
]);
643 destNum
= pntoh16(&ep_pkt
[PEEKCLASSIC_V56_DESTNUM_OFFSET
]);
644 srcNum
= pntoh16(&ep_pkt
[PEEKCLASSIC_V56_SRCNUM_OFFSET
]);
645 protoNum
= pntoh16(&ep_pkt
[PEEKCLASSIC_V56_PROTONUM_OFFSET
]);
646 memcpy(protoStr
, &ep_pkt
[PEEKCLASSIC_V56_PROTOSTR_OFFSET
],
651 * XXX - is the captured packet data padded to a multiple
655 /* force sliceLength to be the actual length of the packet */
656 if (0 == sliceLength
) {
657 sliceLength
= length
;
660 * The maximum value of sliceLength and length are 65535, which
661 * are less than WTAP_MAX_PACKET_SIZE_STANDARD will ever be, so we don't
662 * need to check them.
665 /* fill in packet header values */
666 rec
->rec_type
= REC_TYPE_PACKET
;
667 rec
->block
= wtap_block_create(WTAP_BLOCK_PACKET
);
668 rec
->presence_flags
= WTAP_HAS_TS
|WTAP_HAS_CAP_LEN
;
669 /* timestamp is in milliseconds since reference_time */
670 rec
->ts
.secs
= peekclassic
->reference_time
+ (timestamp
/ 1000);
671 rec
->ts
.nsecs
= 1000 * (timestamp
% 1000) * 1000;
672 rec
->rec_header
.packet_header
.len
= length
;
673 rec
->rec_header
.packet_header
.caplen
= sliceLength
;
675 if (flags
& FLAGS_HAS_CRC_ERROR
)
676 pack_flags
|= PACK_FLAGS_CRC_ERROR
;
677 if (flags
& FLAGS_FRAME_TOO_LONG
)
678 pack_flags
|= PACK_FLAGS_PACKET_TOO_LONG
;
679 if (flags
& FLAGS_FRAME_TOO_SHORT
)
680 pack_flags
|= PACK_FLAGS_PACKET_TOO_SHORT
;
681 wtap_block_add_uint32_option(rec
->block
, OPT_PKT_FLAGS
, pack_flags
);
683 switch (wth
->file_encap
) {
685 case WTAP_ENCAP_ETHERNET
:
686 /* We assume there's no FCS in this frame. */
687 rec
->rec_header
.packet_header
.pseudo_header
.eth
.fcs_len
= 0;
691 /* read the packet data */
692 return wtap_read_packet_bytes(fh
, buf
, sliceLength
, err
, err_info
);
695 static const struct supported_block_type peekclassic_v56_blocks_supported
[] = {
697 * We support packet blocks, with no comments or other options.
699 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
}
702 static const struct file_type_subtype_info peekclassic_v56_info
= {
703 "Savvius classic (V5 and V6)", "peekclassic56", "pkt", "tpc;apc;wpz",
704 false, BLOCKS_SUPPORTED(peekclassic_v56_blocks_supported
),
708 static const struct supported_block_type peekclassic_v7_blocks_supported
[] = {
710 * We support packet blocks, with no comments or other options.
712 { WTAP_BLOCK_PACKET
, MULTIPLE_BLOCKS_SUPPORTED
, NO_OPTIONS_SUPPORTED
}
715 static const struct file_type_subtype_info peekclassic_v7_info
= {
716 "Savvius classic (V7)", "peekclassic7", "pkt", "tpc;apc;wpz",
717 false, BLOCKS_SUPPORTED(peekclassic_v7_blocks_supported
),
721 void register_peekclassic(void)
723 peekclassic_v56_file_type_subtype
= wtap_register_file_type_subtype(&peekclassic_v56_info
);
724 peekclassic_v7_file_type_subtype
= wtap_register_file_type_subtype(&peekclassic_v7_info
);
727 * Register names for backwards compatibility with the
728 * wtap_filetypes table in Lua.
730 wtap_register_backwards_compatibility_lua_name("PEEKCLASSIC_V56",
731 peekclassic_v56_file_type_subtype
);
732 wtap_register_backwards_compatibility_lua_name("PEEKCLASSIC_V7",
733 peekclassic_v7_file_type_subtype
);
737 * Editor modelines - https://www.wireshark.org/tools/modelines.html
742 * indent-tabs-mode: t
745 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
746 * :indentSize=8:tabSize=8:noTabs=false: