0187d10e41ac36b66406bdc9132a4e23317d46f8
[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  * SPDX-License-Identifier: GPL-2.0-or-later
19  */
20
21 #include "config.h"
22 #include <errno.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include "wtap-int.h"
26 #include "file_wrappers.h"
27 #include "peektagged.h"
28 #include <wsutil/frequency-utils.h>
29
30 /* CREDITS
31  *
32  * This file decoder could not have been writen 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).
36  */
37
38 /*
39  * Section header.
40  *
41  * A Peek tagged file consists of multiple sections, each of which begins
42  * with a header in the following format.
43  *
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.
49  *
50  * Files we've seen have the following sections, in order:
51  *
52  * "\177vers" - version information.  The contents are XML, giving
53  * the file format version and application version information.
54  *
55  * "sess" - capture session information.  The contents are XML, giving
56  * various information about the capture session.
57  *
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.
61  */
62 typedef struct peektagged_section_header {
63         gint8   section_id[4];          /* string identifying the section */
64         guint32 section_len;            /* little-endian section length */
65         guint32 section_const;          /* little-endian 0x00000200 */
66 } peektagged_section_header_t;
67
68 /*
69  * Network subtype values.
70  *
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?
74  */
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 */
79
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 */
101
102 #define TAG_PEEKTAGGED_SLICE_LENGTH             0xffff
103
104 /*
105  * Flags.
106  *
107  * We're assuming here that the "remote Peek" flags from bug 9586 are
108  * the same as the "Peek tagged" flags.
109  *
110  * Are these the same as in "Peek classic"?  The first three are.
111  */
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 */
115
116 /*
117  * Status.
118  *
119  * Is this in the next 8 bits of the "flags and status" field?
120  */
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 */
124
125 /*
126  * Extended flags.
127  *
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).
133  */
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
145
146 /* 64-bit time in nanoseconds from the (Windows FILETIME) epoch */
147 typedef struct peektagged_utime {
148         guint32 upper;
149         guint32 lower;
150 } peektagged_utime;
151
152 typedef struct {
153         gboolean        has_fcs;
154 } peektagged_t;
155
156 static gboolean peektagged_read(wtap *wth, int *err, gchar **err_info,
157     gint64 *data_offset);
158 static gboolean peektagged_seek_read(wtap *wth, gint64 seek_off,
159     wtap_rec *rec, Buffer *buf, int *err, gchar **err_info);
160
161 static int wtap_file_read_pattern (wtap *wth, const char *pattern, int *err,
162                                 gchar **err_info)
163 {
164     int c;
165     const char *cp;
166
167     cp = pattern;
168     while (*cp)
169     {
170         c = file_getc(wth->fh);
171         if (c == EOF)
172         {
173             *err = file_error(wth->fh, err_info);
174             if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
175                 return -1;      /* error */
176             return 0;   /* EOF */
177         }
178         if (c == *cp)
179             cp++;
180         else
181         {
182             if (c == pattern[0])
183                 cp = &pattern[1];
184             else
185                 cp = pattern;
186         }
187     }
188     return (*cp == '\0' ? 1 : 0);
189 }
190
191
192 static int wtap_file_read_till_separator (wtap *wth, char *buffer, int buflen,
193                                         const char *separators, int *err,
194                                         gchar **err_info)
195 {
196     int c;
197     char *cp;
198     int i;
199
200     for (cp = buffer, i = 0; i < buflen; i++, cp++)
201     {
202         c = file_getc(wth->fh);
203         if (c == EOF)
204         {
205             *err = file_error(wth->fh, err_info);
206             if (*err != 0 && *err != WTAP_ERR_SHORT_READ)
207                 return -1;      /* error */
208             return 0;   /* EOF */
209         }
210         if (strchr (separators, c) != NULL)
211         {
212             *cp = '\0';
213             break;
214         }
215         else
216             *cp = c;
217     }
218     return i;
219 }
220
221
222 static int wtap_file_read_number (wtap *wth, guint32 *num, int *err,
223                                 gchar **err_info)
224 {
225     int ret;
226     char str_num[12];
227     unsigned long value;
228     char *p;
229
230     ret = wtap_file_read_till_separator (wth, str_num, sizeof (str_num)-1, "<",
231                                          err, err_info);
232     if (ret == 0 || ret == -1) {
233         /* 0 means EOF, which means "not a valid Peek tagged file";
234            -1 means error, and "err" has been set. */
235         return ret;
236     }
237     value = strtoul (str_num, &p, 10);
238     if (p == str_num || value > G_MAXUINT32)
239         return 0;
240     *num = (guint32)value;
241     return 1;
242 }
243
244
245 wtap_open_return_val peektagged_open(wtap *wth, int *err, gchar **err_info)
246 {
247     peektagged_section_header_t ap_hdr;
248     int ret;
249     guint32 fileVersion = 0;
250     guint32 mediaType;
251     guint32 mediaSubType = 0;
252     int file_encap;
253     static const int peektagged_encap[] = {
254         WTAP_ENCAP_ETHERNET,
255         WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
256         WTAP_ENCAP_IEEE_802_11_WITH_RADIO,
257         WTAP_ENCAP_IEEE_802_11_WITH_RADIO
258     };
259     #define NUM_PEEKTAGGED_ENCAPS (sizeof peektagged_encap / sizeof peektagged_encap[0])
260     peektagged_t *peektagged;
261
262     if (!wtap_read_bytes(wth->fh, &ap_hdr, (int)sizeof(ap_hdr), err, err_info)) {
263         if (*err != WTAP_ERR_SHORT_READ)
264             return WTAP_OPEN_ERROR;
265         return WTAP_OPEN_NOT_MINE;
266     }
267
268     if (memcmp (ap_hdr.section_id, "\177ver", sizeof(ap_hdr.section_id)) != 0)
269         return WTAP_OPEN_NOT_MINE;      /* doesn't begin with a "\177ver" section */
270
271     /*
272      * XXX - we should get the length of the "\177ver" section, check
273      * that it's followed by a little-endian 0x00000200, and then,
274      * when reading the XML, make sure we don't go past the end of
275      * that section, and skip to the end of that section when
276      * we have the file version (and possibly check to make sure all
277      * tags are properly opened and closed).
278      */
279     ret = wtap_file_read_pattern (wth, "<FileVersion>", err, err_info);
280     if (ret == -1)
281         return WTAP_OPEN_ERROR;
282     if (ret == 0) {
283         /* 0 means EOF, which means "not a valid Peek tagged file" */
284         return WTAP_OPEN_NOT_MINE;
285     }
286     ret = wtap_file_read_number (wth, &fileVersion, err, err_info);
287     if (ret == -1)
288         return WTAP_OPEN_ERROR;
289     if (ret == 0) {
290         /* 0 means EOF, which means "not a valid Peek tagged file" */
291         return WTAP_OPEN_NOT_MINE;
292     }
293
294     /* If we got this far, we assume it's a Peek tagged file. */
295     if (fileVersion != 9) {
296         /* We only support version 9. */
297         *err = WTAP_ERR_UNSUPPORTED;
298         *err_info = g_strdup_printf("peektagged: version %u unsupported",
299             fileVersion);
300         return WTAP_OPEN_ERROR;
301     }
302
303     /*
304      * XXX - once we've skipped the "\177ver" section, we should
305      * check for a "sess" section and fail if we don't see it.
306      * Then we should get the length of the "sess" section, check
307      * that it's followed by a little-endian 0x00000200, and then,
308      * when reading the XML, make sure we don't go past the end of
309      * that section, and skip to the end of the section when
310      * we have the file version (and possibly check to make sure all
311      * tags are properly opened and closed).
312      */
313     ret = wtap_file_read_pattern (wth, "<MediaType>", err, err_info);
314     if (ret == -1)
315         return WTAP_OPEN_ERROR;
316     if (ret == 0) {
317         *err = WTAP_ERR_BAD_FILE;
318         *err_info = g_strdup("peektagged: <MediaType> tag not found");
319         return WTAP_OPEN_ERROR;
320     }
321     /* XXX - this appears to be 0 in both the EtherPeek and AiroPeek
322        files we've seen; should we require it to be 0? */
323     ret = wtap_file_read_number (wth, &mediaType, err, err_info);
324     if (ret == -1)
325         return WTAP_OPEN_ERROR;
326     if (ret == 0) {
327         *err = WTAP_ERR_BAD_FILE;
328         *err_info = g_strdup("peektagged: <MediaType> value not found");
329         return WTAP_OPEN_ERROR;
330     }
331
332     ret = wtap_file_read_pattern (wth, "<MediaSubType>", 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: <MediaSubType> tag not found");
338         return WTAP_OPEN_ERROR;
339     }
340     ret = wtap_file_read_number (wth, &mediaSubType, err, err_info);
341     if (ret == -1)
342         return WTAP_OPEN_ERROR;
343     if (ret == 0) {
344         *err = WTAP_ERR_BAD_FILE;
345         *err_info = g_strdup("peektagged: <MediaSubType> value not found");
346         return WTAP_OPEN_ERROR;
347     }
348     if (mediaSubType >= NUM_PEEKTAGGED_ENCAPS
349         || peektagged_encap[mediaSubType] == WTAP_ENCAP_UNKNOWN) {
350         *err = WTAP_ERR_UNSUPPORTED;
351         *err_info = g_strdup_printf("peektagged: network type %u unknown or unsupported",
352             mediaSubType);
353         return WTAP_OPEN_ERROR;
354     }
355
356     ret = wtap_file_read_pattern (wth, "pkts", err, err_info);
357     if (ret == -1)
358         return WTAP_OPEN_ERROR;
359     if (ret == 0) {
360         *err = WTAP_ERR_SHORT_READ;
361         return WTAP_OPEN_ERROR;
362     }
363
364     /* skip 8 zero bytes */
365     if (!wtap_read_bytes (wth->fh, NULL, 8, err, err_info)) {
366         return WTAP_OPEN_ERROR;
367     }
368
369     /*
370      * This is an Peek tagged file.
371      */
372     file_encap = peektagged_encap[mediaSubType];
373
374     wth->file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_PEEKTAGGED;
375     wth->file_encap = file_encap;
376     wth->subtype_read = peektagged_read;
377     wth->subtype_seek_read = peektagged_seek_read;
378     wth->file_tsprec = WTAP_TSPREC_NSEC;
379
380     peektagged = (peektagged_t *)g_malloc(sizeof(peektagged_t));
381     wth->priv = (void *)peektagged;
382     switch (mediaSubType) {
383
384     case PEEKTAGGED_NST_ETHERNET:
385     case PEEKTAGGED_NST_802_11:
386     case PEEKTAGGED_NST_802_11_2:
387         peektagged->has_fcs = FALSE;
388         break;
389
390     case PEEKTAGGED_NST_802_11_WITH_FCS:
391         peektagged->has_fcs = TRUE;
392         break;
393     }
394
395     wth->snapshot_length   = 0; /* not available in header */
396
397     return WTAP_OPEN_MINE;
398 }
399
400 /*
401  * Read the packet.
402  *
403  * XXX - we should supply the additional radio information;
404  * the pseudo-header should probably be supplied in a fashion
405  * similar to the radiotap radio header, so that the 802.11
406  * dissector can determine which, if any, information items
407  * are present.
408  */
409 static int
410 peektagged_read_packet(wtap *wth, FILE_T fh, wtap_rec *rec,
411                        Buffer *buf, int *err, gchar **err_info)
412 {
413     peektagged_t *peektagged = (peektagged_t *)wth->priv;
414     gboolean read_a_tag = FALSE;
415     guint8 tag_value[6];
416     guint16 tag;
417     gboolean saw_length = FALSE;
418     guint32 length = 0;
419     guint32 sliceLength = 0;
420     gboolean saw_timestamp_lower = FALSE;
421     gboolean saw_timestamp_upper = FALSE;
422     peektagged_utime timestamp;
423     guint32 ext_flags = 0;
424     gboolean saw_data_rate_or_mcs_index = FALSE;
425     guint32 data_rate_or_mcs_index = 0;
426     gint channel;
427     guint frequency;
428     struct ieee_802_11_phdr ieee_802_11;
429     guint i;
430     int skip_len = 0;
431     guint64 t;
432
433     timestamp.upper = 0;
434     timestamp.lower = 0;
435     memset(&ieee_802_11, 0, sizeof ieee_802_11);
436     ieee_802_11.fcs_len = -1; /* Unknown */
437     ieee_802_11.decrypted = FALSE;
438     ieee_802_11.datapad = FALSE;
439     ieee_802_11.phy = PHDR_802_11_PHY_UNKNOWN;
440
441     /* Extract the fields from the packet header */
442     do {
443         /* Get the tag and value.
444            XXX - this assumes all values are 4 bytes long. */
445         if (!wtap_read_bytes_or_eof(fh, tag_value, sizeof tag_value, err, err_info)) {
446             if (*err == 0) {
447                 /*
448                  * Short read if we've read something already;
449                  * just an EOF if we haven't.
450                  */
451                 if (read_a_tag)
452                     *err = WTAP_ERR_SHORT_READ;
453             }
454             return -1;
455         }
456         read_a_tag = TRUE;
457         tag = pletoh16(&tag_value[0]);
458         switch (tag) {
459
460         case TAG_PEEKTAGGED_LENGTH:
461             if (saw_length) {
462                 *err = WTAP_ERR_BAD_FILE;
463                 *err_info = g_strdup("peektagged: record has two length fields");
464                 return -1;
465             }
466             length = pletoh32(&tag_value[2]);
467             saw_length = TRUE;
468             break;
469
470         case TAG_PEEKTAGGED_TIMESTAMP_LOWER:
471             if (saw_timestamp_lower) {
472                 *err = WTAP_ERR_BAD_FILE;
473                 *err_info = g_strdup("peektagged: record has two timestamp-lower fields");
474                 return -1;
475             }
476             timestamp.lower = pletoh32(&tag_value[2]);
477             saw_timestamp_lower = TRUE;
478             break;
479
480         case TAG_PEEKTAGGED_TIMESTAMP_UPPER:
481             if (saw_timestamp_upper) {
482                 *err = WTAP_ERR_BAD_FILE;
483                 *err_info = g_strdup("peektagged: record has two timestamp-upper fields");
484                 return -1;
485             }
486             timestamp.upper = pletoh32(&tag_value[2]);
487             saw_timestamp_upper = TRUE;
488             break;
489
490         case TAG_PEEKTAGGED_FLAGS_AND_STATUS:
491             /* XXX - not used yet */
492             break;
493
494         case TAG_PEEKTAGGED_CHANNEL:
495             ieee_802_11.has_channel = TRUE;
496             ieee_802_11.channel = pletoh32(&tag_value[2]);
497             break;
498
499         case TAG_PEEKTAGGED_DATA_RATE_OR_MCS_INDEX:
500             data_rate_or_mcs_index = pletoh32(&tag_value[2]);
501             saw_data_rate_or_mcs_index = TRUE;
502             break;
503
504         case TAG_PEEKTAGGED_SIGNAL_PERC:
505             ieee_802_11.has_signal_percent = TRUE;
506             ieee_802_11.signal_percent = pletoh32(&tag_value[2]);
507             break;
508
509         case TAG_PEEKTAGGED_SIGNAL_DBM:
510             ieee_802_11.has_signal_dbm = TRUE;
511             ieee_802_11.signal_dbm = pletoh32(&tag_value[2]);
512             break;
513
514         case TAG_PEEKTAGGED_NOISE_PERC:
515             ieee_802_11.has_noise_percent = TRUE;
516             ieee_802_11.noise_percent = pletoh32(&tag_value[2]);
517             break;
518
519         case TAG_PEEKTAGGED_NOISE_DBM:
520             ieee_802_11.has_noise_dbm = TRUE;
521             ieee_802_11.noise_dbm = pletoh32(&tag_value[2]);
522             break;
523
524         case TAG_PEEKTAGGED_UNKNOWN_0x000A:
525             /*
526              * XXX - seen in some 802.11 captures.
527              * Always seems to have the value 0 or 5.
528              */
529             break;
530
531         case TAG_PEEKTAGGED_CENTER_FREQUENCY:
532             /* XXX - also seen in an EtherPeek capture; value unknown */
533             ieee_802_11.has_frequency = TRUE;
534             ieee_802_11.frequency = pletoh32(&tag_value[2]);
535             break;
536
537         case TAG_PEEKTAGGED_UNKNOWN_0x000E:
538             /*
539              * XXX - seen in some 802.11 captures.
540              * Usually has the value 4, but, in some packets, has the
541              * values 6 or 302.
542              *
543              * Is this the mysterious "band" field that shows up in
544              * some "Peek remote" protocol captures, with values in
545              * the 30x or 40x ranges?  It's not always associated
546              * with the "extended flags" tag for HT/VHT information,
547              * so it's probably not 11n/11ac-specific.  Values other
548              * than 4 appear, in my captures, only in packets with
549              * the "extended flags" tag.  302 appeared in a packet
550              * with EXT_FLAG_MCS_INDEX_USED; 6 appeared in packets
551              * without EXT_FLAG_MCS_INDEX_USED.
552              */
553             break;
554
555         case TAG_PEEKTAGGED_UNKNOWN_0x000F:
556             /*
557              * XXX - seen in some 802.11 captures; dB or dBm value?
558              * Multiple antennas?
559              */
560             break;
561
562         case TAG_PEEKTAGGED_UNKNOWN_0x0010:
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_0x0011:
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_0x0012:
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_0x0013:
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_0x0014:
591             /*
592              * XXX - seen in some 802.11 captures; dB or dBm value?
593              * Multiple antennas?
594              */
595             break;
596
597         case TAG_PEEKTAGGED_EXT_FLAGS:
598             /*
599              * We assume this is present for HT and VHT frames and absent
600              * for other frames.
601              */
602             ext_flags = pletoh32(&tag_value[2]);
603             if (ext_flags & EXT_FLAG_802_11ac) {
604                 ieee_802_11.phy = PHDR_802_11_PHY_11AC;
605                 /*
606                  * XXX - this probably has only one user, so only
607                  * one MCS index and only one NSS, but where's the
608                  * NSS?
609                  */
610                 for (i = 0; i < 4; i++)
611                     ieee_802_11.phy_info.info_11ac.nss[i] = 0;
612
613                 switch (ext_flags & EXT_FLAGS_GI) {
614
615                 case EXT_FLAG_HALF_GI:
616                     ieee_802_11.phy_info.info_11ac.has_short_gi = TRUE;
617                     ieee_802_11.phy_info.info_11ac.short_gi = 1;
618                     break;
619
620                 case EXT_FLAG_FULL_GI:
621                     ieee_802_11.phy_info.info_11ac.has_short_gi = TRUE;
622                     ieee_802_11.phy_info.info_11ac.short_gi = 0;
623                     break;
624
625                 default:
626                     /* Mutually exclusive flags set or nothing set */
627                     break;
628                 }
629             } else {
630                 ieee_802_11.phy = PHDR_802_11_PHY_11N;
631                 switch (ext_flags & EXT_FLAGS_BANDWIDTH) {
632
633                 case 0:
634                     ieee_802_11.phy_info.info_11n.has_bandwidth = TRUE;
635                     ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_MHZ;
636                     break;
637
638                 case EXT_FLAG_20_MHZ_LOWER:
639                     ieee_802_11.phy_info.info_11n.has_bandwidth = TRUE;
640                     ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_20L;
641                     break;
642
643                 case EXT_FLAG_20_MHZ_UPPER:
644                     ieee_802_11.phy_info.info_11n.has_bandwidth = TRUE;
645                     ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_20_20U;
646                     break;
647
648                 case EXT_FLAG_40_MHZ:
649                     ieee_802_11.phy_info.info_11n.has_bandwidth = TRUE;
650                     ieee_802_11.phy_info.info_11n.bandwidth = PHDR_802_11_BANDWIDTH_40_MHZ;
651                     break;
652
653                 default:
654                     /* Mutually exclusive flags set */
655                     break;
656                 }
657
658                 switch (ext_flags & EXT_FLAGS_GI) {
659
660                 case EXT_FLAG_HALF_GI:
661                     ieee_802_11.phy_info.info_11n.has_short_gi = TRUE;
662                     ieee_802_11.phy_info.info_11n.short_gi = 1;
663                     break;
664
665                 case EXT_FLAG_FULL_GI:
666                     ieee_802_11.phy_info.info_11n.has_short_gi = TRUE;
667                     ieee_802_11.phy_info.info_11n.short_gi = 0;
668                     break;
669
670                 default:
671                     /* Mutually exclusive flags set or nothing set */
672                     break;
673                 }
674             }
675             break;
676
677         case TAG_PEEKTAGGED_SLICE_LENGTH:
678             sliceLength = pletoh32(&tag_value[2]);
679             break;
680
681         default:
682             break;
683         }
684     } while (tag != TAG_PEEKTAGGED_SLICE_LENGTH);       /* last tag */
685
686     if (!saw_length) {
687         *err = WTAP_ERR_BAD_FILE;
688         *err_info = g_strdup("peektagged: record has no length field");
689         return -1;
690     }
691     if (!saw_timestamp_lower) {
692         *err = WTAP_ERR_BAD_FILE;
693         *err_info = g_strdup("peektagged: record has no timestamp-lower field");
694         return -1;
695     }
696     if (!saw_timestamp_upper) {
697         *err = WTAP_ERR_BAD_FILE;
698         *err_info = g_strdup("peektagged: record has no timestamp-upper field");
699         return -1;
700     }
701
702     /*
703      * If sliceLength is 0, force it to be the actual length of the packet.
704      */
705     if (sliceLength == 0)
706         sliceLength = length;
707
708     if (sliceLength > WTAP_MAX_PACKET_SIZE_STANDARD) {
709         /*
710          * Probably a corrupt capture file; don't blow up trying
711          * to allocate space for an immensely-large packet.
712          */
713         *err = WTAP_ERR_BAD_FILE;
714         *err_info = g_strdup_printf("peektagged: File has %u-byte packet, bigger than maximum of %u",
715             sliceLength, WTAP_MAX_PACKET_SIZE_STANDARD);
716         return -1;
717     }
718
719     rec->rec_type = REC_TYPE_PACKET;
720     rec->presence_flags = WTAP_HAS_TS|WTAP_HAS_CAP_LEN;
721     rec->rec_header.packet_header.len    = length;
722     rec->rec_header.packet_header.caplen = sliceLength;
723
724     /* calculate and fill in packet time stamp */
725     t = (((guint64) timestamp.upper) << 32) + timestamp.lower;
726     if (!nsfiletime_to_nstime(&rec->ts, t)) {
727         *err = WTAP_ERR_BAD_FILE;
728         *err_info = g_strdup("peektagged: time stamp outside supported range");
729         return -1;
730     }
731
732     switch (wth->file_encap) {
733
734     case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
735         if (saw_data_rate_or_mcs_index) {
736             if (ext_flags & EXT_FLAG_MCS_INDEX_USED) {
737                 /*
738                  * It's an MCS index.
739                  *
740                  * XXX - what about 11ac?
741                  */
742                 if (!(ext_flags & EXT_FLAG_802_11ac)) {
743                     ieee_802_11.phy_info.info_11n.has_mcs_index = TRUE;
744                     ieee_802_11.phy_info.info_11n.mcs_index = data_rate_or_mcs_index;
745                 }
746             } else {
747                 /* It's a data rate. */
748                 ieee_802_11.has_data_rate = TRUE;
749                 ieee_802_11.data_rate = data_rate_or_mcs_index;
750             }
751         }
752         if (ieee_802_11.has_frequency && !ieee_802_11.has_channel) {
753             /* Frequency, but no channel; try to calculate the channel. */
754             channel = ieee80211_mhz_to_chan(ieee_802_11.frequency);
755             if (channel != -1) {
756                 ieee_802_11.has_channel = TRUE;
757                 ieee_802_11.channel = channel;
758             }
759         } else if (ieee_802_11.has_channel && !ieee_802_11.has_frequency) {
760             /*
761              * If it's 11 legacy DHSS, 11b, or 11g, it's 2.4 GHz,
762              * so we can calculate the frequency.
763              *
764              * If it's 11a, it's 5 GHz, so we can calculate the
765              * frequency.
766              */
767             switch (ieee_802_11.phy) {
768
769             case PHDR_802_11_PHY_11_DSSS:
770             case PHDR_802_11_PHY_11B:
771             case PHDR_802_11_PHY_11G:
772                 frequency = ieee80211_chan_to_mhz(ieee_802_11.channel, TRUE);
773                 break;
774
775             case PHDR_802_11_PHY_11A:
776                 frequency = ieee80211_chan_to_mhz(ieee_802_11.channel, FALSE);
777                 break;
778
779             default:
780                 /* We don't know the band. */
781                 frequency = 0;
782                 break;
783             }
784             if (frequency != 0) {
785                 ieee_802_11.has_frequency = TRUE;
786                 ieee_802_11.frequency = frequency;
787             }
788         }
789         rec->rec_header.packet_header.pseudo_header.ieee_802_11 = ieee_802_11;
790         if (peektagged->has_fcs)
791             rec->rec_header.packet_header.pseudo_header.ieee_802_11.fcs_len = 4;
792         else {
793             if (rec->rec_header.packet_header.len < 4 || rec->rec_header.packet_header.caplen < 4) {
794                 *err = WTAP_ERR_BAD_FILE;
795                 *err_info = g_strdup_printf("peektagged: 802.11 packet has length < 4");
796                 return FALSE;
797             }
798             rec->rec_header.packet_header.pseudo_header.ieee_802_11.fcs_len = 0;
799             rec->rec_header.packet_header.len -= 4;
800             rec->rec_header.packet_header.caplen -= 4;
801             skip_len = 4;
802         }
803         rec->rec_header.packet_header.pseudo_header.ieee_802_11.decrypted = FALSE;
804         rec->rec_header.packet_header.pseudo_header.ieee_802_11.datapad = FALSE;
805         break;
806
807     case WTAP_ENCAP_ETHERNET:
808         /*
809          * The last 4 bytes appear to be 0 in the captures I've seen;
810          * are there any captures where it's an FCS?
811          */
812         if (rec->rec_header.packet_header.len < 4 || rec->rec_header.packet_header.caplen < 4) {
813             *err = WTAP_ERR_BAD_FILE;
814             *err_info = g_strdup_printf("peektagged: Ethernet packet has length < 4");
815             return FALSE;
816         }
817         rec->rec_header.packet_header.pseudo_header.eth.fcs_len = 0;
818         rec->rec_header.packet_header.len -= 4;
819         rec->rec_header.packet_header.caplen -= 4;
820         skip_len = 4;
821         break;
822     }
823
824     /* Read the packet data. */
825     if (!wtap_read_packet_bytes(fh, buf, rec->rec_header.packet_header.caplen, err, err_info))
826         return -1;
827
828     return skip_len;
829 }
830
831 static gboolean peektagged_read(wtap *wth, int *err, gchar **err_info,
832     gint64 *data_offset)
833 {
834     int skip_len;
835
836     *data_offset = file_tell(wth->fh);
837
838     /* Read the packet. */
839     skip_len = peektagged_read_packet(wth, wth->fh, &wth->rec,
840                                       wth->rec_data, err, err_info);
841     if (skip_len == -1)
842         return FALSE;
843
844     if (skip_len != 0) {
845         /* Skip extra junk at the end of the packet data. */
846         if (!wtap_read_bytes(wth->fh, NULL, skip_len, err, err_info))
847             return FALSE;
848     }
849
850     return TRUE;
851 }
852
853 static gboolean
854 peektagged_seek_read(wtap *wth, gint64 seek_off,
855     wtap_rec *rec, Buffer *buf, int *err, gchar **err_info)
856 {
857     if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
858         return FALSE;
859
860     /* Read the packet. */
861     if (peektagged_read_packet(wth, wth->random_fh, rec, buf, err, err_info) == -1) {
862         if (*err == 0)
863             *err = WTAP_ERR_SHORT_READ;
864         return FALSE;
865     }
866     return TRUE;
867 }
868
869 /*
870  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
871  *
872  * Local variables:
873  * c-basic-offset: 4
874  * tab-width: 8
875  * indent-tabs-mode: nil
876  * End:
877  *
878  * vi: set shiftwidth=4 tabstop=8 expandtab:
879  * :indentSize=4:tabSize=8:noTabs=true:
880  */