Don't dereference a NULL pointer. Fixes CID 426.
[obnox/wireshark/wip.git] / plugins / docsis / packet-rngrsp.c
1 /* packet-rngrsp.c
2  * Routines for Ranging Response Message dissection
3  * Copyright 2002, Anand V. Narwani <anand[AT]narwani.org>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
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 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <epan/packet.h>
31
32 #define RNGRSP_TIMING 1
33 #define RNGRSP_PWR_LEVEL_ADJ 2
34 #define RNGRSP_OFFSET_FREQ_ADJ 3
35 #define RNGRSP_TRANSMIT_EQ_ADJ 4
36 #define RNGRSP_RANGING_STATUS 5
37 #define RNGRSP_DOWN_FREQ_OVER 6
38 #define RNGRSP_UP_CHID_OVER 7
39
40 /* Initialize the protocol and registered fields */
41 static int proto_docsis_rngrsp = -1;
42 static int hf_docsis_rngrsp_upstream_chid = -1;
43 static int hf_docsis_rngrsp_sid = -1;
44 static int hf_docsis_rngrsp_timing_adj = -1;
45 static int hf_docsis_rngrsp_power_adj = -1;
46 static int hf_docsis_rngrsp_freq_adj = -1;
47 static int hf_docsis_rngrsp_xmit_eq_adj = -1;
48 static int hf_docsis_rngrsp_ranging_status = -1;
49 static int hf_docsis_rngrsp_down_freq_over = -1;
50 static int hf_docsis_rngrsp_upstream_ch_over = -1;
51
52 static const value_string rng_stat_vals[] = {
53   {1, "Continue"},
54   {2, "Abort"},
55   {3, "Success"},
56   {0, NULL}
57 };
58
59 /* Initialize the subtree pointers */
60 static gint ett_docsis_rngrsp = -1;
61
62 /* Code to actually dissect the packets */
63 static void
64 dissect_rngrsp (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
65 {
66   proto_item *it;
67   proto_tree *rngrsp_tree;
68   guint8 tlvtype, tlvlen;
69   int pos;
70   gint length;
71   guint8 upchid;
72   guint16 sid;
73   gint8 pwr;
74   gint32 tim;
75
76   sid = tvb_get_ntohs (tvb, 0);
77   upchid = tvb_get_guint8 (tvb, 2);
78
79   col_clear (pinfo->cinfo, COL_INFO);
80   if (upchid > 0)
81         col_add_fstr (pinfo->cinfo, COL_INFO,
82                       "Ranging Response: SID = %u, Upstream Channel = %u (U%u)",
83                       sid, upchid, upchid - 1);
84   else
85         col_add_fstr (pinfo->cinfo, COL_INFO,
86                       "Ranging Response: SID = %u, Telephony Return", sid);
87
88
89   if (tree)
90     {
91       it =
92         proto_tree_add_protocol_format (tree, proto_docsis_rngrsp, tvb, 0, -1,
93                                         "Ranging Response");
94       rngrsp_tree = proto_item_add_subtree (it, ett_docsis_rngrsp);
95       proto_tree_add_item (rngrsp_tree, hf_docsis_rngrsp_sid, tvb, 0, 2,
96                            FALSE);
97       proto_tree_add_item (rngrsp_tree, hf_docsis_rngrsp_upstream_chid, tvb,
98                            2, 1, FALSE);
99
100       length = tvb_reported_length_remaining (tvb, 0);
101       pos = 3;
102       while (pos < length)
103         {
104           tlvtype = tvb_get_guint8 (tvb, pos++);
105           tlvlen = tvb_get_guint8 (tvb, pos++);
106           switch (tlvtype)
107             {
108             case RNGRSP_TIMING:
109               if (tlvlen == 4)
110                 {
111                   tim = tvb_get_ntohl (tvb, pos);
112                   proto_tree_add_int (rngrsp_tree,
113                                       hf_docsis_rngrsp_timing_adj, tvb, pos,
114                                       tlvlen, tim);
115                 }
116               else
117                 {
118                   THROW (ReportedBoundsError);
119                 }
120               break;
121             case RNGRSP_PWR_LEVEL_ADJ:
122               if (tlvlen == 1)
123                 {
124                   pwr = tvb_get_guint8 (tvb, pos);
125                   proto_tree_add_int (rngrsp_tree, hf_docsis_rngrsp_power_adj,
126                                       tvb, pos, tlvlen, pwr);
127                 }
128               else
129                 {
130                   THROW (ReportedBoundsError);
131                 }
132               break;
133             case RNGRSP_OFFSET_FREQ_ADJ:
134               if (tlvlen == 2)
135                 {
136                   proto_tree_add_item (rngrsp_tree, hf_docsis_rngrsp_freq_adj,
137                                        tvb, pos, tlvlen, FALSE);
138                 }
139               else
140                 {
141                   THROW (ReportedBoundsError);
142                 }
143               break;
144             case RNGRSP_TRANSMIT_EQ_ADJ:
145               proto_tree_add_item (rngrsp_tree, hf_docsis_rngrsp_xmit_eq_adj,
146                                    tvb, pos, tlvlen, FALSE);
147               break;
148             case RNGRSP_RANGING_STATUS:
149               if (tlvlen == 1)
150                 proto_tree_add_item (rngrsp_tree,
151                                      hf_docsis_rngrsp_ranging_status, tvb,
152                                      pos, tlvlen, FALSE);
153               else
154                 {
155                   THROW (ReportedBoundsError);
156                 }
157               break;
158             case RNGRSP_DOWN_FREQ_OVER:
159               if (tlvlen == 4)
160                 proto_tree_add_item (rngrsp_tree,
161                                      hf_docsis_rngrsp_down_freq_over, tvb,
162                                      pos, tlvlen, FALSE);
163               else
164                 {
165                   THROW (ReportedBoundsError);
166                 }
167               break;
168             case RNGRSP_UP_CHID_OVER:
169               if (tlvlen == 1)
170                 proto_tree_add_item (rngrsp_tree,
171                                      hf_docsis_rngrsp_upstream_ch_over, tvb,
172                                      pos, tlvlen, FALSE);
173               else
174                 {
175                   THROW (ReportedBoundsError);
176                 }
177               break;
178
179             }                   /* switch(tlvtype) */
180           pos = pos + tlvlen;
181         }                       /* while (pos < length) */
182     }                           /* if (tree) */
183 }
184
185
186
187
188 /* Register the protocol with Wireshark */
189
190 /* this format is require because a script is used to build the C function
191    that calls all the protocol registration.
192 */
193
194
195 void
196 proto_register_docsis_rngrsp (void)
197 {
198
199 /* Setup list of header fields  See Section 1.6.1 for details*/
200   static hf_register_info hf[] = {
201     {&hf_docsis_rngrsp_sid,
202      {"Service Identifier", "docsis_rngrsp.sid",
203       FT_UINT16, BASE_DEC, NULL, 0x0,
204       NULL, HFILL}
205      },
206     {&hf_docsis_rngrsp_upstream_chid,
207      {"Upstream Channel ID", "docsis_rngrsp.upchid",
208       FT_UINT8, BASE_DEC, NULL, 0x0,
209       NULL, HFILL}
210      },
211     {&hf_docsis_rngrsp_timing_adj,
212      {"Timing Adjust (6.25us/64)", "docsis_rngrsp.timingadj",
213       FT_INT32, BASE_DEC, NULL, 0x0,
214       "Timing Adjust", HFILL}
215      },
216     {&hf_docsis_rngrsp_power_adj,
217      {"Power Level Adjust (0.25dB units)", "docsis_rngrsp.poweradj",
218       FT_INT8, BASE_DEC, NULL, 0x0,
219       "Power Level Adjust", HFILL}
220      },
221     {&hf_docsis_rngrsp_freq_adj,
222      {"Offset Freq Adjust (Hz)", "docsis_rngrsp.freqadj",
223       FT_INT16, BASE_DEC, NULL, 0x0,
224       "Frequency Adjust", HFILL}
225      },
226     {&hf_docsis_rngrsp_xmit_eq_adj,
227      {"Transmit Equalisation Adjust", "docsis_rngrsp.xmit_eq_adj",
228       FT_BYTES, BASE_NONE, NULL, 0x0,
229       "Timing Equalisation Adjust", HFILL}
230      },
231     {&hf_docsis_rngrsp_ranging_status,
232      {"Ranging Status", "docsis_rngrsp.rng_stat",
233       FT_UINT8, BASE_DEC, VALS (rng_stat_vals), 0x0,
234       NULL, HFILL}
235      },
236     {&hf_docsis_rngrsp_down_freq_over,
237      {"Downstream Frequency Override (Hz)", "docsis_rngrsp.freq_over",
238       FT_UINT32, BASE_DEC, NULL, 0x0,
239       "Downstream Frequency Override", HFILL}
240      },
241     {&hf_docsis_rngrsp_upstream_ch_over,
242      {"Upstream Channel ID Override", "docsis_rngrsp.chid_override",
243       FT_UINT8, BASE_DEC, NULL, 0x0,
244       NULL, HFILL}
245      },
246
247   };
248
249 /* Setup protocol subtree array */
250   static gint *ett[] = {
251     &ett_docsis_rngrsp,
252   };
253
254 /* Register the protocol name and description */
255   proto_docsis_rngrsp = proto_register_protocol ("DOCSIS Ranging Response",
256                                                  "DOCSIS RNG-RSP",
257                                                  "docsis_rngrsp");
258
259 /* Required function calls to register the header fields and subtrees used */
260   proto_register_field_array (proto_docsis_rngrsp, hf, array_length (hf));
261   proto_register_subtree_array (ett, array_length (ett));
262
263   register_dissector ("docsis_rngrsp", dissect_rngrsp, proto_docsis_rngrsp);
264 }
265
266
267 /* If this dissector uses sub-dissector registration add a registration routine.
268    This format is required because a script is used to find these routines and
269    create the code that calls these routines.
270 */
271 void
272 proto_reg_handoff_docsis_rngrsp (void)
273 {
274   dissector_handle_t docsis_rngrsp_handle;
275
276   docsis_rngrsp_handle = find_dissector ("docsis_rngrsp");
277   dissector_add_uint ("docsis_mgmt", 0x05, docsis_rngrsp_handle);
278
279 }