From Jesper Peterson:
[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.10 2003/03/08 11:43:54 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 #include "packet-wlancap.h"
45
46 /* protocol */
47 static int proto_prism = -1;
48
49 /* header fields */
50 static int hf_prism_msgcode = -1;
51 static int hf_prism_msglen = -1;
52
53 /* a 802.11 value */
54 struct val_80211 {
55     unsigned int did;
56     unsigned short status, len;
57     unsigned int data;
58 };
59
60 /* header attached during prism monitor mode */
61 struct prism_hdr {
62     unsigned int msgcode, msglen;
63     char devname[16];
64     struct val_80211 hosttime, mactime, channel, rssi, sq, signal,
65         noise, rate, istx, frmlen;
66 };
67
68 #define VALFIELDS(name) \
69     static int hf_prism_ ## name ## _data = -1
70 VALFIELDS(hosttime);
71 VALFIELDS(mactime);
72 VALFIELDS(channel);
73 VALFIELDS(rssi);
74 VALFIELDS(sq);
75 VALFIELDS(signal);
76 VALFIELDS(noise);
77 VALFIELDS(rate);
78 VALFIELDS(istx);
79 VALFIELDS(frmlen);
80
81 static gint ett_prism = -1;
82
83 static dissector_handle_t ieee80211_handle;
84 static dissector_handle_t wlancap_handle;
85
86 void
87 capture_prism(const guchar *pd, int offset, int len, packet_counts *ld)
88 {
89     guint32 cookie = 0;
90     guint32 length = 0;
91     if (!BYTES_ARE_IN_FRAME(offset, len, sizeof(guint32) *2 )) {
92         ld->other++;
93         return;
94     }
95
96     cookie = pntohl(pd);
97     length = pntohl(pd+sizeof(guint32));
98
99     /* Handle the new type of capture format */
100     if (cookie == WLANCAP_MAGIC_COOKIE_V1) {
101       if(!BYTES_ARE_IN_FRAME(offset, len, length)) {
102         ld->other++;
103         return;
104       }
105       offset += length;
106     } else {
107       /* We have an old capture format */
108       if(!BYTES_ARE_IN_FRAME(offset, len, (int)sizeof(struct prism_hdr))) {
109         ld->other++;
110         return;
111       }
112       offset += sizeof(struct prism_hdr);
113     }
114
115     /* 802.11 header follows */
116     capture_ieee80211(pd, offset, len, ld);
117
118 }
119
120 /*
121  * yah, I know, macros, ugh, but it makes the code
122  * below more readable
123  */
124 #define IFHELP(size, name, var, str) \
125         proto_tree_add_uint_format(prism_tree, hf_prism_ ## name, \
126             tvb, offset, size, hdr.var, str, hdr.var);            \
127         offset += (size)
128 #define INTFIELD(size, name, str)       IFHELP(size, name, name, str)
129 #define VALFIELD(name, str) \
130         proto_tree_add_uint_format(prism_tree, hf_prism_ ## name ## _data, \
131             tvb, offset, 12, hdr.name.data,                                \
132             str ": 0x%x (DID 0x%x, Status 0x%x, Length 0x%x)",             \
133             hdr.name.data, hdr.name.did,                                   \
134             hdr.name.status, hdr.name.len);                                \
135         offset += 12
136
137 static void
138 dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
139 {
140     struct prism_hdr hdr;
141     proto_tree *prism_tree;
142     proto_item *ti;
143     tvbuff_t *next_tvb;
144     int offset;
145     guint32 msgcode;
146
147     offset = 0;
148
149     /* handle the new capture type. */
150     msgcode = tvb_get_ntohl(tvb, offset);
151     if (msgcode == WLANCAP_MAGIC_COOKIE_V1) {
152             call_dissector(wlancap_handle, tvb, pinfo, tree);
153             return;
154     }
155       
156     tvb_memcpy(tvb, (guint8 *)&hdr, offset, sizeof(hdr));
157
158     if(check_col(pinfo->cinfo, COL_PROTOCOL))
159         col_set_str(pinfo->cinfo, COL_PROTOCOL, "Prism");
160     if(check_col(pinfo->cinfo, COL_INFO))
161         col_clear(pinfo->cinfo, COL_INFO);
162
163     if(check_col(pinfo->cinfo, COL_INFO))
164         col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %.16s  "
165                      "Message 0x%x, Length %d", hdr.devname,
166                      hdr.msgcode, hdr.msglen);
167
168     if(tree) {
169         ti = proto_tree_add_protocol_format(tree, proto_prism,
170             tvb, 0, sizeof hdr, "Prism Monitoring Header");
171         prism_tree = proto_item_add_subtree(ti, ett_prism);
172
173         INTFIELD(4, msgcode, "Message Code: %d");
174         INTFIELD(4, msglen, "Message Length: %d");
175         proto_tree_add_text(prism_tree, tvb, offset, sizeof hdr.devname,
176             "Device: %s", hdr.devname);
177         offset += sizeof hdr.devname;
178
179         VALFIELD(hosttime, "Host Time");
180         VALFIELD(mactime, "MAC Time");
181         VALFIELD(channel, "Channel Time");
182         VALFIELD(rssi, "RSSI");
183         VALFIELD(sq, "SQ");
184         VALFIELD(signal, "Signal");
185         VALFIELD(noise, "Noise");
186         VALFIELD(rate, "Rate");
187         VALFIELD(istx, "IsTX");
188         VALFIELD(frmlen, "Frame Length");
189     }
190
191     /* dissect the 802.11 header next */
192     next_tvb = tvb_new_subset(tvb, sizeof hdr, -1, -1);
193     call_dissector(ieee80211_handle, next_tvb, pinfo, tree);
194 }
195
196 #define IFHELP2(size, name, var, str) \
197         { &hf_prism_ ## name, {                                    \
198             str, "prism." #var, size, BASE_HEX, NULL, 0x0, "", HFILL } },
199 #define INTFIELD2(size, name, str)      IFHELP2(size, name, name, str)
200 #define VALFIELD2(name, str) \
201    IFHELP2(FT_UINT32, name ## _data, name.data, str " Field")
202
203 void
204 proto_register_prism(void)
205 {
206     static hf_register_info hf[] = {
207         INTFIELD2(FT_UINT32, msgcode, "Message Code")
208         INTFIELD2(FT_UINT32, msglen, "Message Length")
209         VALFIELD2(hosttime, "Host Time")
210         VALFIELD2(mactime, "MAC Time")
211         VALFIELD2(channel, "Channel Time")
212         VALFIELD2(rssi, "RSSI")
213         VALFIELD2(sq, "SQ")
214         VALFIELD2(signal, "Signal")
215         VALFIELD2(noise, "Noise")
216         VALFIELD2(rate, "Rate")
217         VALFIELD2(istx, "IsTX")
218         VALFIELD2(frmlen, "Frame Length")
219
220     };
221     static gint *ett[] = {
222         &ett_prism
223     };
224
225     proto_prism = proto_register_protocol("Prism", "Prism", "prism");
226     proto_register_field_array(proto_prism, hf, array_length(hf));
227     proto_register_subtree_array(ett, array_length(ett));
228 }
229
230 void
231 proto_reg_handoff_prism(void)
232 {
233     dissector_handle_t prism_handle;
234
235     /* handle for 802.11 dissector */
236     ieee80211_handle = find_dissector("wlan");
237     wlancap_handle = find_dissector("wlancap");
238
239     prism_handle = create_dissector_handle(dissect_prism, proto_prism);
240     dissector_add("wtap_encap", WTAP_ENCAP_PRISM_HEADER, prism_handle);
241 }