Coverage Report

Created: 2026-06-30 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-ieee80211-prism.c
Line
Count
Source
1
/* packet-ieee80211-prism.c
2
 * Routines for Prism monitoring mode header dissection
3
 *
4
 * Wireshark - Network traffic analyzer
5
 * By Gerald Combs <gerald@wireshark.org>
6
 * Copyright 1998 Gerald Combs
7
 * Copyright (c) 2016, The Linux Foundation. All rights reserved.
8
 * Copyright 2016 Cisco Meraki
9
 *
10
 * Copied from README.developer
11
 *
12
 * SPDX-License-Identifier: GPL-2.0-or-later
13
 *
14
 */
15
16
#include "config.h"
17
18
#include <epan/packet.h>
19
#include <epan/capture_dissectors.h>
20
#include <wsutil/pint.h>
21
#include <wsutil/802_11-utils.h>
22
#include "packet-ieee80211.h"
23
24
void proto_register_ieee80211_prism(void);
25
void proto_reg_handoff_ieee80211_prism(void);
26
27
0
#define SHORT_STR 256
28
29
static dissector_handle_t wlancap_handle;
30
static dissector_handle_t ieee80211_handle;
31
static dissector_handle_t ieee80211_radio_handle;
32
33
static capture_dissector_handle_t ieee80211_cap_handle;
34
static capture_dissector_handle_t wlancap_cap_handle;
35
36
static int proto_prism;
37
38
/* Prism radio header */
39
40
static int hf_ieee80211_prism_msgcode;
41
static int hf_ieee80211_prism_msglen;
42
static int hf_ieee80211_prism_devname;
43
static int hf_ieee80211_prism_did;
44
static int hf_ieee80211_prism_did_type;
45
static int hf_ieee80211_prism_did_status;
46
static int hf_ieee80211_prism_did_length;
47
static int hf_ieee80211_prism_did_hosttime;
48
static int hf_ieee80211_prism_did_mactime;
49
static int hf_ieee80211_prism_did_channel;
50
static int hf_ieee80211_prism_did_rssi;
51
static int hf_ieee80211_prism_did_sq;
52
static int hf_ieee80211_prism_did_signal;
53
static int hf_ieee80211_prism_did_noise;
54
static int hf_ieee80211_prism_did_rate;
55
static int hf_ieee80211_prism_did_istx;
56
static int hf_ieee80211_prism_did_frmlen;
57
static int hf_ieee80211_prism_did_unknown;
58
59
/* Qualcomm Extensions */
60
static int hf_ieee80211_prism_did_sig_a1;
61
static int hf_ieee80211_prism_did_sig_a2;
62
static int hf_ieee80211_prism_did_sig_b;
63
static int hf_ieee80211_prism_did_sig_rate_field;
64
65
66
static int ett_prism;
67
static int ett_prism_did;
68
static int ett_sig_ab;
69
70
static dissector_handle_t prism_handle;
71
72
/*
73
 * Prism II-based wlan devices have a monitoring mode that sticks
74
 * a proprietary header on each packet with lots of good
75
 * information.  This file is responsible for decoding that
76
 * data.
77
 *
78
 * Support by Tim Newsham
79
 *
80
 * A value from the header.
81
 *
82
 * It appears from looking at the linux-wlan-ng and Prism II HostAP
83
 * drivers, and various patches to the orinoco_cs drivers to add
84
 * Prism headers, that:
85
 *
86
 *      the "did" identifies what the value is (i.e., what it's the value
87
 *      of);
88
 *
89
 *      "status" is 0 if the value is present or 1 if it's absent;
90
 *
91
 *      "len" is the length of the value (always 4, in that code);
92
 *
93
 *      "data" is the value of the data (or 0 if not present).
94
 *
95
 * Note: all of those values are in the *host* byte order of the machine
96
 * on which the capture was written.
97
 */
98
99
100
/*
101
 * Header attached during Prism monitor mode.
102
 *
103
 * At least according to one paper I've seen, the Prism 2.5 chip set
104
 * provides:
105
 *
106
 *      RSSI (receive signal strength indication) is "the total power
107
 *      received by the radio hardware while receiving the frame,
108
 *      including signal, interference, and background noise";
109
 *
110
 *      "silence value" is "the total power observed just before the
111
 *      start of the frame".
112
 *
113
 * None of the drivers I looked at supply the "rssi" or "sq" value,
114
 * but they do supply "signal" and "noise" values, along with a "rate"
115
 * value that's 1/5 of the raw value from what is presumably a raw
116
 * HFA384x frame descriptor, with the comment "set to 802.11 units",
117
 * which presumably means the units are 500 Kb/s.
118
 *
119
 * I infer from the current NetBSD "wi" driver that "signal" and "noise"
120
 * are adjusted dBm values, with the dBm value having 100 added to it
121
 * for the Prism II cards (although the NetBSD code has an XXX comment
122
 * for the #define for WI_PRISM_DBM_OFFSET) and 149 (with no XXX comment)
123
 * for the Orinoco cards.
124
 *
125
 * XXX - what about other drivers that supply Prism headers, such as
126
 * old versions of the MadWifi driver?
127
 *
128
 * I'm not sure where these DID values come from, but they work with
129
 * at least one capture file.  However, in
130
 *
131
 *    https://ask.wireshark.org/questions/14963/how-to-get-the-field-did-unknown-4041-into-the-column
132
 *
133
 * somebody reports a capture where *different* DID values, corresponding
134
 * to
135
 *
136
 *    http://www.martin.cc/linux/prism
137
 *
138
 * are used (and that's not a byte-order issue, as those values are *not*
139
 * just byte-swapped versions of the other values).
140
 */
141
142
0
#define PRISM_HEADER_LENGTH     144             /* Default Prism Header Length */
143
144
/*
145
 * Message code values.
146
 *
147
 * Some Prism captures have headers that begin with 0x00000044; those
148
 * captures have the non-home.martin.cc values for the DID types,
149
 * while a capture with 0x00000041 as the message code have the
150
 * home.martin.cc values for the DID types, and the home.martin.cc
151
 * page has 0x00000041 as the message code.
152
 */
153
6
#define PRISM_TYPE1_MSGCODE      0x00000044      /* Monitor Frame */
154
4
#define PRISM_TYPE2_MSGCODE      0x00000041
155
156
/*
157
 * DID codes - PRISM_TYPE1_xxx are the non-home.martin.cc values, and
158
 * PRISM_TYPE2_xxx are the home.martin.cc values.
159
 */
