Removed some more "statement not reached" warnings.
[obnox/wireshark/wip.git] / epan / dissectors / packet-x224.c
1 /* packet-x224.c
2  *
3  * Routine to dissect X.224
4  * Copyright 2007, Ronnie Sahlberg
5  *
6  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <glib.h>
32 #include <epan/packet.h>
33
34 #include "packet-tpkt.h"
35 #include "packet-frame.h"
36 #include <epan/conversation.h>
37 #include <epan/prefs.h>
38 #include <epan/emem.h>
39
40 /* X.224 header fields             */
41 static int proto_x224                   = -1;
42 static int hf_x224_length               = -1;
43 static int hf_x224_code                 = -1;
44 static int hf_x224_src_ref              = -1;
45 static int hf_x224_dst_ref              = -1;
46 static int hf_x224_class                = -1;
47 static int hf_x224_nr                   = -1;
48 static int hf_x224_eot                  = -1;
49
50
51
52 /* X.224 fields defining a sub tree */
53 static gint ett_x224           = -1;
54
55
56 /* find the dissector for T.125 */
57 static dissector_handle_t t125_handle;
58
59
60 typedef struct _x224_conv_info_t {
61         guint8  class;
62 } x224_conv_info_t;
63
64
65 #define X224_CODE_CR            0xE
66 #define X224_CODE_CC            0xD
67 #define X224_CODE_DR            0x8
68 #define X224_CODE_DC            0xC
69 #define X224_CODE_DT            0xF
70 #define X224_CODE_ED            0x1
71 #define X224_CODE_AK            0x6
72 #define X224_CODE_EA            0x2
73 #define X224_CODE_RJ            0x5
74 #define X224_CODE_ER            0x7
75
76 static const value_string code_vals[] = {
77         {X224_CODE_CR,          "Connection Request"},
78         {X224_CODE_CC,          "Connection Confirm"},
79         {X224_CODE_DR,          "Disconnect Request"},
80         {X224_CODE_DC,          "Disconnect Confirm"},
81         {X224_CODE_DT,          "Data"},
82         {X224_CODE_ED,          "Expedited Data"},
83         {X224_CODE_AK,          "Data Ack"},
84         {X224_CODE_EA,          "Expedited Data Ack"},
85         {X224_CODE_RJ,          "Reject"},
86         {X224_CODE_ER,          "Error"},
87         {0,NULL}
88 };
89
90 static const value_string class_option_vals[] = {
91         {0,     "Class 0"},
92         {1,     "Class 1"},
93         {2,     "Class 2"},
94         {3,     "Class 3"},
95         {4,     "Class 4"},
96         {0,NULL}
97 };
98
99 static int
100 dissect_x224_cr(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, x224_conv_info_t *x224_info _U_)
101 {
102         guint8 class;
103
104         /*DST-REF is always 0 */
105         offset+=2;
106
107         /*SRC-REF*/
108         proto_tree_add_item(tree, hf_x224_src_ref, tvb, offset, 2, FALSE);
109         offset+=2;
110
111         /* class options */
112         class = tvb_get_guint8(tvb, offset);
113         proto_tree_add_item(tree, hf_x224_class, tvb, offset, 1, FALSE);
114         offset+=1;
115
116         return offset;
117 }
118
119 static int
120 dissect_x224_cc(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, x224_conv_info_t *x224_info)
121 {
122         guint8 class;
123
124         /*DST-REF */
125         proto_tree_add_item(tree, hf_x224_dst_ref, tvb, offset, 2, FALSE);
126         offset+=2;
127
128         /*SRC-REF*/
129         proto_tree_add_item(tree, hf_x224_src_ref, tvb, offset, 2, FALSE);
130         offset+=2;
131
132         /* class options */
133         class = tvb_get_guint8(tvb, offset);
134         proto_tree_add_item(tree, hf_x224_class, tvb, offset, 1, FALSE);
135         x224_info->class = class;
136         offset+=1;
137
138         return offset;
139 }
140
141 static int
142 dissect_x224_dt(packet_info *pinfo _U_, proto_tree *tree, tvbuff_t *tvb, int offset, x224_conv_info_t *x224_info, proto_tree *parent_tree)
143 {
144         proto_item *item = NULL;
145         tvbuff_t *next_tvb;
146
147         switch (x224_info->class >>4) {
148         case 2:
149         case 3:
150         case 4:
151                 /*DST-REF */
152                 proto_tree_add_item(tree, hf_x224_dst_ref, tvb, offset, 2, FALSE);
153                 offset+=2;
154                 break;
155         }
156
157         item = proto_tree_add_uint(tree, hf_x224_class, tvb, 0, 0, x224_info->class);
158         PROTO_ITEM_SET_GENERATED(item);
159         
160
161         /* EOT / NR */
162         proto_tree_add_item(tree, hf_x224_eot, tvb, offset, 1, FALSE);
163         proto_tree_add_item(tree, hf_x224_nr, tvb, offset, 1, FALSE);
164         offset+=1;
165
166
167         next_tvb = tvb_new_subset(tvb, offset, -1, -1);
168         call_dissector(t125_handle, next_tvb, pinfo, parent_tree);
169
170         return offset;
171 }
172
173 static void
174 dissect_x224(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
175 {
176         proto_tree *tree = NULL;
177         proto_item *item = NULL;
178         int offset = 0 ;
179         guint8 code, length;
180         conversation_t *conversation;
181         x224_conv_info_t *x224_info;
182
183         if (check_col(pinfo->cinfo, COL_PROTOCOL)){
184                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X.224");
185         }
186         if (check_col(pinfo->cinfo, COL_INFO)){
187                 col_clear(pinfo->cinfo, COL_INFO);
188         }
189
190         length = tvb_get_guint8(tvb, offset);
191         if (parent_tree) {
192                 item = proto_tree_add_item(parent_tree, proto_x224, tvb, offset, length+1, FALSE);
193                 tree = proto_item_add_subtree(item, ett_x224);
194         }
195
196
197         /* length indicator */
198         proto_tree_add_item(tree, hf_x224_length, tvb, offset, 1, FALSE);
199         offset+=1;
200
201         /* code */
202         code = tvb_get_guint8(tvb, offset);
203         proto_tree_add_item(tree, hf_x224_code, tvb, offset, 1, FALSE);
204         offset+=1;
205
206         if (check_col(pinfo->cinfo, COL_INFO)) {
207                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%02x)",
208                         val_to_str(code>>4, code_vals, "Unknown code :%x"),
209                         code);
210         }
211
212
213
214         /*
215          * We need to track some state for this protocol on a per conversation
216          * basis so we can do neat things like request/response tracking
217          */
218         /*
219          * Do we have a conversation for this connection?
220          */
221         conversation = find_conversation(pinfo->fd->num,
222                                 &pinfo->src, &pinfo->dst,
223                                 pinfo->ptype,
224                                 pinfo->srcport, pinfo->destport, 0);
225         if (conversation == NULL) {
226                 /* We don't yet have a conversation, so create one. */
227                 conversation = conversation_new(pinfo->fd->num,
228                                 &pinfo->src, &pinfo->dst,
229                                 pinfo->ptype,
230                                 pinfo->srcport, pinfo->destport, 0);
231         }
232         /*
233          * Do we already have a state structure for this conv
234          */
235         x224_info = conversation_get_proto_data(conversation, proto_x224);
236         if (!x224_info) {
237                 /* No.  Attach that information to the conversation, and add
238                  * it to the list of information structures.
239                  */
240                 x224_info = se_alloc(sizeof(x224_conv_info_t));
241                 x224_info->class=0;
242
243                 conversation_add_proto_data(conversation, proto_x224, x224_info);
244        }
245
246         switch (code>>4) {
247         case X224_CODE_CR:
248                 offset = dissect_x224_cr(pinfo, tree, tvb, offset, x224_info);
249                 break;
250         case X224_CODE_CC:
251                 offset = dissect_x224_cc(pinfo, tree, tvb, offset, x224_info);
252                 break;
253         case X224_CODE_DR:
254                 /* XXX not implemented yet */
255                 break;
256         case X224_CODE_DC:
257                 /* XXX not implemented yet */
258                 break;
259         case X224_CODE_DT:
260                 offset = dissect_x224_dt(pinfo, tree, tvb, offset, x224_info, parent_tree);
261                 break;
262         case X224_CODE_ED:
263                 /* XXX not implemented yet */
264                 break;
265         case X224_CODE_AK:
266                 /* XXX not implemented yet */
267                 break;
268         case X224_CODE_EA:
269                 /* XXX not implemented yet */
270                 break;
271         case X224_CODE_RJ:
272                 /* XXX not implemented yet */
273                 break;
274         case X224_CODE_ER:
275                 /* XXX not implemented yet */
276                 break;
277         }
278 }
279
280 void
281 proto_register_x224(void)
282 {
283         static hf_register_info hf[] =
284         {
285         { &hf_x224_length, {
286         "Length", "x224.length", FT_UINT8, BASE_DEC,
287         NULL, 0, "", HFILL }},
288
289         { &hf_x224_code, {
290         "Code", "x224.code", FT_UINT8, BASE_HEX,
291         VALS(code_vals), 0xf0, "", HFILL }},
292
293         { &hf_x224_src_ref, {
294         "SRC-REF", "x224.src_ref", FT_UINT16, BASE_HEX,
295         NULL, 0, "", HFILL }},
296
297         { &hf_x224_dst_ref, {
298         "DST-REF", "x224.dst_ref", FT_UINT16, BASE_HEX,
299         NULL, 0, "", HFILL }},
300
301         { &hf_x224_class, {
302         "Class", "x224.class", FT_UINT8, BASE_HEX,
303         VALS(class_option_vals), 0xf0, "", HFILL }},
304
305         { &hf_x224_nr, {
306         "NR", "x224.nr", FT_UINT8, BASE_HEX,
307         NULL, 0x7f, "", HFILL }},
308
309         { &hf_x224_eot, {
310         "EOT", "x224.eot", FT_BOOLEAN, 8,
311         NULL, 0x80, "", HFILL }},
312
313         };
314
315         static gint *ett[] =
316         {
317                 &ett_x224,
318         };
319
320         proto_x224 = proto_register_protocol("ITU-T Rec X.224 ", "X.224", "x224");
321         proto_register_field_array(proto_x224, hf, array_length(hf));
322         proto_register_subtree_array(ett, array_length(ett));
323         register_dissector("x224", dissect_x224, proto_x224);
324
325 }
326
327 void
328 proto_reg_handoff_x224(void)
329 {
330         t125_handle = find_dissector("t125");
331 }