Don't include the header file to get the SNMP version unless we're
[obnox/wireshark/wip.git] / packet-prism.c
1 /*
2  *  packet-prism.c
3  *      Decode packets with a Prism header
4  *
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
8  * data.
9  *
10  * By Tim Newsham
11  *
12  * $Id: packet-prism.c,v 1.8 2002/08/28 21:00:25 jmayer Exp $
13  *
14  * Ethereal - Network traffic analyzer
15  * By Gerald Combs <gerald@ethereal.com>
16  * Copyright 1998 Gerald Combs
17  *
18  * Copied from README.developer
19  *
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.
24  *
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.
29  *
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.
33  */
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <glib.h>
40
41 #include <epan/packet.h>
42 #include "packet-ieee80211.h"
43 #include "packet-prism.h"
44
45 /* protocol */
46 static int proto_prism = -1;
47
48 /* header fields */
49 static int hf_prism_msgcode = -1;
50 static int hf_prism_msglen = -1;
51
52 /* a 802.11 value */
53 struct val_80211 {
54     unsigned int did;
55     unsigned short status, len;
56     unsigned int data;
57 };
58
59 /* header attached during prism monitor mode */
60 struct prism_hdr {
61     unsigned int msgcode, msglen;
62     char devname[16];
63     struct val_80211 hosttime, mactime, channel, rssi, sq, signal,
64         noise, rate, istx, frmlen;
65 };
66
67 #define VALFIELDS(name) \
68     static int hf_prism_ ## name ## _data = -1
69 VALFIELDS(hosttime);
70 VALFIELDS(mactime);
71 VALFIELDS(channel);
72 VALFIELDS(rssi);
73 VALFIELDS(sq);
74 VALFIELDS(signal);
75 VALFIELDS(noise);
76 VALFIELDS(rate);
77 VALFIELDS(istx);
78 VALFIELDS(frmlen);
79
80 static gint ett_prism = -1;
81
82 static dissector_handle_t ieee80211_handle;
83
84 void
85 capture_prism(const guchar *pd, int offset, int len, packet_counts *ld)
86 {
87     if(!BYTES_ARE_IN_FRAME(offset, len, (int)sizeof(struct prism_hdr))) {
88         ld->other ++;
89         return;
90     }
91     offset += sizeof(struct prism_hdr);
92
93     /* 802.11 header follows */
94     capture_ieee80211(pd, offset, len, ld);
95 }
96
97 /*
98  * yah, I know, macros, ugh, but it makes the code
99  * below more readable
100  */
101 #define IFHELP(size, name, var, str) \
102         proto_tree_add_uint_format(prism_tree, hf_prism_ ## name, \
103             tvb, offset, size, hdr. ## var, str, hdr. ## var);    \
104         offset += (size)
105 #define INTFIELD(size, name, str)       IFHELP(size, name, name, str)
106 #define VALFIELD(name, str) \
107         proto_tree_add_uint_format(prism_tree, hf_prism_ ## name ## _data, \
108             tvb, offset, 12, hdr. ## name ## .data,                        \
109             str ": 0x%x (DID 0x%x, Status 0x%x, Length 0x%x)",             \
110             hdr. ## name ## .data, hdr. ## name ## .did,                   \
111             hdr. ## name ## .status, hdr. ## name ## .len);                \
112         offset += 12
113
114 static void
115 dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
116 {
117     struct prism_hdr hdr;
118     proto_tree *prism_tree;
119     proto_item *ti;
120     tvbuff_t *next_tvb;
121     int offset;
122
123     if(check_col(pinfo->cinfo, COL_PROTOCOL))
124         col_set_str(pinfo->cinfo, COL_PROTOCOL, "Prism");
125     if(check_col(pinfo->cinfo, COL_INFO))
126         col_clear(pinfo->cinfo, COL_INFO);
127
128     offset = 0;
129     tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof hdr);
130
131     if(check_col(pinfo->cinfo, COL_INFO))
132         col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %.16s  "
133                      "Message 0x%x, Length %d", hdr.devname,
134                      hdr.msgcode, hdr.msglen);
135
136     if(tree) {
137         ti = proto_tree_add_protocol_format(tree, proto_prism,
138             tvb, 0, sizeof hdr, "Prism Monitoring Header");
139         prism_tree = proto_item_add_subtree(ti, ett_prism);
140
141         INTFIELD(4, msgcode, "Message Code: %d");
142         INTFIELD(4, msglen, "Message Length: %d");
143         proto_tree_add_text(prism_tree, tvb, offset, sizeof hdr.devname,
144             "Device: %s", hdr.devname);
145         offset += sizeof hdr.devname;
146
147         VALFIELD(hosttime, "Host Time");
148         VALFIELD(mactime, "MAC Time");
149         VALFIELD(channel, "Channel Time");
150         VALFIELD(rssi, "RSSI");
151         VALFIELD(sq, "SQ");
152         VALFIELD(signal, "Signal");
153         VALFIELD(noise, "Noise");
154         VALFIELD(rate, "Rate");
155         VALFIELD(istx, "IsTX");
156         VALFIELD(frmlen, "Frame Length");
157     }
158
159     /* dissect the 802.11 header next */
160     next_tvb = tvb_new_subset(tvb, sizeof hdr, -1, -1);
161     call_dissector(ieee80211_handle, next_tvb, pinfo, tree);
162 }
163
164 #define IFHELP2(size, name, var, str) \
165         { &hf_prism_ ## name, {                                    \
166             str, "prism." #var, size, BASE_HEX, NULL, 0x0, "", HFILL } },
167 #define INTFIELD2(size, name, str)      IFHELP2(size, name, name, str)
168 #define VALFIELD2(name, str) \
169    IFHELP2(FT_UINT32, name ## _data, name ## .data, str ## " Field")
170
171 void
172 proto_register_prism(void)
173 {
174     static hf_register_info hf[] = {
175         INTFIELD2(FT_UINT32, msgcode, "Message Code")
176         INTFIELD2(FT_UINT32, msglen, "Message Length")
177         VALFIELD2(hosttime, "Host Time")
178         VALFIELD2(mactime, "MAC Time")
179         VALFIELD2(channel, "Channel Time")
180         VALFIELD2(rssi, "RSSI")
181         VALFIELD2(sq, "SQ")
182         VALFIELD2(signal, "Signal")
183         VALFIELD2(noise, "Noise")
184         VALFIELD2(rate, "Rate")
185         VALFIELD2(istx, "IsTX")
186         VALFIELD2(frmlen, "Frame Length")
187
188     };
189     static gint *ett[] = {
190         &ett_prism
191     };
192
193     proto_prism = proto_register_protocol("Prism", "Prism", "prism");
194     proto_register_field_array(proto_prism, hf, array_length(hf));
195     proto_register_subtree_array(ett, array_length(ett));
196 }
197
198 void
199 proto_reg_handoff_prism(void)
200 {
201     dissector_handle_t prism_handle;
202
203     /* handle for 802.11 dissector */
204     ieee80211_handle = find_dissector("wlan");
205
206     prism_handle = create_dissector_handle(dissect_prism, proto_prism);
207     dissector_add("wtap_encap", WTAP_ENCAP_PRISM_HEADER, prism_handle);
208 }