160
0
#define PRISM_TYPE1_HOSTTIME     0x00010044      /* Host time element */
161
0
#define PRISM_TYPE2_HOSTTIME     0x00001041
162
0
#define PRISM_TYPE1_MACTIME      0x00020044      /* Mac time element */
163
0
#define PRISM_TYPE2_MACTIME      0x00002041
164
0
#define PRISM_TYPE1_CHANNEL      0x00030044      /* Channel element */
165
0
#define PRISM_TYPE2_CHANNEL      0x00003041
166
0
#define PRISM_TYPE1_RSSI         0x00040044      /* RSSI element */
167
0
#define PRISM_TYPE2_RSSI         0x00004041
168
0
#define PRISM_TYPE1_SQ           0x00050044      /* SQ element */
169
0
#define PRISM_TYPE2_SQ           0x00005041
170
0
#define PRISM_TYPE1_SIGNAL       0x00060044      /* Signal element */
171
0
#define PRISM_TYPE2_SIGNAL       0x00006041
172
0
#define PRISM_TYPE1_NOISE        0x00070044      /* Noise element */
173
0
#define PRISM_TYPE2_NOISE        0x00007041
174
0
#define PRISM_TYPE1_RATE         0x00080044      /* Rate element */
175
0
#define PRISM_TYPE2_RATE         0x00008041
176
0
#define PRISM_TYPE1_ISTX         0x00090044      /* Is Tx frame */
177
0
#define PRISM_TYPE2_ISTX         0x00009041
178
0
#define PRISM_TYPE1_FRMLEN       0x000A0044      /* Frame length */
179
0
#define PRISM_TYPE2_FRMLEN       0x0000A041
180
181
/* Qualcomm extensions */
182
0
#define PRISM_TYPE1_RATE_SIG_A1  0x000B0044      /* VHT SIGA1 element */
183
0
#define PRISM_TYPE2_RATE_SIG_A1  0x0000B044
184
0
#define PRISM_TYPE1_RATE_SIG_A2  0x000C0044      /* VHT SIGA2 element */
185
0
#define PRISM_TYPE2_RATE_SIG_A2  0x0000C044
186
0
#define PRISM_TYPE1_RATE_SIG_B   0x000D0044      /* VHT SIGB element */
187
0
#define PRISM_TYPE2_RATE_SIG_B   0x0000D044      /* VHT SIGB element */
188
189
static const value_string prism_did_vals[] =
190
{
191
    { PRISM_TYPE1_HOSTTIME,   "Host Time" },
192
    { PRISM_TYPE2_HOSTTIME,   "Host Time" },
193
    { PRISM_TYPE1_MACTIME,    "Mac Time" },
194
    { PRISM_TYPE2_MACTIME,    "Mac Time" },
195
    { PRISM_TYPE1_CHANNEL,    "Channel" },
196
    { PRISM_TYPE2_CHANNEL,    "Channel" },
197
    { PRISM_TYPE1_RSSI,       "RSSI" },
198
    { PRISM_TYPE2_RSSI,       "RSSI" },
199
    { PRISM_TYPE1_SQ,         "SQ" },
200
    { PRISM_TYPE2_SQ,         "SQ" },
201
    { PRISM_TYPE1_SIGNAL,     "Signal" },
202
    { PRISM_TYPE2_SIGNAL,     "Signal" },
203
    { PRISM_TYPE1_NOISE,      "Noise" },
204
    { PRISM_TYPE2_NOISE,      "Noise" },
205
    { PRISM_TYPE1_RATE,       "Rate" },
206
    { PRISM_TYPE2_RATE,       "Rate" },
207
    { PRISM_TYPE1_ISTX,       "Is Tx" },
208
    { PRISM_TYPE2_ISTX,       "Is Tx" },
209
    { PRISM_TYPE1_FRMLEN,     "Frame Length" },
210
    { PRISM_TYPE2_FRMLEN,     "Frame Length" },
211
212
    /* Qualcomm extensions */
213
    { PRISM_TYPE1_RATE_SIG_A1, "SIG A1" },
214
    { PRISM_TYPE2_RATE_SIG_A1, "SIG A1" },
215
    { PRISM_TYPE1_RATE_SIG_A2, "SIG A2" },
216
    { PRISM_TYPE2_RATE_SIG_A2, "SIG A2" },
217
    { PRISM_TYPE1_RATE_SIG_B,  "SIG B" },
218
    { PRISM_TYPE2_RATE_SIG_B,  "SIG B" },
219
    { 0, NULL}
220
};
221
222
/*
223
 * The header file mentioned above says 0 means "supplied" and 1 means
224
 * "not supplied".  I haven't seen a capture file with anything other
225
 * than 0 there, but there is at least one driver that appears to use
226
 * 1 for values it doesn't supply (the Linux acx-20080210 driver).
227
 */
228
static const value_string prism_status_vals[] =
229
{
230
    { 0, "Supplied" },
231
    { 1, "Not Supplied" },
232
    { 0, NULL}
233
};
234
235
static const value_string prism_istx_vals[] =
236
{
237
    { 0, "Rx Packet" },
238
    { 1, "Tx Packet" },
239
    { 0, NULL}
240
};
241
242
static void
243
prism_rate_base_custom(char *result, uint32_t rate)
244
0
{
245
0
    snprintf(result, ITEM_LABEL_LENGTH, "%u.%u", rate /2, rate & 1 ? 5 : 0);
246
0
}
247
248
static char *
249
prism_rate_return(wmem_allocator_t *scope, uint32_t rate)
250
0
{
251
0
    char *result=NULL;
252
0
    result = (char *)wmem_alloc(scope, SHORT_STR);
253
0
    result[0] = '\0';
254
0
    prism_rate_base_custom(result, rate);
255
256
0
    return result;
257
0
}
258
259
260
/* HT20 Rate table MAX NSS = 4 */
261
static const unsigned int ht_20_tbl[32][2] =
262
{
263
    { 65,   72   },   /* MCS 0 */
264
    { 130,  144  },   /* MCS 1 */
265
    { 195,  217  },   /* MCS 2 */
266
    { 260,  289  },   /* MCS 3 */
267
    { 390,  433  },   /* MCS 4 */
268
    { 520,  578  },   /* MCS 5 */
269
    { 585,  650  },   /* MCS 6 */
270
    { 650,  722  },   /* MCS 7 */
271
    { 130,  144  },   /* MCS 8 */
272
    { 260,  289  },   /* MCS 9 */
273
    { 390,  433  },   /* MCS 10 */
274
    { 520,  578  },   /* MCS 11 */
275
    { 780,  867  },   /* MCS 12 */
276
    { 1040, 1156 },   /* MCS 13 */
277
    { 1170, 1300 },   /* MCS 14 */
278
    { 1300, 1444 },   /* MCS 15 */
279
    { 195,  217  },   /* MCS 16 */
280
    { 390,  433  },   /* MCS 17 */
281
    { 585,  650  },   /* MCS 18 */
282
    { 780,  867  },   /* MCS 19 */
283
    { 1170, 1300 },   /* MCS 20 */
284
    { 1560, 1733 },   /* MCS 21 */
285
    { 1755, 1950 },   /* MCS 22 */
286
    { 1950, 2167 },   /* MCS 23 */
287
    { 260,  289  },   /* MCS 24 */
288
    { 520,  578  },   /* MCS 25 */
289
    { 780,  867  },   /* MCS 26 */
290
    { 1040, 1156 },   /* MCS 27 */
291
    { 1560, 1733 },   /* MCS 28 */
292
    { 2080, 2311 },   /* MCS 29 */
293
    { 2340, 2600 },   /* MCS 30 */
294
    { 2600, 2889 }    /* MCS 31 */
295
};
296
297
/* HT40 Rate table MAX NSS = 4 */
298
static const unsigned int ht_40_tbl[32][2] =
299
{
300
    { 135,  150  },    /* MCS 0 */
301
    { 270,  300  },    /* MCS 1 */
302
    { 405,  450  },    /* MCS 2 */
303
    { 540,  600  },    /* MCS 3 */
304
    { 810,  900  },    /* MCS 4 */
305
    { 1080, 1200 },    /* MCS 5 */
306
    { 1215, 1350 },    /* MCS 6 */
307
    { 1350, 1500 },    /* MCS 7 */
308
    { 270,  300  },    /* MCS 8 */
309
    { 540,  600  },    /* MCS 9 */
310
    { 810,  900  },    /* MCS 10 */
311
    { 1080, 1200 },    /* MCS 11 */
312
    { 1620, 1800 },    /* MCS 12 */
313
    { 2160, 2400 },    /* MCS 13 */
314
    { 2430, 2700 },    /* MCS 14 */
315
    { 2700, 3000 },    /* MCS 15 */
316
    { 405,  450  },    /* MCS 16 */
317
    { 810,  900  },    /* MCS 17 */
318
    { 1215, 1350 },    /* MCS 18 */
319
    { 1620, 1800 },    /* MCS 19 */
320
    { 2430, 2700 },    /* MCS 20 */
321
    { 3240, 3600 },    /* MCS 21 */
322
    { 3645, 4050 },    /* MCS 22 */
323
    { 4050, 4500 },    /* MCS 23 */
324
    { 540,  600  },    /* MCS 24 */
325
    { 1080, 1200 },    /* MCS 25 */
326
    { 1620, 1800 },    /* MCS 26 */
327
    { 2160, 2400 },    /* MCS 27 */
328
    { 3240, 3600 },    /* MCS 28 */
329
    { 4320, 4800 },    /* MCS 29 */
330
    { 4860, 5400 },    /* MCS 30 */
331
    { 5400, 6000 }};   /* MCS 31 */
