Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / wiretap / peekclassic.c
blobab94ded313f120422751d35f4bce7c0e62bd14d5
1 /* peekclassic.c
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
14 * version number).
16 * Copyright (c) 2001, Daniel Thompson <d.thompson@gmx.net>
18 * Wiretap Library
19 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
21 * SPDX-License-Identifier: GPL-2.0-or-later
24 #include "config.h"
25 #include "peekclassic.h"
27 #include <string.h>
29 #include <wsutil/epochs.h>
30 #include <wsutil/802_11-utils.h>
31 #include <wsutil/ws_assert.h>
33 #include "wtap-int.h"
34 #include "file_wrappers.h"
36 /* CREDITS
38 * This file decoder could not have been written without examining how
39 * tcptrace (http://www.tcptrace.org/) handles EtherPeek files.
42 /* master header */
43 typedef struct peekclassic_master_header {
44 uint8_t version;
45 uint8_t status;
46 } peekclassic_master_header_t;
47 #define PEEKCLASSIC_MASTER_HDR_SIZE 2
49 /* secondary header (V5,V6,V7) */
50 typedef struct peekclassic_v567_header {
51 uint32_t filelength;
52 uint32_t numPackets;
53 uint32_t timeDate;
54 uint32_t timeStart;
55 uint32_t timeStop;
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 */
60 uint32_t reserved[3];
61 } peekclassic_v567_header_t;
62 #define PEEKCLASSIC_V567_HDR_SIZE 48
64 /* full header */
65 typedef struct peekclassic_header {
66 peekclassic_master_header_t master;
67 union {
68 peekclassic_v567_header_t v567;
69 } secondary;
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 {
100 uint32_t upper;
101 uint32_t lower;
102 } peekclassic_utime;
105 * Packet header (V7).
107 * This doesn't have the same alignment problem, but we do it with
108 * #defines anyway.
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
119 * Flag bits.
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?) */
131 * Status bits.
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?) */
139 typedef struct {
140 time_t reference_time;
141 } peekclassic_t;
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;
165 int file_encap;
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
194 * that bit.
196 ep_hdr.master.version &= ~0x80;
198 /* switch on the file version */
199 switch (ep_hdr.master.version) {
201 case 5:
202 case 6:
203 case 7:
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])) {
217 /* still unknown */
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) {
236 case 0:
238 * "Native" format, presumably meaning
239 * Ethernet or Token Ring.
241 switch (ep_hdr.secondary.v567.mediaType) {
243 case 0:
244 file_encap = WTAP_ENCAP_ETHERNET;
245 break;
247 case 1:
248 file_encap = WTAP_ENCAP_TOKEN_RING;
249 break;
251 default:
253 * Assume this isn't a Peek classic file.
255 return WTAP_OPEN_NOT_MINE;
257 break;
259 case 1:
260 switch (ep_hdr.secondary.v567.mediaType) {
262 case 0:
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;
269 break;
271 default:
273 * Assume this isn't a Peek classic file.
275 return WTAP_OPEN_NOT_MINE;
277 break;
279 default:
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;
311 break;
313 default:
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) {
332 case 5:
333 case 6:
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;
337 break;
339 case 7:
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;
343 break;
345 default:
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)
367 int sliceLength;
369 *data_offset = file_tell(wth->fh);
371 /* Read the packet. */
372 sliceLength = peekclassic_read_packet_v7(wth, wth->fh, rec, buf,
373 err, err_info);
374 if (sliceLength < 0)
375 return false;
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,
380 err, err_info))
381 return false;
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))
388 return false;
391 return true;
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)
398 return false;
400 /* Read the packet. */
401 if (peekclassic_read_packet_v7(wth, wth->random_fh, rec, buf,
402 err, err_info) == -1) {
403 if (*err == 0)
404 *err = WTAP_ERR_SHORT_READ;
405 return false;
407 return true;
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];
416 #if 0
417 uint16_t protoNum;
418 #endif
419 uint16_t length;
420 uint16_t sliceLength;
421 uint8_t flags;
422 uint8_t status;
423 uint64_t timestamp;
424 time_t tsecs;
425 uint32_t tusecs;
426 uint32_t pack_flags;
427 uint8_t radio_info[RADIO_INFO_SIZE];
429 if (!wtap_read_bytes_or_eof(fh, ep_pkt, sizeof(ep_pkt), err, err_info))
430 return -1;
432 /* Extract the fields from the packet */
433 #if 0
434 protoNum = pntoh16(&ep_pkt[PEEKCLASSIC_V7_PROTONUM_OFFSET]);
435 #endif
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;
462 pack_flags = 0;
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");
503 return -1;
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))
511 return -1;
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)) {
527 /* 11b */
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)) {
533 /* 11g */
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;
536 } else {
537 /* 11a */
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
550 * captures.
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");
555 return -1;
557 rec->rec_header.packet_header.len -= 4;
558 rec->rec_header.packet_header.caplen -= 4;
559 break;
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;
566 break;
569 /* read the packet data */
570 if (!wtap_read_packet_bytes(fh, buf, rec->rec_header.packet_header.caplen, err, err_info))
571 return -1;
573 return sliceLength;
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,
583 err, err_info))
584 return false;
587 * XXX - is the captured packet data padded to a multiple
588 * of 2 bytes?
590 return true;
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)
597 return false;
599 /* read the packet */
600 if (!peekclassic_read_packet_v56(wth, wth->random_fh, rec, buf,
601 err, err_info)) {
602 if (*err == 0)
603 *err = WTAP_ERR_SHORT_READ;
604 return false;
606 return true;
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];
614 uint16_t length;
615 uint16_t sliceLength;
616 uint8_t flags;
617 #if 0
618 uint8_t status;
619 #endif
620 uint32_t timestamp;
621 #if 0
622 uint16_t destNum;
623 uint16_t srcNum;
624 #endif
625 #if 0
626 uint16_t protoNum;
627 char protoStr[8];
628 #endif
629 uint32_t pack_flags;
631 if (!wtap_read_bytes_or_eof(fh, ep_pkt, sizeof(ep_pkt), err, err_info))
632 return false;
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];
638 #if 0
639 status = ep_pkt[PEEKCLASSIC_V56_STATUS_OFFSET];
640 #endif
641 timestamp = pntoh32(&ep_pkt[PEEKCLASSIC_V56_TIMESTAMP_OFFSET]);
642 #if 0
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],
647 sizeof protoStr);
648 #endif
651 * XXX - is the captured packet data padded to a multiple
652 * of 2 bytes?
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;
674 pack_flags = 0;
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;
688 break;
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),
705 NULL, NULL, NULL
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),
718 NULL, NULL, NULL
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
739 * Local variables:
740 * c-basic-offset: 8
741 * tab-width: 8
742 * indent-tabs-mode: t
743 * End:
745 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
746 * :indentSize=8:tabSize=8:noTabs=false: