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