332
333
/* VHT20 Rate Table MAX NSS = 4 */
334
static const unsigned int vht_20_tbl[10][8] =
335
{
336
    { 65,  72,  130,  144,  195,  217,   260,   289},    /* MCS 0 */
337
    { 130, 144, 260,  289,  390,  433,   520,   578},    /* MCS 1 */
338
    { 195, 217, 390,  433,  585,  650,   780,   867},    /* MCS 2 */
339
    { 260, 289, 520,  578,  780,  867,   1040,  1156},   /* MCS 3 */
340
    { 390, 433, 780,  867,  1170, 1300,  1560,  1733},   /* MCS 4 */
341
    { 520, 578, 1040, 1156, 1560, 1733,  2080,  2311},   /* MCS 5 */
342
    { 585, 650, 1170, 1300, 1755, 1950,  2340,  2600},   /* MCS 6 */
343
    { 650, 722, 1300, 1444, 1950, 2167,  2600,  2889},   /* MCS 7 */
344
    { 780, 867, 1560, 1733, 2340, 2600,  3120,  3467},   /* MCS 8 */
345
    {   0,   0,    0,    0, 2600, 2889,     0,     0}    /* MCS 9 */
346
};
347
348
/* VHT40 Rate Table MAX NSS = 4 */
349
static const unsigned int vht_40_tbl[10][8] =
350
{
351
    { 135,  150,  270,   300,  405,  450,   540,   600},    /* MCS 0 */
352
    { 270,  300,  540,   600,  810,  900,  1080,  1200},    /* MCS 1 */
353
    { 405,  450,  810,   900, 1215, 1350,  1620,  1800},    /* MCS 2 */
354
    { 540,  600,  1080, 1200, 1620, 1800,  2160,  2400},    /* MCS 3 */
355
    { 810,  900,  1620, 1800, 2430, 2700,  3240,  3600},    /* MCS 4 */
356
    { 1080, 1200, 2160, 2400, 3240, 3600,  4320,  4800},    /* MCS 5 */
357
    { 1215, 1350, 2430, 2700, 3645, 4050,  4860,  5400},    /* MCS 6 */
358
    { 1350, 1500, 2700, 3000, 4050, 4500,  5400,  6000},    /* MCS 7 */
359
    { 1620, 1800, 3240, 3600, 4860, 5400,  6480,  7200},    /* MCS 8 */
360
    { 1800, 2000, 3600, 4000, 5400, 6000,  7200,  8000}     /* MCS 9 */
361
};
362
363
/* VHT80 Rate Table MAX NSS = 4 */
364
static const unsigned int vht_80_tbl[10][8] =
365
{
366
    {  293,  325,  585,  650,   878,   975,   1170,   1300},   /* MCS 0 */
367
    {  585,  650, 1170, 1300,  1755,  1950,   2340,   2600},   /* MCS 1 */
368
    {  878,  975, 1755, 1950,  2633,  2925,   3510,   3900},   /* MCS 2 */
369
    { 1170, 1300, 2340, 2600,  3510,  3900,   4680,   5200},   /* MCS 3 */
370
    { 1755, 1950, 3510, 3900,  5265,  5850,   7020,   7800},   /* MCS 4 */
371
    { 2340, 2600, 4680, 5200,  7020,  7800,   9360,  10400},   /* MCS 5 */
372
    { 2633, 2925, 5265, 5850,     0,     0,  10530,  11700},   /* MCS 6 */
373
    { 2925, 3250, 5850, 6500,  8775,  9750,  11700,  13000},   /* MCS 7 */
374
    { 3510, 3900, 7020, 7800, 10530, 11700,  14040,  15600},   /* MCS 8 */
375
    { 3900, 4333, 7800, 8667, 11700, 13000,  15600,  17333}    /* MCS 9 */
376
};
377
378
/* VHT160 Rate Table MAX NSS = 4 */
379
static const unsigned int vht_160_tbl[10][8] =
380
{
381
    {  585,  650,  1170,  1300,  1755,  1950,  2340,  2600},   /* MCS 0 */
382
    { 1170, 1300,  2340,  2600,  3510,  3900,  4680,  5200},   /* MCS 1 */
383
    { 1755, 1950,  3510,  3900,  5265,  5850,  7020,  7800},   /* MCS 2 */
384
    { 2340, 2600,  4680,  5200,  7020,  7800,  9360, 10400},   /* MCS 3 */
385
    { 3510, 3900,  7020,  7800, 10530, 11700, 14040, 15600},   /* MCS 4 */
386
    { 4680, 5200,  9360, 10400, 14040, 15600, 18720, 20800},   /* MCS 5 */
387
    { 5265, 5850, 10530, 11700, 15795, 17550, 21060, 23400},   /* MCS 6 */
388
    { 5850, 6500, 11700, 13000, 17550, 19500, 23400, 26000},   /* MCS 7 */
389
    { 7020, 7800, 14040, 15600, 21060, 23400, 28080, 31200},   /* MCS 8 */
390
    { 7800, 8667, 15600, 17333,     0,     0, 31200, 34667}    /* MCS 9 */
391
};
392
393
394
static char *
395
prism_rate_return_sig(wmem_allocator_t *scope, uint32_t rate_phy1, uint32_t rate_phy2, struct ieee_802_11_phdr *phdr)
396
0
{
397
0
    char *result = NULL;
398
0
    unsigned int mcs, base, pream_type, disp_rate, bw, sgi, ldpc, stbc, groupid, txbf;
399
0
    bool su_ppdu = false;
400
0
    unsigned int partial_aid, nsts_u1, nsts_u2, nsts_u3, nsts_u4;
401
0
    unsigned int sig_a_1, sig_a_2, nss = 1, nsts_su, signal_type;
402
0
    unsigned int dsss_tbl[] = {22, 11, 4, 2};
403
0
    static const unsigned int bw_map[] = { 0, 1, 4, 11 };
404
405
    /*
406
     * Qualcomm Atheros: Display Nss, MCS/Rate, BW, sgi, LDPC, STBC info
407
     */
408
0
    pream_type =  rate_phy1 & 0xF;
409
0
    switch (pream_type) {
410
411
0
    case 0: /* OFDM */
412
0
        phdr->phy = PHDR_802_11_PHY_11A; /* or 11g? */
413
0
        mcs = (rate_phy1 >> 4) & 0xF;
414
0
        base = (mcs & 0x4) ? 9 : 6;
415
0
        mcs &= ~0x4;
416
0
        mcs = base << (11 - mcs);
417
0
        mcs = (mcs > 54) ? 54 : mcs;
418
0
        phdr->has_data_rate = 1;
419
0
        phdr->data_rate = mcs * 2;
420
0
        signal_type = rate_phy1 & (1 << 12);
421
0
        bw = 20 << ((rate_phy1 >> 13) & 0x3);
422
0
        result = wmem_strdup_printf(scope,
423
0
              "Rate: %u.%u Mb/s OFDM Signaling:%s BW %d",
424
0
               mcs, 0, signal_type ? "Dynamic" : "Static", bw
425
0
              );
426
0
        break;
427
428
0
    case 1: /* DSSS */
429
0
        phdr->phy = PHDR_802_11_PHY_11B;
430
0
        mcs = (rate_phy1 >> 4) & 0xF;
431
0
        base = (mcs & 0x4) ? 1 : 0;
432
0
        phdr->phy_info.info_11b.has_short_preamble = 1;
433
0
        phdr->phy_info.info_11b.short_preamble = base;
434
0
        mcs &= ~0x4;
435
0
        mcs = (mcs - 8) & 0x3;
436
0
        disp_rate = dsss_tbl[mcs];
437
0
        phdr->has_data_rate = 1;
438
0
        phdr->data_rate = disp_rate;
439
0
        result = wmem_strdup_printf(scope, "Rate: %u.%u Mb/s DSSS %s",
440
0
                      disp_rate / 2,
441
0
                      (disp_rate & 1) ? 5 : 0,
442
0
                      base ? "[SP]" : "[LP]");
443
0
        break;
444
445
0
    case 2: /* HT */
446
0
        phdr->phy = PHDR_802_11_PHY_11N;
447
0
        sig_a_1 = (rate_phy1 >> 4) & 0xFFFF;
448
0
        sig_a_2 = (rate_phy2) & 0xFFF;
449
0
        mcs = sig_a_1  & 0x7f;
450
0
        phdr->phy_info.info_11n.has_mcs_index = 1;
451
0
        phdr->phy_info.info_11n.mcs_index = mcs;
452
0
        bw = 20 << ((sig_a_1 >> 7) & 1);
453
0
        phdr->phy_info.info_11n.has_bandwidth = 1;
454
0
        phdr->phy_info.info_11n.bandwidth = ((sig_a_1 >> 7) & 1);
455
0
        sgi = (sig_a_2 >> 7) & 1;
456
0
        phdr->phy_info.info_11n.has_short_gi = 1;
457
0
        phdr->phy_info.info_11n.short_gi = sgi;
458
0
        ldpc = (sig_a_2 >> 6) & 1;
459
0
        phdr->phy_info.info_11n.has_fec = 1;
460
0
        phdr->phy_info.info_11n.fec = ldpc;
461
0
        stbc = ((sig_a_2 >> 4) & 3)?1:0;
462
0
        phdr->phy_info.info_11n.has_stbc_streams = 1;
463
0
        phdr->phy_info.info_11n.stbc_streams = stbc;
464
0
        phdr->phy_info.info_11n.has_ness = 1;
465
0
        phdr->phy_info.info_11n.ness = (sig_a_2 >> 8) & 3;
466
0
        nss = (mcs >> 3) + 1;
467
        /* Check limits */
468
0
        disp_rate = 0;
469
0
        if ((nss <= 4) && (mcs <= 31) && ((bw == 20) || (bw==40))){
470
0
            switch (bw) {
471
472
0
            case 20:
473
0
                if (sgi) {
474
0
                    disp_rate = ht_20_tbl[mcs][1];
475
0
                } else {
476
0
                    disp_rate = ht_20_tbl[mcs][0];
477
0
                }
478
0
                break;
479
480
0
            case 40:
481
0
                if (sgi) {
482
0
                    disp_rate = ht_40_tbl[mcs][1];
483
0
                } else {
484
0
                    disp_rate = ht_40_tbl[mcs][0];
485
0
                }
486
0
                break;
487
0
            }
488
0
        }
489
0
        result = wmem_strdup_printf(scope,
490
0
              "Rate: %u.%u Mb/s HT MCS %d NSS %d BW %d MHz %s %s %s",
491
0
               disp_rate/10, disp_rate%10, mcs, nss, bw,
492
0
               sgi ? "[SGI]" : "",
493
0
               ldpc ? "[LDPC]" : "",
494
0
               stbc ? "[STBC]" : "");
495
0
        break;
496
497
0
    case 3: /* VHT */
498
0
        phdr->phy = PHDR_802_11_PHY_11AC;
499
0
        sig_a_1 = (rate_phy1 >> 4) & 0xFFFFFF;
500
0
        sig_a_2 = (rate_phy2) & 0xFFFFFF;
501
0
        stbc = (sig_a_1 >> 3) & 1;
502
0
        phdr->phy_info.info_11ac.has_stbc = 1;
503
0
        phdr->phy_info.info_11ac.stbc = stbc;
504
0
        sgi = sig_a_2 & 1;
505
0
        phdr->phy_info.info_11ac.has_short_gi = 1;
506
0
        phdr->phy_info.info_11ac.short_gi = sgi;
507
0
        bw = 20 << (sig_a_1 & 3);
508
0
        phdr->phy_info.info_11ac.has_bandwidth = 1;
509
0
        phdr->phy_info.info_11ac.bandwidth = bw_map[(sig_a_1 & 3)];
510
0
        ldpc = (sig_a_2 >> 2) & 1;
511
0
        phdr->phy_info.info_11ac.has_fec = 1;
512
0
        phdr->phy_info.info_11ac.fec = ldpc;
513
0
        groupid = (sig_a_1 >> 4) & 0x3F;
514
0
        phdr->phy_info.info_11ac.has_group_id = 1;
515
0
        phdr->phy_info.info_11ac.group_id = groupid;
516
517
0
        if (groupid == 0 || groupid == 63)
518
0
            su_ppdu = true;
519
520
0
        disp_rate = 0;
521
522
0
        if (su_ppdu) {
523
0
            nsts_su = (sig_a_1 >> 10) & 0x7;
524
0
            if (stbc)
525
0
                nss = nsts_su >> 2;
526
0
            else
527
0
                nss = nsts_su;
528
0
            ++nss;
529
0
            mcs = (sig_a_2 >> 4) & 0xF;
530
0
            phdr->phy_info.info_11ac.mcs[0] = mcs;
531
0
            phdr->phy_info.info_11ac.nss[0] = nss;
532
0
            txbf = (sig_a_2 >> 8) & 1;
533
0
            phdr->phy_info.info_11ac.has_beamformed = 1;
534
0
            phdr->phy_info.info_11ac.beamformed = txbf;
535
0
            partial_aid = (sig_a_1 >> 13) & 0x1FF;
536
0
            phdr->phy_info.info_11ac.has_partial_aid = 1;
537
0
            phdr->phy_info.info_11ac.partial_aid = partial_aid;
538
539
            /* Check limits */
540
0
            if ((nss <= 4) && (mcs <= 9) && ((bw == 20) || (bw==40) || (bw==80) || bw==160)) {
541
0
                switch (bw) {
542
543
0
                case 20:
544
0
                    if (sgi) {
545
0
                        disp_rate = vht_20_tbl[mcs][(nss * 2) - 1];
546
0
                    } else {
547
0
                        disp_rate = vht_20_tbl[mcs][(nss - 1) * 2];
548
0
                    }
549
0
                    break;
550
551
0
                case 40:
552
0
                    if (sgi) {
553
0
                        disp_rate = vht_40_tbl[mcs][(nss * 2) - 1];
554
0
                    } else {
555
0
                        disp_rate = vht_40_tbl[mcs][(nss - 1) * 2];
556
0
                    }
557
0
                    break;
558
559
0
                case 80:
560
0
                    if (sgi) {
561
0
                        disp_rate = vht_80_tbl[mcs][(nss * 2) - 1];
562
0
                    } else {
563
0
                        disp_rate = vht_80_tbl[mcs][(nss - 1) * 2];
564
0
                    }
565
0
                    break;
566
567
0
                case 160:
568
0
                    if (sgi) {
569
0
                        disp_rate = vht_160_tbl[mcs][(nss * 2) - 1];
570
0
                    } else {
571
0
                        disp_rate = vht_160_tbl[mcs][(nss - 1) * 2];
572
0
                    }
573
0
                    break;
574
0
                }
575
0
            }
576
577
0
            result = wmem_strdup_printf(scope,
578
0
                "Rate: %u.%u Mb/s VHT MCS %d NSS %d Partial AID %d BW %d MHz %s %s %s GroupID %d %s %s",
579
0
                disp_rate/10, disp_rate%10,
580
0
                mcs, nss, partial_aid, bw,
581
0
                sgi ? "[SGI]" : "",
582
0
                ldpc ? "[LDPC]" : "",
583
0
                stbc ? "[STBC]" : "",
584
0
                groupid,
585
0
                "[SU_PPDU]",
586
0
                txbf ? "[TxBF]" : "");
587
0
        } else {
588
0
            nsts_u1 = (sig_a_1 >> 10) & 0x7;
589
0
            nsts_u2 = (sig_a_1 >> 13) & 0x7;
590
0
            nsts_u3 = (sig_a_1 >> 16) & 0x7;
591
0
            nsts_u4 = (sig_a_1 >> 19) & 0x7;
592
593
0
            result = wmem_strdup_printf(scope,
594
0
                "VHT NSTS %d %d %d %d BW %d MHz %s %s %s GroupID %d %s",
595
0
                nsts_u1, nsts_u2, nsts_u3, nsts_u4, bw,
596
0
                sgi ? "[SGI]" : "",
597
0
                ldpc ? "[LDPC]" : "",
598
0
                stbc ? "[STBC]" : "",
599
0
                groupid,
600
0
                "[MU_PPDU]");
601
0
        }
602
0
        break;
603
0
    }
604
605
0
    return result;
606
0
}
607
608
static bool
609
capture_prism(const unsigned char *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_)
610
0
{
611
0
    uint32_t cookie;
612
613
0
    if (!BYTES_ARE_IN_FRAME(offset, len, 4))
614
0
        return false;
615
616
    /* Some captures with DLT_PRISM have the AVS WLAN header */
617
0
    cookie = pntohu32(pd);
618
0
    if ((cookie == WLANCAP_MAGIC_COOKIE_V1) ||
619
0
        (cookie == WLANCAP_MAGIC_COOKIE_V2)) {
620
0
        return call_capture_dissector(wlancap_cap_handle, pd, offset, len, cpinfo, pseudo_header);
621
0
    }
622
623
    /* Prism header */
624
0
    if (!BYTES_ARE_IN_FRAME(offset, len, PRISM_HEADER_LENGTH))
625
0
        return false;
626
627
0
    offset += PRISM_HEADER_LENGTH;
628
629
    /* 802.11 header follows */
630
0
    return call_capture_dissector(ieee80211_cap_handle, pd, offset, len, cpinfo, pseudo_header);
631
0
}
632
633
static int
634
dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
635
3
{
636
3
    proto_tree *prism_tree, *prism_did_tree = NULL;
637
3
    proto_item *ti = NULL, *ti_did = NULL;
638
3
    tvbuff_t *next_tvb;
639
3
    int offset;
640
3
    uint32_t msgcode, msglen, did, rate_phy1 = 0, rate_phy2 = 0;
641
3
    unsigned byte_order;
642
3
    uint16_t status;
643
3
    const uint8_t *devname_p;
644
3
    uint32_t mactime;
645
3
    uint32_t channel;
646
3
    uint32_t signal_dbm;
647
3
    uint32_t rate;
648
3
    struct ieee_802_11_phdr phdr;
649
650
3
    offset = 0;
651
3
    did = 0;
652
653
    /* handle the AVS header */
654
3
    msgcode = tvb_get_ntohl(tvb, offset);
655
3
    if ((msgcode == WLANCAP_MAGIC_COOKIE_V1) ||
656
2
        (msgcode == WLANCAP_MAGIC_COOKIE_V2)) {
657
0
        call_dissector(wlancap_handle, tvb, pinfo, tree);
658
0
        return tvb_captured_length(tvb);
659
0
    }
660
661
    /*
662
     * If we don't see a valid message type, assume the Prism or AVS
663
     * header was omitted and just hand off to the 802.11 dissector;
664
     * at least one capture has AVS headers on some packets and no
665
     * radio headers on others (incoming vs. outgoing?).
666
     *
667
     * Check for both byte orders and use that to determine
668
     * the byte order of the fields in the Prism header.
669
     */
670
3
    if ((msgcode == PRISM_TYPE1_MSGCODE) || (msgcode == PRISM_TYPE2_MSGCODE)) {
671
        /* big-endian fetch matched */
672
0
        byte_order = ENC_BIG_ENDIAN;
673
3
    } else if (((msgcode = tvb_get_letohl(tvb, offset)) == PRISM_TYPE1_MSGCODE) ||
674
2
                                               (msgcode == PRISM_TYPE2_MSGCODE)) {
675
        /* little-endian fetch matched */
676
0
        byte_order = ENC_LITTLE_ENDIAN;
677
3
    } else {
678
        /* neither matched - try it as just 802.11 with no Prism header */
679
3
        call_dissector(ieee80211_handle, tvb, pinfo, tree);
680
3
        return tvb_captured_length(tvb);
681
3
    }
682
683
    /* We don't have any 802.11 metadata yet. */
684
0
    memset(&phdr, 0, sizeof(phdr));
685
0
    phdr.fcs_len = -1;
686
0
    phdr.decrypted = false;
687
0
    phdr.datapad = false;
688
0
    phdr.phy = PHDR_802_11_PHY_UNKNOWN;
689
690
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Prism");
691
0
    col_clear(pinfo->cinfo, COL_INFO);
692
693
0
    ti = proto_tree_add_item(tree, proto_prism, tvb, 0, 144, ENC_NA);
694
0
    prism_tree = proto_item_add_subtree(ti, ett_prism);
695
696
    /* Message Code */
697
0
    proto_tree_add_item_ret_uint(prism_tree, hf_ieee80211_prism_msgcode, tvb, offset, 4, byte_order, &msgcode);
698
0
    offset += 4;
699
700
    /* Message Length */
701
0
    proto_tree_add_item_ret_uint(prism_tree, hf_ieee80211_prism_msglen, tvb, offset, 4, byte_order, &msglen);
702
0
    offset += 4;
703
704
    /* Device Name */
705
0
    proto_tree_add_item_ret_string(prism_tree, hf_ieee80211_prism_devname, tvb, offset, 16, ENC_ASCII|ENC_NA, pinfo->pool, &devname_p);
706
0
    offset += 16;
707
708
0
    col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %s, Message 0x%x, Length %d", devname_p, msgcode, msglen);
709
710
0
    while (offset < PRISM_HEADER_LENGTH)
711
0
    {
712
        /* DID */
713
0
        if (tree) {
714
0
            ti_did = proto_tree_add_item(prism_tree, hf_ieee80211_prism_did, tvb, offset, 12, ENC_NA);
715
0
            prism_did_tree = proto_item_add_subtree(ti_did, ett_prism_did);
716
717
0
            proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_type, tvb, offset, 4, byte_order);
718
0
            did = tvb_get_uint32(tvb, offset, byte_order);
719
0
            proto_item_append_text(ti_did, " %s", val_to_str(pinfo->pool, did, prism_did_vals, "Unknown %x") );
720
0
        }
721
0
        offset += 4;
722
723
724
        /* Status */
725
0
        proto_tree_add_item_ret_uint16(prism_did_tree, hf_ieee80211_prism_did_status, tvb, offset, 2, byte_order, &status);
726
0
        offset += 2;
727
728
        /* Length */
729
0
        proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_length, tvb, offset, 2, byte_order);
