72cbdd536bf583640178dda9570757443fa37001
[obnox/wireshark/wip.git] / plugins / docsis / packet-vendor.c
1 /* packet-vendor.c
2  * Routines for Vendor Specific Encodings dissection
3  * Copyright 2002, Anand V. Narwani <anand[AT]narwani.org>
4  *
5  * $Id: packet-vendor.c,v 1.3 2003/07/19 02:11:34 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
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.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  */
25
26
27 /* Notes to Adding dissectors for Vendor specific TLV's:
28  * 1. Create a dissect_<vendorname> function with the following prototype:
29  *   dissect_foovendor(tvbuff_t *tvb, proto_tree *tree, guint8 vsif_len)
30  * 2. vsif_len will be the *entire* length of the vsif TLV (including the 
31  *   Vendor Id TLV, which is 5 bytes long).
32  * 3. Create a new 'case' statement in dissect_vsif, for your specific Vendor
33  *   id.  
34  * 4. In that 'case' statement you will make the following calls:
35  *   (assume for this example that your vendor id is 0x000054)
36  *   #define VENDOR_FOOVENDOR 0x00054 
37  *   case VENDOR_FOOVENDOR:
38  *      proto_item_append_text (it, " (foo vendor)");
39  *      dissect_foovendor (tvb, vsif_tree, vsif_len);
40  *      break;
41  * 5.  Please see dissect_cisco for an example of how to do this.
42  */
43
44 #ifdef HAVE_CONFIG_H
45 # include "config.h"
46 #endif
47
48
49 #include "plugins/plugin_api.h"
50 #include "plugins/plugin_api_defs.h"
51 #include "moduleinfo.h"
52
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56
57 #ifdef HAVE_SYS_TYPES_H
58 # include <sys/types.h>
59 #endif
60
61 #ifdef HAVE_NETINET_IN_H
62 # include <netinet/in.h>
63 #endif
64
65 #include <gmodule.h>
66
67 #ifdef NEED_SNPRINTF_H
68 # include "snprintf.h"
69 #endif
70
71 #include <epan/packet.h>
72
73 /* Define Vendor ID's here */
74 #define VENDOR_CISCO 0x00000C
75
76 /* Initialize the protocol and registered fields */
77 static int proto_docsis_vsif = -1;
78 static int hf_docsis_vsif = -1;
79 static int hf_docsis_vsif_vendorid = -1;
80 static int hf_docsis_vsif_vendor_unknown = -1;
81 static int hf_docsis_vsif_cisco_numphones = -1;
82 static int hf_docsis_vsif_cisco_ipprec = -1;
83 static int hf_docsis_vsif_cisco_ipprec_val = -1;
84 static int hf_docsis_vsif_cisco_ipprec_bw = -1;
85 static int hf_docsis_vsif_cisco_config_file = -1;
86
87 /* Initialize the subtree pointers */
88 static gint ett_docsis_vsif = -1;
89 static gint ett_docsis_vsif_ipprec = -1;
90
91 static const value_string vendorid_vals[] = {
92         {VENDOR_CISCO, "Cisco Systems, Inc."},
93         {0, NULL},
94 };
95
96
97
98 /* Forward Declarations for vendor specific dissectors */
99 static void dissect_cisco (tvbuff_t * tvb, proto_tree * tree,
100                            guint8 vsif_len);
101
102 /* Code to actually dissect the packets */
103 static void
104 dissect_vsif (tvbuff_t * tvb, packet_info * pinfo _U_, proto_tree * tree)
105 {
106   proto_item *it;
107   proto_tree *vsif_tree;
108   guint8 type;
109   guint8 length;
110   guint32 value;
111   guint16 vsif_len;
112
113 /* get the total length of the VSIF TLV */
114   vsif_len = tvb_length_remaining (tvb, 0);
115
116 /* The first TLV in the VSIF encodings must be type 0x08 (Vendor ID) and
117  * length 3.
118  */
119   type = tvb_get_guint8 (tvb, 0);
120   if (type != 0x08)
121     {
122       THROW (ReportedBoundsError);
123     }
124
125   length = tvb_get_guint8 (tvb, 1);
126   if (length != 3)
127     {
128       THROW (ReportedBoundsError);
129     }
130
131   /* Extract the Value of the Vendor ID */
132   value = tvb_get_ntoh24 (tvb, 2);
133   if (tree)
134     {
135       it =
136         proto_tree_add_protocol_format (tree, proto_docsis_vsif, tvb, 0,
137                                         tvb_length_remaining (tvb, 0),
138                                         "VSIF Encodings");
139       vsif_tree = proto_item_add_subtree (it, ett_docsis_vsif);
140       proto_tree_add_item (vsif_tree, hf_docsis_vsif_vendorid, tvb, 2, 3, FALSE);
141
142       /* switch on the Vendor ID */
143       switch (value)
144         {
145         case VENDOR_CISCO:
146           proto_item_append_text (it, " (Cisco)");
147           dissect_cisco (tvb, vsif_tree, vsif_len);
148           break;
149         default:
150           proto_item_append_text (it, " (Unknown)");
151           proto_tree_add_item (vsif_tree, hf_docsis_vsif_vendor_unknown, tvb,
152                                0, -1, FALSE);
153           break;
154         }
155
156     }                           /* if(tree) */
157
158
159 }
160
161
162 /* Dissector for Cisco Vendor Specific TLV's */
163
164 #define NUM_PHONES 0x0a
165 #define IOS_CONFIG_FILE 0x80
166 #define IP_PREC 0x0b
167 #define IP_PREC_VAL 0x01
168 #define IP_PREC_BW  0x02
169
170 static void
171 dissect_cisco (tvbuff_t * tvb, proto_tree * tree, guint8 vsif_len)
172 {
173   /* Start at pos = 5, since tvb includes the Vendor ID field */
174   guint16 pos = 5;
175   guint8 type, length;
176   proto_item *ipprec_it;
177   proto_tree *ipprec_tree;
178   guint16 templen;
179
180   while (pos < vsif_len)
181     {
182       /* Extract the type and length Fields from the TLV */
183       type = tvb_get_guint8 (tvb, pos++);
184       length = tvb_get_guint8 (tvb, pos++);
185       switch (type)
186         {
187         case NUM_PHONES:
188           proto_tree_add_item (tree, hf_docsis_vsif_cisco_numphones, tvb,
189                                pos, length, FALSE);
190           break;
191         case IP_PREC:
192           ipprec_it =
193             proto_tree_add_text (tree, tvb, pos, length, "IP Precedence");
194           ipprec_tree =
195             proto_item_add_subtree (ipprec_it, ett_docsis_vsif_ipprec);
196           /* Handle Sub-TLVs in IP Precedence */
197           templen = pos + length;
198           while (pos < templen)
199             {
200               type = tvb_get_guint8 (tvb, pos++);
201               length = tvb_get_guint8 (tvb, pos++);
202               switch (type)
203                 {
204                 case IP_PREC_VAL:
205                   if (length != 1)
206                     THROW (ReportedBoundsError);
207                   proto_tree_add_item (ipprec_tree,
208                                        hf_docsis_vsif_cisco_ipprec_val, tvb,
209                                        pos, length, FALSE);
210                   break;
211                 case IP_PREC_BW:
212                   if (length != 4)
213                     THROW (ReportedBoundsError);
214                   proto_tree_add_item (ipprec_tree,
215                                        hf_docsis_vsif_cisco_ipprec_bw, tvb,
216                                        pos, length, FALSE);
217                   break;
218                 default:
219                   THROW (ReportedBoundsError);
220                 }
221               pos += length;
222             }
223           break;
224         case IOS_CONFIG_FILE:
225           proto_tree_add_item (tree, hf_docsis_vsif_cisco_config_file, tvb,
226                                pos, length, FALSE);
227         }
228       pos += length;
229     }
230
231 }
232
233
234
235 /* Register the protocol with Ethereal */
236
237 /* this format is require because a script is used to build the C function
238    that calls all the protocol registration.
239 */
240
241
242 void
243 proto_register_docsis_vsif (void)
244 {
245
246 /* Setup list of header fields  See Section 1.6.1 for details*/
247   static hf_register_info hf[] = {
248     {&hf_docsis_vsif,
249      {"VSIF Encodings", "docsis.vsif",
250       FT_BYTES, BASE_HEX, NULL, 0x0,
251       "Vendor Specific Encodings", HFILL}
252      },
253     {&hf_docsis_vsif_vendorid,
254      {"Vendor Id", "docsis.vsif.vendorid",
255       FT_UINT24, BASE_HEX, VALS(vendorid_vals), 0x0,
256       "Vendor Identifier", HFILL}
257      },
258     {&hf_docsis_vsif_vendor_unknown,
259      {"VSIF Encodings", "docsis.vsif.unknown",
260       FT_BYTES, BASE_HEX, NULL, 0x0,
261       "Unknown Vendor", HFILL}
262      },
263     {&hf_docsis_vsif_cisco_numphones,
264      {"Number of phone lines", "docsis.vsif.cisco.numphones",
265       FT_UINT8, BASE_DEC, NULL, 0x0,
266       "Number of phone lines", HFILL}
267      },
268     {&hf_docsis_vsif_cisco_ipprec,
269      {"IP Precedence Encodings", "docsis.vsif.cisco.ipprec",
270       FT_BYTES, BASE_HEX, NULL, 0x0,
271       "IP Precedence Encodings", HFILL}
272      },
273     {&hf_docsis_vsif_cisco_ipprec_val,
274      {"IP Precedence Value", "docsis.vsif.cisco.ipprec.value",
275       FT_UINT8, BASE_DEC, NULL, 0x0,
276       "IP Precedence Value", HFILL}
277      },
278     {&hf_docsis_vsif_cisco_ipprec_bw,
279      {"IP Precedence Bandwidth", "docsis.vsif.cisco.ipprec.bw",
280       FT_UINT8, BASE_DEC, NULL, 0x0,
281       "IP Precedence Bandwidth", HFILL}
282      },
283     {&hf_docsis_vsif_cisco_config_file,
284      {"IOS Config File", "docsis.vsif.cisco.iosfile",
285       FT_STRING, BASE_DEC, NULL, 0x0,
286       "IOS Config File", HFILL}
287      },
288   };
289
290 /* Setup protocol subtree array */
291   static gint *ett[] = {
292     &ett_docsis_vsif,
293     &ett_docsis_vsif_ipprec,
294   };
295
296 /* Register the protocol name and description */
297   proto_docsis_vsif =
298     proto_register_protocol ("DOCSIS Vendor Specific Endodings",
299                              "DOCSIS VSIF", "docsis_vsif");
300
301 /* Required function calls to register the header fields and subtrees used */
302   proto_register_field_array (proto_docsis_vsif, hf, array_length (hf));
303   proto_register_subtree_array (ett, array_length (ett));
304
305   register_dissector ("docsis_vsif", dissect_vsif, proto_docsis_vsif);
306 }
307
308
309 /* If this dissector uses sub-dissector registration add a registration routine.
310    This format is required because a script is used to find these routines and
311    create the code that calls these routines.
312 */
313 void
314 proto_reg_handoff_docsis_vsif (void)
315 {
316   dissector_handle_t docsis_vsif_handle;
317
318   docsis_vsif_handle = find_dissector ("docsis_vsif");
319   dissector_add ("docsis", 0xFD, docsis_vsif_handle);
320
321 }