MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / plugins / wimax / packet-wmx.c
blob50af5e91d961f4d1e09d17094f4d9be9d5585193
1 /* packet-wmx.c
2 * WiMax Protocol and dissectors
4 * Copyright (c) 2007 by Intel Corporation.
6 * Author: Lu Pan <lu.pan@intel.com>
8 * $Id$
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1999 Gerald Combs
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 /* Include files */
31 #include "config.h"
33 #include <string.h>
34 #include <glib.h>
35 #include <epan/packet.h>
36 #include <epan/prefs.h>
37 #include <epan/address.h>
38 #include <epan/wmem/wmem.h>
39 #include "wimax_tlv.h"
40 #include "wimax_bits.h"
42 /* Global variables */
43 gint proto_wimax = -1;
44 gint8 arq_enabled = 0;
45 gint scheduling_service_type = 0;
46 gint mac_sdu_length = 49; /* default SDU size is 49 bytes (11.13.16) */
47 extern guint global_cid_max_basic;
48 extern gboolean include_cor2_changes;
50 address bs_address = {AT_NONE, -1, 0, NULL};
53 static int hf_tlv_type = -1;
54 static int hf_tlv_length = -1;
55 static int hf_tlv_length_size = -1;
57 #define MAX_NUM_TLVS 256
58 /* Global TLV array to retrieve unique subtree identifiers */
59 static gint ett_tlv[MAX_NUM_TLVS];
61 static const gchar tlv_val_1byte[] = "TLV value: %s (0x%02x)";
62 static const gchar tlv_val_2byte[] = "TLV value: %s (0x%04x)";
63 static const gchar tlv_val_3byte[] = "TLV value: %s (0x%06x)";
64 static const gchar tlv_val_4byte[] = "TLV value: %s (0x%08x)";
65 static const gchar tlv_val_5byte[] = "TLV value: %s (0x%08x...)";
67 /*************************************************************/
68 /* add_tlv_subtree() */
69 /* Return a pointer to a proto_item of a TLV value that */
70 /* already contains the type and length of the given TLV. */
71 /* tree - the parent to which the new tree will */
72 /* be attached */
73 /* hfindex - the index of the item to be attached */
74 /* tvb - a pointer to the packet data */
75 /* start - offset within the packet */
76 /* length - length of this item */
77 /* encoding - encoding for proto_tree_add_item */
78 /* return: */
79 /* pointer to a proto_item */
80 /*************************************************************/
81 proto_item *add_tlv_subtree(tlv_info_t *self, proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, const guint encoding)
83 header_field_info *hf;
84 proto_tree *tlv_tree;
85 proto_item *tlv_item;
86 gint tlv_value_length, tlv_val_offset;
87 guint8 size_of_tlv_length_field;
88 guint8 tlv_type;
90 /* Make sure we're dealing with a valid TLV here */
91 if (get_tlv_type(self) < 0)
92 return tree;
94 /* Retrieve the necessary TLV information */
95 tlv_val_offset = get_tlv_value_offset(self);
96 tlv_value_length = get_tlv_length(self);
97 size_of_tlv_length_field = get_tlv_size_of_length(self);
98 tlv_type = get_tlv_type(self);
100 hf = proto_registrar_get_nth(hfindex);
102 tlv_item = proto_tree_add_text(tree, tvb, start, tlv_value_length+tlv_val_offset, "%s", hf->name);
103 tlv_tree = proto_item_add_subtree(tlv_item, ett_tlv[tlv_type]);
105 proto_tree_add_uint(tlv_tree, hf_tlv_type, tvb, start, 1, tlv_type);
106 if (size_of_tlv_length_field > 0) /* It is */
108 /* display the length of the length field TLV */
109 proto_tree_add_uint(tlv_tree, hf_tlv_length_size, tvb, start+1, 1, size_of_tlv_length_field);
110 /* display the TLV length */
111 proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+2, size_of_tlv_length_field, tlv_value_length);
112 } else { /* It is not */
113 /* display the TLV length */
114 proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+1, 1, tlv_value_length);
117 tlv_item = proto_tree_add_item(tlv_tree, hfindex, tvb, start+tlv_val_offset, tlv_value_length, encoding);
119 /* Return a pointer to the value level */
120 return tlv_item;
123 /*************************************************************/
124 /* add_tlv_subtree_no_item() */
125 /* Return a pointer to a proto_tree of a TLV value that */
126 /* already contains the type and length, but no value */
127 /* tree - the parent to which the new tree will */
128 /* be attached */
129 /* hfindex - the index of the item to be attached */
130 /* tvb - a pointer to the packet data */
131 /* start - offset within the packet */
132 /* length - length of this item */
133 /* return: */
134 /* pointer to a proto_tree (to then add value) */
135 /*************************************************************/
136 proto_tree *add_tlv_subtree_no_item(tlv_info_t *self, proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start)
138 header_field_info *hf;
139 proto_tree *tlv_tree;
140 proto_item *tlv_item;
141 gint tlv_value_length, tlv_val_offset;
142 guint8 size_of_tlv_length_field;
143 guint8 tlv_type;
145 /* Make sure we're dealing with a valid TLV here */
146 if (get_tlv_type(self) < 0)
147 return tree;
149 /* Retrieve the necessary TLV information */
150 tlv_val_offset = get_tlv_value_offset(self);
151 tlv_value_length = get_tlv_length(self);
152 size_of_tlv_length_field = get_tlv_size_of_length(self);
153 tlv_type = get_tlv_type(self);
155 hf = proto_registrar_get_nth(hfindex);
157 tlv_item = proto_tree_add_text(tree, tvb, start, tlv_value_length+tlv_val_offset, "%s", hf->name);
158 tlv_tree = proto_item_add_subtree(tlv_item, ett_tlv[tlv_type]);
160 proto_tree_add_uint(tlv_tree, hf_tlv_type, tvb, start, 1, tlv_type);
161 if (size_of_tlv_length_field > 0) /* It is */
163 /* display the length of the length field TLV */
164 proto_tree_add_uint(tlv_tree, hf_tlv_length_size, tvb, start+1, 1, size_of_tlv_length_field);
165 /* display the TLV length */
166 proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+2, size_of_tlv_length_field, tlv_value_length);
167 } else { /* It is not */
168 /* display the TLV length */
169 proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+1, 1, tlv_value_length);
172 /* Return a pointer to the tree level (to manually add item) */
173 return tlv_tree;
176 /*************************************************************/
177 /* add_protocol_subtree() */
178 /* Return a pointer to a proto_tree that already contains */
179 /* the type and length of a given TLV. */
180 /* tree - the parent to which the new tree will */
181 /* be attached */
182 /* hfindex - the index of the item to be attached */
183 /* tvb - a pointer to the packet data */
184 /* start - offset within the packet */
185 /* length - length of this item */
186 /* format - printf style formatting string */
187 /* ... - arguments to format */
188 /* return: */
189 /* pointer to a proto_tree */
190 /*************************************************************/
191 proto_tree *add_protocol_subtree(tlv_info_t *self, gint idx, proto_tree *tree, int hfindex, tvbuff_t *tvb, gint start, gint length _U_, const char *label)
193 /* Declare local variables */
194 proto_tree *tlv_tree;
195 proto_item *tlv_item;
196 gint tlv_value_length, tlv_val_offset;
197 guint8 size_of_tlv_length_field;
198 guint8 tlv_type;
199 guint32 tlv_value;
200 const gchar *hex_fmt;
202 /* Make sure we're dealing with a valid TLV here */
203 if (get_tlv_type(self) < 0)
204 return tree;
206 /* Retrieve the necessary TLV information */
207 tlv_val_offset = get_tlv_value_offset(self);
208 tlv_value_length = get_tlv_length(self);
209 size_of_tlv_length_field = get_tlv_size_of_length(self);
210 tlv_type = get_tlv_type(self);
212 /* display the TLV name and display the value in hex. Highlight type, length, and value. */
213 tlv_item = proto_tree_add_protocol_format(tree, hfindex, tvb, start, tlv_value_length+tlv_val_offset, "%s (%u byte(s))", label, tlv_value_length);
214 tlv_tree = proto_item_add_subtree(tlv_item, ett_tlv[tlv_type]);
216 proto_tree_add_uint(tlv_tree, hf_tlv_type, tvb, start, 1, tlv_type);
217 if (size_of_tlv_length_field > 0) /* It is */
219 /* display the length of the length field TLV */
220 proto_tree_add_uint(tlv_tree, hf_tlv_length_size, tvb, start+1, 1, size_of_tlv_length_field);
221 /* display the TLV length */
222 proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+2, size_of_tlv_length_field, tlv_value_length);
223 } else { /* It is not */
224 /* display the TLV length */
225 proto_tree_add_uint(tlv_tree, hf_tlv_length, tvb, start+1, 1, tlv_value_length);
228 /* display the TLV value and make it a subtree */
229 switch (tlv_value_length)
231 case 1:
232 tlv_value = tvb_get_guint8(tvb, start+tlv_val_offset);
233 hex_fmt = tlv_val_1byte;
234 break;
235 case 2:
236 tlv_value = tvb_get_ntohs(tvb, start+tlv_val_offset);
237 hex_fmt = tlv_val_2byte;
238 break;
239 case 3:
240 tlv_value = tvb_get_ntoh24(tvb, start+tlv_val_offset);
241 hex_fmt = tlv_val_3byte;
242 break;
243 case 4:
244 tlv_value = tvb_get_ntohl(tvb, start+tlv_val_offset);
245 hex_fmt = tlv_val_4byte;
246 break;
247 default:
248 tlv_value = tvb_get_ntohl(tvb, start+tlv_val_offset);
249 hex_fmt = tlv_val_5byte;
250 break;
252 /* Show "TLV value: " */
253 tlv_item = proto_tree_add_text(tlv_tree, tvb, start+tlv_val_offset, tlv_value_length, hex_fmt, label, tlv_value);
254 tlv_tree = proto_item_add_subtree(tlv_item, idx);
256 /* Return a pointer to the value level */
257 return tlv_tree;
262 /* WiMax protocol dissector */
263 static void dissect_wimax(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree _U_)
265 /* display the WiMax protocol name */
266 col_set_str(pinfo->cinfo, COL_PROTOCOL, "WiMax");
267 /* Clear out stuff in the info column */
268 col_clear(pinfo->cinfo, COL_INFO);
271 gboolean is_down_link(packet_info *pinfo)
273 if (pinfo->p2p_dir == P2P_DIR_RECV)
274 return TRUE;
275 if (pinfo->p2p_dir == P2P_DIR_UNKNOWN)
276 if(bs_address.len && !CMP_ADDRESS(&bs_address, &pinfo->src))
277 return TRUE;
278 return FALSE;
282 /* Register Wimax Protocol */
283 void proto_register_wimax(void)
285 int i;
286 module_t *wimax_module;
288 static hf_register_info hf[] = {
289 { &hf_tlv_type, { "TLV type", "wmx.tlv_type", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
290 { &hf_tlv_length, { "TLV length", "wmx.tlv_length", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
291 { &hf_tlv_length_size, { "Size of TLV length field", "wmx.tlv_length_size", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
294 gint *ett_reg[MAX_NUM_TLVS];
296 /* Register the WiMax protocols here */
297 proto_wimax = proto_register_protocol (
298 "WiMax Protocol", /* name */
299 "WiMax (wmx)", /* short name */
300 "wmx" /* abbrev */
303 proto_register_field_array(proto_wimax, hf, array_length(hf));
305 /* Register the ett TLV array to retrieve unique subtree identifiers */
306 for (i = 0; i < MAX_NUM_TLVS; i++)
308 ett_tlv[i] = -1;
309 ett_reg[i] = &ett_tlv[i];
312 proto_register_subtree_array(ett_reg, array_length(ett_reg));
314 /* Register the WiMax dissector */
315 register_dissector("wmx", dissect_wimax, proto_wimax);
317 wimax_module = prefs_register_protocol(proto_wimax, NULL);
319 prefs_register_uint_preference(wimax_module, "basic_cid_max",
320 "Maximum Basic CID",
321 "Set the maximum Basic CID"
322 " used in the Wimax decoder"
323 " (if other than the default of 320)."
324 " Note: The maximum Primary CID is"
325 " double the maximum Basic CID.",
326 10, &global_cid_max_basic);
328 prefs_register_bool_preference(wimax_module, "corrigendum_2_version",
329 "Corrigendum 2 Version",
330 "Set to TRUE to use the Corrigendum"
331 " 2 version of Wimax message decoding."
332 " Set to FALSE to use the 802.16e-2005"
333 " version.",
334 &include_cor2_changes);
335 prefs_register_obsolete_preference(wimax_module, "wimax.basic_cid_max");
336 prefs_register_obsolete_preference(wimax_module, "wimax.corrigendum_2_version");