730
0
        offset += 2;
731
732
        /* Data, if present... */
733
0
        if (status == 0) {
734
0
            switch (did) {
735
736
0
            case PRISM_TYPE1_HOSTTIME:
737
0
            case PRISM_TYPE2_HOSTTIME:
738
0
                if (tree) {
739
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_hosttime, tvb, offset, 4, byte_order);
740
0
                    proto_item_append_text(ti_did, " %d", tvb_get_uint32(tvb, offset, byte_order) );
741
0
                }
742
0
                break;
743
744
0
            case PRISM_TYPE1_MACTIME:
745
0
            case PRISM_TYPE2_MACTIME:
746
0
                mactime = tvb_get_uint32(tvb, offset, byte_order);
747
0
                phdr.has_tsf_timestamp = 1;
748
0
                phdr.tsf_timestamp = mactime;
749
0
                if (tree) {
750
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_mactime, tvb, offset, 4, byte_order);
751
0
                    proto_item_append_text(ti_did, " %d", mactime );
752
0
                }
753
0
                break;
754
755
0
            case PRISM_TYPE1_CHANNEL:
756
0
            case PRISM_TYPE2_CHANNEL:
757
0
                channel = tvb_get_uint32(tvb, offset, byte_order);
758
0
                phdr.has_channel = true;
