MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-ieee80211-prism.c
blobb7e7fbaaea76cd1ba647fa2af422acdf0b2ac3c3
1 /* packet-ieee80211-prism.c
2 * Routines for Prism monitoring mode header dissection
4 * $Id$
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * Copied from README.developer
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27 #include "config.h"
29 #include <epan/packet.h>
30 #include <wsutil/pint.h>
31 #include <epan/wmem/wmem.h>
32 #include "packet-ieee80211.h"
34 #define SHORT_STR 256
36 static dissector_handle_t wlancap_handle;
37 static dissector_handle_t ieee80211_handle;
39 static int proto_prism = -1;
41 /* Prism radio header */
43 static int hf_ieee80211_prism_msgcode = -1;
44 static int hf_ieee80211_prism_msglen = -1;
45 static int hf_ieee80211_prism_devname = -1;
46 static int hf_ieee80211_prism_did = -1;
47 static int hf_ieee80211_prism_did_type = -1;
48 static int hf_ieee80211_prism_did_status = -1;
49 static int hf_ieee80211_prism_did_length = -1;
50 static int hf_ieee80211_prism_did_hosttime = -1;
51 static int hf_ieee80211_prism_did_mactime = -1;
52 static int hf_ieee80211_prism_did_channel = -1;
53 static int hf_ieee80211_prism_did_rssi = -1;
54 static int hf_ieee80211_prism_did_sq = -1;
55 static int hf_ieee80211_prism_did_signal = -1;
56 static int hf_ieee80211_prism_did_noise = -1;
57 static int hf_ieee80211_prism_did_rate = -1;
58 static int hf_ieee80211_prism_did_istx = -1;
59 static int hf_ieee80211_prism_did_frmlen = -1;
60 static int hf_ieee80211_prism_did_unknown = -1;
62 static gint ett_prism = -1;
63 static gint ett_prism_did = -1;
66 * Prism II-based wlan devices have a monitoring mode that sticks
67 * a proprietary header on each packet with lots of good
68 * information. This file is responsible for decoding that
69 * data.
71 * Support by Tim Newsham
73 * A value from the header.
75 * It appears from looking at the linux-wlan-ng and Prism II HostAP
76 * drivers, and various patches to the orinoco_cs drivers to add
77 * Prism headers, that:
79 * the "did" identifies what the value is (i.e., what it's the value
80 * of);
82 * "status" is 0 if the value is present or 1 if it's absent;
84 * "len" is the length of the value (always 4, in that code);
86 * "data" is the value of the data (or 0 if not present).
88 * Note: all of those values are in the *host* byte order of the machine
89 * on which the capture was written.
94 * Header attached during Prism monitor mode.
96 * At least according to one paper I've seen, the Prism 2.5 chip set
97 * provides:
99 * RSSI (receive signal strength indication) is "the total power
100 * received by the radio hardware while receiving the frame,
101 * including signal, interfereence, and background noise";
103 * "silence value" is "the total power observed just before the
104 * start of the frame".
106 * None of the drivers I looked at supply the "rssi" or "sq" value,
107 * but they do supply "signal" and "noise" values, along with a "rate"
108 * value that's 1/5 of the raw value from what is presumably a raw
109 * HFA384x frame descriptor, with the comment "set to 802.11 units",
110 * which presumably means the units are 500 Kb/s.
112 * I infer from the current NetBSD "wi" driver that "signal" and "noise"
113 * are adjusted dBm values, with the dBm value having 100 added to it
114 * for the Prism II cards (although the NetBSD code has an XXX comment
115 * for the #define for WI_PRISM_DBM_OFFSET) and 149 (with no XXX comment)
116 * for the Orinoco cards.
118 * XXX - what about other drivers that supply Prism headers, such as
119 * old versions of the MadWifi driver?
121 * I'm not sure where these DID values come from, but they work with
122 * at least one capture file. However, in
124 * http://ask.wireshark.org/questions/14963/how-to-get-the-field-did-unknown-4041-into-the-column
126 * somebody reports a capture where *different* DID values, corresponding
127 * to
129 * http://home.martin.cc/linux/prism
131 * are used (and that's not a byte-order issue, as those values are *not*
132 * just byte-swapped versions of the other values).
135 #define PRISM_HEADER_LENGTH 144 /* Default Prism Header Length */
138 * Message code values.
140 * Some Prism captures have headers that begin with 0x00000044; those
141 * captures have the non-home.martin.cc values for the DID types,
142 * while a capture with 0x00000041 as the message code have the
143 * home.martin.cc values for the DID types, and the home.martin.cc
144 * page has 0x00000041 as the message code.
146 #define PRISM_TYPE1_MSGCODE 0x00000044 /* Monitor Frame */
147 #define PRISM_TYPE2_MSGCODE 0x00000041
150 * DID codes - PRISM_TYPE1_xxx are the non-home.martin.cc values, and
151 * PRISM_TYPE2_xxx are the home.martin.cc values.
153 #define PRISM_TYPE1_HOSTTIME 0x00010044 /* Host time element */
154 #define PRISM_TYPE2_HOSTTIME 0x00001041
155 #define PRISM_TYPE1_MACTIME 0x00020044 /* Mac time element */
156 #define PRISM_TYPE2_MACTIME 0x00002041
157 #define PRISM_TYPE1_CHANNEL 0x00030044 /* Channel element */
158 #define PRISM_TYPE2_CHANNEL 0x00003041
159 #define PRISM_TYPE1_RSSI 0x00040044 /* RSSI element */
160 #define PRISM_TYPE2_RSSI 0x00004041
161 #define PRISM_TYPE1_SQ 0x00050044 /* SQ element */
162 #define PRISM_TYPE2_SQ 0x00005041
163 #define PRISM_TYPE1_SIGNAL 0x00060044 /* Signal element */
164 #define PRISM_TYPE2_SIGNAL 0x00006041
165 #define PRISM_TYPE1_NOISE 0x00070044 /* Noise element */
166 #define PRISM_TYPE2_NOISE 0x00007041
167 #define PRISM_TYPE1_RATE 0x00080044 /* Rate element */
168 #define PRISM_TYPE2_RATE 0x00008041
169 #define PRISM_TYPE1_ISTX 0x00090044 /* Is Tx frame */
170 #define PRISM_TYPE2_ISTX 0x00009041
171 #define PRISM_TYPE1_FRMLEN 0x000A0044 /* Frame length */
172 #define PRISM_TYPE2_FRMLEN 0x0000A041
174 static const value_string prism_did_vals[] =
176 { PRISM_TYPE1_HOSTTIME, "Host Time" },
177 { PRISM_TYPE2_HOSTTIME, "Host Time" },
178 { PRISM_TYPE1_MACTIME, "Mac Time" },
179 { PRISM_TYPE2_MACTIME, "Mac Time" },
180 { PRISM_TYPE1_CHANNEL, "Channel" },
181 { PRISM_TYPE2_CHANNEL, "Channel" },
182 { PRISM_TYPE1_RSSI, "RSSI" },
183 { PRISM_TYPE2_RSSI, "RSSI" },
184 { PRISM_TYPE1_SQ, "SQ" },
185 { PRISM_TYPE2_SQ, "SQ" },
186 { PRISM_TYPE1_SIGNAL, "Signal" },
187 { PRISM_TYPE2_SIGNAL, "Signal" },
188 { PRISM_TYPE1_NOISE, "Noise" },
189 { PRISM_TYPE2_NOISE, "Noise" },
190 { PRISM_TYPE1_RATE, "Rate" },
191 { PRISM_TYPE2_RATE, "Rate" },
192 { PRISM_TYPE1_ISTX, "Is Tx" },
193 { PRISM_TYPE2_ISTX, "Is Tx" },
194 { PRISM_TYPE1_FRMLEN, "Frame Length" },
195 { PRISM_TYPE2_FRMLEN, "Frame Length" },
196 { 0, NULL}
200 * The header file mentioned above says 0 means "supplied" and 1 means
201 * "not supplied". I haven't seen a capture file with anything other
202 * than 0 there.
204 static const value_string prism_status_vals[] =
206 { 0, "Supplied" },
207 { 1, "Not Supplied" },
208 { 0, NULL}
211 static const value_string prism_istx_vals[] =
213 { 0, "Rx Packet" },
214 { 1, "Tx Packet" },
215 { 0, NULL}
218 static void
219 prism_rate_base_custom(gchar *result, guint32 rate)
221 g_snprintf(result, ITEM_LABEL_LENGTH, "%u.%u", rate /2, rate & 1 ? 5 : 0);
224 static gchar *
225 prism_rate_return(guint32 rate)
227 gchar *result=NULL;
228 result = (gchar *)wmem_alloc(wmem_packet_scope(), SHORT_STR);
229 result[0] = '\0';
230 prism_rate_base_custom(result, rate);
232 return result;
236 void
237 capture_prism(const guchar *pd, int offset, int len, packet_counts *ld)
239 guint32 cookie;
241 if (!BYTES_ARE_IN_FRAME(offset, len, 4)) {
242 ld->other++;
243 return;
246 /* Some captures with DLT_PRISM have the AVS WLAN header */
247 cookie = pntohl(pd);
248 if ((cookie == WLANCAP_MAGIC_COOKIE_V1) ||
249 (cookie == WLANCAP_MAGIC_COOKIE_V2)) {
250 capture_wlancap(pd, offset, len, ld);
251 return;
254 /* Prism header */
255 if (!BYTES_ARE_IN_FRAME(offset, len, PRISM_HEADER_LENGTH)) {
256 ld->other++;
257 return;
259 offset += PRISM_HEADER_LENGTH;
261 /* 802.11 header follows */
262 capture_ieee80211(pd, offset, len, ld);
265 static void
266 dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
268 proto_tree *prism_tree = NULL, *prism_did_tree = NULL;
269 proto_item *ti = NULL, *ti_did = NULL;
270 tvbuff_t *next_tvb;
271 int offset;
272 guint32 msgcode, msglen, did;
273 guint16 status;
274 guint8 *devname_p;
276 offset = 0;
277 did = 0;
279 /* handle the AVS header */
280 msgcode = tvb_get_ntohl(tvb, offset);
281 if ((msgcode == WLANCAP_MAGIC_COOKIE_V1) ||
282 (msgcode == WLANCAP_MAGIC_COOKIE_V2)) {
283 call_dissector(wlancap_handle, tvb, pinfo, tree);
284 return;
288 * If we don't see a valid message type, assume the Prism or AVS
289 * header was omitted and just hand off to the 802.11 dissector;
290 * at least one capture has AVS headers on some packets and no
291 * radio headers on others (incoming vs. outgoing?).
293 * XXX - check for both byte orders and use that to determine
294 * the byte order of the fields in the Prism header?
296 msgcode = tvb_get_letohl(tvb, offset);
297 if ((msgcode != PRISM_TYPE1_MSGCODE) &&
298 (msgcode != PRISM_TYPE2_MSGCODE)) {
299 call_dissector(ieee80211_handle, tvb, pinfo, tree);
300 return;
303 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Prism");
304 col_clear(pinfo->cinfo, COL_INFO);
306 if(tree) {
307 ti = proto_tree_add_item(tree, proto_prism, tvb, 0, 144, ENC_NA);
308 prism_tree = proto_item_add_subtree(ti, ett_prism);
311 /* Message Code */
312 if(tree) {
313 proto_tree_add_item(prism_tree, hf_ieee80211_prism_msgcode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
315 msgcode = tvb_get_letohl(tvb, offset);
316 offset += 4;
318 /* Message Length */
319 if(tree) {
320 proto_tree_add_item(prism_tree, hf_ieee80211_prism_msglen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
322 msglen = tvb_get_letohl(tvb, offset);
323 offset += 4;
325 /* Device Name */
326 if(tree) {
327 proto_tree_add_item(prism_tree, hf_ieee80211_prism_devname, tvb, offset, 16, ENC_ASCII|ENC_NA);
329 devname_p = tvb_get_string(wmem_packet_scope(), tvb, offset, 16);
330 offset += 16;
332 col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %s, Message 0x%x, Length %d", devname_p, msgcode, msglen);
335 while(offset < PRISM_HEADER_LENGTH)
337 /* DID */
338 if(tree) {
339 ti_did = proto_tree_add_item(prism_tree, hf_ieee80211_prism_did, tvb, offset, 12, ENC_NA);
340 prism_did_tree = proto_item_add_subtree(ti_did, ett_prism_did);
342 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
343 did = tvb_get_letohl(tvb, offset);
344 proto_item_append_text(ti_did, " %s", val_to_str(did, prism_did_vals, "Unknown %x") );
346 offset += 4;
349 /* Status */
350 status = tvb_get_letohs(tvb, offset);
351 if(tree) {
352 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_status, tvb, offset, 2, ENC_LITTLE_ENDIAN);
354 offset += 2;
356 /* Length */
357 if(tree) {
358 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
360 offset += 2;
362 /* Data, if present... */
363 if (status == 0) {
364 switch(did){
365 case PRISM_TYPE1_HOSTTIME:
366 case PRISM_TYPE2_HOSTTIME:
367 if(tree){
368 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_hosttime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
369 proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
371 break;
373 case PRISM_TYPE1_MACTIME:
374 case PRISM_TYPE2_MACTIME:
375 if(tree){
376 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_mactime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
377 proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
379 break;
381 case PRISM_TYPE1_CHANNEL:
382 case PRISM_TYPE2_CHANNEL:
383 if(tree){
384 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_channel, tvb, offset, 4, ENC_LITTLE_ENDIAN);
385 proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
387 col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", tvb_get_letohl(tvb, offset));
388 break;
390 case PRISM_TYPE1_RSSI:
391 case PRISM_TYPE2_RSSI:
392 if(tree){
393 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rssi, tvb, offset, 4, ENC_LITTLE_ENDIAN);
394 proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
396 col_add_fstr(pinfo->cinfo, COL_RSSI, "%d", tvb_get_letohl(tvb, offset));
397 break;
399 case PRISM_TYPE1_SQ:
400 case PRISM_TYPE2_SQ:
401 if(tree){
402 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_sq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
403 proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
405 break;
407 case PRISM_TYPE1_SIGNAL:
408 case PRISM_TYPE2_SIGNAL:
409 if(tree){
410 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_signal, tvb, offset, 4, ENC_LITTLE_ENDIAN);
411 proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
413 break;
415 case PRISM_TYPE1_NOISE:
416 case PRISM_TYPE2_NOISE:
417 if(tree){
418 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_noise, tvb, offset, 4, ENC_LITTLE_ENDIAN);
419 proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
421 break;
423 case PRISM_TYPE1_RATE:
424 case PRISM_TYPE2_RATE:
425 if(tree){
426 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
427 proto_item_append_text(ti_did, " %s Mb/s", prism_rate_return(tvb_get_letohl(tvb, offset)) );
429 col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%s", prism_rate_return(tvb_get_letohl(tvb, offset)) );
430 break;
432 case PRISM_TYPE1_ISTX:
433 case PRISM_TYPE2_ISTX:
434 if(tree){
435 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_istx, tvb, offset, 4, ENC_LITTLE_ENDIAN);
436 proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
438 break;
440 case PRISM_TYPE1_FRMLEN:
441 case PRISM_TYPE2_FRMLEN:
442 if(tree){
443 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_frmlen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
444 proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
446 break;
448 default:
449 if(tree){
450 proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_unknown, tvb, offset, 4, ENC_LITTLE_ENDIAN);
452 break;
455 offset += 4;
458 /* dissect the 802.11 header next */
459 next_tvb = tvb_new_subset_remaining(tvb, offset);
460 call_dissector(ieee80211_handle, next_tvb, pinfo, tree);
463 static hf_register_info hf_prism[] = {
464 /* Prism-specific header fields
465 XXX - make as many of these generic as possible. */
466 { &hf_ieee80211_prism_msgcode,
467 {"Message Code", "prism.msgcode", FT_UINT32, BASE_HEX, NULL, 0x0,
468 NULL, HFILL }},
470 { &hf_ieee80211_prism_msglen,
471 {"Message Length", "prism.msglen", FT_UINT32, BASE_DEC, NULL, 0x0,
472 NULL, HFILL }},
474 { &hf_ieee80211_prism_devname,
475 {"Device Name", "prism.devname", FT_STRING, BASE_NONE, NULL, 0x0,
476 NULL, HFILL }},
478 { &hf_ieee80211_prism_did,
479 {"DID", "prism.did.type", FT_NONE, BASE_NONE, NULL, 0x0,
480 NULL, HFILL }},
482 { &hf_ieee80211_prism_did_type,
483 {"DID", "prism.did.type", FT_UINT32, BASE_HEX, VALS(prism_did_vals), 0x0,
484 "Different ID for each parameter", HFILL }},
486 { &hf_ieee80211_prism_did_status,
487 {"Status", "prism.did.status", FT_UINT16, BASE_DEC, VALS(prism_status_vals), 0x0,
488 "Supplied by the driver or not", HFILL }},
490 { &hf_ieee80211_prism_did_length,
491 {"Length", "prism.did.length", FT_UINT16, BASE_DEC, NULL, 0x0,
492 "Length of data", HFILL }},
494 { &hf_ieee80211_prism_did_hosttime,
495 {"Host Time", "prism.did.hosttime", FT_UINT32, BASE_DEC, NULL, 0x0,
496 "In jiffies - for our system this is in 10ms units", HFILL }},
498 { &hf_ieee80211_prism_did_mactime,
499 {"MAC timestamp (lower 32 bits)", "prism.did.mactime", FT_UINT32, BASE_DEC, NULL, 0x0,
500 "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 }},
502 { &hf_ieee80211_prism_did_channel,
503 {"Channel", "prism.did.channel", FT_UINT32, BASE_DEC, NULL, 0x0,
504 NULL, HFILL }},
506 { &hf_ieee80211_prism_did_rssi,
507 {"RSSI", "prism.did.rssi", FT_INT32, BASE_DEC, NULL, 0x0,
508 NULL, HFILL }},
510 { &hf_ieee80211_prism_did_sq,
511 {"Signal Quality", "prism.did.sq", FT_UINT32, BASE_DEC, NULL, 0x0,
512 NULL, HFILL }},
514 { &hf_ieee80211_prism_did_signal,
515 {"Signal", "prism.did.signal", FT_INT32, BASE_DEC, NULL, 0x0,
516 NULL, HFILL }},
518 { &hf_ieee80211_prism_did_noise,
519 {"Noise", "prism.did.noise", FT_INT32, BASE_DEC, NULL, 0x0,
520 NULL, HFILL }},
522 { &hf_ieee80211_prism_did_rate,
523 {"Data rate (Mb/s)", "prism.did.rate", FT_UINT32, BASE_CUSTOM, prism_rate_base_custom, 0x0,
524 "Speed this frame was sent/received at", HFILL }},
526 { &hf_ieee80211_prism_did_istx,
527 {"IsTX", "prism.did.istx", FT_UINT32, BASE_HEX, VALS(prism_istx_vals), 0x0,
528 "Type of packet (RX or TX?)", HFILL }},
530 { &hf_ieee80211_prism_did_frmlen,
531 {"Frame Length", "prism.did.frmlen", FT_UINT32, BASE_DEC, NULL, 0x0,
532 "Length of the following frame in bytes", HFILL }},
534 { &hf_ieee80211_prism_did_unknown,
535 {"Unknown DID Field", "prism.did.unknown", FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
536 NULL, HFILL }}
539 static gint *tree_array[] = {
540 &ett_prism,
541 &ett_prism_did
544 void proto_register_ieee80211_prism(void)
546 proto_prism = proto_register_protocol("Prism capture header", "Prism",
547 "prism");
548 proto_register_field_array(proto_prism, hf_prism, array_length(hf_prism));
549 proto_register_subtree_array(tree_array, array_length(tree_array));
552 void proto_reg_handoff_ieee80211_prism(void)
554 dissector_handle_t prism_handle;
556 prism_handle = create_dissector_handle(dissect_prism, proto_prism);
557 dissector_add_uint("wtap_encap", WTAP_ENCAP_IEEE_802_11_PRISM, prism_handle);
558 ieee80211_handle = find_dissector("wlan");
559 wlancap_handle = find_dissector("wlancap");
563 * Editor modelines
565 * Local Variables:
566 * c-basic-offset: 2
567 * tab-width: 8
568 * indent-tabs-mode: nil
569 * End:
571 * ex: set shiftwidth=2 tabstop=8 expandtab:
572 * :indentSize=2:tabSize=8:noTabs=true: