Fix [-Wmissing-prototypes]
[metze/wireshark/wip.git] / epan / dissectors / packet-mrp-mmrp.c
1 /* packet-mrp_mmrp.c
2  * Routines for MMRP (MRP Multiple Mac Registration Protocol) dissection
3  * Copyright 2011, Johannes Jochen <johannes.jochen[AT]belden.com>
4  *
5  *
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>
8  * Copyright 2010
9  *
10  * $Id$
11  *
12  * Wireshark - Network traffic analyzer
13  * By Gerald Combs <gerald[AT]wireshark.org>
14  * Copyright 1998 Gerald Combs
15  *
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.
20  *
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.
25  *
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.
29  *
30  * The MMRP Protocol specification can be found at the following:
31  * http://standards.ieee.org/about/get/802/802.1.html
32  *
33  */
34
35 #include "config.h"
36
37 #include <epan/packet.h>
38 #include <epan/etypes.h>
39
40 void proto_register_mrp_mmrp(void);
41 void proto_reg_handoff_mrp_mmrp(void);
42
43 /* MMRP End Mark Sequence */
44 #define MMRP_END_MARK       0x0000
45
46 /**********************************************************/
47 /* Offsets of fields within an MMRP packet                */
48 /**********************************************************/
49 #define MMRP_PROTOCOL_VERSION_OFFSET        0
50
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)
55
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 */
58
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
66
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 */
69
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)
72
73 /**********************************************************/
74 /* Valid field contents                                   */
75 /**********************************************************/
76
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" },
83     { 0,                                    NULL }
84 };
85
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" },
92     { 0,                 NULL }
93 };
94
95 /* Three Packed Event definitions */
96 static const value_string three_packed_vals[] = {
97     { 0, "New" },
98     { 1, "JoinIn" },
99     { 2, "In" },
100     { 3, "JoinMt" },
101     { 4, "Mt" },
102     { 5, "Lv" },
103     { 0, NULL }
104 };
105
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 */
116
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,
125     NULL
126 };
127
128 static int hf_mmrp_first_value = -1; /* FirstValue is a group of fields */
129
130 static int hf_mmrp_three_packed_event = -1;
131
132 static int hf_mmrp_end_mark = -1;
133
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;
140
141
142
143 /**********************************************************/
144 /* Dissector starts here                                  */
145 /**********************************************************/
146
147 /* dissect_mmrp_common1 (called from dissect_mmrp)
148  *
149  * dissect the following fields which are common to all MMRP attributes:
150  *   Attribute Type
151  *   Attribute Length
152  *   Attribute List Length
153  */
154 static void
155 dissect_mmrp_common1(proto_tree *msg_tree, tvbuff_t *tvb, int msg_offset)
156 {
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);
161 }
162
163
164 /* dissect_mmrp_common2 (called from dissect_mmrp)
165  *
166  * dissect the following fields which are common to all MMRP attributes:
167  *   Leave All Event
168  *   Number of Values fields
169  */
170 static void
171 dissect_mmrp_common2(proto_tree *vect_attr_tree, tvbuff_t *tvb, int msg_offset)
172 {
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);
175 }
176
177 /* dissect_mmrp_three_packed_event (called from dissect_mmrp)
178  *
179  * dissect one or more ThreePackedEvents
180  */
181 static guint
182 dissect_mmrp_three_packed_event(proto_tree *vect_attr_tree, tvbuff_t *tvb, guint offset, guint16 number_of_values)
183 {
184     guint counter;
185
186     for ( counter = 0; counter < number_of_values; ) {
187         guint8 value;
188         guint8 three_packed_event[3];
189
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;
196
197         proto_tree_add_uint(vect_attr_tree, hf_mmrp_three_packed_event, tvb, offset, sizeof(guint8),
198                             three_packed_event[0]);
199         counter++;
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]);
203             counter++;
204         }
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]);
208             counter++;
209         }
210
211         offset++;
212     }
213     return( offset );
214 }
215
216 /* dissect_main
217  *
218  * main dissect function that calls the other functions listed above as necessary
219  */
220 static void
221 dissect_mmrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
222 {
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;
226
227     /* Make entries in Protocol column and Info column on summary display */
228     col_set_str(pinfo->cinfo, COL_PROTOCOL, "MRP-MMRP");
229
230     col_set_str(pinfo->cinfo, COL_INFO, "Multiple Mac Registration Protocol");
231
232     if (tree) {
233         guint8 attribute_type;
234         guint8 attribute_length;
235         guint16 number_of_values;
236         guint offset = 0;
237         int vect_attr_len;
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. */
240
241         ti = proto_tree_add_item(tree, proto_mmrp, tvb, 0, -1, ENC_NA);
242         mmrp_tree = proto_item_add_subtree(ti, ett_mmrp);
243
244         proto_tree_add_item(mmrp_tree, hf_mmrp_proto_id, tvb, MMRP_PROTOCOL_VERSION_OFFSET, 1, ENC_BIG_ENDIAN);
245
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).
250          */
251         msg_offset = 0;
252         while (tvb_get_ntohs(tvb, MMRP_ATTRIBUTE_TYPE_OFFSET + msg_offset) != MMRP_END_MARK) {
253
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);
256
257             /* MMRP Message is a group of fields
258              *
259              * Contains AttributeType (1 byte)
260              *        + AttributeLength (1 byte)
261              *        + AttributeList (AttributeListLength bytes)
262             *        bytes of data
263             */
264             msg_ti = proto_tree_add_item(mmrp_tree, hf_mmrp_message, tvb,
265                                          MMRP_MESSAGE_GROUP_OFFSET + msg_offset,
266                                          -1, ENC_NA);
267             msg_tree = proto_item_add_subtree(msg_ti, ett_msg);
268
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>"),
272                                    attribute_type);
273
274             dissect_mmrp_common1(msg_tree, tvb, msg_offset);
275
276             /* MMRP AttributeList is a group of fields
277              *
278              * Contains AttributeListLength bytes of data NOT
279              */
280             attr_list_ti = proto_tree_add_item(msg_tree, hf_mmrp_attribute_list, tvb,
281                                                MMRP_ATTRIBUTE_LIST_GROUP_OFFSET + msg_offset,
282                                                -1, ENC_NA);
283             attr_list_tree = proto_item_add_subtree(attr_list_ti, ett_attr_list);
284
285
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).
290              */
291             vect_offset = 0;
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
294                  *
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)
299                  *        bytes of data
300                  */
301                 number_of_values = tvb_get_ntohs(tvb, MMRP_NUMBER_OF_VALUES_OFFSET + msg_offset + vect_offset)
302                                    & MMRP_NUMBER_OF_VALUES_MASK;
303
304                 vect_attr_len = 2 + attribute_length + (number_of_values + 2)/3; /* stores 3 values per byte */
305
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);
309
310                 vect_attr_tree = proto_item_add_subtree(vect_attr_ti, ett_vect_attr);
311
312                 dissect_mmrp_common2(vect_attr_tree, tvb, msg_offset + vect_offset);
313
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,
322                                                              number_of_values);
323
324                 }
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,
332                                                              number_of_values);
333
334                 }
335
336                 vect_offset += vect_attr_len; /* Move to next Vector Attribute, if there is one */
337             } /* Multiple VectorAttribute while() */
338
339             proto_tree_add_item(attr_list_tree, hf_mmrp_end_mark, tvb, offset, 2, ENC_NA); /* VectorAttribute EndMark */
340
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*/
344
345         } /* Multiple Message while() */
346
347         proto_tree_add_item(mmrp_tree, hf_mmrp_end_mark, tvb, offset+2, 2, ENC_NA); /* Message EndMark */
348     }
349 }
350
351
352 /* Register the protocol with Wireshark */
353 void
354 proto_register_mrp_mmrp(void)
355 {
356     static hf_register_info hf[] = {
357         { &hf_mmrp_proto_id,
358             { "Protocol Version",      "mrp-mmrp.protocol_version",
359               FT_UINT8,  BASE_DEC, NULL, 0x0, NULL, HFILL }
360         },
361         { &hf_mmrp_message, /* Message is a group of fields */
362             { "Message",               "mrp-mmrp.message",
363               FT_NONE,  BASE_NONE, NULL, 0x0, NULL, HFILL }
364         },
365         { &hf_mmrp_attribute_type,
366             { "Attribute Type",        "mrp-mmrp.attribute_type",
367               FT_UINT8,  BASE_DEC, VALS(attribute_type_vals), 0x0, NULL, HFILL }
368         },
369         { &hf_mmrp_attribute_length,
370             { "Attribute Length",      "mrp-mmrp.attribute_length",
371               FT_UINT8,  BASE_DEC, NULL, 0x0, NULL, HFILL }
372         },
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 }
376         },
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 }
380         },
381         { &hf_mmrp_vector_header,
382             { "Vector Header",         "mrp-mmrp.vector_header",
383               FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
384         },
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 }
388         },
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 }
392         },
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 }
396         },
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 }
400         },
401         { &hf_mmrp_end_mark,
402             { "End Mark",              "mrp-mmrp.end_mark",
403               FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
404         },
405     };
406
407     /* Setup protocol subtree array */
408     static gint *ett[] = {
409         &ett_mmrp,
410         &ett_msg,
411         &ett_attr_list,
412         &ett_vect_attr,
413         &ett_vector_header,
414         &ett_first_value
415     };
416
417     /* Register the protocol name and description */
418     proto_mmrp = proto_register_protocol("Multiple Mac Registration Protocol",
419                                          "MRP-MMRP", "mrp-mmrp");
420
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));
424 }
425
426 void
427 proto_reg_handoff_mrp_mmrp(void)
428 {
429     dissector_handle_t mmrp_handle;
430
431     mmrp_handle = create_dissector_handle(dissect_mmrp, proto_mmrp);
432     dissector_add_uint("ethertype", ETHERTYPE_MMRP, mmrp_handle);
433 }