759
0
                phdr.channel = channel;
760
0
                if (tree) {
761
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_channel, tvb, offset, 4, byte_order);
762
0
                    proto_item_append_text(ti_did, " %u", channel);
763
0
                }
764
0
                col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", channel);
765
0
                break;
766
767
0
            case PRISM_TYPE1_RSSI:
768
0
            case PRISM_TYPE2_RSSI:
769
0
                signal_dbm = tvb_get_uint32(tvb, offset, byte_order);
770
0
                phdr.has_signal_dbm = 1;
771
0
                phdr.signal_dbm = signal_dbm;
772
0
                if (tree) {
773
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rssi, tvb, offset, 4, byte_order);
774
0
                    proto_item_append_text(ti_did, " %d", signal_dbm );
775
0
                }
776
0
                col_add_fstr(pinfo->cinfo, COL_RSSI, "%d", signal_dbm);
777
0
                break;
778
779
0
            case PRISM_TYPE1_SQ:
780
0
            case PRISM_TYPE2_SQ:
781
0
                 if (tree) {
782
0
                      proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_sq, tvb, offset, 4, byte_order);
783
0
                      proto_item_append_text(ti_did, " 0x%x", tvb_get_uint32(tvb, offset, byte_order) );
784
0
                }
785
0
                break;
