Export libwireshark symbols using WS_DLL_PUBLIC define
[metze/wireshark/wip.git] / epan / dissectors / packet-ppi.c
1 /*
2  * packet-ppi.c
3  * Routines for PPI Packet Header dissection
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 2007 Gerald Combs
10  *
11  * Copyright (c) 2006 CACE Technologies, Davis (California)
12  * All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. Neither the name of the project nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
31  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
34  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40  * SUCH DAMAGE.
41  *
42  *
43  * Dustin Johnson - Dustin@Dustinj.us, Dustin.Johnson@cacetech.com
44  *     May 7, 2008 - Added 'Aggregation Extension' and '802.3 Extension'
45  */
46
47
48 #include "config.h"
49
50 #include <glib.h>
51
52 #include <epan/packet.h>
53 #include <epan/ptvcursor.h>
54 #include <epan/prefs.h>
55 #include <epan/reassemble.h>
56 #include <epan/frequency-utils.h>
57
58 /* Needed for wtap_pcap_encap_to_wtap_encap(). */
59 #include <wiretap/pcap-encap.h>
60
61 #include "packet-frame.h"
62 #include "packet-eth.h"
63 #include "packet-ieee80211.h"
64 #include "packet-ppi.h"
65
66 /*
67  * Per-Packet Information (PPI) header.
68  * See the PPI Packet Header documentation at http://www.cacetech.com/documents
69  * for details.
70  */
71
72 /*
73  * PPI headers have the following format:
74  *
75  * ,---------------------------------------------------------.
76  * | PPH | PFH 1 | Field data 1 | PFH 2 | Field data 2 | ... |
77  * `---------------------------------------------------------'
78  *
79  * The PPH struct has the following format:
80  *
81  * typedef struct ppi_packetheader {
82  *     guint8  pph_version;     // Version.  Currently 0
83  *     guint8  pph_flags;       // Flags.
84  *     guint16 pph_len; // Length of entire message, including this header and TLV payload.
85  *     guint32 pph_dlt; // libpcap Data Link Type of the captured packet data.
86  * } ppi_packetheader_t;
87  *
88  * The PFH struct has the following format:
89  *
90  * typedef struct ppi_fieldheader {
91  *     guint16 pfh_type;        // Type
92  *     guint16 pfh_datalen;     // Length of data
93  * } ppi_fieldheader_t;
94  *
95  * Anyone looking to add their own PPI dissector would probably do well to imitate the GPS
96  * ones separation into a distinct file.  Here is a step by step guide:
97  * 1) add the number you received to the enum ppi_field_type declaration.
98  * 2) Add a value string for your number into vs_ppi_field_type
99  * 3) declare a dissector handle by the ppi_gps_handle, and initialize it inside proto_reg_handoff
100  * 4) add  case inside dissect_ppi to call your new handle.
101  * 5) Write your parser, and get it loaded.
102  * Following these steps will result in less churn inside the ppi proper parser, and avoid namespace issues.
103  */
104
105
106 #define PPI_PADDED (1 << 0)
107
108 #define PPI_V0_HEADER_LEN 8
109 #define PPI_80211_COMMON_LEN 20
110 #define PPI_80211N_MAC_LEN 12
111 #define PPI_80211N_MAC_PHY_OFF 9
112 #define PPI_80211N_MAC_PHY_LEN 48
113 #define PPI_AGGREGATION_EXTENSION_LEN 4
114 #define PPI_8023_EXTENSION_LEN 8
115
116 #define PPI_FLAG_ALIGN 0x01
117 #define IS_PPI_FLAG_ALIGN(x) ((x) & PPI_FLAG_ALIGN)
118
119 #define DOT11_FLAG_HAVE_FCS 0x0001
120
121 #define DOT11N_FLAG_IS_AGGREGATE 0x0010
122 #define DOT11N_FLAG_MORE_AGGREGATES 0x0020
123 #define DOT11N_FLAG_AGG_CRC_ERROR 0x0040
124
125 #define DOT11N_IS_AGGREGATE(flags)      (flags & DOT11N_FLAG_IS_AGGREGATE)
126 #define DOT11N_MORE_AGGREGATES(flags)   ( \
127     (flags & DOT11N_FLAG_MORE_AGGREGATES) && \
128     !(flags & DOT11N_FLAG_AGG_CRC_ERROR))
129 #define AGGREGATE_MAX 65535
130 #define AMPDU_MAX 16383
131
132 /* XXX - Start - Copied from packet-radiotap.c */
133 /* Channel flags. */
134 #define IEEE80211_CHAN_TURBO    0x0010  /* Turbo channel */
135 #define IEEE80211_CHAN_CCK      0x0020  /* CCK channel */
136 #define IEEE80211_CHAN_OFDM     0x0040  /* OFDM channel */
137 #define IEEE80211_CHAN_2GHZ     0x0080  /* 2 GHz spectrum channel. */
138 #define IEEE80211_CHAN_5GHZ     0x0100  /* 5 GHz spectrum channel */
139 #define IEEE80211_CHAN_PASSIVE  0x0200  /* Only passive scan allowed */
140 #define IEEE80211_CHAN_DYN      0x0400  /* Dynamic CCK-OFDM channel */
141 #define IEEE80211_CHAN_GFSK     0x0800  /* GFSK channel (FHSS PHY) */
142
143 /*
144  * Useful combinations of channel characteristics.
145  */
146 #define IEEE80211_CHAN_FHSS \
147         (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK)
148 #define IEEE80211_CHAN_A \
149         (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM)
150 #define IEEE80211_CHAN_B \
151         (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK)
152 #define IEEE80211_CHAN_PUREG \
153         (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM)
154 #define IEEE80211_CHAN_G \
155         (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN)
156 #define IEEE80211_CHAN_T \
157         (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO)
158 #define IEEE80211_CHAN_108G \
159         (IEEE80211_CHAN_G | IEEE80211_CHAN_TURBO)
160 #define IEEE80211_CHAN_108PUREG \
161         (IEEE80211_CHAN_PUREG | IEEE80211_CHAN_TURBO)
162 /* XXX - End - Copied from packet-radiotap.c */
163
164 typedef enum {
165     /* 0 - 29999: Public types */
166     PPI_80211_COMMON          =  2,
167     PPI_80211N_MAC            =  3,
168     PPI_80211N_MAC_PHY        =  4,
169     PPI_SPECTRUM_MAP          =  5,
170     PPI_PROCESS_INFO          =  6,
171     PPI_CAPTURE_INFO          =  7,
172     PPI_AGGREGATION_EXTENSION =  8,
173     PPI_8023_EXTENSION        =  9,
174     /* 11 - 29999: RESERVED */
175
176     /* 30000 - 65535: Private types */
177     INTEL_CORP_PRIVATE           = 30000,
178     MOHAMED_THAGA_PRIVATE        = 30001,
179     PPI_GPS_INFO                 = 30002, /* 30002 - 30005 described in PPI-GEOLOCATION specifcation */
180     PPI_VECTOR_INFO              = 30003, /* currently available in draft from. jellch@harris.com */
181     PPI_SENSOR_INFO              = 30004,
182     PPI_ANTENNA_INFO             = 30005,
183     CACE_PRIVATE                 = 0xCACE
184     /* All others RESERVED.  Contact the WinPcap team for an assignment */
185 } ppi_field_type;
186
187 /* Protocol */
188 static int proto_ppi = -1;
189
190 /* Packet header */
191 static int hf_ppi_head_version = -1;
192 static int hf_ppi_head_flags = -1;
193 static int hf_ppi_head_flag_alignment = -1;
194 static int hf_ppi_head_flag_reserved = -1;
195 static int hf_ppi_head_len = -1;
196 static int hf_ppi_head_dlt = -1;
197
198 /* Field header */
199 static int hf_ppi_field_type = -1;
200 static int hf_ppi_field_len = -1;
201
202 /* 802.11 Common */
203 static int hf_80211_common_tsft = -1;
204 static int hf_80211_common_flags = -1;
205 static int hf_80211_common_flags_fcs = -1;
206 static int hf_80211_common_flags_tsft = -1;
207 static int hf_80211_common_flags_fcs_valid = -1;
208 static int hf_80211_common_flags_phy_err = -1;
209 static int hf_80211_common_rate = -1;
210 static int hf_80211_common_chan_freq = -1;
211 static int hf_80211_common_chan_flags = -1;
212
213 static int hf_80211_common_chan_flags_turbo = -1;
214 static int hf_80211_common_chan_flags_cck = -1;
215 static int hf_80211_common_chan_flags_ofdm = -1;
216 static int hf_80211_common_chan_flags_2ghz = -1;
217 static int hf_80211_common_chan_flags_5ghz = -1;
218 static int hf_80211_common_chan_flags_passive = -1;
219 static int hf_80211_common_chan_flags_dynamic = -1;
220 static int hf_80211_common_chan_flags_gfsk = -1;
221
222 static int hf_80211_common_fhss_hopset = -1;
223 static int hf_80211_common_fhss_pattern = -1;
224 static int hf_80211_common_dbm_antsignal = -1;
225 static int hf_80211_common_dbm_antnoise = -1;
226
227 /* 802.11n MAC */
228 static int hf_80211n_mac_flags = -1;
229 static int hf_80211n_mac_flags_greenfield = -1;
230 static int hf_80211n_mac_flags_ht20_40 = -1;
231 static int hf_80211n_mac_flags_rx_guard_interval = -1;
232 static int hf_80211n_mac_flags_duplicate_rx = -1;
233 static int hf_80211n_mac_flags_more_aggregates = -1;
234 static int hf_80211n_mac_flags_aggregate = -1;
235 static int hf_80211n_mac_flags_delimiter_crc_after = -1;
236 static int hf_80211n_mac_ampdu_id = -1;
237 static int hf_80211n_mac_num_delimiters = -1;
238 static int hf_80211n_mac_reserved = -1;
239
240 /* 802.11n MAC+PHY */
241 static int hf_80211n_mac_phy_mcs = -1;
242 static int hf_80211n_mac_phy_num_streams = -1;
243 static int hf_80211n_mac_phy_rssi_combined = -1;
244 static int hf_80211n_mac_phy_rssi_ant0_ctl = -1;
245 static int hf_80211n_mac_phy_rssi_ant1_ctl = -1;
246 static int hf_80211n_mac_phy_rssi_ant2_ctl = -1;
247 static int hf_80211n_mac_phy_rssi_ant3_ctl = -1;
248 static int hf_80211n_mac_phy_rssi_ant0_ext = -1;
249 static int hf_80211n_mac_phy_rssi_ant1_ext = -1;
250 static int hf_80211n_mac_phy_rssi_ant2_ext = -1;
251 static int hf_80211n_mac_phy_rssi_ant3_ext = -1;
252 static int hf_80211n_mac_phy_ext_chan_freq = -1;
253 static int hf_80211n_mac_phy_ext_chan_flags = -1;
254 static int hf_80211n_mac_phy_ext_chan_flags_turbo = -1;
255 static int hhf_80211n_mac_phy_ext_chan_flags_cck = -1;
256 static int hf_80211n_mac_phy_ext_chan_flags_ofdm = -1;
257 static int hhf_80211n_mac_phy_ext_chan_flags_2ghz = -1;
258 static int hf_80211n_mac_phy_ext_chan_flags_5ghz = -1;
259 static int hf_80211n_mac_phy_ext_chan_flags_passive = -1;
260 static int hf_80211n_mac_phy_ext_chan_flags_dynamic = -1;
261 static int hf_80211n_mac_phy_ext_chan_flags_gfsk = -1;
262 static int hf_80211n_mac_phy_dbm_ant0signal = -1;
263 static int hf_80211n_mac_phy_dbm_ant0noise = -1;
264 static int hf_80211n_mac_phy_dbm_ant1signal = -1;
265 static int hf_80211n_mac_phy_dbm_ant1noise = -1;
266 static int hf_80211n_mac_phy_dbm_ant2signal = -1;
267 static int hf_80211n_mac_phy_dbm_ant2noise = -1;
268 static int hf_80211n_mac_phy_dbm_ant3signal = -1;
269 static int hf_80211n_mac_phy_dbm_ant3noise = -1;
270 static int hf_80211n_mac_phy_evm0 = -1;
271 static int hf_80211n_mac_phy_evm1 = -1;
272 static int hf_80211n_mac_phy_evm2 = -1;
273 static int hf_80211n_mac_phy_evm3 = -1;
274
275 /* 802.11n-Extensions A-MPDU fragments */
276 static int hf_ampdu_reassembled_in = -1;
277 /* static int hf_ampdu_segments = -1; */
278 static int hf_ampdu_segment = -1;
279 static int hf_ampdu_count  = -1;
280
281 /* Spectrum-Map */
282 static int hf_spectrum_map = -1;
283
284 /* Process-Info */
285 static int hf_process_info = -1;
286
287 /* Capture-Info */
288 static int hf_capture_info = -1;
289
290 /* Aggregation Extension */
291 static int hf_aggregation_extension_interface_id = -1;
292
293 /* 802.3 Extension */
294 static int hf_8023_extension_flags = -1;
295 static int hf_8023_extension_flags_fcs_present = -1;
296 static int hf_8023_extension_errors = -1;
297 static int hf_8023_extension_errors_fcs = -1;
298 static int hf_8023_extension_errors_sequence = -1;
299 static int hf_8023_extension_errors_symbol = -1;
300 static int hf_8023_extension_errors_data = -1;
301
302 static gint ett_ppi_pph = -1;
303 static gint ett_ppi_flags = -1;
304 static gint ett_dot11_common = -1;
305 static gint ett_dot11_common_flags = -1;
306 static gint ett_dot11_common_channel_flags = -1;
307 static gint ett_dot11n_mac = -1;
308 static gint ett_dot11n_mac_flags = -1;
309 static gint ett_dot11n_mac_phy = -1;
310 static gint ett_dot11n_mac_phy_ext_channel_flags = -1;
311 static gint ett_ampdu_segments = -1;
312 static gint ett_ampdu = -1;
313 static gint ett_ampdu_segment  = -1;
314 static gint ett_aggregation_extension = -1;
315 static gint ett_8023_extension = -1;
316 static gint ett_8023_extension_flags = -1;
317 static gint ett_8023_extension_errors = -1;
318
319 static dissector_handle_t data_handle;
320 static dissector_handle_t ieee80211_ht_handle;
321 static dissector_handle_t ppi_gps_handle, ppi_vector_handle, ppi_sensor_handle, ppi_antenna_handle;
322
323
324 static const true_false_string tfs_ppi_head_flag_alignment = { "32-bit aligned", "Not aligned" };
325 static const true_false_string tfs_tsft_ms = { "milliseconds", "microseconds" };
326 static const true_false_string tfs_ht20_40 = { "HT40", "HT20" };
327 static const true_false_string tfs_invalid_valid = { "Invalid", "Valid" };
328 static const true_false_string tfs_phy_error = { "PHY error", "No errors"};
329
330 static const value_string vs_ppi_field_type[] = {
331     {PPI_80211_COMMON,          "802.11-Common"},
332     {PPI_80211N_MAC,            "802.11n MAC Extensions"},
333     {PPI_80211N_MAC_PHY,        "802.11n MAC+PHY Extensions"},
334     {PPI_SPECTRUM_MAP,          "Spectrum-Map"},
335     {PPI_PROCESS_INFO,          "Process-Info"},
336     {PPI_CAPTURE_INFO,          "Capture-Info"},
337     {PPI_AGGREGATION_EXTENSION, "Aggregation Extension"},
338     {PPI_8023_EXTENSION,        "802.3 Extension"},
339
340     {INTEL_CORP_PRIVATE,        "Intel Corporation (private)"},
341     {MOHAMED_THAGA_PRIVATE,     "Mohamed Thaga (private)"},
342     {PPI_GPS_INFO,              "GPS Tagging"},
343     {PPI_VECTOR_INFO,           "Vector Tagging"},
344     {PPI_SENSOR_INFO,           "Sensor tagging"},
345     {PPI_ANTENNA_INFO,          "Antenna Tagging"},
346     {CACE_PRIVATE,              "CACE Technologies (private)"},
347     {0, NULL}
348 };
349
350 /* XXX - Start - Copied from packet-radiotap.c */
351 static const value_string vs_80211_common_phy_type[] = {
352     { 0, "Unknown" },
353     { IEEE80211_CHAN_A,         "802.11a" },
354     { IEEE80211_CHAN_B,         "802.11b" },
355     { IEEE80211_CHAN_PUREG,     "802.11g (pure-g)" },
356     { IEEE80211_CHAN_G,         "802.11g" },
357     { IEEE80211_CHAN_T,         "802.11a (turbo)" },
358     { IEEE80211_CHAN_108PUREG,  "802.11g (pure-g, turbo)" },
359     { IEEE80211_CHAN_108G,      "802.11g (turbo)" },
360     { IEEE80211_CHAN_FHSS,      "FHSS" },
361     { 0, NULL },
362 };
363 /* XXX - End - Copied from packet-radiotap.c */
364
365 /* Tables for A-MPDU reassembly */
366 static GHashTable *ampdu_fragment_table = NULL;
367 static GHashTable *ampdu_reassembled_table = NULL;
368
369 /* Reassemble A-MPDUs? */
370 static gboolean ppi_ampdu_reassemble = TRUE;
371
372
373 void
374 capture_ppi(const guchar *pd, int len, packet_counts *ld)
375 {
376     guint32  dlt;
377     guint    ppi_len, data_type, data_len;
378     guint    offset = PPI_V0_HEADER_LEN;
379     gboolean is_htc = FALSE;
380
381     ppi_len = pletohs(pd+2);
382     if(ppi_len < PPI_V0_HEADER_LEN || !BYTES_ARE_IN_FRAME(0, len, ppi_len)) {
383         ld->other++;
384         return;
385     }
386
387     dlt = pletohl(pd+4);
388
389     /* Figure out if we're +HTC */
390     while (offset < ppi_len) {
391         data_type = pletohs(pd+offset);
392         data_len = pletohs(pd+offset+2) + 4;
393         offset += data_len;
394
395         if (data_type == PPI_80211N_MAC || data_type == PPI_80211N_MAC_PHY) {
396             is_htc = TRUE;
397             break;
398         }
399     }
400
401     /* XXX - We should probably combine this with capture_info.c:capture_info_packet() */
402     switch(dlt) {
403         case 1: /* DLT_EN10MB */
404             capture_eth(pd, ppi_len, len, ld);
405             return;
406         case 105: /* DLT_DLT_IEEE802_11 */
407             if (is_htc)
408                 capture_ieee80211_ht(pd, ppi_len, len, ld);
409             else
410                 capture_ieee80211(pd, ppi_len, len, ld);
411             return;
412         default:
413             break;
414     }
415
416     ld->other++;
417 }
418
419 static void
420 ptvcursor_add_invalid_check(ptvcursor_t *csr, int hf, gint len, guint64 invalid_val) {
421     proto_item *ti;
422     guint64     val = invalid_val;
423
424     switch (len) {
425         case 8:
426             val = tvb_get_letoh64(ptvcursor_tvbuff(csr),
427                 ptvcursor_current_offset(csr));
428             break;
429         case 4:
430             val = tvb_get_letohl(ptvcursor_tvbuff(csr),
431                 ptvcursor_current_offset(csr));
432             break;
433         case 2:
434             val = tvb_get_letohs(ptvcursor_tvbuff(csr),
435                 ptvcursor_current_offset(csr));
436             break;
437         case 1:
438             val = tvb_get_guint8(ptvcursor_tvbuff(csr),
439                 ptvcursor_current_offset(csr));
440             break;
441         default:
442             DISSECTOR_ASSERT_NOT_REACHED();
443     }
444
445     ti = ptvcursor_add(csr, hf, len, ENC_LITTLE_ENDIAN);
446     if (val == invalid_val)
447         proto_item_append_text(ti, " [invalid]");
448 }
449
450 static void
451 add_ppi_field_header(tvbuff_t *tvb, proto_tree *tree, int *offset)
452 {
453     ptvcursor_t *csr;
454
455     csr = ptvcursor_new(tree, tvb, *offset);
456     ptvcursor_add(csr, hf_ppi_field_type, 2, ENC_LITTLE_ENDIAN);
457     ptvcursor_add(csr, hf_ppi_field_len, 2, ENC_LITTLE_ENDIAN);
458     ptvcursor_free(csr);
459     *offset=ptvcursor_current_offset(csr);
460 }
461
462 /* XXX - The main dissection function in the 802.11 dissector has the same name. */
463 static void
464 dissect_80211_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int data_len)
465 {
466     proto_tree  *ftree = NULL;
467     proto_item  *ti    = NULL;
468     ptvcursor_t *csr;
469     gint         rate_kbps;
470     guint32      common_flags;
471     guint16      common_frequency;
472     gchar       *chan_str;
473
474     ti = proto_tree_add_text(tree, tvb, offset, data_len, "802.11-Common");
475     ftree = proto_item_add_subtree(ti, ett_dot11_common);
476     add_ppi_field_header(tvb, ftree, &offset);
477     data_len -= 4; /* Subtract field header length */
478
479     if (data_len != PPI_80211_COMMON_LEN) {
480         proto_tree_add_text(ftree, tvb, offset, data_len, "Invalid length: %u", data_len);
481         THROW(ReportedBoundsError);
482     }
483
484     common_flags = tvb_get_letohs(tvb, offset + 8);
485     if (common_flags & DOT11_FLAG_HAVE_FCS)
486         pinfo->pseudo_header->ieee_802_11.fcs_len = 4;
487     else
488         pinfo->pseudo_header->ieee_802_11.fcs_len = 0;
489
490     csr = ptvcursor_new(ftree, tvb, offset);
491
492     ptvcursor_add_invalid_check(csr, hf_80211_common_tsft, 8, 0);
493
494     ptvcursor_add_with_subtree(csr, hf_80211_common_flags, 2, ENC_LITTLE_ENDIAN,
495                                ett_dot11_common_flags);
496     ptvcursor_add_no_advance(csr, hf_80211_common_flags_fcs, 2, ENC_LITTLE_ENDIAN);
497     ptvcursor_add_no_advance(csr, hf_80211_common_flags_tsft, 2, ENC_LITTLE_ENDIAN);
498     ptvcursor_add_no_advance(csr, hf_80211_common_flags_fcs_valid, 2, ENC_LITTLE_ENDIAN);
499     ptvcursor_add(csr, hf_80211_common_flags_phy_err, 2, ENC_LITTLE_ENDIAN);
500     ptvcursor_pop_subtree(csr);
501
502     rate_kbps = tvb_get_letohs(tvb, ptvcursor_current_offset(csr)) * 500;
503     ti = proto_tree_add_uint_format(ftree, hf_80211_common_rate, tvb,
504                                     ptvcursor_current_offset(csr), 2, rate_kbps, "Rate: %.1f Mbps",
505                                     rate_kbps / 1000.0);
506     if (rate_kbps == 0)
507         proto_item_append_text(ti, " [invalid]");
508     if (check_col(pinfo->cinfo, COL_TX_RATE)) {
509         col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%.1f Mbps", rate_kbps / 1000.0);
510     }
511     ptvcursor_advance(csr, 2);
512
513     common_frequency = tvb_get_letohs(ptvcursor_tvbuff(csr), ptvcursor_current_offset(csr));
514     chan_str = ieee80211_mhz_to_str(common_frequency);
515     proto_tree_add_uint_format(ptvcursor_tree(csr), hf_80211_common_chan_freq, ptvcursor_tvbuff(csr),
516                                ptvcursor_current_offset(csr), 2, common_frequency, "Channel frequency: %s", chan_str);
517     if (check_col(pinfo->cinfo, COL_FREQ_CHAN)) {
518         col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%s", chan_str);
519     }
520     g_free(chan_str);
521     ptvcursor_advance(csr, 2);
522
523     ptvcursor_add_with_subtree(csr, hf_80211_common_chan_flags, 2, ENC_LITTLE_ENDIAN,
524                                ett_dot11_common_channel_flags);
525     ptvcursor_add_no_advance(csr, hf_80211_common_chan_flags_turbo, 2, ENC_LITTLE_ENDIAN);
526     ptvcursor_add_no_advance(csr, hf_80211_common_chan_flags_cck, 2, ENC_LITTLE_ENDIAN);
527     ptvcursor_add_no_advance(csr, hf_80211_common_chan_flags_ofdm, 2, ENC_LITTLE_ENDIAN);
528     ptvcursor_add_no_advance(csr, hf_80211_common_chan_flags_2ghz, 2, ENC_LITTLE_ENDIAN);
529     ptvcursor_add_no_advance(csr, hf_80211_common_chan_flags_5ghz, 2, ENC_LITTLE_ENDIAN);
530     ptvcursor_add_no_advance(csr, hf_80211_common_chan_flags_passive, 2, ENC_LITTLE_ENDIAN);
531     ptvcursor_add_no_advance(csr, hf_80211_common_chan_flags_dynamic, 2, ENC_LITTLE_ENDIAN);
532     ptvcursor_add(csr, hf_80211_common_chan_flags_gfsk, 2, ENC_LITTLE_ENDIAN);
533     ptvcursor_pop_subtree(csr);
534
535
536     ptvcursor_add(csr, hf_80211_common_fhss_hopset, 1, ENC_LITTLE_ENDIAN);
537     ptvcursor_add(csr, hf_80211_common_fhss_pattern, 1, ENC_LITTLE_ENDIAN);
538
539     if (check_col(pinfo->cinfo, COL_RSSI)) {
540         col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm",
541             (gint8) tvb_get_guint8(tvb, ptvcursor_current_offset(csr)));
542     }
543     ptvcursor_add_invalid_check(csr, hf_80211_common_dbm_antsignal, 1, 0x80); /* -128 */
544     ptvcursor_add_invalid_check(csr, hf_80211_common_dbm_antnoise, 1, 0x80);
545
546     ptvcursor_free(csr);
547 }
548
549 static void
550 dissect_80211n_mac(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, int data_len, gboolean add_subtree, guint32 *n_mac_flags, guint32 *ampdu_id)
551 {
552     proto_tree  *ftree       = tree;
553     proto_item  *ti          = NULL;
554     ptvcursor_t *csr;
555     int          subtree_off = add_subtree ? 4 : 0;
556
557     *n_mac_flags = tvb_get_letohl(tvb, offset + subtree_off);
558     *ampdu_id = tvb_get_letohl(tvb, offset + 4 + subtree_off);
559
560     if (add_subtree) {
561         ti = proto_tree_add_text(tree, tvb, offset, data_len, "802.11n MAC");
562         ftree = proto_item_add_subtree(ti, ett_dot11n_mac);
563         add_ppi_field_header(tvb, ftree, &offset);
564         data_len -= 4; /* Subtract field header length */
565     }
566
567     if (data_len != PPI_80211N_MAC_LEN) {
568         proto_tree_add_text(ftree, tvb, offset, data_len, "Invalid length: %u", data_len);
569         THROW(ReportedBoundsError);
570     }
571
572     csr = ptvcursor_new(ftree, tvb, offset);
573
574     ptvcursor_add_with_subtree(csr, hf_80211n_mac_flags, 4, ENC_LITTLE_ENDIAN,
575                                ett_dot11n_mac_flags);
576     ptvcursor_add_no_advance(csr, hf_80211n_mac_flags_greenfield, 4, ENC_LITTLE_ENDIAN);
577     ptvcursor_add_no_advance(csr, hf_80211n_mac_flags_ht20_40, 4, ENC_LITTLE_ENDIAN);
578     ptvcursor_add_no_advance(csr, hf_80211n_mac_flags_rx_guard_interval, 4, ENC_LITTLE_ENDIAN);
579     ptvcursor_add_no_advance(csr, hf_80211n_mac_flags_duplicate_rx, 4, ENC_LITTLE_ENDIAN);
580     ptvcursor_add_no_advance(csr, hf_80211n_mac_flags_aggregate, 4, ENC_LITTLE_ENDIAN);
581     ptvcursor_add_no_advance(csr, hf_80211n_mac_flags_more_aggregates, 4, ENC_LITTLE_ENDIAN);
582     ptvcursor_add(csr, hf_80211n_mac_flags_delimiter_crc_after, 4, ENC_LITTLE_ENDIAN); /* Last */
583     ptvcursor_pop_subtree(csr);
584
585     ptvcursor_add(csr, hf_80211n_mac_ampdu_id, 4, ENC_LITTLE_ENDIAN);
586     ptvcursor_add(csr, hf_80211n_mac_num_delimiters, 1, ENC_LITTLE_ENDIAN);
587
588     if (add_subtree) {
589         ptvcursor_add(csr, hf_80211n_mac_reserved, 3, ENC_LITTLE_ENDIAN);
590     }
591
592     ptvcursor_free(csr);
593 }
594
595 static void
596 dissect_80211n_mac_phy(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int data_len, guint32 *n_mac_flags, guint32 *ampdu_id)
597 {
598     proto_tree  *ftree = NULL;
599     proto_item  *ti    = NULL;
600     ptvcursor_t *csr;
601     guint16      ext_frequency;
602     gchar       *chan_str;
603
604     ti = proto_tree_add_text(tree, tvb, offset, data_len, "802.11n MAC+PHY");
605     ftree = proto_item_add_subtree(ti, ett_dot11n_mac_phy);
606     add_ppi_field_header(tvb, ftree, &offset);
607     data_len -= 4; /* Subtract field header length */
608
609     if (data_len != PPI_80211N_MAC_PHY_LEN) {
610         proto_tree_add_text(ftree, tvb, offset, data_len, "Invalid length: %u", data_len);
611         THROW(ReportedBoundsError);
612     }
613
614     dissect_80211n_mac(tvb, pinfo, ftree, offset, PPI_80211N_MAC_LEN,
615                        FALSE, n_mac_flags, ampdu_id);
616     offset += PPI_80211N_MAC_PHY_OFF;
617
618     csr = ptvcursor_new(ftree, tvb, offset);
619
620     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_mcs, 1, 255);
621     ti = ptvcursor_add(csr, hf_80211n_mac_phy_num_streams, 1, ENC_LITTLE_ENDIAN);
622     if (tvb_get_guint8(tvb, ptvcursor_current_offset(csr) - 1) == 0)
623         proto_item_append_text(ti, " (unknown)");
624     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_rssi_combined, 1, 255);
625     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_rssi_ant0_ctl, 1, 255);
626     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_rssi_ant1_ctl, 1, 255);
627     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_rssi_ant2_ctl, 1, 255);
628     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_rssi_ant3_ctl, 1, 255);
629     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_rssi_ant0_ext, 1, 255);
630     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_rssi_ant1_ext, 1, 255);
631     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_rssi_ant2_ext, 1, 255);
632     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_rssi_ant3_ext, 1, 255);
633
634     ext_frequency = tvb_get_letohs(ptvcursor_tvbuff(csr), ptvcursor_current_offset(csr));
635     chan_str = ieee80211_mhz_to_str(ext_frequency);
636     proto_tree_add_uint_format(ptvcursor_tree(csr), hf_80211n_mac_phy_ext_chan_freq, ptvcursor_tvbuff(csr),
637                                ptvcursor_current_offset(csr), 2, ext_frequency, "Ext. Channel frequency: %s", chan_str);
638     g_free(chan_str);
639     ptvcursor_advance(csr, 2);
640
641     ptvcursor_add_with_subtree(csr, hf_80211n_mac_phy_ext_chan_flags, 2, ENC_LITTLE_ENDIAN,
642                                ett_dot11n_mac_phy_ext_channel_flags);
643     ptvcursor_add_no_advance(csr, hf_80211n_mac_phy_ext_chan_flags_turbo, 2, ENC_LITTLE_ENDIAN);
644     ptvcursor_add_no_advance(csr, hhf_80211n_mac_phy_ext_chan_flags_cck, 2, ENC_LITTLE_ENDIAN);
645     ptvcursor_add_no_advance(csr, hf_80211n_mac_phy_ext_chan_flags_ofdm, 2, ENC_LITTLE_ENDIAN);
646     ptvcursor_add_no_advance(csr, hhf_80211n_mac_phy_ext_chan_flags_2ghz, 2, ENC_LITTLE_ENDIAN);
647     ptvcursor_add_no_advance(csr, hf_80211n_mac_phy_ext_chan_flags_5ghz, 2, ENC_LITTLE_ENDIAN);
648     ptvcursor_add_no_advance(csr, hf_80211n_mac_phy_ext_chan_flags_passive, 2, ENC_LITTLE_ENDIAN);
649     ptvcursor_add_no_advance(csr, hf_80211n_mac_phy_ext_chan_flags_dynamic, 2, ENC_LITTLE_ENDIAN);
650     ptvcursor_add(csr, hf_80211n_mac_phy_ext_chan_flags_gfsk, 2, ENC_LITTLE_ENDIAN);
651     ptvcursor_pop_subtree(csr);
652
653     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_dbm_ant0signal, 1, 0x80); /* -128 */
654     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_dbm_ant0noise, 1, 0x80);
655     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_dbm_ant1signal, 1, 0x80);
656     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_dbm_ant1noise, 1, 0x80);
657     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_dbm_ant2signal, 1, 0x80);
658     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_dbm_ant2noise, 1, 0x80);
659     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_dbm_ant3signal, 1, 0x80);
660     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_dbm_ant3noise, 1, 0x80);
661     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_evm0, 4, 0);
662     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_evm1, 4, 0);
663     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_evm2, 4, 0);
664     ptvcursor_add_invalid_check(csr, hf_80211n_mac_phy_evm3, 4, 0);
665
666     ptvcursor_free(csr);
667 }
668
669 static void
670 dissect_aggregation_extension(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, int data_len)
671 {
672     proto_tree *ftree = tree;
673     proto_item *ti = NULL;
674     ptvcursor_t *csr;
675
676     ti = proto_tree_add_text(tree, tvb, offset, data_len, "Aggregation Extension");
677     ftree = proto_item_add_subtree(ti, ett_aggregation_extension);
678     add_ppi_field_header(tvb, ftree, &offset);
679     data_len -= 4; /* Subtract field header length */
680
681     if (data_len != PPI_AGGREGATION_EXTENSION_LEN) {
682         proto_tree_add_text(ftree, tvb, offset, data_len, "Invalid length: %u", data_len);
683         THROW(ReportedBoundsError);
684     }
685
686     csr = ptvcursor_new(ftree, tvb, offset);
687
688     ptvcursor_add(csr, hf_aggregation_extension_interface_id, 4, ENC_LITTLE_ENDIAN); /* Last */
689     ptvcursor_free(csr);
690 }
691
692 static void
693 dissect_8023_extension(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, int data_len)
694 {
695     proto_tree  *ftree = tree;
696     proto_item  *ti    = NULL;
697     ptvcursor_t *csr;
698
699     ti = proto_tree_add_text(tree, tvb, offset, data_len, "802.3 Extension");
700     ftree = proto_item_add_subtree(ti, ett_8023_extension);
701     add_ppi_field_header(tvb, ftree, &offset);
702     data_len -= 4; /* Subtract field header length */
703
704     if (data_len != PPI_8023_EXTENSION_LEN) {
705         proto_tree_add_text(ftree, tvb, offset, data_len, "Invalid length: %u", data_len);
706         THROW(ReportedBoundsError);
707     }
708
709     csr = ptvcursor_new(ftree, tvb, offset);
710
711     ptvcursor_add_with_subtree(csr, hf_8023_extension_flags, 4, ENC_LITTLE_ENDIAN, ett_8023_extension_flags);
712     ptvcursor_add(csr, hf_8023_extension_flags_fcs_present, 4, ENC_LITTLE_ENDIAN);
713     ptvcursor_pop_subtree(csr);
714
715     ptvcursor_add_with_subtree(csr, hf_8023_extension_errors, 4, ENC_LITTLE_ENDIAN, ett_8023_extension_errors);
716     ptvcursor_add_no_advance(csr, hf_8023_extension_errors_fcs, 4, ENC_LITTLE_ENDIAN);
717     ptvcursor_add_no_advance(csr, hf_8023_extension_errors_sequence, 4, ENC_LITTLE_ENDIAN);
718     ptvcursor_add_no_advance(csr, hf_8023_extension_errors_symbol, 4, ENC_LITTLE_ENDIAN);
719     ptvcursor_add(csr, hf_8023_extension_errors_data, 4, ENC_LITTLE_ENDIAN);
720     ptvcursor_pop_subtree(csr);
721
722     ptvcursor_free(csr);
723 }
724
725
726 #define PADDING4(x) ((((x + 3) >> 2) << 2) - x)
727 #define ADD_BASIC_TAG(hf_tag) \
728     if (tree)   \
729         proto_tree_add_item(ppi_tree, hf_tag, tvb, offset, data_len, ENC_NA)
730
731 static void
732 dissect_ppi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
733 {
734     proto_tree    *ppi_tree    = NULL, *ppi_flags_tree = NULL, *seg_tree = NULL, *ampdu_tree = NULL;
735     proto_tree    *agg_tree    = NULL;
736     proto_item    *ti          = NULL;
737     tvbuff_t      *next_tvb;
738     int            offset      = 0;
739     guint          version, flags;
740     gint           tot_len, data_len;
741     guint          data_type;
742     guint32        dlt;
743     guint32        n_ext_flags = 0;
744     guint32        ampdu_id    = 0;
745     fragment_data *fd_head     = NULL, *ft_fdh = NULL;
746     gint           mpdu_count  = 0;
747     gchar         *mpdu_str;
748     gboolean       first_mpdu  = TRUE;
749     guint          last_frame  = 0;
750     gboolean       is_ht       = FALSE;
751     gint len_remain, /*pad_len = 0,*/ ampdu_len = 0;
752
753     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PPI");
754     col_clear(pinfo->cinfo, COL_INFO);
755
756     version = tvb_get_guint8(tvb, offset);
757     flags = tvb_get_guint8(tvb, offset + 1);
758
759     tot_len = tvb_get_letohs(tvb, offset+2);
760     dlt = tvb_get_letohl(tvb, offset+4);
761
762     col_add_fstr(pinfo->cinfo, COL_INFO, "PPI version %u, %u bytes",
763                  version, tot_len);
764
765     /* Dissect the packet */
766     if (tree) {
767         ti = proto_tree_add_protocol_format(tree, proto_ppi,
768                                             tvb, 0, tot_len, "PPI version %u, %u bytes", version, tot_len);
769         ppi_tree = proto_item_add_subtree(ti, ett_ppi_pph);
770         proto_tree_add_item(ppi_tree, hf_ppi_head_version,
771                             tvb, offset, 1, ENC_LITTLE_ENDIAN);
772
773         ti = proto_tree_add_item(ppi_tree, hf_ppi_head_flags,
774                                  tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
775         ppi_flags_tree = proto_item_add_subtree(ti, ett_ppi_flags);
776         proto_tree_add_item(ppi_flags_tree, hf_ppi_head_flag_alignment,
777                             tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
778         proto_tree_add_item(ppi_flags_tree, hf_ppi_head_flag_reserved,
779                             tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
780
781         proto_tree_add_item(ppi_tree, hf_ppi_head_len,
782                                  tvb, offset + 2, 2, ENC_LITTLE_ENDIAN);
783         proto_tree_add_item(ppi_tree, hf_ppi_head_dlt,
784                                  tvb, offset + 4, 4, ENC_LITTLE_ENDIAN);
785     }
786
787     tot_len -= PPI_V0_HEADER_LEN;
788     offset += 8;
789
790     while (tot_len > 0) {
791         data_type = tvb_get_letohs(tvb, offset);
792         data_len = tvb_get_letohs(tvb, offset + 2) + 4;
793         tot_len -= data_len;
794
795         switch (data_type) {
796             case PPI_80211_COMMON:
797                 dissect_80211_common(tvb, pinfo, ppi_tree, offset, data_len);
798                 break;
799
800             case PPI_80211N_MAC:
801                 dissect_80211n_mac(tvb, pinfo, ppi_tree, offset, data_len,
802                     TRUE, &n_ext_flags, &ampdu_id);
803                 is_ht = TRUE;
804                 break;
805
806             case PPI_80211N_MAC_PHY:
807                 dissect_80211n_mac_phy(tvb, pinfo, ppi_tree, offset,
808                     data_len, &n_ext_flags, &ampdu_id);
809                 is_ht = TRUE;
810                 break;
811
812             case PPI_SPECTRUM_MAP:
813                 ADD_BASIC_TAG(hf_spectrum_map);
814                 break;
815
816             case PPI_PROCESS_INFO:
817                 ADD_BASIC_TAG(hf_process_info);
818                 break;
819
820             case PPI_CAPTURE_INFO:
821                 ADD_BASIC_TAG(hf_capture_info);
822                 break;
823
824             case PPI_AGGREGATION_EXTENSION:
825                 dissect_aggregation_extension(tvb, pinfo, ppi_tree, offset, data_len);
826                 break;
827
828         case PPI_8023_EXTENSION:
829             dissect_8023_extension(tvb, pinfo, ppi_tree, offset, data_len);
830             break;
831         case PPI_GPS_INFO:
832             if (ppi_gps_handle == NULL)
833             {
834                 proto_tree_add_text(ppi_tree, tvb, offset, data_len,
835                                     "%s (%u bytes)", val_to_str_const(data_type, vs_ppi_field_type, "GPS: "), data_len);
836             }
837             else /* we found a suitable dissector */
838             {
839                 /* skip over the ppi_fieldheader, and pass it off to the dedicated GPS dissetor */
840                 next_tvb = tvb_new_subset(tvb, offset + 4, data_len - 4 , -1);
841                 call_dissector(ppi_gps_handle, next_tvb, pinfo, ppi_tree);
842             }
843             break;
844         case PPI_VECTOR_INFO:
845             if (ppi_vector_handle == NULL)
846             {
847                 proto_tree_add_text(ppi_tree, tvb, offset, data_len,
848                                     "%s (%u bytes)", val_to_str_const(data_type, vs_ppi_field_type, "VECTOR: "), data_len);
849             }
850             else /* we found a suitable dissector */
851             {
852                 /* skip over the ppi_fieldheader, and pass it off to the dedicated VECTOR dissetor */
853                 next_tvb = tvb_new_subset(tvb, offset + 4, data_len - 4 , -1);
854                 call_dissector(ppi_vector_handle, next_tvb, pinfo, ppi_tree);
855             }
856             break;
857         case PPI_SENSOR_INFO:
858             if (ppi_sensor_handle == NULL)
859             {
860                 proto_tree_add_text(ppi_tree, tvb, offset, data_len,
861                                     "%s (%u bytes)", val_to_str_const(data_type, vs_ppi_field_type, "HARRIS: "), data_len);
862             }
863             else /* we found a suitable dissector */
864             {
865                 /* skip over the ppi_fieldheader, and pass it off to the dedicated SENSOR dissetor */
866                 next_tvb = tvb_new_subset(tvb, offset + 4, data_len - 4 , -1);
867                 call_dissector(ppi_sensor_handle, next_tvb, pinfo, ppi_tree);
868             }
869             break;
870         case PPI_ANTENNA_INFO:
871             if (ppi_antenna_handle == NULL)
872             {
873                 proto_tree_add_text(ppi_tree, tvb, offset, data_len,
874                                     "%s (%u bytes)", val_to_str_const(data_type, vs_ppi_field_type, "ANTENNA: "), data_len);
875             }
876             else /* we found a suitable dissector */
877             {
878                 /* skip over the ppi_fieldheader, and pass it off to the dedicated ANTENNA dissetor */
879                 next_tvb = tvb_new_subset(tvb, offset + 4, data_len - 4 , -1);
880                 call_dissector(ppi_antenna_handle, next_tvb, pinfo, ppi_tree);
881             }
882             break;
883
884         default:
885             if (tree)
886                 proto_tree_add_text(ppi_tree, tvb, offset, data_len,
887                                     "%s (%u bytes)", val_to_str_const(data_type, vs_ppi_field_type, "Reserved"), data_len);
888         }
889
890         offset += data_len;
891         if (IS_PPI_FLAG_ALIGN(flags)){
892             offset += PADDING4(offset);
893         }
894     }
895
896     if (ppi_ampdu_reassemble && DOT11N_IS_AGGREGATE(n_ext_flags)) {
897         len_remain = tvb_length_remaining(tvb, offset);
898 #if 0 /* XXX: pad_len never actually used ?? */
899         if (DOT11N_MORE_AGGREGATES(n_ext_flags)) {
900             pad_len = PADDING4(len_remain);
901         }
902 #endif
903         pinfo->fragmented = TRUE;
904
905         /* Make sure we aren't going to go past AGGREGATE_MAX
906          * and caclulate our full A-MPDU length */
907         fd_head = fragment_get(pinfo, ampdu_id, ampdu_fragment_table);
908         while (fd_head) {
909             ampdu_len += fd_head->len + PADDING4(fd_head->len) + 4;
910             fd_head = fd_head->next;
911         }
912         if (ampdu_len > AGGREGATE_MAX) {
913             if (tree) {
914                 proto_tree_add_text(ppi_tree, tvb, offset, -1,
915                     "[Aggregate length greater than maximum (%u)]", AGGREGATE_MAX);
916                 THROW(ReportedBoundsError);
917             } else {
918                 return;
919             }
920         }
921
922         /*
923          * Note that we never actually reassemble our A-MPDUs.  Doing
924          * so would require prepending each MPDU with an A-MPDU delimiter
925          * and appending it with padding, only to hand it off to some
926          * routine which would un-do the work we just did.  We're using
927          * the reassembly code to track MPDU sizes and frame numbers.
928          */
929         /*??fd_head = */fragment_add_seq_next(tvb, offset, pinfo, ampdu_id,
930             ampdu_fragment_table, ampdu_reassembled_table,
931             len_remain, TRUE);
932         pinfo->fragmented = TRUE;
933
934         /* Do reassembly? */
935         fd_head = fragment_get(pinfo, ampdu_id, ampdu_fragment_table);
936
937         /* Show our fragments */
938         if (fd_head && tree) {
939             ft_fdh = fd_head;
940             /* List our fragments */
941             ti = proto_tree_add_text(ppi_tree, tvb, offset, -1, "A-MPDU (%u bytes w/hdrs):", ampdu_len);
942             PROTO_ITEM_SET_GENERATED(ti);
943             seg_tree = proto_item_add_subtree(ti, ett_ampdu_segments);
944
945             while (ft_fdh) {
946                 if (ft_fdh->data && ft_fdh->len) {
947                     last_frame = ft_fdh->frame;
948                     if (!first_mpdu)
949                         proto_item_append_text(ti, ",");
950                     first_mpdu = FALSE;
951                     proto_item_append_text(ti, " #%u(%u)",
952                         ft_fdh->frame, ft_fdh->len);
953                     proto_tree_add_uint_format(seg_tree, hf_ampdu_segment,
954                         tvb, 0, 0, last_frame,
955                         "Frame: %u (%u byte%s)",
956                         last_frame,
957                         ft_fdh->len,
958                         plurality(ft_fdh->len, "", "s"));
959                 }
960                 ft_fdh = ft_fdh->next;
961             }
962             if (last_frame && last_frame != pinfo->fd->num)
963                 proto_tree_add_uint(seg_tree, hf_ampdu_reassembled_in,
964                     tvb, 0, 0, last_frame);
965         }
966
967         if (fd_head && !DOT11N_MORE_AGGREGATES(n_ext_flags)) {
968             if (tree) {
969                 ti = proto_tree_add_protocol_format(tree,
970                     proto_get_id_by_filter_name("wlan_aggregate"),
971                     tvb, 0, tot_len, "IEEE 802.11 Aggregate MPDU");
972                 agg_tree = proto_item_add_subtree(ti, ett_ampdu);
973             }
974
975             while (fd_head) {
976                 if (fd_head->data && fd_head->len) {
977                     mpdu_count++;
978                     mpdu_str = ep_strdup_printf("MPDU #%d", mpdu_count);
979
980                     next_tvb = tvb_new_child_real_data(tvb, fd_head->data,
981                         fd_head->len, fd_head->len);
982                     add_new_data_source(pinfo, next_tvb, mpdu_str);
983
984                     if (agg_tree) {
985                         ti = proto_tree_add_text(agg_tree, next_tvb, 0, -1, "%s", mpdu_str);
986                         ampdu_tree = proto_item_add_subtree(ti, ett_ampdu_segment);
987                     }
988                     call_dissector(ieee80211_ht_handle, next_tvb, pinfo, ampdu_tree);
989                 }
990                 fd_head = fd_head->next;
991             }
992             proto_tree_add_uint(seg_tree, hf_ampdu_count, tvb, 0, 0, mpdu_count);
993             pinfo->fragmented=FALSE;
994         } else {
995             next_tvb = tvb_new_subset_remaining(tvb, offset);
996             col_set_str(pinfo->cinfo, COL_PROTOCOL, "IEEE 802.11n");
997             col_set_str(pinfo->cinfo, COL_INFO, "Unreassembled A-MPDU data");
998             call_dissector(data_handle, next_tvb, pinfo, tree);
999         }
1000         return;
1001     }
1002
1003     next_tvb = tvb_new_subset_remaining(tvb, offset);
1004     if (is_ht) { /* We didn't hit the reassembly code */
1005         call_dissector(ieee80211_ht_handle, next_tvb, pinfo, tree);
1006     } else {
1007         dissector_try_uint(wtap_encap_dissector_table,
1008             wtap_pcap_encap_to_wtap_encap(dlt), next_tvb, pinfo, tree);
1009     }
1010 }
1011
1012 /* Establish our beachead */
1013
1014 static void
1015 ampdu_reassemble_init(void)
1016 {
1017     fragment_table_init(&ampdu_fragment_table);
1018     reassembled_table_init(&ampdu_reassembled_table);
1019 }
1020
1021 void
1022 proto_register_ppi(void)
1023 {
1024     static hf_register_info hf[] = {
1025     { &hf_ppi_head_version,
1026       { "Version", "ppi.version",
1027         FT_UINT8, BASE_DEC, NULL, 0x0,
1028         "PPI header format version", HFILL } },
1029     { &hf_ppi_head_flags,
1030       { "Flags", "ppi.flags",
1031         FT_UINT8, BASE_HEX, NULL, 0x0,
1032         "PPI header flags", HFILL } },
1033     { &hf_ppi_head_flag_alignment,
1034       { "Alignment", "ppi.flags.alignment",
1035         FT_BOOLEAN, 8, TFS(&tfs_ppi_head_flag_alignment), 0x01,
1036         "PPI header flags - 32bit Alignment", HFILL } },
1037     { &hf_ppi_head_flag_reserved,
1038       { "Reserved", "ppi.flags.reserved",
1039         FT_UINT8, BASE_HEX, NULL, 0xFE,
1040         "PPI header flags - Reserved Flags", HFILL } },
1041     { &hf_ppi_head_len,
1042        { "Header length", "ppi.length",
1043          FT_UINT16, BASE_DEC, NULL, 0x0,
1044          "Length of header including payload", HFILL } },
1045     { &hf_ppi_head_dlt,
1046        { "DLT", "ppi.dlt",
1047          FT_UINT32, BASE_DEC, NULL, 0x0, "libpcap Data Link Type (DLT) of the payload", HFILL } },
1048
1049     { &hf_ppi_field_type,
1050        { "Field type", "ppi.field_type",
1051          FT_UINT16, BASE_DEC, VALS(vs_ppi_field_type), 0x0, "PPI data field type", HFILL } },
1052     { &hf_ppi_field_len,
1053        { "Field length", "ppi.field_len",
1054          FT_UINT16, BASE_DEC, NULL, 0x0, "PPI data field length", HFILL } },
1055
1056     { &hf_80211_common_tsft,
1057        { "TSFT", "ppi.80211-common.tsft",
1058          FT_UINT64, BASE_DEC, NULL, 0x0, "PPI 802.11-Common Timing Synchronization Function Timer (TSFT)", HFILL } },
1059     { &hf_80211_common_flags,
1060        { "Flags", "ppi.80211-common.flags",
1061          FT_UINT16, BASE_HEX, NULL, 0x0, "PPI 802.11-Common Flags", HFILL } },
1062     { &hf_80211_common_flags_fcs,
1063        { "FCS present flag", "ppi.80211-common.flags.fcs",
1064          FT_BOOLEAN, 16, TFS(&tfs_present_absent), 0x0001, "PPI 802.11-Common Frame Check Sequence (FCS) Present Flag", HFILL } },
1065     { &hf_80211_common_flags_tsft,
1066        { "TSFT flag", "ppi.80211-common.flags.tsft",
1067          FT_BOOLEAN, 16, TFS(&tfs_tsft_ms), 0x0002, "PPI 802.11-Common Timing Synchronization Function Timer (TSFT) msec/usec flag", HFILL } },
1068     { &hf_80211_common_flags_fcs_valid,
1069        { "FCS validity", "ppi.80211-common.flags.fcs-invalid",
1070          FT_BOOLEAN, 16, TFS(&tfs_invalid_valid), 0x0004, "PPI 802.11-Common Frame Check Sequence (FCS) Validity flag", HFILL } },
1071     { &hf_80211_common_flags_phy_err,
1072        { "PHY error flag", "ppi.80211-common.flags.phy-err",
1073          FT_BOOLEAN, 16, TFS(&tfs_phy_error), 0x0008, "PPI 802.11-Common Physical level (PHY) Error", HFILL } },
1074     { &hf_80211_common_rate,
1075        { "Data rate", "ppi.80211-common.rate",
1076          FT_UINT16, BASE_DEC, NULL, 0x0, "PPI 802.11-Common Data Rate (x 500 Kbps)", HFILL } },
1077     { &hf_80211_common_chan_freq,
1078        { "Channel frequency", "ppi.80211-common.chan.freq",
1079          FT_UINT16, BASE_DEC, NULL, 0x0,
1080         "PPI 802.11-Common Channel Frequency", HFILL } },
1081     { &hf_80211_common_chan_flags,
1082        { "Channel type", "ppi.80211-common.chan.type",
1083          FT_UINT16, BASE_HEX, VALS(vs_80211_common_phy_type), 0x0, "PPI 802.11-Common Channel Type", HFILL } },
1084
1085     { &hf_80211_common_chan_flags_turbo,
1086        { "Turbo", "ppi.80211-common.chan.type.turbo",
1087          FT_BOOLEAN, 16, NULL, 0x0010, "PPI 802.11-Common Channel Type Turbo", HFILL } },
1088     { &hf_80211_common_chan_flags_cck,
1089        { "Complementary Code Keying (CCK)", "ppi.80211-common.chan.type.cck",
1090          FT_BOOLEAN, 16, NULL, 0x0020, "PPI 802.11-Common Channel Type Complementary Code Keying (CCK) Modulation", HFILL } },
1091     { &hf_80211_common_chan_flags_ofdm,
1092        { "Orthogonal Frequency-Division Multiplexing (OFDM)", "ppi.80211-common.chan.type.ofdm",
1093          FT_BOOLEAN, 16, NULL, 0x0040, "PPI 802.11-Common Channel Type Orthogonal Frequency-Division Multiplexing (OFDM)", HFILL } },
1094     { &hf_80211_common_chan_flags_2ghz,
1095        { "2 GHz spectrum", "ppi.80211-common.chan.type.2ghz",
1096          FT_BOOLEAN, 16, NULL, 0x0080, "PPI 802.11-Common Channel Type 2 GHz spectrum", HFILL } },
1097     { &hf_80211_common_chan_flags_5ghz,
1098        { "5 GHz spectrum", "ppi.80211-common.chan.type.5ghz",
1099          FT_BOOLEAN, 16, NULL, 0x0100, "PPI 802.11-Common Channel Type 5 GHz spectrum", HFILL } },
1100     { &hf_80211_common_chan_flags_passive,
1101        { "Passive", "ppi.80211-common.chan.type.passive",
1102          FT_BOOLEAN, 16, NULL, 0x0200, "PPI 802.11-Common Channel Type Passive", HFILL } },
1103     { &hf_80211_common_chan_flags_dynamic,
1104        { "Dynamic CCK-OFDM", "ppi.80211-common.chan.type.dynamic",
1105          FT_BOOLEAN, 16, NULL, 0x0400, "PPI 802.11-Common Channel Type Dynamic CCK-OFDM Channel", HFILL } },
1106     { &hf_80211_common_chan_flags_gfsk,
1107        { "Gaussian Frequency Shift Keying (GFSK)", "ppi.80211-common.chan.type.gfsk",
1108          FT_BOOLEAN, 16, NULL, 0x0800, "PPI 802.11-Common Channel Type Gaussian Frequency Shift Keying (GFSK) Modulation", HFILL } },
1109
1110     { &hf_80211_common_fhss_hopset,
1111        { "FHSS hopset", "ppi.80211-common.fhss.hopset",
1112          FT_UINT8, BASE_HEX, NULL, 0x0, "PPI 802.11-Common Frequency-Hopping Spread Spectrum (FHSS) Hopset", HFILL } },
1113     { &hf_80211_common_fhss_pattern,
1114        { "FHSS pattern", "ppi.80211-common.fhss.pattern",
1115          FT_UINT8, BASE_HEX, NULL, 0x0, "PPI 802.11-Common Frequency-Hopping Spread Spectrum (FHSS) Pattern", HFILL } },
1116     { &hf_80211_common_dbm_antsignal,
1117        { "dBm antenna signal", "ppi.80211-common.dbm.antsignal",
1118          FT_INT8, BASE_DEC, NULL, 0x0, "PPI 802.11-Common dBm Antenna Signal", HFILL } },
1119     { &hf_80211_common_dbm_antnoise,
1120        { "dBm antenna noise", "ppi.80211-common.dbm.antnoise",
1121          FT_INT8, BASE_DEC, NULL, 0x0, "PPI 802.11-Common dBm Antenna Noise", HFILL } },
1122
1123     /* 802.11n MAC */
1124     { &hf_80211n_mac_flags,
1125        { "MAC flags", "ppi.80211n-mac.flags",
1126          FT_UINT32, BASE_HEX, NULL, 0x0, "PPI 802.11n MAC flags", HFILL } },
1127     { &hf_80211n_mac_flags_greenfield,
1128        { "Greenfield flag", "ppi.80211n-mac.flags.greenfield",
1129          FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x0001, "PPI 802.11n MAC Greenfield Flag", HFILL } },
1130     { &hf_80211n_mac_flags_ht20_40,
1131        { "HT20/HT40 flag", "ppi.80211n-mac.flags.ht20_40",
1132          FT_BOOLEAN, 32, TFS(&tfs_ht20_40), 0x0002, "PPI 802.11n MAC HT20/HT40 Flag", HFILL } },
1133     { &hf_80211n_mac_flags_rx_guard_interval,
1134        { "RX Short Guard Interval (SGI) flag", "ppi.80211n-mac.flags.rx.short_guard_interval",
1135          FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x0004, "PPI 802.11n MAC RX Short Guard Interval (SGI) Flag", HFILL } },
1136     { &hf_80211n_mac_flags_duplicate_rx,
1137        { "Duplicate RX flag", "ppi.80211n-mac.flags.rx.duplicate",
1138          FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x0008, "PPI 802.11n MAC Duplicate RX Flag", HFILL } },
1139     { &hf_80211n_mac_flags_aggregate,
1140        { "Aggregate flag", "ppi.80211n-mac.flags.agg",
1141          FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x0010, "PPI 802.11 MAC Aggregate Flag", HFILL } },
1142     { &hf_80211n_mac_flags_more_aggregates,
1143        { "More aggregates flag", "ppi.80211n-mac.flags.more_agg",
1144          FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x0020, "PPI 802.11n MAC More Aggregates Flag", HFILL } },
1145     { &hf_80211n_mac_flags_delimiter_crc_after,
1146        { "A-MPDU Delimiter CRC error after this frame flag", "ppi.80211n-mac.flags.delim_crc_error_after",
1147          FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x0040, "PPI 802.11n MAC A-MPDU Delimiter CRC Error After This Frame Flag", HFILL } },
1148     { &hf_80211n_mac_ampdu_id,
1149        { "AMPDU-ID", "ppi.80211n-mac.ampdu_id",
1150          FT_UINT32, BASE_HEX, NULL, 0x0, "PPI 802.11n MAC AMPDU-ID", HFILL } },
1151     { &hf_80211n_mac_num_delimiters,
1152        { "Num-Delimiters", "ppi.80211n-mac.num_delimiters",
1153          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC number of zero-length pad delimiters", HFILL } },
1154     { &hf_80211n_mac_reserved,
1155        { "Reserved", "ppi.80211n-mac.reserved",
1156          FT_UINT24, BASE_HEX, NULL, 0x0, "PPI 802.11n MAC Reserved", HFILL } },
1157
1158
1159     /* 802.11n MAC+PHY */
1160     { &hf_80211n_mac_phy_mcs,
1161        { "MCS", "ppi.80211n-mac-phy.mcs",
1162          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Modulation Coding Scheme (MCS)", HFILL } },
1163     { &hf_80211n_mac_phy_num_streams,
1164        { "Number of spatial streams", "ppi.80211n-mac-phy.num_streams",
1165          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY number of spatial streams", HFILL } },
1166     { &hf_80211n_mac_phy_rssi_combined,
1167        { "RSSI combined", "ppi.80211n-mac-phy.rssi.combined",
1168          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Received Signal Strength Indication (RSSI) Combined", HFILL } },
1169     { &hf_80211n_mac_phy_rssi_ant0_ctl,
1170        { "Antenna 0 control RSSI", "ppi.80211n-mac-phy.rssi.ant0ctl",
1171          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Antenna 0 Control Channel Received Signal Strength Indication (RSSI)", HFILL } },
1172     { &hf_80211n_mac_phy_rssi_ant1_ctl,
1173        { "Antenna 1 control RSSI", "ppi.80211n-mac-phy.rssi.ant1ctl",
1174          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Antenna 1 Control Channel Received Signal Strength Indication (RSSI)", HFILL } },
1175     { &hf_80211n_mac_phy_rssi_ant2_ctl,
1176        { "Antenna 2 control RSSI", "ppi.80211n-mac-phy.rssi.ant2ctl",
1177          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Antenna 2 Control Channel Received Signal Strength Indication (RSSI)", HFILL } },
1178     { &hf_80211n_mac_phy_rssi_ant3_ctl,
1179        { "Antenna 3 control RSSI", "ppi.80211n-mac-phy.rssi.ant3ctl",
1180          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Antenna 3 Control Channel Received Signal Strength Indication (RSSI)", HFILL } },
1181     { &hf_80211n_mac_phy_rssi_ant0_ext,
1182        { "Antenna 0 extension RSSI", "ppi.80211n-mac-phy.rssi.ant0ext",
1183          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Antenna 0 Extension Channel Received Signal Strength Indication (RSSI)", HFILL } },
1184     { &hf_80211n_mac_phy_rssi_ant1_ext,
1185        { "Antenna 1 extension RSSI", "ppi.80211n-mac-phy.rssi.ant1ext",
1186          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Antenna 1 Extension Channel Received Signal Strength Indication (RSSI)", HFILL } },
1187     { &hf_80211n_mac_phy_rssi_ant2_ext,
1188        { "Antenna 2 extension RSSI", "ppi.80211n-mac-phy.rssi.ant2ext",
1189          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Antenna 2 Extension Channel Received Signal Strength Indication (RSSI)", HFILL } },
1190     { &hf_80211n_mac_phy_rssi_ant3_ext,
1191        { "Antenna 3 extension RSSI", "ppi.80211n-mac-phy.rssi.ant3ext",
1192          FT_UINT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Antenna 3 Extension Channel Received Signal Strength Indication (RSSI)", HFILL } },
1193     { &hf_80211n_mac_phy_ext_chan_freq,
1194        { "Extended channel frequency", "ppi.80211-mac-phy.ext-chan.freq",
1195          FT_UINT16, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Extended Channel Frequency", HFILL } },
1196     { &hf_80211n_mac_phy_ext_chan_flags,
1197        { "Channel type", "ppi.80211-mac-phy.ext-chan.type",
1198          FT_UINT16, BASE_HEX, VALS(vs_80211_common_phy_type), 0x0, "PPI 802.11n MAC+PHY Channel Type", HFILL } },
1199     { &hf_80211n_mac_phy_ext_chan_flags_turbo,
1200        { "Turbo", "ppi.80211-mac-phy.ext-chan.type.turbo",
1201          FT_BOOLEAN, 16, NULL, 0x0010, "PPI 802.11n MAC+PHY Channel Type Turbo", HFILL } },
1202     { &hhf_80211n_mac_phy_ext_chan_flags_cck,
1203        { "Complementary Code Keying (CCK)", "ppi.80211-mac-phy.ext-chan.type.cck",
1204          FT_BOOLEAN, 16, NULL, 0x0020, "PPI 802.11n MAC+PHY Channel Type Complementary Code Keying (CCK) Modulation", HFILL } },
1205     { &hf_80211n_mac_phy_ext_chan_flags_ofdm,
1206        { "Orthogonal Frequency-Division Multiplexing (OFDM)", "ppi.80211-mac-phy.ext-chan.type.ofdm",
1207          FT_BOOLEAN, 16, NULL, 0x0040, "PPI 802.11n MAC+PHY Channel Type Orthogonal Frequency-Division Multiplexing (OFDM)", HFILL } },
1208     { &hhf_80211n_mac_phy_ext_chan_flags_2ghz,
1209        { "2 GHz spectrum", "ppi.80211-mac-phy.ext-chan.type.2ghz",
1210          FT_BOOLEAN, 16, NULL, 0x0080, "PPI 802.11n MAC+PHY Channel Type 2 GHz spectrum", HFILL } },
1211     { &hf_80211n_mac_phy_ext_chan_flags_5ghz,
1212        { "5 GHz spectrum", "ppi.80211-mac-phy.ext-chan.type.5ghz",
1213          FT_BOOLEAN, 16, NULL, 0x0100, "PPI 802.11n MAC+PHY Channel Type 5 GHz spectrum", HFILL } },
1214     { &hf_80211n_mac_phy_ext_chan_flags_passive,
1215        { "Passive", "ppi.80211-mac-phy.ext-chan.type.passive",
1216          FT_BOOLEAN, 16, NULL, 0x0200, "PPI 802.11n MAC+PHY Channel Type Passive", HFILL } },
1217     { &hf_80211n_mac_phy_ext_chan_flags_dynamic,
1218        { "Dynamic CCK-OFDM", "ppi.80211-mac-phy.ext-chan.type.dynamic",
1219          FT_BOOLEAN, 16, NULL, 0x0400, "PPI 802.11n MAC+PHY Channel Type Dynamic CCK-OFDM Channel", HFILL } },
1220     { &hf_80211n_mac_phy_ext_chan_flags_gfsk,
1221        { "Gaussian Frequency Shift Keying (GFSK)", "ppi.80211-mac-phy.ext-chan.type.gfsk",
1222          FT_BOOLEAN, 16, NULL, 0x0800, "PPI 802.11n MAC+PHY Channel Type Gaussian Frequency Shift Keying (GFSK) Modulation", HFILL } },
1223     { &hf_80211n_mac_phy_dbm_ant0signal,
1224        { "dBm antenna 0 signal", "ppi.80211n-mac-phy.dbmant0.signal",
1225          FT_INT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY dBm Antenna 0 Signal", HFILL } },
1226     { &hf_80211n_mac_phy_dbm_ant0noise,
1227        { "dBm antenna 0 noise", "ppi.80211n-mac-phy.dbmant0.noise",
1228          FT_INT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY dBm Antenna 0 Noise", HFILL } },
1229     { &hf_80211n_mac_phy_dbm_ant1signal,
1230        { "dBm antenna 1 signal", "ppi.80211n-mac-phy.dbmant1.signal",
1231          FT_INT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY dBm Antenna 1 Signal", HFILL } },
1232     { &hf_80211n_mac_phy_dbm_ant1noise,
1233        { "dBm antenna 1 noise", "ppi.80211n-mac-phy.dbmant1.noise",
1234          FT_INT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY dBm Antenna 1 Noise", HFILL } },
1235     { &hf_80211n_mac_phy_dbm_ant2signal,
1236        { "dBm antenna 2 signal", "ppi.80211n-mac-phy.dbmant2.signal",
1237          FT_INT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY dBm Antenna 2 Signal", HFILL } },
1238     { &hf_80211n_mac_phy_dbm_ant2noise,
1239        { "dBm antenna 2 noise", "ppi.80211n-mac-phy.dbmant2.noise",
1240          FT_INT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY dBm Antenna 2 Noise", HFILL } },
1241     { &hf_80211n_mac_phy_dbm_ant3signal,
1242        { "dBm antenna 3 signal", "ppi.80211n-mac-phy.dbmant3.signal",
1243          FT_INT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY dBm Antenna 3 Signal", HFILL } },
1244     { &hf_80211n_mac_phy_dbm_ant3noise,
1245        { "dBm antenna 3 noise", "ppi.80211n-mac-phy.dbmant3.noise",
1246          FT_INT8, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY dBm Antenna 3 Noise", HFILL } },
1247     { &hf_80211n_mac_phy_evm0,
1248        { "EVM-0", "ppi.80211n-mac-phy.evm0",
1249          FT_UINT32, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Error Vector Magnitude (EVM) for chain 0", HFILL } },
1250     { &hf_80211n_mac_phy_evm1,
1251        { "EVM-1", "ppi.80211n-mac-phy.evm1",
1252          FT_UINT32, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Error Vector Magnitude (EVM) for chain 1", HFILL } },
1253     { &hf_80211n_mac_phy_evm2,
1254        { "EVM-2", "ppi.80211n-mac-phy.evm2",
1255          FT_UINT32, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Error Vector Magnitude (EVM) for chain 2", HFILL } },
1256     { &hf_80211n_mac_phy_evm3,
1257        { "EVM-3", "ppi.80211n-mac-phy.evm3",
1258          FT_UINT32, BASE_DEC, NULL, 0x0, "PPI 802.11n MAC+PHY Error Vector Magnitude (EVM) for chain 3", HFILL } },
1259
1260     { &hf_ampdu_segment,
1261         { "A-MPDU", "ppi.80211n-mac.ampdu",
1262             FT_FRAMENUM, BASE_NONE, NULL, 0x0, "802.11n Aggregated MAC Protocol Data Unit (A-MPDU)", HFILL }},
1263 #if 0
1264     { &hf_ampdu_segments,
1265         { "Reassembled A-MPDU", "ppi.80211n-mac.ampdu.reassembled",
1266             FT_NONE, BASE_NONE, NULL, 0x0, "Reassembled Aggregated MAC Protocol Data Unit (A-MPDU)", HFILL }},
1267 #endif
1268     { &hf_ampdu_reassembled_in,
1269         { "Reassembled A-MPDU in frame", "ppi.80211n-mac.ampdu.reassembled_in",
1270             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1271             "The A-MPDU that doesn't end in this segment is reassembled in this frame",
1272             HFILL }},
1273     { &hf_ampdu_count,
1274         { "MPDU count", "ppi.80211n-mac.ampdu.count",
1275             FT_UINT16, BASE_DEC, NULL, 0x0, "The number of aggregated MAC Protocol Data Units (MPDUs)", HFILL }},
1276
1277     { &hf_spectrum_map,
1278        { "Radio spectrum map", "ppi.spectrum-map",
1279             FT_BYTES, BASE_NONE, NULL, 0x0, "PPI Radio spectrum map", HFILL } },
1280     { &hf_process_info,
1281        { "Process information", "ppi.proc-info",
1282             FT_BYTES, BASE_NONE, NULL, 0x0, "PPI Process information", HFILL } },
1283     { &hf_capture_info,
1284        { "Capture information", "ppi.cap-info",
1285             FT_BYTES, BASE_NONE, NULL, 0x0, "PPI Capture information", HFILL } },
1286
1287     /* Aggregtion Extension */
1288     { &hf_aggregation_extension_interface_id,
1289        { "Interface ID", "ppi.aggregation_extension.interface_id",
1290             FT_UINT32, BASE_DEC, NULL, 0x0, "Zero-based index of the physical interface the packet was captured from", HFILL } },
1291
1292     /* 802.3 Extension */
1293     { &hf_8023_extension_flags,
1294        { "Flags", "ppi.8023_extension.flags",
1295             FT_UINT32, BASE_HEX, NULL, 0x0, "PPI 802.3 Extension Flags", HFILL } },
1296     { &hf_8023_extension_flags_fcs_present,
1297        { "FCS Present Flag", "ppi.8023_extension.flags.fcs_present",
1298             FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x0001, "FCS (4 bytes) is present at the end of the packet", HFILL } },
1299     { &hf_8023_extension_errors,
1300        { "Errors", "ppi.8023_extension.errors",
1301             FT_UINT32, BASE_HEX, NULL, 0x0, "PPI 802.3 Extension Errors", HFILL } },
1302     { &hf_8023_extension_errors_fcs,
1303        { "FCS Error", "ppi.8023_extension.errors.fcs",
1304             FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x0001,
1305             "PPI 802.3 Extension FCS Error", HFILL } },
1306     { &hf_8023_extension_errors_sequence,
1307        { "Sequence Error", "ppi.8023_extension.errors.sequence",
1308             FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x0002,
1309             "PPI 802.3 Extension Sequence Error", HFILL } },
1310     { &hf_8023_extension_errors_symbol,
1311        { "Symbol Error", "ppi.8023_extension.errors.symbol",
1312             FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x0004,
1313             "PPI 802.3 Extension Symbol Error", HFILL } },
1314     { &hf_8023_extension_errors_data,
1315        { "Data Error", "ppi.8023_extension.errors.data",
1316             FT_BOOLEAN, 32, TFS(&tfs_true_false), 0x0008,
1317             "PPI 802.3 Extension Data Error", HFILL } },
1318
1319     };
1320
1321     static gint *ett[] = {
1322         &ett_ppi_pph,
1323         &ett_ppi_flags,
1324         &ett_dot11_common,
1325         &ett_dot11_common_flags,
1326         &ett_dot11_common_channel_flags,
1327         &ett_dot11n_mac,
1328         &ett_dot11n_mac_flags,
1329         &ett_dot11n_mac_phy,
1330         &ett_dot11n_mac_phy_ext_channel_flags,
1331         &ett_ampdu_segments,
1332         &ett_ampdu,
1333         &ett_ampdu_segment,
1334         &ett_aggregation_extension,
1335         &ett_8023_extension,
1336         &ett_8023_extension_flags,
1337         &ett_8023_extension_errors
1338     };
1339
1340     module_t *ppi_module;
1341
1342     proto_ppi = proto_register_protocol("PPI Packet Header", "PPI", "ppi");
1343     proto_register_field_array(proto_ppi, hf, array_length(hf));
1344     proto_register_subtree_array(ett, array_length(ett));
1345     register_dissector("ppi", dissect_ppi, proto_ppi);
1346
1347     register_init_routine(ampdu_reassemble_init);
1348
1349     /* Configuration options */
1350     ppi_module = prefs_register_protocol(proto_ppi, NULL);
1351     prefs_register_bool_preference(ppi_module, "reassemble",
1352                                    "Reassemble fragmented 802.11 A-MPDUs",
1353                                    "Whether fragmented 802.11 aggregated MPDUs should be reassembled",
1354                                    &ppi_ampdu_reassemble);
1355 }
1356
1357 void
1358 proto_reg_handoff_ppi(void)
1359 {
1360     dissector_handle_t ppi_handle;
1361
1362     ppi_handle = create_dissector_handle(dissect_ppi, proto_ppi);
1363     data_handle = find_dissector("data");
1364     ieee80211_ht_handle = find_dissector("wlan_ht");
1365     ppi_gps_handle = find_dissector("ppi_gps");
1366     ppi_vector_handle = find_dissector("ppi_vector");
1367     ppi_sensor_handle = find_dissector("ppi_sensor");
1368     ppi_antenna_handle = find_dissector("ppi_antenna");
1369
1370     dissector_add_uint("wtap_encap", WTAP_ENCAP_PPI, ppi_handle);
1371 }
1372
1373 /*
1374  * Editor modelines
1375  *
1376  * Local Variables:
1377  * c-basic-offset: 4
1378  * tab-width: 8
1379  * indent-tabs-mode: nil
1380  * End:
1381  *
1382  * ex: set shiftwidth=4 tabstop=8 expandtab:
1383  * :indentSize=4:tabSize=8:noTabs=true:
1384  */