Move 3 ASN1 dissectors to 'clean' group; move 1 PIDL dissector to 'dirty' group.
[metze/wireshark/wip.git] / epan / dissectors / packet-brp.c
1 /* packet-brp.c
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 /*
25  * This is a dissector for the BRP (Bandwidth Reservation Protocol). This protocol
26  * is used by various telecommunications vendors to establish VoD (Video
27  * On-Demand) sessions between a STB (Set Top Box) at the customer's home and the
28  * VoD server at the video head-end.
29  */
30
31 #include "config.h"
32
33 #include <glib.h>
34 #include <epan/packet.h>
35 #include <epan/expert.h>
36 #include <epan/prefs.h>
37
38 /* Forward declaration we need below */
39 void proto_reg_handoff_brp(void);
40
41 #define PROTO_TAG_BRP   "BRP"
42
43 /* Wireshark ID of the BRP protocol */
44 static int proto_brp = -1;
45
46 /*static int global_brp_port = 1958; *//* The port is registered for another protocol */
47
48 static const value_string brp_packettype_names[] = {
49     {  0, "BRP" },
50     {  1, "Setup Request - BRC -> BRS" },
51     {  2, "Setup Response - BRS -> BRC" },
52     {  3, "Teardown Request - BRC -> BRS" },
53     {  4, "Teardown Response - BRS -> BRC" },
54     {  5, "Heartbeat Request - BRS -> BRC" },
55     {  6, "Heartbeat Response - BRC -> BRS" },
56     {  7, "Unidirectional Flow Create Request - BRC -> BRS" },
57     {  8, "Flow Create Response - BRS -> BRC" },
58     {  9, "Flow Delete Request BRC -> BRS" },
59     { 10, "Flow Delete Response - BRS -> BRC" },
60     { 11, "Flow Get Request - BRC -> BRS" },
61     { 12, "Flow Get Response - BRS -> BRC" },
62     { 13, "Flow Get Next Request - BRC -> BRS" },
63     { 14, "Flow Get Next Response - BRS -> BRC" },
64     { 15, "Flow Abort - BRS -> BRC" },
65     { 0, NULL }
66 };
67
68 static const value_string brp_stat_vals[] = {
69     {  0, "OK" },
70     {  1, "Comm Error - Network connectivity has been lost (Client Message)." },
71     {  2, "No Bandwidth - There is insufficient bandwidth available in the network to honor the request (Server Message)." },
72     {  3, "Insufficient Resource - Either there is insufficient memory or resource available to transmit the request or,"
73            " insufficient resources existed at the server to complete the request. Note that insufficient bandwidth in the"
74            " network is handled by the previous status value. This is the catchall for all other resource deficiencies"
75            " (Client/Server Message)." },
76     {  4, "No Such - The requested flow does not exist (Server Message)." },
77     {  5, "No Session - There is no active session. The server may return this in the event that the client and server"
78            " are out of sync. In that eventuality, the client must reestablish its session and recreate any flows that"
79            " it believes have been lost (Server Message)." },
80     {  6, "Invalid Argument - One of the input arguments to the call was not valid (Client/Server Message)." },
81     {  7, "Unreachable - The specified BRS is not reachable (Client Message)." },
82     {  8, "Internal Error - An internal fault has occurred. This is generally indicative of a fatal condition within"
83            " the client system (Server Message)." },
84     {  9, "Already Exists - The flow or session that the client requested already exists (Server Message)." },
85     { 10, "Flow Removed - The flow was removed or lost due to issues internal to the network (Server Message)." },
86     { 11, "Invalid Sender - Received packet was from an unknown sender (Server Message)." },
87     { 12, "Invalid Message - Input message is not defined or malformed (Client/Server Message)." },
88     { 13, "Unsupported Version - The requested version (in a setup) is not supported (Server Message)." },
89     { 14, "Pending - The requested operation is proceeding and a status will be returned with the final result"
90            " shortly (Server Message)." },
91     { 0, NULL }
92 };
93
94 /* The following hf_* variables are used to hold the Wireshark IDs of
95 * our data fields; they are filled out when we call
96 * proto_register_field_array() in proto_register_brp()
97 */
98 static gint hf_brp_type = -1;
99 static gint hf_brp_trans = -1;
100 static gint hf_brp_ver = -1;
101 static gint hf_brp_stat = -1;
102 static gint hf_brp_srcip = -1;
103 static gint hf_brp_dstip = -1;
104 static gint hf_brp_dstuport = -1;
105 static gint hf_brp_mbz = -1;
106 static gint hf_brp_bw = -1;
107 static gint hf_brp_life = -1;
108 static gint hf_brp_flid = -1;
109 static gint hf_brp_rmttl = -1;
110 static gint hf_brp_fltype = -1;
111
112 /* These are the ids of the subtrees that we may be creating */
113 static gint ett_brp = -1;
114 static gint ett_brp_type = -1;
115 static gint ett_brp_trans = -1;
116 static gint ett_brp_ver = -1;
117 static gint ett_brp_stat = -1;
118 static gint ett_brp_srcip = -1;
119 static gint ett_brp_dstip = -1;
120 static gint ett_brp_dstuport = -1;
121 static gint ett_brp_mbz = -1;
122 static gint ett_brp_bw = -1;
123 static gint ett_brp_life = -1;
124 static gint ett_brp_flid = -1;
125 static gint ett_brp_rmttl = -1;
126 static gint ett_brp_fltype = -1;
127
128 /* Preferences */
129 static guint global_brp_port = 0;
130
131 static int
132 dissect_brp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
133 {
134
135     proto_item *brp_item    = NULL;
136     proto_tree *brp_tree    = NULL;
137     gint        offset      = 0;
138     guint8      type        = 0;
139     guint8      packet_type = tvb_get_guint8(tvb, 0);
140
141     /* If there is a "tree" requested, we handle that request. */
142
143     col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_BRP);
144     if(check_col(pinfo->cinfo,COL_INFO)){
145         /* We add some snazzy bizness to the info field to quickly ascertain
146            what type of message was sent to/from the BRS/BRC. */
147         col_add_fstr(pinfo->cinfo, COL_INFO, "Message Type - %s",
148              val_to_str(packet_type, brp_packettype_names, "Unknown (0x%02x)"));
149     }
150
151     /* This call adds our tree to the main dissection tree. */
152
153     if (tree) { /* we are being asked for details */
154
155         /* Here we add our tree/subtree so we can have a collapsible branch. */
156         brp_item = proto_tree_add_item( tree, proto_brp, tvb, 0, -1, ENC_NA );
157         brp_tree = proto_item_add_subtree( brp_item, ett_brp);
158
159         /* We use tvb_get_guint8 to get our type value out. */
160         type = tvb_get_guint8(tvb, offset);
161         offset += 0;
162
163         brp_item = proto_tree_add_item( brp_tree, hf_brp_type, tvb, offset, 1, ENC_BIG_ENDIAN );
164         offset += 1;
165
166         /* Now let's break down each packet and display it in the collapsible branch */
167         switch(type)
168         {
169         case 1: /* Setup Request */
170             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
171             offset += 3;
172             proto_tree_add_item( brp_tree, hf_brp_ver, tvb, offset, 4, ENC_BIG_ENDIAN );
173             offset +=4;
174             break;
175
176         case 2: /* Setup Response */
177             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
178             offset += 3;
179             proto_tree_add_item( brp_tree, hf_brp_stat, tvb, offset, 4, ENC_BIG_ENDIAN );
180             offset +=4;
181             break;
182
183         case 3: /* Teardown Request */
184             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
185             offset += 3;
186             break;
187
188         case 4: /* Teardown Response */
189             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
190             offset += 3;
191             break;
192
193         case 5: /* Heartbeat Request */
194             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
195             offset += 3;
196             break;
197
198         case 6: /* Heartbeat Response */
199             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
200             offset += 3;
201             break;
202
203         case 7: /* Uni Flow Create Request */
204             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
205             offset += 3;
206             proto_tree_add_item( brp_tree, hf_brp_srcip, tvb, offset, 4, ENC_BIG_ENDIAN );
207             offset +=4;
208             proto_tree_add_item( brp_tree, hf_brp_dstip, tvb, offset, 4, ENC_BIG_ENDIAN );
209             offset +=4;
210             proto_tree_add_item( brp_tree, hf_brp_dstuport, tvb, offset, 2, ENC_BIG_ENDIAN );
211             offset +=2;
212             proto_tree_add_item( brp_tree, hf_brp_mbz, tvb, offset, 2, ENC_BIG_ENDIAN );
213             offset +=2;
214             proto_tree_add_item( brp_tree, hf_brp_bw, tvb, offset, 4, ENC_BIG_ENDIAN );
215             offset +=4;
216             proto_tree_add_item( brp_tree, hf_brp_life, tvb, offset, 4, ENC_BIG_ENDIAN );
217             offset +=4;
218             break;
219
220         case 8: /* Flow Create Response */
221             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
222             offset += 3;
223             proto_tree_add_item( brp_tree, hf_brp_stat, tvb, offset, 4, ENC_BIG_ENDIAN );
224             offset +=4;
225             proto_tree_add_item( brp_tree, hf_brp_flid, tvb, offset, 4, ENC_BIG_ENDIAN );
226             offset +=4;
227             break;
228
229         case 9: /* Flow Delete Request */
230             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
231             offset += 3;
232             proto_tree_add_item( brp_tree, hf_brp_flid, tvb, offset, 4, ENC_BIG_ENDIAN );
233             offset +=4;
234             break;
235
236         case 10: /* Flow Delete Response */
237             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
238             offset += 3;
239             proto_tree_add_item( brp_tree, hf_brp_stat, tvb, offset, 4, ENC_BIG_ENDIAN );
240             offset +=4;
241             break;
242
243         case 11: /* Flow Get Request */
244             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
245             offset += 3;
246             proto_tree_add_item( brp_tree, hf_brp_flid, tvb, offset, 4, ENC_BIG_ENDIAN );
247             offset +=4;
248             break;
249
250         case 12: /* Flow Get Response */
251             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
252             offset += 3;
253             proto_tree_add_item( brp_tree, hf_brp_stat, tvb, offset, 4, ENC_BIG_ENDIAN );
254             offset +=4;
255             proto_tree_add_item( brp_tree, hf_brp_rmttl, tvb, offset, 4, ENC_BIG_ENDIAN );
256             offset +=4;
257             proto_tree_add_item( brp_tree, hf_brp_srcip, tvb, offset, 4, ENC_BIG_ENDIAN );
258             offset +=4;
259             proto_tree_add_item( brp_tree, hf_brp_dstip, tvb, offset, 4, ENC_BIG_ENDIAN );
260             offset +=4;
261             proto_tree_add_item( brp_tree, hf_brp_dstuport, tvb, offset, 2, ENC_BIG_ENDIAN );
262             offset +=2;
263             proto_tree_add_item( brp_tree, hf_brp_mbz, tvb, offset, 2, ENC_BIG_ENDIAN );
264             offset +=2;
265             proto_tree_add_item( brp_tree, hf_brp_fltype, tvb, offset, 1, ENC_BIG_ENDIAN );
266             offset +=1;
267             proto_tree_add_item( brp_tree, hf_brp_bw, tvb, offset, 3, ENC_BIG_ENDIAN );
268             offset +=3;
269             proto_tree_add_item( brp_tree, hf_brp_life, tvb, offset, 4, ENC_BIG_ENDIAN );
270             offset +=4;
271             proto_tree_add_item( brp_tree, hf_brp_flid, tvb, offset, 4, ENC_BIG_ENDIAN );
272             offset +=4;
273             break;
274
275         case 13: /* Flow Get Next Request */
276             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
277             offset += 3;
278             proto_tree_add_item( brp_tree, hf_brp_flid, tvb, offset, 4, ENC_BIG_ENDIAN );
279             offset +=4;
280             break;
281
282         case 14: /* Flow Get Next Response */
283             proto_tree_add_item( brp_tree, hf_brp_trans, tvb, offset, 3, ENC_BIG_ENDIAN );
284             offset += 3;
285             proto_tree_add_item( brp_tree, hf_brp_stat, tvb, offset, 4, ENC_BIG_ENDIAN );
286             offset +=4;
287             proto_tree_add_item( brp_tree, hf_brp_rmttl, tvb, offset, 4, ENC_BIG_ENDIAN );
288             offset +=4;
289             proto_tree_add_item( brp_tree, hf_brp_srcip, tvb, offset, 4, ENC_BIG_ENDIAN );
290             offset +=4;
291             proto_tree_add_item( brp_tree, hf_brp_dstip, tvb, offset, 4, ENC_BIG_ENDIAN );
292             offset +=4;
293             proto_tree_add_item( brp_tree, hf_brp_dstuport, tvb, offset, 2, ENC_BIG_ENDIAN );
294             offset +=2;
295             proto_tree_add_item( brp_tree, hf_brp_mbz, tvb, offset, 2, ENC_BIG_ENDIAN );
296             offset +=2;
297             proto_tree_add_item( brp_tree, hf_brp_fltype, tvb, offset, 1, ENC_BIG_ENDIAN );
298             offset +=1;
299             proto_tree_add_item( brp_tree, hf_brp_bw, tvb, offset, 3, ENC_BIG_ENDIAN );
300             offset +=3;
301             proto_tree_add_item( brp_tree, hf_brp_life, tvb, offset, 4, ENC_BIG_ENDIAN );
302             offset +=4;
303             proto_tree_add_item( brp_tree, hf_brp_flid, tvb, offset, 4, ENC_BIG_ENDIAN );
304             offset +=4;
305             break;
306
307         case 15: /* Flow Abort */
308             proto_tree_add_item( brp_tree, hf_brp_mbz, tvb, offset, 3, ENC_BIG_ENDIAN );
309             offset +=3;
310             proto_tree_add_item( brp_tree, hf_brp_flid, tvb, offset, 4, ENC_BIG_ENDIAN );
311             offset +=4;
312             break;
313
314         default:
315             /* Invalid type */
316             expert_add_info_format(pinfo, brp_item, PI_UNDECODED, PI_WARN, "Unknown packet type");
317             break;
318         }
319
320     }
321 return offset;
322 }
323
324 /*--- proto_register_brp ----------------------------------------------*/
325 void proto_register_brp (void)
326 {
327     module_t *brp_module;
328
329     /* A data field is something you can search/filter on.
330     *
331     * We create a structure to register our fields. It consists of an
332     * array of hf_register_info structures, each of which are of the format
333     * {&(field id), {name, abbrev, type, display, strings, bitmask, blurb, HFILL}}.
334     */
335     static hf_register_info hf[] = {
336         { &hf_brp_type,
337           { "Type", "brp.type", FT_UINT8, BASE_DEC, VALS(brp_packettype_names), 0x0,
338             NULL, HFILL }},
339         { &hf_brp_trans,
340           { "Transaction ID", "brp.trans", FT_UINT8, BASE_DEC, NULL, 0x0,
341             NULL, HFILL }},
342         { &hf_brp_ver,
343           { "Version", "brp.ver", FT_UINT8, BASE_DEC, NULL, 0x0,
344             NULL, HFILL }},
345         { &hf_brp_stat,
346           { "Status", "brp.stat", FT_UINT8, BASE_DEC, VALS(brp_stat_vals), 0x0,
347             NULL, HFILL }},
348         { &hf_brp_srcip,
349           { "Source IP Address", "brp.srcip", FT_IPv4, BASE_NONE, NULL, 0x0,
350             NULL, HFILL }},
351         { &hf_brp_dstip,
352           { "Destination IP Address", "brp.dstip", FT_IPv4, BASE_NONE, NULL, 0x0,
353             NULL, HFILL }},
354         { &hf_brp_dstuport,
355           { "Destination UDP Port", "brp.dstuport", FT_UINT16, BASE_DEC, NULL, 0x0,
356             NULL, HFILL }},
357         { &hf_brp_mbz,
358           { "MBZ", "brp.mbz", FT_UINT8, BASE_DEC, NULL, 0x0,
359             NULL, HFILL }},
360         { &hf_brp_bw,
361           { "Bandwidth - Kbytes/sec", "brp.bw", FT_UINT32, BASE_DEC, NULL, 0x0,
362             NULL, HFILL }},
363         { &hf_brp_life,
364           { "Lifetime", "brp.life", FT_UINT32, BASE_DEC, NULL, 0x0,
365             NULL, HFILL }},
366         { &hf_brp_flid,
367           { "Flow Identifier", "brp.flid", FT_UINT16, BASE_DEC, NULL, 0x0,
368             NULL, HFILL }},
369         { &hf_brp_fltype,
370           { "Flow Type", "brp.fltype", FT_UINT8, BASE_DEC, NULL, 0x0,
371             NULL, HFILL }},
372         { &hf_brp_rmttl,
373           { "Remaining TTL", "brp.rmttl", FT_UINT32, BASE_DEC, NULL, 0x0,
374             NULL, HFILL }},
375     };
376     static gint *ett[] = {
377         &ett_brp,
378         &ett_brp_type,
379         &ett_brp_trans,
380         &ett_brp_ver,
381         &ett_brp_stat,
382         &ett_brp_srcip,
383         &ett_brp_dstip,
384         &ett_brp_dstuport,
385         &ett_brp_mbz,
386         &ett_brp_bw,
387         &ett_brp_life,
388         &ett_brp_flid,
389         &ett_brp_fltype,
390         &ett_brp_rmttl
391
392     };
393     proto_brp = proto_register_protocol ("BRP Protocol", "BRP", "brp");
394     proto_register_field_array (proto_brp, hf, array_length (hf));
395     proto_register_subtree_array (ett, array_length (ett));
396
397     /* Register preferences module */
398     brp_module = prefs_register_protocol(proto_brp, proto_reg_handoff_brp);
399
400     /* Register preferences */
401     prefs_register_uint_preference(brp_module, "port",
402                                    "BRP Port",
403                                    "Set the UDP port for BRP messages",
404                                    10, &global_brp_port);
405
406     new_register_dissector("brp", dissect_brp, proto_brp);
407 }
408
409 /*--- proto_reg_handoff_brp -------------------------------------------*/
410 void proto_reg_handoff_brp(void)
411 {
412     static gboolean           initialized = FALSE;
413     static dissector_handle_t brp_handle;
414     static guint              saved_brp_port;
415
416     if (!initialized) {
417         brp_handle = new_create_dissector_handle(dissect_brp, proto_brp);
418         dissector_add_handle("udp.port", brp_handle);
419         initialized = TRUE;
420     } else {
421         if (saved_brp_port != 0) {
422             dissector_delete_uint("udp.port", saved_brp_port, brp_handle);
423         }
424     }
425
426     /* Set the port number */
427     if (global_brp_port != 0) {
428         dissector_add_uint("udp.port", global_brp_port, brp_handle);
429     }
430     saved_brp_port = global_brp_port;
431 }
432