HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-mim.c
blob1503e1254a51574da69bcfd3aeb1e22eb41a796c
1 /* packet-mim.c
2 * Routines for analyzing Cisco FabricPath MiM packets
3 * Copyright 2011, Leonard Tracy <letracy@cisco.com>
5 * $Id$
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA.
30 #include "config.h"
32 #include <glib.h>
33 #include <epan/packet.h>
34 #include <epan/etypes.h>
35 #include <epan/addr_resolv.h>
36 #include <epan/prefs.h>
38 static int proto_fp = -1 ;
39 static gint ett_mim = -1 ;
40 static gint ett_hmac = -1 ;
42 /* Main protocol items */
43 static int hf_s_hmac = -1;
44 static int hf_d_hmac = -1;
45 static int hf_d_hmac_mc = -1;
46 static int hf_ftag = -1;
47 static int hf_ttl = -1;
51 /* HMAC subtrees */
52 static int hf_swid = -1 ;
53 static int hf_sswid = -1;
54 static int hf_eid = -1;
55 static int hf_lid = -1;
56 static int hf_ul = -1;
57 static int hf_ig = -1;
58 static int hf_ooodl = -1;
60 /* Ethernet heuristic dissectors (such as this one) get called for
61 * every Ethernet frame Wireshark handles. In order to not impose that
62 * performance penalty on everyone this dissector disables itself by
63 * default.
65 * This is done separately from the disabled protocols list mainly so
66 * we can disable it by default. XXX Maybe there's a better way.
68 static gboolean mim_enable_dissector = FALSE;
70 static const true_false_string ig_tfs = {
71 "Group address (multicast/broadcast)",
72 "Individual address (unicast)"
74 static const true_false_string ul_tfs = {
75 "Locally administered address (this is NOT the factory default)",
76 "Globally unique address (factory default)"
78 static const true_false_string ooodl_tfs = {
79 "Out of order delivery (If DA) or Do not learn (If SA)",
80 "Deliver in order (If DA) or Learn (If SA)"
83 static dissector_handle_t eth_dissector ;
86 #define FP_PROTO_COL_NAME "FabricPath"
87 #define FP_PROTO_COL_INFO "Cisco FabricPath MiM Encapsulated Frame"
89 #define FP_FIELD_LEN 3
91 #define FP_EID_MASK 0x00FCC0
92 #define FP_3B_EID_MASK 0xFCC000
94 #define FP_UL_MASK 0x020000
95 #define FP_IG_MASK 0x010000
96 #define FP_EID2_MASK 0x00C000
97 #define FP_RES_MASK 0x002000
98 #define FP_OOO_MASK 0x001000
99 #define FP_SWID_MASK 0x000FFF
101 #define FP_BF_LEN 3
102 #define FP_LID_LEN 2
103 #define FP_SSWID_LEN 1
104 #define FP_FTAG_LEN 2
106 #define FP_FTAG_MASK 0xFFC0
107 #define FP_TTL_MASK 0x003F
109 #define FP_HMAC_IG_MASK G_GINT64_CONSTANT(0x010000000000)
110 #define FP_HMAC_SWID_MASK G_GINT64_CONSTANT(0x000FFF000000)
111 #define FP_HMAC_SSWID_MASK G_GINT64_CONSTANT(0x000000FF0000)
112 #define FP_HMAC_LID_MASK G_GINT64_CONSTANT(0x00000000FFFF)
115 #define FP_HMAC_LEN 6
116 #define FP_HEADER_SIZE (16)
119 static int dissect_fp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ );
120 void proto_reg_handoff_fabricpath(void);
123 static gboolean
124 dissect_fp_heur (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
127 guint16 type = 0;
130 * Is ethertype ETHERTYPE_DCE
133 type = tvb_get_ntohs (tvb, 12);
135 if (type == ETHERTYPE_DCE) {
136 dissect_fp (tvb, pinfo, tree, NULL);
137 return TRUE;
138 } else {
139 return FALSE;
143 static gboolean
144 fp_is_ig_set (guint64 hmac)
146 if (hmac & FP_HMAC_IG_MASK) {
147 return TRUE;
148 } else {
149 return FALSE;
153 static void
154 fp_get_hmac_addr (guint64 hmac, guint16 *swid, guint16 *sswid, guint16 *lid) {
156 if (!swid || !sswid || !lid) {
157 return;
160 *swid = (guint16) ((hmac & FP_HMAC_SWID_MASK) >> 24);
161 *sswid = (guint16) ((hmac & FP_HMAC_SSWID_MASK) >> 16);
162 *lid = (guint16) (hmac & FP_HMAC_LID_MASK);
165 static void
166 fp_add_hmac (tvbuff_t *tvb, proto_tree *tree, int offset) {
168 guint16 eid;
170 if (!tree) {
171 return;
174 eid = tvb_get_ntohs(tvb, offset);
176 eid &= FP_EID_MASK;
177 eid = ((eid & 0x00C0) >> 6) + ((eid & 0xFC00) >> 8);
178 proto_tree_add_uint(tree, hf_eid, tvb, offset, FP_BF_LEN, eid);
180 proto_tree_add_item (tree, hf_ul, tvb, offset, FP_BF_LEN, ENC_NA);
181 proto_tree_add_item (tree, hf_ig, tvb, offset, FP_BF_LEN, ENC_NA);
182 proto_tree_add_item (tree, hf_ooodl, tvb, offset, FP_BF_LEN, ENC_NA);
183 proto_tree_add_item (tree, hf_swid, tvb, offset, FP_BF_LEN, ENC_BIG_ENDIAN);
184 offset += FP_BF_LEN;
186 proto_tree_add_item (tree, hf_sswid, tvb, offset, FP_SSWID_LEN, ENC_BIG_ENDIAN);
187 offset += FP_SSWID_LEN;
189 proto_tree_add_item (tree, hf_lid, tvb, offset, FP_LID_LEN, ENC_BIG_ENDIAN);
190 /*offset += FP_LID_LEN;*/
193 /* FabricPath MiM Dissector */
194 static int
195 dissect_fp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ )
197 proto_item *ti ;
198 proto_tree *fp_tree ;
199 proto_tree *fp_addr_tree ;
200 tvbuff_t *next_tvb ;
201 int offset = 0 ;
202 guint64 hmac_src;
203 guint64 hmac_dst;
204 guint16 sswid = 0;
205 guint16 ssswid = 0;
206 guint16 slid = 0;
207 guint16 dswid = 0;
208 guint16 dsswid = 0;
209 guint16 dlid = 0;
210 const guint8 *dst_addr = NULL;
211 gboolean dest_ig = FALSE;
213 col_set_str( pinfo->cinfo, COL_PROTOCOL, FP_PROTO_COL_NAME ) ;
214 col_set_str( pinfo->cinfo, COL_INFO, FP_PROTO_COL_INFO ) ;
216 if (tree) {
218 hmac_dst = tvb_get_ntoh48 (tvb, 0);
219 hmac_src = tvb_get_ntoh48 (tvb, 6);
221 dest_ig = fp_is_ig_set(hmac_dst);
222 if (!dest_ig) {
223 fp_get_hmac_addr (hmac_dst, &dswid, &dsswid, &dlid);
224 } else {
225 hmac_dst = GUINT64_TO_BE (hmac_dst);
226 /* Get pointer to most sig byte of destination address
227 in network order
229 dst_addr = ((const guint8 *) &hmac_dst) + 2;
234 fp_get_hmac_addr (hmac_src, &sswid, &ssswid, &slid);
236 if (PTREE_DATA(tree)->visible) {
237 if (dest_ig) {
239 ti = proto_tree_add_protocol_format(tree, proto_fp, tvb, 0, FP_HEADER_SIZE,
240 "Cisco FabricPath, Src: %03x.%02x.%04x, Dst: %s (%s)",
241 sswid, ssswid, slid,
242 get_ether_name(dst_addr), ether_to_str(dst_addr));
243 } else {
244 ti = proto_tree_add_protocol_format(tree, proto_fp, tvb, 0, FP_HEADER_SIZE,
245 "Cisco FabricPath, Src: %03x.%02x.%04x, Dst: %03x.%02x.%04x",
246 sswid, ssswid, slid,
247 dswid, dsswid, dlid);
249 } else {
250 ti = proto_tree_add_item( tree, proto_fp, tvb, 0, -1, ENC_NA ) ;
252 fp_tree = proto_item_add_subtree( ti, ett_mim ) ;
254 offset = 0;
255 /* Add dest and source heir. mac */
256 if (dest_ig) {
257 /* MCAST address */
258 proto_tree_add_ether( fp_tree, hf_d_hmac_mc, tvb, offset, 6,
259 dst_addr);
260 } else {
261 /* Unicast */
262 ti = proto_tree_add_none_format (fp_tree, hf_d_hmac, tvb, offset, 6, "Destination: %03x.%02x.%04x", dswid, dsswid, dlid);
263 fp_addr_tree = proto_item_add_subtree (ti, ett_hmac);
264 fp_add_hmac (tvb, fp_addr_tree, offset);
267 offset += FP_HMAC_LEN;
268 ti = proto_tree_add_none_format (fp_tree, hf_s_hmac, tvb, offset, 6,
269 "Source: %03x.%02x.%04x", sswid, ssswid, slid);
270 fp_addr_tree = proto_item_add_subtree (ti, ett_hmac);
271 fp_add_hmac (tvb, fp_addr_tree, offset);
273 offset += FP_HMAC_LEN;
274 /* Skip ethertype */
275 offset += 2;
277 proto_tree_add_item (fp_tree, hf_ftag, tvb, offset, FP_FTAG_LEN, ENC_BIG_ENDIAN);
279 proto_tree_add_item (fp_tree, hf_ttl, tvb, offset, FP_FTAG_LEN, ENC_BIG_ENDIAN);
282 /* call the eth dissector */
283 next_tvb = tvb_new_subset_remaining( tvb, FP_HEADER_SIZE) ;
284 call_dissector( eth_dissector, next_tvb, pinfo, tree ) ;
286 return tvb_length( tvb ) ;
289 /* Register the protocol with Wireshark */
290 void
291 proto_register_mim(void)
293 static hf_register_info hf[] = {
294 { &hf_s_hmac,
295 { "Source HMAC", "cfp.s_hmac",
296 FT_NONE, BASE_NONE, NULL,
297 0, "Source Hierarchical MAC", HFILL }},
299 { &hf_d_hmac,
300 { "Destination HMAC", "cfp.d_hmac",
301 FT_NONE, BASE_NONE, NULL,
302 0, "Destination Hierarchical MAC", HFILL }},
304 { &hf_d_hmac_mc,
305 { "MC Destination", "cfp.d_hmac",
306 FT_ETHER, BASE_NONE, NULL,
307 0, "Multicast Destination Address", HFILL }},
309 { &hf_ftag,
310 { "FTAG", "cfp.ftag",
311 FT_UINT16, BASE_DEC, NULL, FP_FTAG_MASK,
312 "FTAG field identifying forwarding distribution tree.", HFILL }},
314 { &hf_ttl,
315 { "TTL", "cfp.ttl",
316 FT_UINT16, BASE_DEC, NULL, FP_TTL_MASK,
317 "The remaining hop count for this frame", HFILL }},
319 &hf_swid,
320 { "switch-id", "cfp.swid",
321 FT_UINT24, BASE_DEC_HEX, NULL, FP_SWID_MASK,
322 "Switch-id/nickname of switch in FabricPath network", HFILL }},
324 &hf_sswid,
325 { "sub-switch-id", "cfp.sswid",
326 FT_UINT8, BASE_DEC_HEX, NULL, 0x0,
327 "Sub-switch-id of switch in FabricPath network", HFILL }},
329 &hf_eid,
330 { "End Node ID", "cfp.eid",
331 FT_UINT24, BASE_DEC_HEX, NULL, FP_3B_EID_MASK,
332 "Cisco FabricPath End node ID", HFILL }},
334 &hf_lid,
335 { "Source LID", "cfp.lid",
336 FT_UINT16, BASE_DEC_HEX, NULL, 0x0,
337 "Source or Destination Port index on switch in FabricPath network", HFILL }},
339 &hf_ul,
340 { "U/L bit", "cfp.ul",
341 FT_BOOLEAN, 24, TFS(&ul_tfs), FP_UL_MASK,
342 "Specifies if this is a locally administered or globally unique (IEEE assigned) address", HFILL }},
344 &hf_ig,
345 { "I/G bit", "cfp.ig",
346 FT_BOOLEAN, 24 /* FP_BF_LEN */, TFS(&ig_tfs), FP_IG_MASK,
347 "Specifies if this is an individual (unicast) or group (broadcast/multicast) address", HFILL }},
349 &hf_ooodl,
350 { "OOO/DL Bit", "cfp.ooodl",
351 FT_BOOLEAN, 24 /* FP_BF_LEN */, TFS(&ooodl_tfs), FP_OOO_MASK,
352 "Specifies Out of Order Delivery OK in destination address and Do Not Learn when set in source address", HFILL }}
356 static gint *ett[] = {
357 &ett_mim,
358 &ett_hmac
361 module_t *mim_module;
363 proto_fp = proto_register_protocol("Cisco FabricPath", "CFP", "cfp");
365 mim_module = prefs_register_protocol (proto_fp, proto_reg_handoff_fabricpath);
367 prefs_register_bool_preference (mim_module, "enable", "Enable dissector",
368 "Enable this dissector (default is false)",
369 &mim_enable_dissector);
371 proto_register_field_array(proto_fp, hf, array_length(hf));
372 proto_register_subtree_array(ett, array_length(ett));
375 void
376 proto_reg_handoff_fabricpath(void)
379 dissector_handle_t fp_handle;
380 fp_handle = new_create_dissector_handle(dissect_fp, proto_fp);
381 dissector_add_uint("ethertype", ETHERTYPE_DCE, fp_handle);
383 static gboolean prefs_initialized = FALSE;
385 if (!prefs_initialized) {
387 * Using Heuristic dissector (As opposed to
388 * registering the ethertype) in order to
389 * get outer source and destination MAC
390 * before the standard ethernet dissector
392 heur_dissector_add ("eth", dissect_fp_heur, proto_fp);
393 eth_dissector = find_dissector( "eth" );
394 prefs_initialized = TRUE;
397 proto_set_decoding(proto_fp, mim_enable_dissector);