2 * Routines for GMRP (GARP Multicast Registration Protocol) dissection
3 * Copyright 2001, Markus Seehofer <mseehofe@nt.hirschmann.de>
5 * Based on the code from packet-gvrp.c (GVRP) from
6 * Kevin Shi <techishi@ms22.hinet.net> Copyright 2000
10 * Wireshark - Network traffic analyzer
11 * By Gerald Combs <gerald@wireshark.org>
12 * Copyright 1998 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.
33 #include <epan/packet.h>
34 #include <epan/llcsaps.h>
36 /* Initialize the protocol and registered fields */
37 static int proto_gmrp
= -1;
38 static int hf_gmrp_proto_id
= -1;
39 static int hf_gmrp_attribute_type
= -1;
40 static int hf_gmrp_attribute_length
= -1;
41 static int hf_gmrp_attribute_event
= -1;
42 static int hf_gmrp_attribute_value_group_membership
= -1;
43 static int hf_gmrp_attribute_value_service_requirement
= -1;
44 /*static int hf_gmrp_end_of_mark = -1;*/
46 /* Initialize the subtree pointers */
47 static gint ett_gmrp
= -1;
48 /*static gint ett_gmrp_message = -1;
49 static gint ett_gmrp_attribute_list = -1;
50 static gint ett_gmrp_attribute = -1;*/
52 static dissector_handle_t data_handle
;
54 /* Constant definitions */
55 #define GARP_DEFAULT_PROTOCOL_ID 0x0001
56 #define GARP_END_OF_MARK 0x00
58 #define GMRP_ATTRIBUTE_TYPE_GROUP_MEMBERSHIP 0x01
59 #define GMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT 0x02
61 #define GMRP_SERVICE_REQUIREMENT_FORWARD_ALL 0x00
62 #define GMRP_SERVICE_REQUIREMENT_FORWARD_ALL_UNREGISTERED 0x01
64 static const value_string attribute_type_vals
[] = {
65 { GMRP_ATTRIBUTE_TYPE_GROUP_MEMBERSHIP
,"Group Membership" },
66 { GMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT
,"Service Requirement" },
70 /* The length of GMRP LeaveAll attribute should be 2 octets (one for length
71 * and the other for event) */
72 #define GMRP_LENGTH_LEAVEALL (int)(sizeof(guint8)+sizeof(guint8))
74 /* The length of GMRP attribute other than LeaveAll should be:
76 * 8 bytes for Group Membership (1 for length, 1 for event and 6 for mac address to register)
78 * 3 bytes for Service Requirement (1 for length, 1 for event, 1 for attribute value)
81 #define GMRP_GROUP_MEMBERSHIP_NON_LEAVEALL (int)(sizeof(guint8)+sizeof(guint8)+(6*sizeof(guint8)))
82 #define GMRP_SERVICE_REQUIREMENT_NON_LEAVEALL (int)(sizeof(guint8)+sizeof(guint8)+sizeof(guint8))
84 /* Packet offset definitions */
85 #define GARP_PROTOCOL_ID 0
87 /* Event definitions */
88 #define GMRP_EVENT_LEAVEALL 0
89 #define GMRP_EVENT_JOINEMPTY 1
90 #define GMRP_EVENT_JOININ 2
91 #define GMRP_EVENT_LEAVEEMPTY 3
92 #define GMRP_EVENT_LEAVEIN 4
93 #define GMRP_EVENT_EMPTY 5
95 static const value_string event_vals
[] = {
96 { GMRP_EVENT_LEAVEALL
, "Leave All" },
97 { GMRP_EVENT_JOINEMPTY
, "Join Empty" },
98 { GMRP_EVENT_JOININ
, "Join In" },
99 { GMRP_EVENT_LEAVEEMPTY
, "Leave Empty" },
100 { GMRP_EVENT_LEAVEIN
, "Leave In" },
101 { GMRP_EVENT_EMPTY
, "Empty" },
106 /* Code to actually dissect the packets */
108 dissect_gmrp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
111 proto_tree
*gmrp_tree
;
114 guint8 attribute_type
;
115 int msg_index
, attr_index
, offset
= 0, length
= tvb_reported_length(tvb
);
117 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "GMRP");
119 col_set_str(pinfo
->cinfo
, COL_INFO
, "GMRP");
123 ti
= proto_tree_add_item(tree
, proto_gmrp
, tvb
, 0, -1, ENC_NA
);
125 gmrp_tree
= proto_item_add_subtree(ti
, ett_gmrp
);
127 /* Read in GARP protocol ID */
128 protocol_id
= tvb_get_ntohs(tvb
, GARP_PROTOCOL_ID
);
130 proto_tree_add_uint_format(gmrp_tree
, hf_gmrp_proto_id
, tvb
,
131 GARP_PROTOCOL_ID
, (int)sizeof(guint16
),
133 "Protocol Identifier: 0x%04x (%s)",
135 protocol_id
== GARP_DEFAULT_PROTOCOL_ID
?
136 "GARP Multicast Registration Protocol" :
139 /* Currently only one protocol ID is supported */
140 if (protocol_id
!= GARP_DEFAULT_PROTOCOL_ID
)
142 proto_tree_add_text(gmrp_tree
, tvb
, GARP_PROTOCOL_ID
, (int)sizeof(guint16
),
143 " (Warning: this version of Wireshark only knows about protocol id = 1)");
144 call_dissector(data_handle
,
145 tvb_new_subset_remaining(tvb
, GARP_PROTOCOL_ID
+ (int)sizeof(guint16
)),
150 offset
+= (int)sizeof(guint16
);
151 length
-= (int)sizeof(guint16
);
155 /* Begin to parse GARP messages */
158 proto_item
*msg_item
;
159 int msg_start
= offset
;
161 /* Read in attribute type. */
162 attribute_type
= octet
= tvb_get_guint8(tvb
, offset
);
164 /* Check for end of mark */
165 if (octet
== GARP_END_OF_MARK
)
167 /* End of GARP PDU */
170 proto_tree_add_text(gmrp_tree
, tvb
, offset
, (int)sizeof(guint8
),
176 call_dissector(data_handle
,
177 tvb_new_subset_remaining(tvb
, offset
),
183 offset
+= (int)sizeof(guint8
);
184 length
-= (int)sizeof(guint8
);
186 msg_item
= proto_tree_add_text(gmrp_tree
, tvb
, msg_start
, -1,
187 "Message %d", msg_index
+ 1);
189 proto_tree_add_uint(gmrp_tree
, hf_gmrp_attribute_type
, tvb
,
190 msg_start
, (int)sizeof(guint8
), octet
);
192 /* GMRP supports Group Membership and Service Requirement as attribute types */
193 if ( (octet
!= GMRP_ATTRIBUTE_TYPE_GROUP_MEMBERSHIP
) && (octet
!= GMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT
) )
195 call_dissector(data_handle
,
196 tvb_new_subset_remaining(tvb
, offset
), pinfo
,
205 int attr_start
= offset
;
206 proto_item
*attr_item
;
208 /* Read in attribute length. */
209 octet
= tvb_get_guint8(tvb
, offset
);
211 /* Check for end of mark */
212 if (octet
== GARP_END_OF_MARK
)
214 /* If at least one message has been already read,
215 * check for another end of mark.
219 proto_tree_add_text(gmrp_tree
, tvb
, offset
,
220 (int)sizeof(guint8
), " End of mark");
222 offset
+= (int)sizeof(guint8
);
223 length
-= (int)sizeof(guint8
);
225 proto_item_set_len(msg_item
, offset
- msg_start
);
230 call_dissector(data_handle
,
231 tvb_new_subset_remaining(tvb
, offset
),
240 offset
+= (int)sizeof(guint8
);
241 length
-= (int)sizeof(guint8
);
243 attr_item
= proto_tree_add_text(gmrp_tree
, tvb
,
244 attr_start
, -1, " Attribute %d", attr_index
+ 1);
246 proto_tree_add_uint(gmrp_tree
, hf_gmrp_attribute_length
,
247 tvb
, attr_start
, (int)sizeof(guint8
), octet
);
249 /* Read in attribute event */
250 event
= tvb_get_guint8(tvb
, offset
);
252 proto_tree_add_uint(gmrp_tree
, hf_gmrp_attribute_event
,
253 tvb
, offset
, (int)sizeof(guint8
), event
);
255 offset
+= (int)sizeof(guint8
);
256 length
-= (int)sizeof(guint8
);
260 case GMRP_EVENT_LEAVEALL
:
261 if (octet
!= GMRP_LENGTH_LEAVEALL
)
263 call_dissector(data_handle
,
264 tvb_new_subset_remaining(tvb
, offset
),
270 case GMRP_EVENT_JOINEMPTY
:
271 case GMRP_EVENT_JOININ
:
272 case GMRP_EVENT_LEAVEEMPTY
:
273 case GMRP_EVENT_LEAVEIN
:
274 case GMRP_EVENT_EMPTY
:
275 if ( (octet
!= GMRP_GROUP_MEMBERSHIP_NON_LEAVEALL
) &&
276 (octet
!= GMRP_SERVICE_REQUIREMENT_NON_LEAVEALL
) )
278 call_dissector(data_handle
,
279 tvb_new_subset_remaining(tvb
, offset
),
284 /* Show attribute value */
286 if ( GMRP_ATTRIBUTE_TYPE_GROUP_MEMBERSHIP
== attribute_type
)
288 /* Group Membership */
289 proto_tree_add_item(gmrp_tree
, hf_gmrp_attribute_value_group_membership
,
290 tvb
, offset
, (int)(6*sizeof(guint8
)), ENC_NA
);
292 offset
+= (int)(6*sizeof(guint8
));
293 length
-= (int)(6*sizeof(guint8
));
296 if ( GMRP_ATTRIBUTE_TYPE_SERVICE_REQUIREMENT
== attribute_type
)
298 /* Service Requirement */
299 proto_tree_add_item(gmrp_tree
, hf_gmrp_attribute_value_service_requirement
,
300 tvb
, offset
, (int)sizeof(guint8
), ENC_BIG_ENDIAN
);
302 offset
+= (int)sizeof(guint8
);
303 length
-= (int)sizeof(guint8
);
307 call_dissector(data_handle
,
308 tvb_new_subset_remaining(tvb
, offset
),
316 call_dissector(data_handle
,
317 tvb_new_subset_remaining(tvb
, offset
),
323 proto_item_set_len(attr_item
, offset
- attr_start
);
335 /* Register the protocol with Wireshark */
337 proto_register_gmrp(void)
339 static hf_register_info hf
[] = {
341 { "Protocol ID", "gmrp.protocol_id",
342 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
345 { &hf_gmrp_attribute_type
,
346 { "Type", "gmrp.attribute_type",
347 FT_UINT8
, BASE_HEX
, VALS(attribute_type_vals
), 0x0,
350 { &hf_gmrp_attribute_length
,
351 { "Length", "gmrp.attribute_length",
352 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
355 { &hf_gmrp_attribute_event
,
356 { "Event", "gmrp.attribute_event",
357 FT_UINT8
, BASE_DEC
, VALS(event_vals
), 0x0,
360 { &hf_gmrp_attribute_value_group_membership
,
361 { "Value", "gmrp.attribute_value_group_membership",
362 FT_ETHER
, BASE_NONE
, NULL
, 0x0,
365 { &hf_gmrp_attribute_value_service_requirement
,
366 { "Value", "gmrp.attribute_value_service_requirement",
367 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
373 static gint
*ett
[] = {
377 /* Register the protocol name and description for GMRP */
378 proto_gmrp
= proto_register_protocol("GARP Multicast Registration Protocol", "GMRP", "gmrp");
380 /* Required function calls to register the header fields and subtrees
382 proto_register_field_array(proto_gmrp
, hf
, array_length(hf
));
383 proto_register_subtree_array(ett
, array_length(ett
));
385 register_dissector("gmrp", dissect_gmrp
, proto_gmrp
);
390 proto_reg_handoff_gmrp(void){
391 data_handle
= find_dissector("data");