2 * Routines for MMRP (MRP Multiple Mac Registration Protocol) dissection
3 * Copyright 2011, Johannes Jochen <johannes.jochen[AT]belden.com>
6 * Based on the code from packet-mrp-msrp.c (MSRP) from
7 * Torrey Atcitty <tatcitty[AT]harman.com> and Craig Gunther <craig.gunther[AT]harman.com>
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald[AT]wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 * The MMRP Protocol specification can be found at the following:
31 * http://standards.ieee.org/about/get/802/802.1.html
37 #include <epan/packet.h>
38 #include <epan/etypes.h>
40 void proto_register_mrp_mmrp(void);
41 void proto_reg_handoff_mrp_mmrp(void);
43 /* MMRP End Mark Sequence */
44 #define MMRP_END_MARK 0x0000
46 /**********************************************************/
47 /* Offsets of fields within an MMRP packet */
48 /**********************************************************/
49 #define MMRP_PROTOCOL_VERSION_OFFSET 0
51 /* Next comes the MMRP Message group */
52 #define MMRP_MESSAGE_GROUP_OFFSET (MMRP_PROTOCOL_VERSION_OFFSET + 1) /* Message is a group of fields */
53 #define MMRP_ATTRIBUTE_TYPE_OFFSET (MMRP_MESSAGE_GROUP_OFFSET)
54 #define MMRP_ATTRIBUTE_LENGTH_OFFSET (MMRP_ATTRIBUTE_TYPE_OFFSET + 1)
56 /* Next comes the MMRP AttributeList group */
57 #define MMRP_ATTRIBUTE_LIST_GROUP_OFFSET (MMRP_ATTRIBUTE_LENGTH_OFFSET + 1) /* AttributeList is a group of fields */
59 /* Next comes the MMRP VectorAttribute group */
60 #define MMRP_VECTOR_ATTRIBUTE_GROUP_OFFSET (MMRP_ATTRIBUTE_LIST_GROUP_OFFSET) /* VectorAttribute is a group of fields */
61 #define MMRP_VECTOR_HEADER_OFFSET (MMRP_VECTOR_ATTRIBUTE_GROUP_OFFSET) /* contains the following two fields */
62 #define MMRP_LEAVE_ALL_EVENT_OFFSET (MMRP_VECTOR_HEADER_OFFSET)
63 #define MMRP_LEAVE_ALL_EVENT_MASK 0xE000
64 #define MMRP_NUMBER_OF_VALUES_OFFSET (MMRP_VECTOR_HEADER_OFFSET)
65 #define MMRP_NUMBER_OF_VALUES_MASK 0x1fff
67 /* Next comes the MMRP FirstValue group */
68 #define MMRP_FIRST_VALUE_GROUP_OFFSET (MMRP_VECTOR_HEADER_OFFSET + 2) /* FirstValue is a group of fields */
70 #define MMRP_SERVICE_THREE_PACKED_OFFSET (MMRP_FIRST_VALUE_GROUP_OFFSET + 1)
71 #define MMRP_MAC_THREE_PACKED_OFFSET (MMRP_FIRST_VALUE_GROUP_OFFSET + 6)
73 /**********************************************************/
74 /* Valid field contents */
75 /**********************************************************/
77 /* Attribute Type definitions */
78 #define MMRP_ATTRIBUTE_TYPE_SERVICE 0x01
79 #define MMRP_ATTRIBUTE_TYPE_MAC 0x02
80 static const value_string attribute_type_vals[] = {
81 { MMRP_ATTRIBUTE_TYPE_SERVICE, "Service Requirement" },
82 { MMRP_ATTRIBUTE_TYPE_MAC, "MAC" },
86 /* Leave All Event definitions */
87 #define MMRP_NULLLEAVEALL 0
88 #define MMRP_LEAVEALL 1
89 static const value_string leave_all_vals[] = {
90 { MMRP_NULLLEAVEALL, "Null" },
91 { MMRP_LEAVEALL, "Leave All" },
95 /* Three Packed Event definitions */
96 static const value_string three_packed_vals[] = {
106 /**********************************************************/
107 /* Initialize the protocol and registered fields */
108 /**********************************************************/
109 static int proto_mmrp = -1;
110 static int hf_mmrp_proto_id = -1;
111 static int hf_mmrp_message = -1; /* Message is a group of fields */
112 static int hf_mmrp_attribute_type = -1;
113 static int hf_mmrp_attribute_length = -1;
114 static int hf_mmrp_attribute_list = -1; /* AttributeList is a group of fields */
115 static int hf_mmrp_vector_attribute = -1; /* VectorAttribute is a group of fields */
117 /* The following VectorHeader contains the LeaveAllEvent and NumberOfValues */
118 static int hf_mmrp_vector_header = -1;
119 static int hf_mmrp_leave_all_event = -1;
120 static int hf_mmrp_number_of_values = -1;
121 static gint ett_vector_header = -1;
122 static const int *vector_header_fields[] = {
123 &hf_mmrp_leave_all_event,
124 &hf_mmrp_number_of_values,
128 static int hf_mmrp_first_value = -1; /* FirstValue is a group of fields */
130 static int hf_mmrp_three_packed_event = -1;
132 static int hf_mmrp_end_mark = -1;
134 /* Initialize the subtree pointers */
135 static gint ett_mmrp = -1;
136 static gint ett_msg = -1;
137 static gint ett_attr_list = -1;
138 static gint ett_vect_attr = -1;
139 static gint ett_first_value = -1;
143 /**********************************************************/
144 /* Dissector starts here */
145 /**********************************************************/
147 /* dissect_mmrp_common1 (called from dissect_mmrp)
149 * dissect the following fields which are common to all MMRP attributes:
152 * Attribute List Length
155 dissect_mmrp_common1(proto_tree *msg_tree, tvbuff_t *tvb, int msg_offset)
157 proto_tree_add_item(msg_tree, hf_mmrp_attribute_type, tvb,
158 MMRP_ATTRIBUTE_TYPE_OFFSET + msg_offset, 1, ENC_BIG_ENDIAN);
159 proto_tree_add_item(msg_tree, hf_mmrp_attribute_length, tvb,
160 MMRP_ATTRIBUTE_LENGTH_OFFSET + msg_offset, 1, ENC_BIG_ENDIAN);
164 /* dissect_mmrp_common2 (called from dissect_mmrp)
166 * dissect the following fields which are common to all MMRP attributes:
168 * Number of Values fields
171 dissect_mmrp_common2(proto_tree *vect_attr_tree, tvbuff_t *tvb, int msg_offset)
173 proto_tree_add_bitmask(vect_attr_tree, tvb, MMRP_VECTOR_HEADER_OFFSET + msg_offset,
174 hf_mmrp_vector_header, ett_vector_header, vector_header_fields, ENC_BIG_ENDIAN);
177 /* dissect_mmrp_three_packed_event (called from dissect_mmrp)
179 * dissect one or more ThreePackedEvents
182 dissect_mmrp_three_packed_event(proto_tree *vect_attr_tree, tvbuff_t *tvb, guint offset, guint16 number_of_values)
186 for ( counter = 0; counter < number_of_values; ) {
188 guint8 three_packed_event[3];
190 value = tvb_get_guint8(tvb, offset);
191 three_packed_event[0] = value / 36;
192 value -= 36 * three_packed_event[0];
193 three_packed_event[1] = value / 6;
194 value -= 6 * three_packed_event[1];
195 three_packed_event[2] = value;
197 proto_tree_add_uint(vect_attr_tree, hf_mmrp_three_packed_event, tvb, offset, sizeof(guint8),
198 three_packed_event[0]);
200 if ( counter < number_of_values ) {
201 proto_tree_add_uint(vect_attr_tree, hf_mmrp_three_packed_event, tvb, offset, sizeof(guint8),
202 three_packed_event[1]);
205 if ( counter < number_of_values ) {
206 proto_tree_add_uint(vect_attr_tree, hf_mmrp_three_packed_event, tvb, offset, sizeof(guint8),
207 three_packed_event[2]);
218 * main dissect function that calls the other functions listed above as necessary
221 dissect_mmrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
223 /* Set up structures needed to add the protocol subtrees and manage them */
224 proto_item *ti, *msg_ti, *attr_list_ti, *vect_attr_ti;
225 proto_tree *mmrp_tree, *msg_tree, *attr_list_tree, *vect_attr_tree;
227 /* Make entries in Protocol column and Info column on summary display */
228 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MRP-MMRP");
230 col_set_str(pinfo->cinfo, COL_INFO, "Multiple Mac Registration Protocol");
233 guint8 attribute_type;
234 guint8 attribute_length;
235 guint16 number_of_values;
238 int msg_offset; /* Use when handling multiple messages. This points to current msg being decoded. */
239 int vect_offset; /* Use when handling multiple vector attributes. This points to the current vector attribute being decoded. */
241 ti = proto_tree_add_item(tree, proto_mmrp, tvb, 0, -1, ENC_NA);
242 mmrp_tree = proto_item_add_subtree(ti, ett_mmrp);
244 proto_tree_add_item(mmrp_tree, hf_mmrp_proto_id, tvb, MMRP_PROTOCOL_VERSION_OFFSET, 1, ENC_BIG_ENDIAN);
246 /* MMRP supports multiple MRP Messages per frame. Handle those Messages in
247 * the following while() loop. You will know you are at the end of the list
248 * of messages when the EndMark (0x0000) is encountered instead of an
249 * Attribute Type and Attribute Length (guaranteed to not be 0x0000).
252 while (tvb_get_ntohs(tvb, MMRP_ATTRIBUTE_TYPE_OFFSET + msg_offset) != MMRP_END_MARK) {
254 attribute_type = tvb_get_guint8(tvb, MMRP_ATTRIBUTE_TYPE_OFFSET + msg_offset);
255 attribute_length = tvb_get_guint8(tvb, MMRP_ATTRIBUTE_LENGTH_OFFSET + msg_offset);
257 /* MMRP Message is a group of fields
259 * Contains AttributeType (1 byte)
260 * + AttributeLength (1 byte)
261 * + AttributeList (AttributeListLength bytes)
264 msg_ti = proto_tree_add_item(mmrp_tree, hf_mmrp_message, tvb,
265 MMRP_MESSAGE_GROUP_OFFSET + msg_offset,
267 msg_tree = proto_item_add_subtree(msg_ti, ett_msg);
269 /* Append AttributeType description to the end of the "Message" heading */
270 proto_item_append_text(msg_tree, ": %s (%d)",
271 val_to_str_const(attribute_type, attribute_type_vals, "<Unknown>"),
274 dissect_mmrp_common1(msg_tree, tvb, msg_offset);
276 /* MMRP AttributeList is a group of fields
278 * Contains AttributeListLength bytes of data NOT
280 attr_list_ti = proto_tree_add_item(msg_tree, hf_mmrp_attribute_list, tvb,
281 MMRP_ATTRIBUTE_LIST_GROUP_OFFSET + msg_offset,
283 attr_list_tree = proto_item_add_subtree(attr_list_ti, ett_attr_list);
286 /* MMRP supports multiple MRP Vector Attributes per Attribute List. Handle those
287 * Vector Attributes in the following while() loop. You will know you are at the
288 * end of the list of Vector Attributes when the EndMark (0x0000) is encountered
289 * instead of a Vector Header (guaranteed to not be 0x0000).
292 while (tvb_get_ntohs(tvb, MMRP_VECTOR_HEADER_OFFSET + msg_offset + vect_offset) != MMRP_END_MARK) {
293 /* MMRP VectorAttribute is a group of fields
295 * Contains VectorHeader (2 bytes)
296 * + FirstValue (AttributeLength bytes)
297 * + VectorThreePacked (NumberOfValues @ 3/vector bytes)
298 * + VectorFourPacked (NumberOfValues @ 4/vector bytes only for Listener attributes)
301 number_of_values = tvb_get_ntohs(tvb, MMRP_NUMBER_OF_VALUES_OFFSET + msg_offset + vect_offset)
302 & MMRP_NUMBER_OF_VALUES_MASK;
304 vect_attr_len = 2 + attribute_length + (number_of_values + 2)/3; /* stores 3 values per byte */
306 vect_attr_ti = proto_tree_add_item(attr_list_tree, hf_mmrp_vector_attribute, tvb,
307 MMRP_VECTOR_ATTRIBUTE_GROUP_OFFSET + msg_offset + vect_offset,
308 vect_attr_len, ENC_NA);
310 vect_attr_tree = proto_item_add_subtree(vect_attr_ti, ett_vect_attr);
312 dissect_mmrp_common2(vect_attr_tree, tvb, msg_offset + vect_offset);
314 if (attribute_type == MMRP_ATTRIBUTE_TYPE_MAC) {
315 /* MMRP FirstValue is a Mac Adress*/
316 proto_tree_add_item(vect_attr_tree, hf_mmrp_first_value, tvb,
317 MMRP_FIRST_VALUE_GROUP_OFFSET + msg_offset + vect_offset,
318 attribute_length, ENC_NA);
319 /* Decode three packed events. */
320 offset = dissect_mmrp_three_packed_event(vect_attr_tree, tvb,
321 MMRP_MAC_THREE_PACKED_OFFSET + msg_offset + vect_offset,
325 else if (attribute_type == MMRP_ATTRIBUTE_TYPE_SERVICE) {
326 /* MMRP Service Requierment*/
327 proto_tree_add_item(vect_attr_tree, hf_mmrp_first_value, tvb,
328 MMRP_FIRST_VALUE_GROUP_OFFSET + msg_offset + vect_offset,
329 attribute_length, ENC_NA);
330 offset = dissect_mmrp_three_packed_event(vect_attr_tree, tvb,
331 MMRP_MAC_THREE_PACKED_OFFSET + msg_offset + vect_offset,
336 vect_offset += vect_attr_len; /* Move to next Vector Attribute, if there is one */
337 } /* Multiple VectorAttribute while() */
339 proto_tree_add_item(attr_list_tree, hf_mmrp_end_mark, tvb, offset, 2, ENC_NA); /* VectorAttribute EndMark */
341 proto_item_set_len(attr_list_ti, vect_offset); /*without an endmark*/
342 msg_offset += vect_offset + 2; /* + endmark; Move to next Message, if there is one */
343 proto_item_set_len(msg_ti, vect_offset + 2); /*length of message*/
345 } /* Multiple Message while() */
347 proto_tree_add_item(mmrp_tree, hf_mmrp_end_mark, tvb, offset+2, 2, ENC_NA); /* Message EndMark */
352 /* Register the protocol with Wireshark */
354 proto_register_mrp_mmrp(void)
356 static hf_register_info hf[] = {
358 { "Protocol Version", "mrp-mmrp.protocol_version",
359 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
361 { &hf_mmrp_message, /* Message is a group of fields */
362 { "Message", "mrp-mmrp.message",
363 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
365 { &hf_mmrp_attribute_type,
366 { "Attribute Type", "mrp-mmrp.attribute_type",
367 FT_UINT8, BASE_DEC, VALS(attribute_type_vals), 0x0, NULL, HFILL }
369 { &hf_mmrp_attribute_length,
370 { "Attribute Length", "mrp-mmrp.attribute_length",
371 FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
373 { &hf_mmrp_attribute_list, /* AttributeList is a group of fields */
374 { "Attribute List", "mrp-mmrp.attribute_list",
375 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
377 { &hf_mmrp_vector_attribute, /* VectorAttribute is a group of fields */
378 { "Vector Attribute", "mrp-mmrp.vector_attribute",
379 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
381 { &hf_mmrp_vector_header,
382 { "Vector Header", "mrp-mmrp.vector_header",
383 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
385 { &hf_mmrp_leave_all_event,
386 { "Leave All Event", "mrp-mmrp.leave_all_event",
387 FT_UINT16, BASE_DEC, VALS(leave_all_vals), MMRP_LEAVE_ALL_EVENT_MASK, NULL, HFILL }
389 { &hf_mmrp_number_of_values,
390 { "Number of Values", "mrp-mmrp.number_of_values",
391 FT_UINT16, BASE_DEC, NULL, MMRP_NUMBER_OF_VALUES_MASK, NULL, HFILL }
393 { &hf_mmrp_first_value, /* FirstValue is a group of fields */
394 { "First Value", "mrp-mmrp.first_value",
395 FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }
397 { &hf_mmrp_three_packed_event,
398 { "Attribute Event", "mrp-msrp.three_packed_event",
399 FT_UINT8, BASE_DEC, VALS(three_packed_vals), 0x0, NULL, HFILL }
402 { "End Mark", "mrp-mmrp.end_mark",
403 FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
407 /* Setup protocol subtree array */
408 static gint *ett[] = {
417 /* Register the protocol name and description */
418 proto_mmrp = proto_register_protocol("Multiple Mac Registration Protocol",
419 "MRP-MMRP", "mrp-mmrp");
421 /* Required function calls to register the header fields and subtrees used */
422 proto_register_field_array(proto_mmrp, hf, array_length(hf));
423 proto_register_subtree_array(ett, array_length(ett));
427 proto_reg_handoff_mrp_mmrp(void)
429 dissector_handle_t mmrp_handle;
431 mmrp_handle = create_dissector_handle(dissect_mmrp, proto_mmrp);
432 dissector_add_uint("ethertype", ETHERTYPE_MMRP, mmrp_handle);