786
787
0
            case PRISM_TYPE1_SIGNAL:
788
0
            case PRISM_TYPE2_SIGNAL:
789
0
                if (tree) {
790
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_signal, tvb, offset, 4, byte_order);
791
0
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_uint32(tvb, offset, byte_order) );
792
0
                }
793
0
                break;
794
795
0
            case PRISM_TYPE1_NOISE:
796
0
            case PRISM_TYPE2_NOISE:
797
0
                if (tree) {
798
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_noise, tvb, offset, 4, byte_order);
799
0
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_uint32(tvb, offset, byte_order) );
800
0
                }
801
0
                break;
802
803
0
            case PRISM_TYPE1_RATE:
804
0
            case PRISM_TYPE2_RATE:
805
0
                rate = tvb_get_uint32(tvb, offset, byte_order);
806
0
                phdr.has_data_rate = true;
807
0
                phdr.data_rate = rate;
808
0
                if (tree) {
809
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rate, tvb, offset, 4, byte_order);
810
0
                    proto_item_append_text(ti_did, " %s Mb/s", prism_rate_return(pinfo->pool, rate));
811
0
                }
812
0
                col_add_str(pinfo->cinfo, COL_TX_RATE, prism_rate_return(pinfo->pool, rate));
813
0
                break;
814
815
0
            case PRISM_TYPE1_RATE_SIG_A1:
