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