3 * Decode packets with a Prism header
5 * Prism II-based wlan devices have a monitoring mode that sticks
6 * a proprietary header on each packet with lots of good
7 * information. This file is responsible for decoding that
14 * Ethereal - Network traffic analyzer
15 * By Gerald Combs <gerald@ethereal.com>
16 * Copyright 1998 Gerald Combs
18 * Copied from README.developer
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 #include <epan/packet.h>
42 #include "packet-ieee80211.h"
43 #include "packet-prism.h"
44 #include "packet-wlancap.h"
47 static int proto_prism = -1;
50 static int hf_prism_msgcode = -1;
51 static int hf_prism_msglen = -1;
54 * A value from the header.
56 * It appears from looking at the linux-wlan-ng and Prism II HostAP
57 * drivers, and various patches to the orinoco_cs drivers to add
58 * Prism headers, that:
60 * the "did" identifies what the value is (i.e., what it's the value
63 * "status" is 0 if the value is present or 1 if it's absent;
65 * "len" is the length of the value (always 4, in that code);
67 * "data" is the value of the data (or 0 if not present).
69 * Note: all of those values are in the *host* byte order of the machine
70 * on which the capture was written.
74 unsigned short status, len;
79 * Header attached during Prism monitor mode.
81 * At least according to one paper I've seen, the Prism 2.5 chip set
84 * RSSI (receive signal strength indication) is "the total power
85 * received by the radio hardware while receiving the frame,
86 * including signal, interfereence, and background noise";
88 * "silence value" is "the total power observed just before the
89 * start of the frame".
91 * None of the drivers I looked at supply the "rssi" or "sq" value,
92 * but they do supply "signal" and "noise" values, along with a "rate"
93 * value that's 1/5 of the raw value from what is presumably a raw
94 * HFA384x frame descriptor, with the comment "set to 802.11 units",
95 * which presumably means the units are 500 Kb/s.
97 * I infer from the current NetBSD "wi" driver that "signal" and "noise"
98 * are adjusted dBm values, with the dBm value having 100 added to it
99 * for the Prism II cards (although the NetBSD code has an XXX comment
100 * for the #define for WI_PRISM_DBM_OFFSET) and 149 (with no XXX comment)
101 * for the Orinoco cards.
104 unsigned int msgcode, msglen;
106 struct val_80211 hosttime, mactime, channel, rssi, sq, signal,
107 noise, rate, istx, frmlen;
110 #define VALFIELDS(name) \
111 static int hf_prism_ ## name ## _data = -1
123 static gint ett_prism = -1;
125 static dissector_handle_t ieee80211_handle;
126 static dissector_handle_t wlancap_handle;
129 capture_prism(const guchar *pd, int offset, int len, packet_counts *ld)
133 if (!BYTES_ARE_IN_FRAME(offset, len, sizeof(guint32) *2 )) {
139 length = pntohl(pd+sizeof(guint32));
141 /* Handle the new type of capture format */
142 if (cookie == WLANCAP_MAGIC_COOKIE_V1) {
143 if(!BYTES_ARE_IN_FRAME(offset, len, length)) {
149 /* We have an old capture format */
150 if(!BYTES_ARE_IN_FRAME(offset, len, (int)sizeof(struct prism_hdr))) {
154 offset += sizeof(struct prism_hdr);
157 /* 802.11 header follows */
158 capture_ieee80211(pd, offset, len, ld);
163 * yah, I know, macros, ugh, but it makes the code
164 * below more readable
166 #define IFHELP(size, name, var, str) \
168 proto_tree_add_uint_format(prism_tree, hf_prism_ ## name, \
169 tvb, offset, size, hdr.var, str, hdr.var); \
172 #define INTFIELD(size, name, str) IFHELP(size, name, name, str)
173 #define VALFIELD(name, str) \
174 if (hdr.name.status == 0) { \
176 proto_tree_add_uint_format(prism_tree, hf_prism_ ## name ## _data, \
177 tvb, offset, 12, hdr.name.data, \
178 str ": 0x%x (DID 0x%x, Status 0x%x, Length 0x%x)", \
179 hdr.name.data, hdr.name.did, \
180 hdr.name.status, hdr.name.len); \
186 dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
188 struct prism_hdr hdr;
189 proto_tree *prism_tree = NULL;
197 /* handle the new capture type. */
198 msgcode = tvb_get_ntohl(tvb, offset);
199 if (msgcode == WLANCAP_MAGIC_COOKIE_V1) {
200 call_dissector(wlancap_handle, tvb, pinfo, tree);
204 tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
206 if(check_col(pinfo->cinfo, COL_PROTOCOL))
207 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Prism");
208 if(check_col(pinfo->cinfo, COL_INFO))
209 col_clear(pinfo->cinfo, COL_INFO);
211 if(check_col(pinfo->cinfo, COL_INFO))
212 col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %.16s "
213 "Message 0x%x, Length %d", hdr.devname,
214 hdr.msgcode, hdr.msglen);
217 ti = proto_tree_add_protocol_format(tree, proto_prism,
218 tvb, 0, sizeof hdr, "Prism Monitoring Header");
219 prism_tree = proto_item_add_subtree(ti, ett_prism);
222 INTFIELD(4, msgcode, "Message Code: %d");
223 INTFIELD(4, msglen, "Message Length: %d");
225 proto_tree_add_text(prism_tree, tvb, offset, sizeof hdr.devname,
226 "Device: %s", hdr.devname);
228 offset += sizeof hdr.devname;
230 VALFIELD(hosttime, "Host Time");
231 VALFIELD(mactime, "MAC Time");
232 VALFIELD(channel, "Channel");
233 if (hdr.rate.status == 0) {
234 if (check_col(pinfo->cinfo, COL_RSSI))
235 col_add_fstr(pinfo->cinfo, COL_RSSI, "%d", hdr.rssi.data);
237 proto_tree_add_uint_format(prism_tree, hf_prism_rssi_data,
238 tvb, offset, 12, hdr.rssi.data,
239 "RSSI: 0x%x (DID 0x%x, Status 0x%x, Length 0x%x)",
240 hdr.rssi.data, hdr.rssi.did, hdr.rssi.status, hdr.rssi.len);
245 VALFIELD(signal, "Signal");
246 VALFIELD(noise, "Noise");
247 if (hdr.rate.status == 0) {
248 if (check_col(pinfo->cinfo, COL_TX_RATE)) {
249 col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u",
250 hdr.rate.data / 2, hdr.rate.data & 1 ? 5 : 0);
253 proto_tree_add_uint_format(prism_tree, hf_prism_rate_data,
254 tvb, offset, 12, hdr.rate.data,
255 "Data Rate: %u.%u Mb/s",
256 hdr.rate.data / 2, hdr.rate.data & 1 ? 5 : 0);
260 VALFIELD(istx, "IsTX");
261 VALFIELD(frmlen, "Frame Length");
263 /* dissect the 802.11 header next */
264 next_tvb = tvb_new_subset(tvb, sizeof hdr, -1, -1);
265 call_dissector(ieee80211_handle, next_tvb, pinfo, tree);
268 #define IFHELP2(size, name, var, str) \
269 { &hf_prism_ ## name, { \
270 str, "prism." #var, size, BASE_HEX, NULL, 0x0, "", HFILL } },
271 #define INTFIELD2(size, name, str) IFHELP2(size, name, name, str)
272 #define VALFIELD2(name, str) \
273 IFHELP2(FT_UINT32, name ## _data, name.data, str " Field")
276 proto_register_prism(void)
278 static hf_register_info hf[] = {
279 INTFIELD2(FT_UINT32, msgcode, "Message Code")
280 INTFIELD2(FT_UINT32, msglen, "Message Length")
281 VALFIELD2(hosttime, "Host Time")
282 VALFIELD2(mactime, "MAC Time")
283 VALFIELD2(channel, "Channel")
284 VALFIELD2(rssi, "RSSI")
286 VALFIELD2(signal, "Signal")
287 VALFIELD2(noise, "Noise")
288 VALFIELD2(rate, "Rate")
289 VALFIELD2(istx, "IsTX")
290 VALFIELD2(frmlen, "Frame Length")
293 static gint *ett[] = {
297 proto_prism = proto_register_protocol("Prism", "Prism", "prism");
298 proto_register_field_array(proto_prism, hf, array_length(hf));
299 proto_register_subtree_array(ett, array_length(ett));
303 proto_reg_handoff_prism(void)
305 dissector_handle_t prism_handle;
307 /* handle for 802.11 dissector */
308 ieee80211_handle = find_dissector("wlan");
309 wlancap_handle = find_dissector("wlancap");
311 prism_handle = create_dissector_handle(dissect_prism, proto_prism);
312 dissector_add("wtap_encap", WTAP_ENCAP_PRISM_HEADER, prism_handle);