816
0
            case PRISM_TYPE2_RATE_SIG_A1:
817
                /*
818
                 * XXX - always little-endian, or same byte order as the
819
                 * rest of the Prism header?
820
                 */
821
0
                rate_phy1 = tvb_get_letohl(tvb, offset);
822
0
                if (tree) {
823
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_sig_a1, tvb, offset, 4, byte_order);
824
0
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset));
825
0
                }
826
0
                break;
827
828
0
            case PRISM_TYPE1_RATE_SIG_A2:
829
0
            case PRISM_TYPE2_RATE_SIG_A2:
830
                /*
831
                 * XXX - always little-endian, or same byte order as the
832
                 * rest of the Prism header?
833
                 */
834
0
                rate_phy2 = tvb_get_letohl(tvb, offset);
835
0
                if (tree) {
836
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_sig_a2, tvb, offset, 4, byte_order);
837
0
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset));
838
0
                }
839
0
                break;
840
841
0
            case PRISM_TYPE1_RATE_SIG_B:
842
0
            case PRISM_TYPE2_RATE_SIG_B:
843
0
                if (tree && rate_phy1 && rate_phy2) {
844
0
                    proto_item *sig_sub_item;
845
846
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_sig_b, tvb, offset, 4, byte_order);
847
0
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset));
848
849
0
                    sig_sub_item = proto_tree_add_item(prism_tree, hf_ieee80211_prism_did_sig_rate_field, tvb, offset, 4, byte_order);
850
0
                    proto_item_append_text(sig_sub_item, " %s", prism_rate_return_sig(pinfo->pool, rate_phy1, rate_phy2, &phdr));
851
0
                  }
852
0
                  break;
853
854
0
            case PRISM_TYPE1_ISTX:
855
0
            case PRISM_TYPE2_ISTX:
856
0
                if (tree) {
857
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_istx, tvb, offset, 4, byte_order);
858
0
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_uint32(tvb, offset, byte_order) );
859
0
                }
860
0
                break;
861
862
0
            case PRISM_TYPE1_FRMLEN:
863
0
            case PRISM_TYPE2_FRMLEN:
864
0
                if (tree) {
865
0
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_frmlen, tvb, offset, 4, byte_order);
866
0
                    proto_item_append_text(ti_did, " %d", tvb_get_uint32(tvb, offset, byte_order));
867
0
                }
868
0
                break;
869
870
0
            default:
871
0
                proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_unknown, tvb, offset, 4, byte_order);
872
0
                break;
873
0
            }
874
0
        }
875
0
        offset += 4;
876
0
    }
877
878
    /*
879
     * The only DIDs that directly indicate the packet modulation
880
     * are the SIG_A1 and SIG_A2 DIDs; if they're not present, we
881
     * ned to use some other way to determine the packet modulation,
882
     * so, if the modulation is unknown at this point:
883
     *
884
     *  if the data rate is 1 Mb/s or 2 Mb/s, the packet was
885
     *  transmitted using the 802.11 legacy DSSS modulation
886
     *  (we ignore the IR PHY - was it ever implemented?);
887
     *
888
     *  if the data rate is 5 Mb/s or 11 Mb/s, the packet
889
     *  was transmitted using the 802.11b DSSS/CCK modulation
890
     *  (or the now-obsolete DSSS/PBCC modulation; *if* we can
891
     *  rely on the channel/xchannel field's "CCK channel" and
892
     *  "Dynamic CCK-OFDM channel" flags, the absence of either
893
     *  flag would presumably indicate DSSS/PBCC);
894
     *
895
     *  if the data rate is 22 Mb/s or 33 Mb/s, the packet was
896
     *  transmitted using the 802.11b DSSS/PBCC modulation (as
897
     *  those speeds aren't supported by DSSS/CCK);
898
     *
899
     *  if the data rate is one of the OFDM rates for the 11a
900
     *  OFDM PHY and the OFDM part of the 11g ERP PHY, the
901
     *  packet was transmitted with the 11g/11a OFDM modulation -
902
     *  we distinguish between them based on the channel, if we
903
     *  have it.
904
     *
905
     * In addition, if they *are* present, and indicate that the
906
     * modulation uses OFDM and isn't HT, VHT, or HE, all we know
907
     * from that is that it's 11a or 11g, not which of those it
908
     * is.  We use the channel to distinguish between them.
909
     */
910
0
    if (phdr.has_data_rate) {
911
0
        if (phdr.phy == PHDR_802_11_PHY_UNKNOWN) {
912
            /*
913
             * We don't know they PHY, but we do have the
914
             * data rate; try to guess it based on the
915
             * data rate and center frequency.
916
             */
917
0
            if (RATE_IS_DSSS(phdr.data_rate)) {
918
                /* 11b */
919
0
                phdr.phy = PHDR_802_11_PHY_11B;
920
0
            } else if (RATE_IS_OFDM(phdr.data_rate)) {
921
                /* 11a or 11g, depending on the band. */
922
0
                if (phdr.has_channel) {
923
0
                    if (CHAN_IS_BG(phdr.channel)) {
924
                        /* 11g */
925
0
                        phdr.phy = PHDR_802_11_PHY_11G;
926
0
                    } else {
927
                        /* 11a */
928
0
                        phdr.phy = PHDR_802_11_PHY_11A;
929
0
                    }
930
0
                }
931
0
            }
932
0
        } else if (phdr.phy == PHDR_802_11_PHY_11A) {
933
            /*
934
             * All we know is that it's OFDM; we guessed
935
             * 11a in prism_rate_return_sig(), but if
936
             * the channel is  2.4 GHz channel, it's
937
             * 11g.
938
             */
939
0
            if (phdr.has_channel) {
940
0
                if (CHAN_IS_BG(phdr.channel)) {
941
                    /* 11g */
942
0
                    phdr.phy = PHDR_802_11_PHY_11G;
943
0
                }
944
0
            }
945
0
            if (RATE_IS_DSSS(phdr.data_rate)) {
946
                /* DSSS, so 11b. */
947
0
                phdr.phy = PHDR_802_11_PHY_11B;
948
0
            }
949
0
        }
950
0
    }
951
952
    /* dissect the 802.11 header next */
953
0
    next_tvb = tvb_new_subset_remaining(tvb, offset);
954
0
    call_dissector_with_data(ieee80211_radio_handle, next_tvb, pinfo, tree, (void *)&phdr);
955
0
    return tvb_captured_length(tvb);
