dcerpc-netlogon: improve NetrLogonGetCapabilities dissection
[wireshark-sm.git] / wiretap / peektagged.c
blobd2e72622e1b32d1e97010593900d0924917364d4
1 /* peektagged.c
2 * Routines for opening files in what Savvius (formerly WildPackets) calls
3 * the tagged 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 2.0
9 * and later, EtherPeek 6.0 and later, EtherPeek NX 3.0 and later,
10 * EtherPeek VX 1.0 and later, GigaPeek NX 1.0 and later, Omni3 1.0
11 * and later (both OmniPeek and the Remote Engine), and WANPeek NX
12 * 1.0 and later. They also say it'll be used by future Savvius
13 * products.
15 * Wiretap Library
16 * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
18 * SPDX-License-Identifier: GPL-2.0-or-later
21 #include "config.h"
22 #include "peektagged.h"
24 #include <string.h>
25 #include <stdlib.h>
26 #include "wtap-int.h"
27 #include "file_wrappers.h"
28 #include <wsutil/802_11-utils.h>
30 /* CREDITS
32 * This file decoder could not have been written without examining
33 * http://www.varsanofiev.com/inside/airopeekv9.htm, the help from
34 * Martin Regner and Guy Harris, and the etherpeek.c file (as it
35 * was called before renaming it to peekclassic.c).
39 * Section header.
41 * A Peek tagged file consists of multiple sections, each of which begins
42 * with a header in the following format.
44 * The section ID is a 4-character string saying what type of section
45 * it is. The section length is a little-endian field giving the
46 * length of the section, in bytes, including the section header
47 * itself. The other field of the section header is a little-endian
48 * constant that always appears to be 0x00000200.
50 * Files we've seen have the following sections, in order:
52 * "\177vers" - version information. The contents are XML, giving
53 * the file format version and application version information.
55 * "sess" - capture session information. The contents are XML, giving
56 * various information about the capture session.
58 * "pkts" - captured packets. The contents are binary records, one for
59 * each packet, with the record being a list of tagged values followed
60 * by the raw packet data.
62 typedef struct peektagged_section_header {
63 int8_t section_id[4]; /* string identifying the section */
64 uint32_t section_len; /* little-endian section length */
65 uint32_t section_const; /* little-endian 0x00000200 */
66 } peektagged_section_header_t;
69 * Network subtype values.
71 * XXX - do different network subtype values for 802.11 indicate different
72 * network adapter types, with some adapters supplying the FCS and others
73 * not supplying the FCS?
75 #define PEEKTAGGED_NST_ETHERNET 0
76 #define PEEKTAGGED_NST_802_11 1 /* 802.11 with 0's at the end */
77 #define PEEKTAGGED_NST_802_11_2 2 /* 802.11 with 0's at the end */
78 #define PEEKTAGGED_NST_802_11_WITH_FCS 3 /* 802.11 with FCS at the end */
80 /* tags for fields in packet header */
81 #define TAG_PEEKTAGGED_LENGTH 0x0000
82 #define TAG_PEEKTAGGED_TIMESTAMP_LOWER 0x0001
83 #define TAG_PEEKTAGGED_TIMESTAMP_UPPER 0x0002
84 #define TAG_PEEKTAGGED_FLAGS_AND_STATUS 0x0003 /* upper 24 bits unused? */
85 #define TAG_PEEKTAGGED_CHANNEL 0x0004
86 #define TAG_PEEKTAGGED_DATA_RATE_OR_MCS_INDEX 0x0005
87 #define TAG_PEEKTAGGED_SIGNAL_PERC 0x0006
88 #define TAG_PEEKTAGGED_SIGNAL_DBM 0x0007
89 #define TAG_PEEKTAGGED_NOISE_PERC 0x0008
90 #define TAG_PEEKTAGGED_NOISE_DBM 0x0009
91 #define TAG_PEEKTAGGED_UNKNOWN_0x000A 0x000A
92 #define TAG_PEEKTAGGED_CENTER_FREQUENCY 0x000D /* Frequency */
93 #define TAG_PEEKTAGGED_UNKNOWN_0x000E 0x000E /* "Band"? */
94 #define TAG_PEEKTAGGED_UNKNOWN_0x000F 0x000F /* antenna 2 signal dBm? */
95 #define TAG_PEEKTAGGED_UNKNOWN_0x0010 0x0010 /* antenna 3 signal dBm? */
96 #define TAG_PEEKTAGGED_UNKNOWN_0x0011 0x0011 /* antenna 4 signal dBm? */
97 #define TAG_PEEKTAGGED_UNKNOWN_0x0012 0x0012 /* antenna 2 noise dBm? */
98 #define TAG_PEEKTAGGED_UNKNOWN_0x0013 0x0013 /* antenna 3 noise dBm? */
99 #define TAG_PEEKTAGGED_UNKNOWN_0x0014 0x0014 /* antenna 4 noise dBm? */
100 #define TAG_PEEKTAGGED_EXT_FLAGS 0x0015 /* Extended flags for 802.11n and beyond */
102 #define TAG_PEEKTAGGED_SLICE_LENGTH 0xffff
105 * Flags.
107 * We're assuming here that the "remote Peek" flags from bug 9586 are
108 * the same as the "Peek tagged" flags.
110 * Are these the same as in "Peek classic"? The first three are.
112 #define FLAGS_CONTROL_FRAME 0x01 /* Frame is a control frame */
113 #define FLAGS_HAS_CRC_ERROR 0x02 /* Frame has a CRC error */
114 #define FLAGS_HAS_FRAME_ERROR 0x04 /* Frame has a frame error */
117 * Status.
119 * Is this in the next 8 bits of the "flags and status" field?
121 #define STATUS_PROTECTED 0x0400 /* Frame is protected (encrypted) */
122 #define STATUS_DECRYPT_ERROR 0x0800 /* Error decrypting protected frame */
123 #define STATUS_SHORT_PREAMBLE 0x4000 /* Short preamble */
126 * Extended flags.
128 * Some determined from bug 10637, some determined from bug 9586,
129 * and the ones present in both agree, so we're assuming that
130 * the "remote Peek" protocol and the "Peek tagged" file format
131 * use the same bits (which wouldn't be too surprising, as they
132 * both come from Wildpackets).
134 #define EXT_FLAG_20_MHZ_LOWER 0x00000001
135 #define EXT_FLAG_20_MHZ_UPPER 0x00000002
136 #define EXT_FLAG_40_MHZ 0x00000004
137 #define EXT_FLAGS_BANDWIDTH 0x00000007
138 #define EXT_FLAG_HALF_GI 0x00000008
139 #define EXT_FLAG_FULL_GI 0x00000010
140 #define EXT_FLAGS_GI 0x00000018
141 #define EXT_FLAG_AMPDU 0x00000020
142 #define EXT_FLAG_AMSDU 0x00000040
143 #define EXT_FLAG_802_11ac 0x00000080
144 #define EXT_FLAG_MCS_INDEX_USED 0x00000100
146 /* 64-bit time in nanoseconds from the (Windows FILETIME) epoch */
147 typedef struct peektagged_utime {
148 uint32_t upper;
149 uint32_t lower;
150 } peektagged_utime;
152 typedef struct {
153 bool has_fcs;
154 } peektagged_t;
156 static bool peektagged_read(wtap *wth, wtap_rec *rec, Buffer *buf,
157 int *err, char **err_info, int64_t *data_offset);
158 static bool peektagged_seek_read(wtap *wth, int64_t seek_off,
159 wtap_rec *rec, Buffer *buf, int *err, char **err_info);
161 static int peektagged_file_type_subtype = -1;
163 void register_peektagged(void);
165 static int wtap_file_read_pattern (wtap *wth, const char *pattern, int *err,
166 char **err_info)
168 int c;
169 const char *cp;
171 cp = pattern;
172 while (*cp)
174 c = file_getc(wth->fh);
175 if (c == EOF)
177 *err = file_error(wth->fh, err_info);
178 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
179 return -1; /* error */
180 return 0; /* EOF */
182 if (c == *cp)
183 cp++;
184 else
186 if (c == pattern[0])
187 cp = &pattern[1];
188 else
189 cp = pattern;
192 return (*cp == '\0' ? 1 : 0);
196 static int wtap_file_read_till_separator (wtap *wth, char *buffer, int buflen,
197 const char *separators, int *err,
198 char **err_info)
200 int c;
201 char *cp;
202 int i;
204 for (cp = buffer, i = 0; i < buflen; i++, cp++)
206 c = file_getc(wth->fh);
207 if (c == EOF)
209 *err = file_error(wth->fh, err_info);
210 if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
211 return -1; /* error */
212 return 0; /* EOF */
214 if (strchr (separators, c) != NULL)
216 *cp = '\0';
217 break;
219 else
220 *cp = c;
222 return i;
226 static int wtap_file_read_number (wtap *wth, uint32_t *num, int *err,
227 char **err_info)
229 int ret;
230 char str_num[12];
231 unsigned long value;
232 char *p;
234 ret = wtap_file_read_till_separator (wth, str_num, sizeof (str_num)-1, "<",
235 err, err_info);
236 if (ret == 0 || ret == -1) {
237 /* 0 means EOF, which means "not a valid Peek tagged file";
238 -1 means error, and "err" has been set. */
239 return ret;
241 value = strtoul (str_num, &p, 10);
242 if (p == str_num || value > UINT32_MAX)
243 return 0;
244 *num = (uint32_t)value;
245 return 1;
249 wtap_open_return_val peektagged_open(wtap *wth, int *err, char **err_info)
251 peektagged_section_header_t ap_hdr;
252 int ret;
253 uint32_t fileVersion = 0;
254 uint32_t mediaType;
255 uint32_t mediaSubType = 0;
256 int file_encap;
257 static const int peektagged_encap[] = {
258 WTAP_ENCAP_ETHERNET,
259 WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
260 WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
261 WTAP_ENCAP_IEEE_802_11_WITH_RADIO
263 #define NUM_PEEKTAGGED_ENCAPS array_length(peektagged_encap)
264 peektagged_t *peektagged;
266 if (!wtap_read_bytes(wth->fh, &ap_hdr, (int)sizeof(ap_hdr), err, err_info)) {
267 if (*err != WTAP_ERR_SHORT_READ)
268 return WTAP_OPEN_ERROR;
269 return WTAP_OPEN_NOT_MINE;
272 if (memcmp (ap_hdr.section_id, "\177ver", sizeof(ap_hdr.section_id)) != 0)
273 return WTAP_OPEN_NOT_MINE; /* doesn't begin with a "\177ver" section */
276 * XXX - we should get the length of the "\177ver" section, check
277 * that it's followed by a little-endian 0x00000200, and then,
278 * when reading the XML, make sure we don't go past the end of
279 * that section, and skip to the end of that section when
280 * we have the file version (and possibly check to make sure all
281 * tags are properly opened and closed).
283 ret = wtap_file_read_pattern (wth, "<FileVersion>", err, err_info);
284 if (ret == -1)
285 return WTAP_OPEN_ERROR;
286 if (ret == 0) {
287 /* 0 means EOF, which means "not a valid Peek tagged file" */
288 return WTAP_OPEN_NOT_MINE;
290 ret = wtap_file_read_number (wth, &fileVersion, err, err_info);
291 if (ret == -1)
292 return WTAP_OPEN_ERROR;
293 if (ret == 0) {
294 /* 0 means EOF, which means "not a valid Peek tagged file" */
295 return WTAP_OPEN_NOT_MINE;
298 /* If we got this far, we assume it's a Peek tagged file. */
299 if (fileVersion != 9) {
300 /* We only support version 9. */
301 *err = WTAP_ERR_UNSUPPORTED;
302 *err_info = ws_strdup_printf("peektagged: version %u unsupported",
303 fileVersion);
304 return WTAP_OPEN_ERROR;
308 * XXX - once we've skipped the "\177ver" section, we should
309 * check for a "sess" section and fail if we don't see it.
310 * Then we should get the length of the "sess" section, check
311 * that it's followed by a little-endian 0x00000200, and then,
312 * when reading the XML, make sure we don't go past the end of
313 * that section, and skip to the end of the section when
314 * we have the file version (and possibly check to make sure all
315 * tags are properly opened and closed).
317 ret = wtap_file_read_pattern (wth, "<MediaType>", err, err_info);
318 if (ret == -1)
319 return WTAP_OPEN_ERROR;
320 if (ret == 0) {
321 *err = WTAP_ERR_BAD_FILE;
322 *err_info = g_strdup("peektagged: <MediaType> tag not found");
323 return WTAP_OPEN_ERROR;
325 /* XXX - this appears to be 0 in both the EtherPeek and AiroPeek
326 files we've seen; should we require it to be 0? */
327 ret = wtap_file_read_number (wth, &mediaType, err, err_info);
328 if (ret == -1)
329 return WTAP_OPEN_ERROR;
330 if (ret == 0) {
331 *err = WTAP_ERR_BAD_FILE;
332 *err_info = g_strdup("peektagged: <MediaType> value not found");
333 return WTAP_OPEN_ERROR;
336 ret = wtap_file_read_pattern (wth, "<MediaSubType>", err, err_info);
337 if (ret == -1)
338 return WTAP_OPEN_ERROR;
339 if (ret == 0) {
340 *err = WTAP_ERR_BAD_FILE;
341 *err_info = g_strdup("peektagged: <MediaSubType> tag not found");
342 return WTAP_OPEN_ERROR;
344 ret = wtap_file_read_number (wth, &mediaSubType, err, err_info);
345 if (ret == -1)
346 return WTAP_OPEN_ERROR;
347 if (ret == 0) {
348 *err = WTAP_ERR_BAD_FILE;
349 *err_info = g_strdup("peektagged: <MediaSubType> value not found");
350 return WTAP_OPEN_ERROR;
352 if (mediaSubType >= NUM_PEEKTAGGED_ENCAPS
353 || peektagged_encap[mediaSubType] == WTAP_ENCAP_UNKNOWN) {
354 *err = WTAP_ERR_UNSUPPORTED;
355 *err_info = ws_strdup_printf("peektagged: network type %u unknown or unsupported",
356 mediaSubType);
357 return WTAP_OPEN_ERROR;
360 ret = wtap_file_read_pattern (wth, "pkts", err, err_info);
361 if (ret == -1)
362 return WTAP_OPEN_ERROR;
363 if (ret == 0) {
364 *err = WTAP_ERR_SHORT_READ;
365 return WTAP_OPEN_ERROR;
368 /* skip 8 zero bytes */
369 if (!wtap_read_bytes (wth->fh, NULL, 8, err, err_info)) {
370 return WTAP_OPEN_ERROR;
374 * This is an Peek tagged file.
376 file_encap = peektagged_encap[mediaSubType];
378 wth->file_type_subtype = peektagged_file_type_subtype;
379 wth->file_encap = file_encap;
380 wth->subtype_read = peektagged_read;
381 wth->subtype_seek_read = peektagged_seek_read;
382 wth->file_tsprec = WTAP_TSPREC_NSEC;
384 peektagged = g_new(peektagged_t, 1);
385 wth->priv = (void *)peektagged;
386 switch (mediaSubType) {
388 case PEEKTAGGED_NST_ETHERNET:
389 case PEEKTAGGED_NST_802_11:
390 case PEEKTAGGED_NST_802_11_2:
391 peektagged->has_fcs = false;
392 break;
394 case PEEKTAGGED_NST_802_11_WITH_FCS:
395 peektagged->has_fcs = true;
396 break;
399 wth->snapshot_length = 0; /* not available in header */
402 * Add an IDB; we don't know how many interfaces were involved,
403 * so we just say one interface, about which we only know
404 * the link-layer type, snapshot length, and time stamp
405 * resolution.
407 wtap_add_generated_idb(wth);
409 return WTAP_OPEN_MINE;
413 * Read the packet.
415 * XXX - we should supply the additional radio information;
416 * the pseudo-header should probably be supplied in a fashion
417 * similar to the radiotap radio header, so that the 802.11
418 * dissector can determine which, if any, information items
419 * are present.
421 static int
422 peektagged_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
423 Buffer *buf, int *err, char **err_info)
425 peektagged_t *peektagged = (peektagged_t *)wth->priv;
426 bool read_a_tag = false;
427 uint8_t tag_value[6];
428 uint16_t tag;
429 bool saw_length = false;
430 uint32_t length = 0;
431 uint32_t sliceLength = 0;
432 bool saw_timestamp_lower = false;
433 bool saw_timestamp_upper = false;
434 bool saw_flags_and_status = false;
435 peektagged_utime timestamp;
436 uint32_t flags_and_status = 0;
437 uint32_t ext_flags = 0;
438 bool saw_data_rate_or_mcs_index = false;
439 uint32_t data_rate_or_mcs_index = 0;
440 int channel;
441 unsigned frequency;
442 struct ieee_802_11_phdr ieee_802_11 = {0};
443 unsigned i;
444 int skip_len = 0;
445 uint64_t t;
447 timestamp.upper = 0;
448 timestamp.lower = 0;
449 ieee_802_11.fcs_len = -1; /* Unknown */
450 ieee_802_11.decrypted = false;
451 ieee_802_11.datapad = false;
452 ieee_802_11.phy = PHDR_802_11_PHY_UNKNOWN;
454 /* Extract the fields from the packet header */
455 do {
456 /* Get the tag and value.
457 XXX - this assumes all values are 4 bytes long. */
458 if (!wtap_read_bytes_or_eof(fh, tag_value, sizeof tag_value, err, err_info)) {
459 if (*err == 0) {
461 * Short read if we've read something already;
462 * just an EOF if we haven't.
464 if (read_a_tag)
465 *err = WTAP_ERR_SHORT_READ;
467 return -1;
469 read_a_tag = true;
470 tag = pletoh16(&tag_value[0]);
471 switch (tag) {
473 case TAG_PEEKTAGGED_LENGTH:
474 if (saw_length) {
475 *err = WTAP_ERR_BAD_FILE;
476 *err_info = g_strdup("peektagged: record has two length fields");
477 return -1;
479 length = pletoh32(&tag_value[2]);
480 saw_length = true;
481 break;
483 case TAG_PEEKTAGGED_TIMESTAMP_LOWER:
484 if (saw_timestamp_lower) {
485 *err = WTAP_ERR_BAD_FILE;
486 *err_info = g_strdup("peektagged: record has two timestamp-lower fields");
487 return -1;
489 timestamp.lower = pletoh32(&tag_value[2]);
490 saw_timestamp_lower = true;
491 break;
493 case TAG_PEEKTAGGED_TIMESTAMP_UPPER:
494 if (saw_timestamp_upper) {
495 *err = WTAP_ERR_BAD_FILE;
496 *err_info = g_strdup("peektagged: record has two timestamp-upper fields");
497 return -1;
499 timestamp.upper = pletoh32(&tag_value[2]);
500 saw_timestamp_upper = true;
501 break;
503 case TAG_PEEKTAGGED_FLAGS_AND_STATUS:
504 saw_flags_and_status = true;
505 flags_and_status = pletoh32(&tag_value[2]);
506 break;
508 case TAG_PEEKTAGGED_CHANNEL:
509 ieee_802_11.has_channel = true;
510 ieee_802_11.channel = pletoh32(&tag_value[2]);
511 break;
513 case TAG_PEEKTAGGED_DATA_RATE_OR_MCS_INDEX:
514 data_rate_or_mcs_index = pletoh32(&tag_value[2]);
515 saw_data_rate_or_mcs_index = true;
516 break;
518 case TAG_PEEKTAGGED_SIGNAL_PERC:
519 ieee_802_11.has_signal_percent = true;
520 ieee_802_11.signal_percent = pletoh32(&tag_value[2]);
521 break;
523 case TAG_PEEKTAGGED_SIGNAL_DBM:
524 ieee_802_11.has_signal_dbm = true;
525 ieee_802_11.signal_dbm = pletoh32(&tag_value[2]);
526 break;
528 case TAG_PEEKTAGGED_NOISE_PERC:
529 ieee_802_11.has_noise_percent = true;
530 ieee_802_11.noise_percent = pletoh32(&tag_value[2]);
531 break;
533 case TAG_PEEKTAGGED_NOISE_DBM:
534 ieee_802_11.has_noise_dbm = true;
535 ieee_802_11.noise_dbm = pletoh32(&tag_value[2]);
536 break;
538 case TAG_PEEKTAGGED_UNKNOWN_0x000A:
540 * XXX - seen in some 802.11 captures.
541 * Always seems to have the value 0 or 5.
543 break;
545 case TAG_PEEKTAGGED_CENTER_FREQUENCY:
546 /* XXX - also seen in an EtherPeek capture; value unknown */
547 ieee_802_11.has_frequency = true;
548 ieee_802_11.frequency = pletoh32(&tag_value[2]);
549 break;
551 case TAG_PEEKTAGGED_UNKNOWN_0x000E:
553 * XXX - seen in some 802.11 captures.
554 * Usually has the value 4, but, in some packets, has the
555 * values 6 or 302.
557 * Is this the mysterious "band" field that shows up in
558 * some "Peek remote" protocol captures, with values in
559 * the 30x or 40x ranges? It's not always associated
560 * with the "extended flags" tag for HT/VHT information,
561 * so it's probably not 11n/11ac-specific. Values other
562 * than 4 appear, in my captures, only in packets with
563 * the "extended flags" tag. 302 appeared in a packet
564 * with EXT_FLAG_MCS_INDEX_USED; 6 appeared in packets
565 * without EXT_FLAG_MCS_INDEX_USED.
567 break;
569 case TAG_PEEKTAGGED_UNKNOWN_0x000F:
571 * XXX - seen in some 802.11 captures; dB or dBm value?
572 * Multiple antennas?
574 break;
576 case TAG_PEEKTAGGED_UNKNOWN_0x0010:
578 * XXX - seen in some 802.11 captures; dB or dBm value?
579 * Multiple antennas?
581 break;
583 case TAG_PEEKTAGGED_UNKNOWN_0x0011:
585 * XXX - seen in some 802.11 captures; dB or dBm value?
586 * Multiple antennas?
588 break;
590 case TAG_PEEKTAGGED_UNKNOWN_0x0012:
592 * XXX - seen in some 802.11 captures; dB or dBm value?
593 * Multiple antennas?
595 break;
597 case TAG_PEEKTAGGED_UNKNOWN_0x0013:
599 * XXX - seen in some 802.11 captures; dB or dBm value?
600 * Multiple antennas?
602 break;
604 case TAG_PEEKTAGGED_UNKNOWN_0x0014:
606 * XXX - seen in some 802.11 captures; dB or dBm value?
607 * Multiple antennas?
609 break;
611 case TAG_PEEKTAGGED_EXT_FLAGS:
613 * We assume this is present for HT and VHT frames and absent
614 * for other frames.
616 ext_flags = pletoh32(&tag_value[2]);
617 if (ext_flags & EXT_FLAG_802_11ac) {
618 ieee_802_11.phy = PHDR_802_11_PHY_11AC;
620 * XXX - this probably has only one user, so only
621 * one MCS index and only one NSS, but where's the
622 * NSS?
624 for (i = 0; i < 4; i++)
625 ieee_802_11.phy_info.info_11ac.nss[i] = 0;
627 switch (ext_flags & EXT_FLAGS_GI) {
629 case EXT_FLAG_HALF_GI:
630 ieee_802_11.phy_info.info_11ac.has_short_gi = true;
631 ieee_802_11.phy_info.info_11ac.short_gi = 1;
632 break;
634 case EXT_FLAG_FULL_GI:
635 ieee_802_11.phy_info.info_11ac.has_short_gi = true;
636 ieee_802_11.phy_info.info_11ac.short_gi = 0;
637 break;
639 default:
640 /* Mutually exclusive flags set or nothing set */
641 break;
643 } else {
644 ieee_802_11.phy = PHDR_802_11_PHY_11N;
645 switch (ext_flags & EXT_FLAGS_BANDWIDTH) {
647 case 0:
648 ieee_802_11.phy_info.info_11n.has_bandwidth = true;
649 ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_MHZ;
650 break;
652 case EXT_FLAG_20_MHZ_LOWER:
653 ieee_802_11.phy_info.info_11n.has_bandwidth = true;
654 ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_20L;
655 break;
657 case EXT_FLAG_20_MHZ_UPPER:
658 ieee_802_11.phy_info.info_11n.has_bandwidth = true;
659 ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_20U;
660 break;
662 case EXT_FLAG_40_MHZ:
663 ieee_802_11.phy_info.info_11n.has_bandwidth = true;
664 ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_40_MHZ;
665 break;
667 default:
668 /* Mutually exclusive flags set */
669 break;
672 switch (ext_flags & EXT_FLAGS_GI) {
674 case EXT_FLAG_HALF_GI:
675 ieee_802_11.phy_info.info_11n.has_short_gi = true;
676 ieee_802_11.phy_info.info_11n.short_gi = 1;
677 break;
679 case EXT_FLAG_FULL_GI:
680 ieee_802_11.phy_info.info_11n.has_short_gi = true;
681 ieee_802_11.phy_info.info_11n.short_gi = 0;
682 break;
684 default:
685 /* Mutually exclusive flags set or nothing set */
686 break;
689 break;
691 case TAG_PEEKTAGGED_SLICE_LENGTH:
692 sliceLength = pletoh32(&tag_value[2]);
693 break;
695 default:
696 break;
698 } while (tag != TAG_PEEKTAGGED_SLICE_LENGTH); /* last tag */
700 if (!saw_length) {
701 *err = WTAP_ERR_BAD_FILE;
702 *err_info = g_strdup("peektagged: record has no length field");
703 return -1;
705 if (!saw_timestamp_lower) {
706 *err = WTAP_ERR_BAD_FILE;
707 *err_info = g_strdup("peektagged: record has no timestamp-lower field");
708 return -1;
710 if (!saw_timestamp_upper) {
711 *err = WTAP_ERR_BAD_FILE;
712 *err_info = g_strdup("peektagged: record has no timestamp-upper field");
713 return -1;
717 * If sliceLength is 0, force it to be the actual length of the packet.
719 if (sliceLength == 0)
720 sliceLength = length;
722 if (sliceLength > WTAP_MAX_PACKET_SIZE_STANDARD) {
724 * Probably a corrupt capture file; don't blow up trying
725 * to allocate space for an immensely-large packet.
727 *err = WTAP_ERR_BAD_FILE;
728 *err_info = ws_strdup_printf("peektagged: File has %u-byte packet, bigger than maximum of %u",
729 sliceLength, WTAP_MAX_PACKET_SIZE_STANDARD);
730 return -1;
733 rec->rec_type = REC_TYPE_PACKET;
734 rec->block = wtap_block_create(WTAP_BLOCK_PACKET);
735 rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
736 rec->rec_header.packet_header.len = length;
737 rec->rec_header.packet_header.caplen = sliceLength;
738 if (saw_flags_and_status) {
739 uint32_t flags = 0;
740 if (flags_and_status & FLAGS_HAS_CRC_ERROR)
741 flags |= PACK_FLAGS_CRC_ERROR;
742 wtap_block_add_uint32_option(rec->block, OPT_PKT_FLAGS, flags);
745 /* calculate and fill in packet time stamp */
746 t = (((uint64_t) timestamp.upper) << 32) + timestamp.lower;
747 if (!filetime_ns_to_nstime(&rec->ts, t)) {
748 *err = WTAP_ERR_BAD_FILE;
749 *err_info = g_strdup("peektagged: time stamp outside supported range");
750 return -1;
753 switch (wth->file_encap) {
755 case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
756 if (saw_data_rate_or_mcs_index) {
757 if (ext_flags & EXT_FLAG_MCS_INDEX_USED) {
759 * It's an MCS index.
761 * XXX - what about 11ac?
763 if (!(ext_flags & EXT_FLAG_802_11ac)) {
764 ieee_802_11.phy_info.info_11n.has_mcs_index = true;
765 ieee_802_11.phy_info.info_11n.mcs_index = data_rate_or_mcs_index;
767 } else {
768 /* It's a data rate. */
769 ieee_802_11.has_data_rate = true;
770 ieee_802_11.data_rate = data_rate_or_mcs_index;
771 if (ieee_802_11.phy == PHDR_802_11_PHY_UNKNOWN) {
773 * We don't know they PHY; try to guess it based
774 * on the data rate and channel/center frequency.
776 if (RATE_IS_DSSS(ieee_802_11.data_rate)) {
777 /* 11b */
778 ieee_802_11.phy = PHDR_802_11_PHY_11B;
779 if (saw_flags_and_status) {
780 ieee_802_11.phy_info.info_11b.has_short_preamble = true;
781 ieee_802_11.phy_info.info_11b.short_preamble =
782 (flags_and_status & STATUS_SHORT_PREAMBLE) ? true : false;
783 } else
784 ieee_802_11.phy_info.info_11b.has_short_preamble = false;
785 } else if (RATE_IS_OFDM(ieee_802_11.data_rate)) {
786 /* 11a or 11g, depending on the band. */
787 if (ieee_802_11.has_channel) {
788 if (CHAN_IS_BG(ieee_802_11.channel)) {
789 /* 11g */
790 ieee_802_11.phy = PHDR_802_11_PHY_11G;
791 } else {
792 /* 11a */
793 ieee_802_11.phy = PHDR_802_11_PHY_11A;
795 } else if (ieee_802_11.has_frequency) {
796 if (FREQ_IS_BG(ieee_802_11.frequency)) {
797 /* 11g */
798 ieee_802_11.phy = PHDR_802_11_PHY_11G;
799 } else {
800 /* 11a */
801 ieee_802_11.phy = PHDR_802_11_PHY_11A;
804 if (ieee_802_11.phy == PHDR_802_11_PHY_11G) {
805 /* Set 11g metadata */
806 ieee_802_11.phy_info.info_11g.has_mode = false;
807 } else if (ieee_802_11.phy == PHDR_802_11_PHY_11A) {
808 /* Set 11a metadata */
809 ieee_802_11.phy_info.info_11a.has_channel_type = false;
810 ieee_802_11.phy_info.info_11a.has_turbo_type = false;
812 /* Otherwise we don't know the PHY */
817 if (ieee_802_11.has_frequency && !ieee_802_11.has_channel) {
818 /* Frequency, but no channel; try to calculate the channel. */
819 channel = ieee80211_mhz_to_chan(ieee_802_11.frequency);
820 if (channel != -1) {
821 ieee_802_11.has_channel = true;
822 ieee_802_11.channel = channel;
824 } else if (ieee_802_11.has_channel && !ieee_802_11.has_frequency) {
826 * If it's 11 legacy DHSS, 11b, or 11g, it's 2.4 GHz,
827 * so we can calculate the frequency.
829 * If it's 11a, it's 5 GHz, so we can calculate the
830 * frequency.
832 switch (ieee_802_11.phy) {
834 case PHDR_802_11_PHY_11_DSSS:
835 case PHDR_802_11_PHY_11B:
836 case PHDR_802_11_PHY_11G:
837 frequency = ieee80211_chan_to_mhz(ieee_802_11.channel, true);
838 break;
840 case PHDR_802_11_PHY_11A:
841 frequency = ieee80211_chan_to_mhz(ieee_802_11.channel, false);
842 break;
844 default:
845 /* We don't know the band. */
846 frequency = 0;
847 break;
849 if (frequency != 0) {
850 ieee_802_11.has_frequency = true;
851 ieee_802_11.frequency = frequency;
854 rec->rec_header.packet_header.pseudo_header.ieee_802_11 = ieee_802_11;
855 if (peektagged->has_fcs)
856 rec->rec_header.packet_header.pseudo_header.ieee_802_11.fcs_len = 4;
857 else {
858 if (rec->rec_header.packet_header.len < 4 || rec->rec_header.packet_header.caplen < 4) {
859 *err = WTAP_ERR_BAD_FILE;
860 *err_info = ws_strdup_printf("peektagged: 802.11 packet has length < 4");
861 return false;
863 rec->rec_header.packet_header.pseudo_header.ieee_802_11.fcs_len = 0;
864 rec->rec_header.packet_header.len -= 4;
865 rec->rec_header.packet_header.caplen -= 4;
866 skip_len = 4;
868 rec->rec_header.packet_header.pseudo_header.ieee_802_11.decrypted = false;
869 rec->rec_header.packet_header.pseudo_header.ieee_802_11.datapad = false;
870 break;
872 case WTAP_ENCAP_ETHERNET:
874 * The last 4 bytes appear to be 0 in the captures I've seen;
875 * are there any captures where it's an FCS?
877 if (rec->rec_header.packet_header.len < 4 || rec->rec_header.packet_header.caplen < 4) {
878 *err = WTAP_ERR_BAD_FILE;
879 *err_info = ws_strdup_printf("peektagged: Ethernet packet has length < 4");
880 return false;
882 rec->rec_header.packet_header.pseudo_header.eth.fcs_len = 0;
883 rec->rec_header.packet_header.len -= 4;
884 rec->rec_header.packet_header.caplen -= 4;
885 skip_len = 4;
886 break;
889 /* Read the packet data. */
890 if (!wtap_read_packet_bytes(fh, buf, rec->rec_header.packet_header.caplen, err, err_info))
891 return -1;
893 return skip_len;
896 static bool peektagged_read(wtap *wth, wtap_rec *rec, Buffer *buf,
897 int *err, char **err_info, int64_t *data_offset)
899 int skip_len;
901 *data_offset = file_tell(wth->fh);
903 /* Read the packet. */
904 skip_len = peektagged_read_packet(wth, wth->fh, rec, buf, err, err_info);
905 if (skip_len == -1)
906 return false;
908 if (skip_len != 0) {
909 /* Skip extra junk at the end of the packet data. */
910 if (!wtap_read_bytes(wth->fh, NULL, skip_len, err, err_info))
911 return false;
914 return true;
917 static bool
918 peektagged_seek_read(wtap *wth, int64_t seek_off,
919 wtap_rec *rec, Buffer *buf, int *err, char **err_info)
921 if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
922 return false;
924 /* Read the packet. */
925 if (peektagged_read_packet(wth, wth->random_fh, rec, buf, err, err_info) == -1) {
926 if (*err == 0)
927 *err = WTAP_ERR_SHORT_READ;
928 return false;
930 return true;
933 static const struct supported_block_type peektagged_blocks_supported[] = {
935 * We support packet blocks, with no comments or other options.
937 { WTAP_BLOCK_PACKET, MULTIPLE_BLOCKS_SUPPORTED, NO_OPTIONS_SUPPORTED }
940 static const struct file_type_subtype_info peektagged_info = {
941 "Savvius tagged", "peektagged", "pkt", "tpc;apc;wpz",
942 false, BLOCKS_SUPPORTED(peektagged_blocks_supported),
943 NULL, NULL, NULL
946 void register_peektagged(void)
948 peektagged_file_type_subtype = wtap_register_file_type_subtype(&peektagged_info);
951 * Register name for backwards compatibility with the
952 * wtap_filetypes table in Lua.
954 wtap_register_backwards_compatibility_lua_name("PEEKTAGGED",
955 peektagged_file_type_subtype);
959 * Editor modelines - https://www.wireshark.org/tools/modelines.html
961 * Local variables:
962 * c-basic-offset: 4
963 * tab-width: 8
964 * indent-tabs-mode: nil
965 * End:
967 * vi: set shiftwidth=4 tabstop=8 expandtab:
968 * :indentSize=4:tabSize=8:noTabs=true: