Squelch a compiler warning.
[metze/wireshark/wip.git] / wiretap / peektagged.c
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).
7  *
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.
14  *
15  * Wiretap Library
16  * Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License
20  * as published by the Free Software Foundation; either version 2
21  * of the License, or (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31  */
32
33 #include "config.h"
34 #include <errno.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include "wtap-int.h"
38 #include "file_wrappers.h"
39 #include "peektagged.h"
40
41 /* CREDITS
42  *
43  * This file decoder could not have been writen without examining
44  * http://www.varsanofiev.com/inside/airopeekv9.htm, the help from
45  * Martin Regner and Guy Harris, and the etherpeek.c file (as it
46  * was called before renaming it to peekclassic.c).
47  */
48
49 /*
50  * Section header.
51  *
52  * A Peek tagged file consists of multiple sections, each of which begins
53  * with a header in the following format.
54  *
55  * The section ID is a 4-character string saying what type of section
56  * it is.  The section length is a little-endian field giving the
57  * length of the section, in bytes, including the section header
58  * itself.  The other field of the section header is a little-endian
59  * constant that always appears to be 0x00000200.
60  *
61  * Files we've seen have the following sections, in order:
62  *
63  * "\177vers" - version information.  The contents are XML, giving
64  * the file format version and application version information.
65  *
66  * "sess" - capture session information.  The contents are XML, giving
67  * various information about the capture session.
68  *
69  * "pkts" - captured packets.  The contents are binary records, one for
70  * each packet, with the record being a list of tagged values followed
71  * by the raw packet data.
72  */
73 typedef struct peektagged_section_header {
74         gint8   section_id[4];          /* string identifying the section */
75         guint32 section_len;            /* little-endian section length */
76         guint32 section_const;          /* little-endian 0x00000200 */
77 } peektagged_section_header_t;
78
79 /*
80  * Network subtype values.
81  *
82  * XXX - do different network subtype values for 802.11 indicate different
83  * network adapter types, with some adapters supplying the FCS and others
84  * not supplying the FCS?
85  */
86 #define PEEKTAGGED_NST_ETHERNET         0
87 #define PEEKTAGGED_NST_802_11           1       /* 802.11 with 0's at the end */
88 #define PEEKTAGGED_NST_802_11_2         2       /* 802.11 with 0's at the end */
89 #define PEEKTAGGED_NST_802_11_WITH_FCS  3       /* 802.11 with FCS at the end */
90
91 /* tags for fields in packet header */
92 #define TAG_PEEKTAGGED_LENGTH                   0x0000
93 #define TAG_PEEKTAGGED_TIMESTAMP_LOWER          0x0001
94 #define TAG_PEEKTAGGED_TIMESTAMP_UPPER          0x0002
95 #define TAG_PEEKTAGGED_FLAGS_AND_STATUS         0x0003  /* upper 24 bits unused? */
96 #define TAG_PEEKTAGGED_CHANNEL                  0x0004
97 #define TAG_PEEKTAGGED_DATA_RATE_OR_MCS_INDEX   0x0005
98 #define TAG_PEEKTAGGED_SIGNAL_PERC              0x0006
99 #define TAG_PEEKTAGGED_SIGNAL_DBM               0x0007
100 #define TAG_PEEKTAGGED_NOISE_PERC               0x0008
101 #define TAG_PEEKTAGGED_NOISE_DBM                0x0009
102 #define TAG_PEEKTAGGED_UNKNOWN_0x000A           0x000A
103 #define TAG_PEEKTAGGED_CENTER_FREQUENCY         0x000D  /* Frequency */
104 #define TAG_PEEKTAGGED_UNKNOWN_0x000E           0x000E  /* "Band"? */
105 #define TAG_PEEKTAGGED_UNKNOWN_0x000F           0x000F  /* antenna 2 signal dBm? */
106 #define TAG_PEEKTAGGED_UNKNOWN_0x0010           0x0010  /* antenna 3 signal dBm? */
107 #define TAG_PEEKTAGGED_UNKNOWN_0x0011           0x0011  /* antenna 4 signal dBm? */
108 #define TAG_PEEKTAGGED_UNKNOWN_0x0012           0x0012  /* antenna 2 noise dBm? */
109 #define TAG_PEEKTAGGED_UNKNOWN_0x0013           0x0013  /* antenna 3 noise dBm? */
110 #define TAG_PEEKTAGGED_UNKNOWN_0x0014           0x0014  /* antenna 4 noise dBm? */
111 #define TAG_PEEKTAGGED_EXT_FLAGS                0x0015  /* Extended flags for 802.11n and beyond */
112
113 #define TAG_PEEKTAGGED_SLICE_LENGTH             0xffff
114
115 /*
116  * Flags.
117  *
118  * We're assuming here that the "remote Peek" flags from bug 9586 are
119  * the same as the "Peek tagged" flags.
120  */
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
125 /*
126  * Status.
127  *
128  * Is this in the next 8 bits of the "flags and status" field?
129  */
130 #define STATUS_PROTECTED        0x0400  /* Frame is protected (encrypted) */
131 #define STATUS_DECRYPT_ERROR    0x0800  /* Error decrypting protected frame */
132 #define STATUS_SHORT_PREAMBLE   0x4000  /* Short preamble */
133
134 /*
135  * Extended flags.
136  *
137  * Some determined from bug 10637, some determined from bug 9586,
138  * and the ones present in both agree, so we're assuming that
139  * the "remote Peek" protocol and the "Peek tagged" file format
140  * use the same bits (which wouldn't be too surprising, as they
141  * both come from Wildpackets).
142  */
143 #define EXT_FLAG_20_MHZ_LOWER                   0x00000001
144 #define EXT_FLAG_20_MHZ_UPPER                   0x00000002
145 #define EXT_FLAG_40_MHZ                         0x00000004
146 #define EXT_FLAGS_BANDWIDTH                     0x00000007
147 #define EXT_FLAG_HALF_GI                        0x00000008
148 #define EXT_FLAG_FULL_GI                        0x00000010
149 #define EXT_FLAGS_GI                            0x00000018
150 #define EXT_FLAG_AMPDU                          0x00000020
151 #define EXT_FLAG_AMSDU                          0x00000040
152 #define EXT_FLAG_802_11ac                       0x00000080
153 #define EXT_FLAG_MCS_INDEX_USED                 0x00000100
154
155 /* 64-bit time in nanoseconds from the (Windows FILETIME) epoch */
156 typedef struct peektagged_utime {
157         guint32 upper;
158         guint32 lower;
159 } peektagged_utime;
160
161 typedef struct {
162         gboolean        has_fcs;
163 } peektagged_t;
164
165 static gboolean peektagged_read(wtap *wth, int *err, gchar **err_info,
166     gint64 *data_offset);
167 static gboolean peektagged_seek_read(wtap *wth, gint64 seek_off,
168     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info);
169
170 static int wtap_file_read_pattern (wtap *wth, const char *pattern, int *err,
171                                 gchar **err_info)
172 {
173     int c;
174     const char *cp;
175
176     cp = pattern;
177     while (*cp)
178     {
179         c = file_getc(wth->fh);
180         if (c == EOF)
181         {
182             *err = file_error(wth->fh, err_info);
183             if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
184                 return -1;      /* error */
185             return 0;   /* EOF */
186         }
187         if (c == *cp)
188             cp++;
189         else
190         {
191             if (c == pattern[0])
192                 cp = &pattern[1];
193             else
194                 cp = pattern;
195         }
196     }
197     return (*cp == '\0' ? 1 : 0);
198 }
199
200
201 static int wtap_file_read_till_separator (wtap *wth, char *buffer, int buflen,
202                                         const char *separators, int *err,
203                                         gchar **err_info)
204 {
205     int c;
206     char *cp;
207     int i;
208
209     for (cp = buffer, i = 0; i < buflen; i++, cp++)
210     {
211         c = file_getc(wth->fh);
212         if (c == EOF)
213         {
214             *err = file_error(wth->fh, err_info);
215             if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
216                 return -1;      /* error */
217             return 0;   /* EOF */
218         }
219         if (strchr (separators, c) != NULL)
220         {
221             *cp = '\0';
222             break;
223         }
224         else
225             *cp = c;
226     }
227     return i;
228 }
229
230
231 static int wtap_file_read_number (wtap *wth, guint32 *num, int *err,
232                                 gchar **err_info)
233 {
234     int ret;
235     char str_num[12];
236     unsigned long value;
237     char *p;
238
239     ret = wtap_file_read_till_separator (wth, str_num, sizeof (str_num)-1, "<",
240                                          err, err_info);
241     if (ret == 0 || ret == -1) {
242         /* 0 means EOF, which means "not a valid Peek tagged file";
243            -1 means error, and "err" has been set. */
244         return ret;
245     }
246     value = strtoul (str_num, &p, 10);
247     if (p == str_num || value > G_MAXUINT32)
248         return 0;
249     *num = (guint32)value;
250     return 1;
251 }
252
253
254 wtap_open_return_val peektagged_open(wtap *wth, int *err, gchar **err_info)
255 {
256     peektagged_section_header_t ap_hdr;
257     int ret;
258     guint32 fileVersion = 0;
259     guint32 mediaType;
260     guint32 mediaSubType = 0;
261     int file_encap;
262     static const int peektagged_encap[] = {
263         WTAP_ENCAP_ETHERNET,
264         WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
265         WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
266         WTAP_ENCAP_IEEE_802_11_WITH_RADIO
267     };
268     #define NUM_PEEKTAGGED_ENCAPS (sizeof peektagged_encap / sizeof peektagged_encap[0])
269     peektagged_t *peektagged;
270
271     if (!wtap_read_bytes(wth->fh, &ap_hdr, (int)sizeof(ap_hdr), err, err_info)) {
272         if (*err != WTAP_ERR_SHORT_READ)
273             return WTAP_OPEN_ERROR;
274         return WTAP_OPEN_NOT_MINE;
275     }
276
277     if (memcmp (ap_hdr.section_id, "\177ver", sizeof(ap_hdr.section_id)) != 0)
278         return WTAP_OPEN_NOT_MINE;      /* doesn't begin with a "\177ver" section */
279
280     /*
281      * XXX - we should get the length of the "\177ver" section, check
282      * that it's followed by a little-endian 0x00000200, and then,
283      * when reading the XML, make sure we don't go past the end of
284      * that section, and skip to the end of that section when
285      * we have the file version (and possibly check to make sure all
286      * tags are properly opened and closed).
287      */
288     ret = wtap_file_read_pattern (wth, "<FileVersion>", err, err_info);
289     if (ret == -1)
290         return WTAP_OPEN_ERROR;
291     if (ret == 0) {
292         /* 0 means EOF, which means "not a valid Peek tagged file" */
293         return WTAP_OPEN_NOT_MINE;
294     }
295     ret = wtap_file_read_number (wth, &fileVersion, err, err_info);
296     if (ret == -1)
297         return WTAP_OPEN_ERROR;
298     if (ret == 0) {
299         /* 0 means EOF, which means "not a valid Peek tagged file" */
300         return WTAP_OPEN_NOT_MINE;
301     }
302
303     /* If we got this far, we assume it's a Peek tagged file. */
304     if (fileVersion != 9) {
305         /* We only support version 9. */
306         *err = WTAP_ERR_UNSUPPORTED;
307         *err_info = g_strdup_printf("peektagged: version %u unsupported",
308             fileVersion);
309         return WTAP_OPEN_ERROR;
310     }
311
312     /*
313      * XXX - once we've skipped the "\177ver" section, we should
314      * check for a "sess" section and fail if we don't see it.
315      * Then we should get the length of the "sess" section, check
316      * that it's followed by a little-endian 0x00000200, and then,
317      * when reading the XML, make sure we don't go past the end of
318      * that section, and skip to the end of the section when
319      * we have the file version (and possibly check to make sure all
320      * tags are properly opened and closed).
321      */
322     ret = wtap_file_read_pattern (wth, "<MediaType>", err, err_info);
323     if (ret == -1)
324         return WTAP_OPEN_ERROR;
325     if (ret == 0) {
326         *err = WTAP_ERR_BAD_FILE;
327         *err_info = g_strdup("peektagged: <MediaType> tag not found");
328         return WTAP_OPEN_ERROR;
329     }
330     /* XXX - this appears to be 0 in both the EtherPeek and AiroPeek
331        files we've seen; should we require it to be 0? */
332     ret = wtap_file_read_number (wth, &mediaType, err, err_info);
333     if (ret == -1)
334         return WTAP_OPEN_ERROR;
335     if (ret == 0) {
336         *err = WTAP_ERR_BAD_FILE;
337         *err_info = g_strdup("peektagged: <MediaType> value not found");
338         return WTAP_OPEN_ERROR;
339     }
340
341     ret = wtap_file_read_pattern (wth, "<MediaSubType>", err, err_info);
342     if (ret == -1)
343         return WTAP_OPEN_ERROR;
344     if (ret == 0) {
345         *err = WTAP_ERR_BAD_FILE;
346         *err_info = g_strdup("peektagged: <MediaSubType> tag not found");
347         return WTAP_OPEN_ERROR;
348     }
349     ret = wtap_file_read_number (wth, &mediaSubType, err, err_info);
350     if (ret == -1)
351         return WTAP_OPEN_ERROR;
352     if (ret == 0) {
353         *err = WTAP_ERR_BAD_FILE;
354         *err_info = g_strdup("peektagged: <MediaSubType> value not found");
355         return WTAP_OPEN_ERROR;
356     }
357     if (mediaSubType >= NUM_PEEKTAGGED_ENCAPS
358         || peektagged_encap[mediaSubType] == WTAP_ENCAP_UNKNOWN) {
359         *err = WTAP_ERR_UNSUPPORTED;
360         *err_info = g_strdup_printf("peektagged: network type %u unknown or unsupported",
361             mediaSubType);
362         return WTAP_OPEN_ERROR;
363     }
364
365     ret = wtap_file_read_pattern (wth, "pkts", err, err_info);
366     if (ret == -1)
367         return WTAP_OPEN_ERROR;
368     if (ret == 0) {
369         *err = WTAP_ERR_SHORT_READ;
370         return WTAP_OPEN_ERROR;
371     }
372
373     /* skip 8 zero bytes */
374     if (file_seek (wth->fh, 8L, SEEK_CUR, err) == -1)
375         return WTAP_OPEN_NOT_MINE;
376
377     /*
378      * This is an Peek tagged file.
379      */
380     file_encap = peektagged_encap[mediaSubType];
381
382     wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PEEKTAGGED;
383     wth->file_encap = file_encap;
384     wth->subtype_read = peektagged_read;
385     wth->subtype_seek_read = peektagged_seek_read;
386     wth->file_tsprec = WTAP_TSPREC_NSEC;
387
388     peektagged = (peektagged_t *)g_malloc(sizeof(peektagged_t));
389     wth->priv = (void *)peektagged;
390     switch (mediaSubType) {
391
392     case PEEKTAGGED_NST_ETHERNET:
393     case PEEKTAGGED_NST_802_11:
394     case PEEKTAGGED_NST_802_11_2:
395         peektagged->has_fcs = FALSE;
396         break;
397
398     case PEEKTAGGED_NST_802_11_WITH_FCS:
399         peektagged->has_fcs = TRUE;
400         break;
401     }
402
403     wth->snapshot_length   = 0; /* not available in header */
404
405     return WTAP_OPEN_MINE;
406 }
407
408 /*
409  * Read the packet.
410  *
411  * XXX - we should supply the additional radio information;
412  * the pseudo-header should probably be supplied in a fashion
413  * similar to the radiotap radio header, so that the 802.11
414  * dissector can determine which, if any, information items
415  * are present.
416  */
417 static int
418 peektagged_read_packet(wtap *wth, FILE_T fh, struct wtap_pkthdr *phdr,
419                        Buffer *buf, int *err, gchar **err_info)
420 {
421     peektagged_t *peektagged = (peektagged_t *)wth->priv;
422     gboolean read_a_tag = FALSE;
423     guint8 tag_value[6];
424     guint16 tag;
425     gboolean saw_length = FALSE;
426     guint32 length = 0;
427     guint32 sliceLength = 0;
428     gboolean saw_timestamp_lower = FALSE;
429     gboolean saw_timestamp_upper = FALSE;
430     peektagged_utime timestamp;
431     guint32 ext_flags = 0;
432     gboolean saw_data_rate_or_mcs_index = FALSE;
433     guint32 data_rate_or_mcs_index = 0;
434     struct ieee_802_11_phdr ieee_802_11;
435     int skip_len = 0;
436     guint64 t;
437
438     timestamp.upper = 0;
439     timestamp.lower = 0;
440     /* Shouldn't be necessary, but squelches a compiler warning. */
441     memset(&ieee_802_11, 0, sizeof ieee_802_11);
442     ieee_802_11.fcs_len = -1; /* Unknown */
443     ieee_802_11.decrypted = FALSE;
444     ieee_802_11.datapad = FALSE;
445     ieee_802_11.phy = PHDR_802_11_PHY_UNKNOWN;
446     ieee_802_11.presence_flags = 0;
447
448     /* Extract the fields from the packet header */
449     do {
450         /* Get the tag and value.
451            XXX - this assumes all values are 4 bytes long. */
452         if (!wtap_read_bytes_or_eof(fh, tag_value, sizeof tag_value, err, err_info)) {
453             if (*err == 0) {
454                 /*
455                  * Short read if we've read something already;
456                  * just an EOF if we haven't.
457                  */
458                 if (read_a_tag)
459                     *err = WTAP_ERR_SHORT_READ;
460             }
461             return -1;
462         }
463         read_a_tag = TRUE;
464         tag = pletoh16(&tag_value[0]);
465         switch (tag) {
466
467         case TAG_PEEKTAGGED_LENGTH:
468             if (saw_length) {
469                 *err = WTAP_ERR_BAD_FILE;
470                 *err_info = g_strdup("peektagged: record has two length fields");
471                 return -1;
472             }
473             length = pletoh32(&tag_value[2]);
474             saw_length = TRUE;
475             break;
476
477         case TAG_PEEKTAGGED_TIMESTAMP_LOWER:
478             if (saw_timestamp_lower) {
479                 *err = WTAP_ERR_BAD_FILE;
480                 *err_info = g_strdup("peektagged: record has two timestamp-lower fields");
481                 return -1;
482             }
483             timestamp.lower = pletoh32(&tag_value[2]);
484             saw_timestamp_lower = TRUE;
485             break;
486
487         case TAG_PEEKTAGGED_TIMESTAMP_UPPER:
488             if (saw_timestamp_upper) {
489                 *err = WTAP_ERR_BAD_FILE;
490                 *err_info = g_strdup("peektagged: record has two timestamp-upper fields");
491                 return -1;
492             }
493             timestamp.upper = pletoh32(&tag_value[2]);
494             saw_timestamp_upper = TRUE;
495             break;
496
497         case TAG_PEEKTAGGED_FLAGS_AND_STATUS:
498             /* XXX - not used yet */
499             break;
500
501         case TAG_PEEKTAGGED_CHANNEL:
502             ieee_802_11.presence_flags |= PHDR_802_11_HAS_CHANNEL;
503             ieee_802_11.channel = pletoh32(&tag_value[2]);
504             break;
505
506         case TAG_PEEKTAGGED_DATA_RATE_OR_MCS_INDEX:
507             data_rate_or_mcs_index = pletoh32(&tag_value[2]);
508             saw_data_rate_or_mcs_index = TRUE;
509             break;
510
511         case TAG_PEEKTAGGED_SIGNAL_PERC:
512             ieee_802_11.presence_flags |= PHDR_802_11_HAS_SIGNAL_PERCENT;
513             ieee_802_11.signal_percent = pletoh32(&tag_value[2]);
514             break;
515
516         case TAG_PEEKTAGGED_SIGNAL_DBM:
517             ieee_802_11.presence_flags |= PHDR_802_11_HAS_SIGNAL_DBM;
518             ieee_802_11.signal_dbm = pletoh32(&tag_value[2]);
519             break;
520
521         case TAG_PEEKTAGGED_NOISE_PERC:
522             ieee_802_11.presence_flags |= PHDR_802_11_HAS_NOISE_PERCENT;
523             ieee_802_11.noise_percent = pletoh32(&tag_value[2]);
524             break;
525
526         case TAG_PEEKTAGGED_NOISE_DBM:
527             ieee_802_11.presence_flags |= PHDR_802_11_HAS_NOISE_DBM;
528             ieee_802_11.noise_dbm = pletoh32(&tag_value[2]);
529             break;
530
531         case TAG_PEEKTAGGED_UNKNOWN_0x000A:
532             /*
533              * XXX - seen in some 802.11 captures.
534              * Always seems to have the value 0 or 5.
535              */
536             break;
537
538         case TAG_PEEKTAGGED_CENTER_FREQUENCY:
539             /* XXX - also seen in an EtherPeek capture; value unknown */
540             ieee_802_11.presence_flags |= PHDR_802_11_HAS_FREQUENCY;
541             ieee_802_11.frequency = pletoh32(&tag_value[2]);
542             break;
543
544         case TAG_PEEKTAGGED_UNKNOWN_0x000E:
545             /*
546              * XXX - seen in some 802.11 captures.
547              * Usually has the value 4, but, in some packets, has the
548              * values 6 or 302.
549              *
550              * Is this the mysterious "band" field that shows up in
551              * some "Peek remote" protocol captures, with values in
552              * the 30x or 40x ranges?  It's not always associated
553              * with the "extended flags" tag for HT/VHT information,
554              * so it's probably not 11n/11ac-specific.  Values other
555              * than 4 appear, in my captures, only in packets with
556              * the "extended flags" tag.  302 appeared in a packet
557              * with EXT_FLAG_MCS_INDEX_USED; 6 appeared in packets
558              * without EXT_FLAG_MCS_INDEX_USED.
559              */
560             break;
561
562         case TAG_PEEKTAGGED_UNKNOWN_0x000F:
563             /*
564              * XXX - seen in some 802.11 captures; dB or dBm value?
565              * Multiple antennas?
566              */
567             break;
568
569         case TAG_PEEKTAGGED_UNKNOWN_0x0010:
570             /*
571              * XXX - seen in some 802.11 captures; dB or dBm value?
572              * Multiple antennas?
573              */
574             break;
575
576         case TAG_PEEKTAGGED_UNKNOWN_0x0011:
577             /*
578              * XXX - seen in some 802.11 captures; dB or dBm value?
579              * Multiple antennas?
580              */
581             break;
582
583         case TAG_PEEKTAGGED_UNKNOWN_0x0012:
584             /*
585              * XXX - seen in some 802.11 captures; dB or dBm value?
586              * Multiple antennas?
587              */
588             break;
589
590         case TAG_PEEKTAGGED_UNKNOWN_0x0013:
591             /*
592              * XXX - seen in some 802.11 captures; dB or dBm value?
593              * Multiple antennas?
594              */
595             break;
596
597         case TAG_PEEKTAGGED_UNKNOWN_0x0014:
598             /*
599              * XXX - seen in some 802.11 captures; dB or dBm value?
600              * Multiple antennas?
601              */
602             break;
603
604         case TAG_PEEKTAGGED_EXT_FLAGS:
605             /*
606              * We assume this is present for HT and VHT frames and absent
607              * for other frames.
608              */
609             ext_flags = pletoh32(&tag_value[2]);
610             if (ext_flags & EXT_FLAG_802_11ac) {
611                 ieee_802_11.phy = PHDR_802_11_PHY_11AC;
612                 ieee_802_11.phy_info.info_11ac.presence_flags = 0;
613
614                 switch (ext_flags & EXT_FLAGS_GI) {
615
616                 case EXT_FLAG_HALF_GI:
617                     ieee_802_11.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_SHORT_GI;
618                     ieee_802_11.phy_info.info_11ac.short_gi = 1;
619                     break;
620
621                 case EXT_FLAG_FULL_GI:
622                     ieee_802_11.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_SHORT_GI;
623                     ieee_802_11.phy_info.info_11ac.short_gi = 0;
624                     break;
625
626                 default:
627                     /* Mutually exclusive flags set or nothing set */
628                     break;
629                 }
630             } else {
631                 ieee_802_11.phy = PHDR_802_11_PHY_11N;
632                 switch (ext_flags & EXT_FLAGS_BANDWIDTH) {
633
634                 case 0:
635                     ieee_802_11.phy_info.info_11n.presence_flags = PHDR_802_11N_HAS_BANDWIDTH;
636                     ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_MHZ;
637                     break;
638
639                 case EXT_FLAG_20_MHZ_LOWER:
640                     ieee_802_11.phy_info.info_11n.presence_flags = PHDR_802_11N_HAS_BANDWIDTH;
641                     ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_20L;
642                     break;
643
644                 case EXT_FLAG_20_MHZ_UPPER:
645                     ieee_802_11.phy_info.info_11n.presence_flags = PHDR_802_11N_HAS_BANDWIDTH;
646                     ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_20U;
647                     break;
648
649                 case EXT_FLAG_40_MHZ:
650                     ieee_802_11.phy_info.info_11n.presence_flags = PHDR_802_11N_HAS_BANDWIDTH;
651                     ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_40_MHZ;
652                     break;
653
654                 default:
655                     /* Mutually exclusive flags set */
656                     ieee_802_11.phy_info.info_11n.presence_flags = 0;
657                     break;
658                 }
659
660                 switch (ext_flags & EXT_FLAGS_GI) {
661
662                 case EXT_FLAG_HALF_GI:
663                     ieee_802_11.phy_info.info_11n.presence_flags |= PHDR_802_11N_HAS_SHORT_GI;
664                     ieee_802_11.phy_info.info_11n.short_gi = 1;
665                     break;
666
667                 case EXT_FLAG_FULL_GI:
668                     ieee_802_11.phy_info.info_11n.presence_flags |= PHDR_802_11N_HAS_SHORT_GI;
669                     ieee_802_11.phy_info.info_11n.short_gi = 0;
670                     break;
671
672                 default:
673                     /* Mutually exclusive flags set or nothing set */
674                     break;
675                 }
676             }
677             break;
678
679         case TAG_PEEKTAGGED_SLICE_LENGTH:
680             sliceLength = pletoh32(&tag_value[2]);
681             break;
682
683         default:
684             break;
685         }
686     } while (tag != TAG_PEEKTAGGED_SLICE_LENGTH);       /* last tag */
687
688     if (!saw_length) {
689         *err = WTAP_ERR_BAD_FILE;
690         *err_info = g_strdup("peektagged: record has no length field");
691         return -1;
692     }
693     if (!saw_timestamp_lower) {
694         *err = WTAP_ERR_BAD_FILE;
695         *err_info = g_strdup("peektagged: record has no timestamp-lower field");
696         return -1;
697     }
698     if (!saw_timestamp_upper) {
699         *err = WTAP_ERR_BAD_FILE;
700         *err_info = g_strdup("peektagged: record has no timestamp-upper field");
701         return -1;
702     }
703
704     /*
705      * If sliceLength is 0, force it to be the actual length of the packet.
706      */
707     if (sliceLength == 0)
708         sliceLength = length;
709
710     if (sliceLength > WTAP_MAX_PACKET_SIZE) {
711         /*
712          * Probably a corrupt capture file; don't blow up trying
713          * to allocate space for an immensely-large packet.
714          */
715         *err = WTAP_ERR_BAD_FILE;
716         *err_info = g_strdup_printf("peektagged: File has %u-byte packet, bigger than maximum of %u",
717             sliceLength, WTAP_MAX_PACKET_SIZE);
718         return -1;
719     }
720
721     phdr->rec_type = REC_TYPE_PACKET;
722     phdr->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
723     phdr->len    = length;
724     phdr->caplen = sliceLength;
725
726     /* calculate and fill in packet time stamp */
727     t = (((guint64) timestamp.upper) << 32) + timestamp.lower;
728     if (!nsfiletime_to_nstime(&phdr->ts, t)) {
729         *err = WTAP_ERR_BAD_FILE;
730         *err_info = g_strdup_printf("peektagged: time stamp outside supported range");
731         return -1;
732     }
733
734     switch (wth->file_encap) {
735
736     case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
737         if (saw_data_rate_or_mcs_index) {
738             if (ext_flags & EXT_FLAG_MCS_INDEX_USED) {
739                 /* It's an MCS index. */
740                 if (ext_flags & EXT_FLAG_802_11ac) {
741                     ieee_802_11.phy_info.info_11ac.presence_flags |= PHDR_802_11AC_HAS_MCS_INDEX;
742                     ieee_802_11.phy_info.info_11ac.mcs_index = data_rate_or_mcs_index;
743                 } else {
744                     ieee_802_11.phy_info.info_11n.presence_flags |= PHDR_802_11N_HAS_MCS_INDEX;
745                     ieee_802_11.phy_info.info_11n.mcs_index = data_rate_or_mcs_index;
746                 }
747             } else {
748                 /* It's a data rate. */
749                 ieee_802_11.presence_flags |= PHDR_802_11_HAS_DATA_RATE;
750                 ieee_802_11.data_rate = data_rate_or_mcs_index;
751             }
752         }
753         phdr->pseudo_header.ieee_802_11 = ieee_802_11;
754         if (peektagged->has_fcs)
755             phdr->pseudo_header.ieee_802_11.fcs_len = 4;
756         else {
757             if (phdr->len < 4 || phdr->caplen < 4) {
758                 *err = WTAP_ERR_BAD_FILE;
759                 *err_info = g_strdup_printf("peektagged: 802.11 packet has length < 4");
760                 return FALSE;
761             }
762             phdr->pseudo_header.ieee_802_11.fcs_len = 0;
763             phdr->len -= 4;
764             phdr->caplen -= 4;
765             skip_len = 4;
766         }
767         phdr->pseudo_header.ieee_802_11.decrypted = FALSE;
768         phdr->pseudo_header.ieee_802_11.datapad = FALSE;
769         break;
770
771     case WTAP_ENCAP_ETHERNET:
772         /*
773          * The last 4 bytes appear to be 0 in the captures I've seen;
774          * are there any captures where it's an FCS?
775          */
776         if (phdr->len < 4 || phdr->caplen < 4) {
777             *err = WTAP_ERR_BAD_FILE;
778             *err_info = g_strdup_printf("peektagged: Ethernet packet has length < 4");
779             return FALSE;
780         }
781         phdr->pseudo_header.eth.fcs_len = 0;
782         phdr->len -= 4;
783         phdr->caplen -= 4;
784         skip_len = 4;
785         break;
786     }
787
788     /* Read the packet data. */
789     if (!wtap_read_packet_bytes(fh, buf, phdr->caplen, err, err_info))
790         return -1;
791
792     return skip_len;
793 }
794
795 static gboolean peektagged_read(wtap *wth, int *err, gchar **err_info,
796     gint64 *data_offset)
797 {
798     int skip_len;
799
800     *data_offset = file_tell(wth->fh);
801
802     /* Read the packet. */
803     skip_len = peektagged_read_packet(wth, wth->fh, &wth->phdr,
804                                       wth->frame_buffer, err, err_info);
805     if (skip_len == -1)
806         return FALSE;
807
808     if (skip_len != 0) {
809         /* Skip extra junk at the end of the packet data. */
810         if (!file_skip(wth->fh, skip_len, err))
811             return FALSE;
812     }
813
814     return TRUE;
815 }
816
817 static gboolean
818 peektagged_seek_read(wtap *wth, gint64 seek_off,
819     struct wtap_pkthdr *phdr, Buffer *buf, int *err, gchar **err_info)
820 {
821     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
822         return FALSE;
823
824     /* Read the packet. */
825     if (peektagged_read_packet(wth, wth->random_fh, phdr, buf, err, err_info) == -1) {
826         if (*err == 0)
827             *err = WTAP_ERR_SHORT_READ;
828         return FALSE;
829     }
830     return TRUE;
831 }
832
833 /*
834  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
835  *
836  * Local variables:
837  * c-basic-offset: 4
838  * tab-width: 8
839  * indent-tabs-mode: nil
840  * End:
841  *
842  * vi: set shiftwidth=4 tabstop=8 expandtab:
843  * :indentSize=4:tabSize=8:noTabs=true:
844  */