956
0
}
957
958
static hf_register_info hf_prism[] = {
959
    /* Prism-specific header fields
960
       XXX - make as many of these generic as possible. */
961
    { &hf_ieee80211_prism_msgcode,
962
     {"Message Code", "prism.msgcode", FT_UINT32, BASE_HEX, NULL, 0x0,
963
      NULL, HFILL }},
964
965
    { &hf_ieee80211_prism_msglen,
966
     {"Message Length", "prism.msglen", FT_UINT32, BASE_DEC, NULL, 0x0,
967
      NULL, HFILL }},
968
969
    { &hf_ieee80211_prism_devname,
970
     {"Device Name", "prism.devname", FT_STRING, BASE_NONE, NULL, 0x0,
971
      NULL, HFILL }},
972
973
    { &hf_ieee80211_prism_did,
974
     {"DID", "prism.did", FT_NONE, BASE_NONE, NULL, 0x0,
975
      NULL, HFILL }},
976
977
    { &hf_ieee80211_prism_did_type,
978
     {"DID", "prism.did.type", FT_UINT32, BASE_HEX, VALS(prism_did_vals), 0x0,
979
      "Different ID for each parameter", HFILL }},
980
981
    { &hf_ieee80211_prism_did_status,
982
     {"Status", "prism.did.status", FT_UINT16, BASE_DEC, VALS(prism_status_vals), 0x0,
983
      "Supplied by the driver or not", HFILL }},
984
985
    { &hf_ieee80211_prism_did_length,
986
     {"Length", "prism.did.length", FT_UINT16, BASE_DEC, NULL, 0x0,
987
      "Length of data", HFILL }},
988
989
    { &hf_ieee80211_prism_did_hosttime,
990
     {"Host Time", "prism.did.hosttime", FT_UINT32, BASE_DEC, NULL, 0x0,
991
      "In jiffies - for our system this is in 10ms units", HFILL }},
992
993
    { &hf_ieee80211_prism_did_mactime,
994
     {"MAC timestamp (lower 32 bits)", "prism.did.mactime", FT_UINT32, BASE_DEC, NULL, 0x0,
995
      "Lower 32 bits of value in microseconds of the MAC's Time Synchronization Function timer when the first bit of the MPDU arrived at the MAC.", HFILL }},
996
997
    { &hf_ieee80211_prism_did_channel,
998
     {"Channel", "prism.did.channel", FT_UINT32, BASE_DEC, NULL, 0x0,
999
      NULL, HFILL }},
1000
1001
    { &hf_ieee80211_prism_did_rssi,
1002
     {"RSSI", "prism.did.rssi", FT_INT32, BASE_DEC, NULL, 0x0,
1003
      NULL, HFILL }},
1004
1005
    { &hf_ieee80211_prism_did_sq,
1006
     {"Signal Quality", "prism.did.sq", FT_UINT32, BASE_DEC, NULL, 0x0,
1007
      NULL, HFILL }},
1008
1009
    { &hf_ieee80211_prism_did_signal,
1010
     {"Signal", "prism.did.signal", FT_INT32, BASE_DEC, NULL, 0x0,
1011
      NULL, HFILL }},
1012
1013
    { &hf_ieee80211_prism_did_noise,
1014
     {"Noise", "prism.did.noise", FT_INT32, BASE_DEC, NULL, 0x0,
1015
      NULL, HFILL }},
1016
1017
    { &hf_ieee80211_prism_did_rate,
1018
     {"Data rate (Mb/s)", "prism.did.rate", FT_UINT32, BASE_CUSTOM, CF_FUNC(prism_rate_base_custom), 0x0,
1019
      "Speed this frame was sent/received at", HFILL }},
1020
1021
    { &hf_ieee80211_prism_did_sig_a1,
1022
     {"SIG_A1", "prism.did.siga1", FT_UINT32, BASE_HEX, NULL, 0x0,
1023
      NULL, HFILL }},
1024
1025
    { &hf_ieee80211_prism_did_sig_a2,
1026
     {"SIG_A2", "prism.did.siga2", FT_UINT32, BASE_HEX, NULL, 0x0,
1027
      NULL, HFILL }},
1028
1029
    { &hf_ieee80211_prism_did_sig_b,
1030
     {"SIG", "prism.did.sigb", FT_UINT32, BASE_HEX, NULL, 0x0,
1031
     NULL, HFILL}},
1032
1033
    { &hf_ieee80211_prism_did_sig_rate_field,
1034
     {"SIG Field", "prism.did.sigab", FT_NONE, BASE_NONE, 0, 0x0,
1035
      NULL, HFILL}},
1036
1037
    { &hf_ieee80211_prism_did_istx,
1038
     {"IsTX", "prism.did.istx", FT_UINT32, BASE_HEX, VALS(prism_istx_vals), 0x0,
1039
      "Type of packet (RX or TX?)", HFILL }},
1040
1041
    { &hf_ieee80211_prism_did_frmlen,
1042
     {"Frame Length", "prism.did.frmlen", FT_UINT32, BASE_DEC, NULL, 0x0,
1043
      "Length of the following frame in bytes", HFILL }},
1044
1045
    { &hf_ieee80211_prism_did_unknown,
1046
     {"Unknown DID Field", "prism.did.unknown", FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
1047
      NULL, HFILL }}
1048
};
1049
1050
static int *ett_array[] = {
1051
    &ett_prism,
1052
    &ett_prism_did,
1053
    &ett_sig_ab
1054
};
1055
1056
void proto_register_ieee80211_prism(void)
1057
14
{
1058
14
    proto_prism = proto_register_protocol("Prism capture header", "Prism",
1059
14
                                          "prism");
1060
14
    proto_register_field_array(proto_prism, hf_prism, array_length(hf_prism));
1061
14
    proto_register_subtree_array(ett_array, array_length(ett_array));
1062
1063
14
    prism_handle = register_dissector("prism", dissect_prism, proto_prism);
1064
14
}
1065
1066
void proto_reg_handoff_ieee80211_prism(void)
1067
14
{
1068
14
    capture_dissector_handle_t ieee80211_prism_cap_handle;
1069
1070
14
    dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE_802_11_PRISM, prism_handle);
1071
14
    ieee80211_handle = find_dissector_add_dependency("wlan", proto_prism);
1072
14
    ieee80211_radio_handle = find_dissector_add_dependency("wlan_radio", proto_prism);
1073
14
    wlancap_handle = find_dissector_add_dependency("wlancap", proto_prism);
1074
1075
14
    ieee80211_prism_cap_handle = create_capture_dissector_handle(capture_prism, proto_prism);
1076
14
    capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE_802_11_PRISM, ieee80211_prism_cap_handle);
1077
1078
14
    ieee80211_cap_handle = find_capture_dissector("ieee80211");
1079
14
    wlancap_cap_handle = find_capture_dissector("wlancap");
1080
14
}
1081
1082
/*
1083
 * Editor modelines
1084
 *
1085
 * Local Variables:
1086
 * c-basic-offset: 4
1087
 * tab-width: 8
1088
 * indent-tabs-mode: nil
1089
 * End:
1090
 *
1091
 * ex: set shiftwidth=4 tabstop=8 expandtab:
1092
 * :indentSize=4:tabSize=8:noTabs=true:
1093
 */