aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-prism.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-prism.c')
-rw-r--r--epan/dissectors/packet-prism.c313
1 files changed, 313 insertions, 0 deletions
diff --git a/epan/dissectors/packet-prism.c b/epan/dissectors/packet-prism.c
new file mode 100644
index 0000000000..57cc16b38a
--- /dev/null
+++ b/epan/dissectors/packet-prism.c
@@ -0,0 +1,313 @@
+/*
+ * packet-prism.c
+ * Decode packets with a Prism header
+ *
+ * Prism II-based wlan devices have a monitoring mode that sticks
+ * a proprietary header on each packet with lots of good
+ * information. This file is responsible for decoding that
+ * data.
+ *
+ * By Tim Newsham
+ *
+ * $Id$
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from README.developer
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <glib.h>
+
+#include <epan/packet.h>
+#include "packet-ieee80211.h"
+#include "packet-prism.h"
+#include "packet-wlancap.h"
+
+/* protocol */
+static int proto_prism = -1;
+
+/* header fields */
+static int hf_prism_msgcode = -1;
+static int hf_prism_msglen = -1;
+
+/*
+ * A value from the header.
+ *
+ * It appears from looking at the linux-wlan-ng and Prism II HostAP
+ * drivers, and various patches to the orinoco_cs drivers to add
+ * Prism headers, that:
+ *
+ * the "did" identifies what the value is (i.e., what it's the value
+ * of);
+ *
+ * "status" is 0 if the value is present or 1 if it's absent;
+ *
+ * "len" is the length of the value (always 4, in that code);
+ *
+ * "data" is the value of the data (or 0 if not present).
+ *
+ * Note: all of those values are in the *host* byte order of the machine
+ * on which the capture was written.
+ */
+struct val_80211 {
+ unsigned int did;
+ unsigned short status, len;
+ unsigned int data;
+};
+
+/*
+ * Header attached during Prism monitor mode.
+ *
+ * At least according to one paper I've seen, the Prism 2.5 chip set
+ * provides:
+ *
+ * RSSI (receive signal strength indication) is "the total power
+ * received by the radio hardware while receiving the frame,
+ * including signal, interfereence, and background noise";
+ *
+ * "silence value" is "the total power observed just before the
+ * start of the frame".
+ *
+ * None of the drivers I looked at supply the "rssi" or "sq" value,
+ * but they do supply "signal" and "noise" values, along with a "rate"
+ * value that's 1/5 of the raw value from what is presumably a raw
+ * HFA384x frame descriptor, with the comment "set to 802.11 units",
+ * which presumably means the units are 500 Kb/s.
+ *
+ * I infer from the current NetBSD "wi" driver that "signal" and "noise"
+ * are adjusted dBm values, with the dBm value having 100 added to it
+ * for the Prism II cards (although the NetBSD code has an XXX comment
+ * for the #define for WI_PRISM_DBM_OFFSET) and 149 (with no XXX comment)
+ * for the Orinoco cards.
+ */
+struct prism_hdr {
+ unsigned int msgcode, msglen;
+ char devname[16];
+ struct val_80211 hosttime, mactime, channel, rssi, sq, signal,
+ noise, rate, istx, frmlen;
+};
+
+#define VALFIELDS(name) \
+ static int hf_prism_ ## name ## _data = -1
+VALFIELDS(hosttime);
+VALFIELDS(mactime);
+VALFIELDS(channel);
+VALFIELDS(rssi);
+VALFIELDS(sq);
+VALFIELDS(signal);
+VALFIELDS(noise);
+VALFIELDS(rate);
+VALFIELDS(istx);
+VALFIELDS(frmlen);
+
+static gint ett_prism = -1;
+
+static dissector_handle_t ieee80211_handle;
+static dissector_handle_t wlancap_handle;
+
+void
+capture_prism(const guchar *pd, int offset, int len, packet_counts *ld)
+{
+ guint32 cookie = 0;
+ guint32 length = 0;
+ if (!BYTES_ARE_IN_FRAME(offset, len, sizeof(guint32) *2 )) {
+ ld->other++;
+ return;
+ }
+
+ cookie = pntohl(pd);
+ length = pntohl(pd+sizeof(guint32));
+
+ /* Handle the new type of capture format */
+ if (cookie == WLANCAP_MAGIC_COOKIE_V1) {
+ if(!BYTES_ARE_IN_FRAME(offset, len, length)) {
+ ld->other++;
+ return;
+ }
+ offset += length;
+ } else {
+ /* We have an old capture format */
+ if(!BYTES_ARE_IN_FRAME(offset, len, (int)sizeof(struct prism_hdr))) {
+ ld->other++;
+ return;
+ }
+ offset += sizeof(struct prism_hdr);
+ }
+
+ /* 802.11 header follows */
+ capture_ieee80211(pd, offset, len, ld);
+
+}
+
+/*
+ * yah, I know, macros, ugh, but it makes the code
+ * below more readable
+ */
+#define IFHELP(size, name, var, str) \
+ if(tree) { \
+ proto_tree_add_uint_format(prism_tree, hf_prism_ ## name, \
+ tvb, offset, size, hdr.var, str, hdr.var); \
+ } \
+ offset += (size)
+#define INTFIELD(size, name, str) IFHELP(size, name, name, str)
+#define VALFIELD(name, str) \
+ if (hdr.name.status == 0) { \
+ if(tree) { \
+ proto_tree_add_uint_format(prism_tree, hf_prism_ ## name ## _data, \
+ tvb, offset, 12, hdr.name.data, \
+ str ": 0x%x (DID 0x%x, Status 0x%x, Length 0x%x)", \
+ hdr.name.data, hdr.name.did, \
+ hdr.name.status, hdr.name.len); \
+ } \
+ } \
+ offset += 12
+
+static void
+dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ struct prism_hdr hdr;
+ proto_tree *prism_tree = NULL;
+ proto_item *ti;
+ tvbuff_t *next_tvb;
+ int offset;
+ guint32 msgcode;
+
+ offset = 0;
+
+ /* handle the new capture type. */
+ msgcode = tvb_get_ntohl(tvb, offset);
+ if (msgcode == WLANCAP_MAGIC_COOKIE_V1) {
+ call_dissector(wlancap_handle, tvb, pinfo, tree);
+ return;
+ }
+
+ tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
+
+ if(check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "Prism");
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ if(check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %.16s "
+ "Message 0x%x, Length %d", hdr.devname,
+ hdr.msgcode, hdr.msglen);
+
+ if(tree) {
+ ti = proto_tree_add_protocol_format(tree, proto_prism,
+ tvb, 0, sizeof hdr, "Prism Monitoring Header");
+ prism_tree = proto_item_add_subtree(ti, ett_prism);
+ }
+
+ INTFIELD(4, msgcode, "Message Code: %d");
+ INTFIELD(4, msglen, "Message Length: %d");
+ if(tree) {
+ proto_tree_add_text(prism_tree, tvb, offset, sizeof hdr.devname,
+ "Device: %s", hdr.devname);
+ }
+ offset += sizeof hdr.devname;
+
+ VALFIELD(hosttime, "Host Time");
+ VALFIELD(mactime, "MAC Time");
+ VALFIELD(channel, "Channel");
+ if (hdr.rate.status == 0) {
+ if (check_col(pinfo->cinfo, COL_RSSI))
+ col_add_fstr(pinfo->cinfo, COL_RSSI, "%d", hdr.rssi.data);
+ if (tree) {
+ proto_tree_add_uint_format(prism_tree, hf_prism_rssi_data,
+ tvb, offset, 12, hdr.rssi.data,
+ "RSSI: 0x%x (DID 0x%x, Status 0x%x, Length 0x%x)",
+ hdr.rssi.data, hdr.rssi.did, hdr.rssi.status, hdr.rssi.len);
+ }
+ }
+ offset += 12;
+ VALFIELD(sq, "SQ");
+ VALFIELD(signal, "Signal");
+ VALFIELD(noise, "Noise");
+ if (hdr.rate.status == 0) {
+ if (check_col(pinfo->cinfo, COL_TX_RATE)) {
+ col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u",
+ hdr.rate.data / 2, hdr.rate.data & 1 ? 5 : 0);
+ }
+ if (tree) {
+ proto_tree_add_uint_format(prism_tree, hf_prism_rate_data,
+ tvb, offset, 12, hdr.rate.data,
+ "Data Rate: %u.%u Mb/s",
+ hdr.rate.data / 2, hdr.rate.data & 1 ? 5 : 0);
+ }
+ }
+ offset += 12;
+ VALFIELD(istx, "IsTX");
+ VALFIELD(frmlen, "Frame Length");
+
+ /* dissect the 802.11 header next */
+ next_tvb = tvb_new_subset(tvb, sizeof hdr, -1, -1);
+ call_dissector(ieee80211_handle, next_tvb, pinfo, tree);
+}
+
+#define IFHELP2(size, name, var, str) \
+ { &hf_prism_ ## name, { \
+ str, "prism." #var, size, BASE_HEX, NULL, 0x0, "", HFILL } },
+#define INTFIELD2(size, name, str) IFHELP2(size, name, name, str)
+#define VALFIELD2(name, str) \
+ IFHELP2(FT_UINT32, name ## _data, name.data, str " Field")
+
+void
+proto_register_prism(void)
+{
+ static hf_register_info hf[] = {
+ INTFIELD2(FT_UINT32, msgcode, "Message Code")
+ INTFIELD2(FT_UINT32, msglen, "Message Length")
+ VALFIELD2(hosttime, "Host Time")
+ VALFIELD2(mactime, "MAC Time")
+ VALFIELD2(channel, "Channel")
+ VALFIELD2(rssi, "RSSI")
+ VALFIELD2(sq, "SQ")
+ VALFIELD2(signal, "Signal")
+ VALFIELD2(noise, "Noise")
+ VALFIELD2(rate, "Rate")
+ VALFIELD2(istx, "IsTX")
+ VALFIELD2(frmlen, "Frame Length")
+
+ };
+ static gint *ett[] = {
+ &ett_prism
+ };
+
+ proto_prism = proto_register_protocol("Prism", "Prism", "prism");
+ proto_register_field_array(proto_prism, hf, array_length(hf));
+ proto_register_subtree_array(ett, array_length(ett));
+}
+
+void
+proto_reg_handoff_prism(void)
+{
+ dissector_handle_t prism_handle;
+
+ /* handle for 802.11 dissector */
+ ieee80211_handle = find_dissector("wlan");
+ wlancap_handle = find_dissector("wlancap");
+
+ prism_handle = create_dissector_handle(dissect_prism, proto_prism);
+ dissector_add("wtap_encap", WTAP_ENCAP_PRISM_HEADER, prism_handle);
+}