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