From Joerg Mayer: explicitly fill in all members of a
[obnox/wireshark/wip.git] / packet-mtp3.c
1 /* packet-mtp3.c
2  * Routines for Message Transfer Part Level 3 dissection
3  * Copyright 2001, Michael Tuexen <Michael.Tuexen@icn.siemens.de>
4  *
5  * $Id: packet-mtp3.c,v 1.4 2001/06/18 02:17:49 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from README.developer
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
38 #endif
39
40 #ifdef HAVE_NETINET_IN_H
41 # include <netinet/in.h>
42 #endif
43
44 #include <glib.h>
45
46 #include "packet.h"
47 #include "prefs.h"
48
49 /* Initialize the protocol and registered fields */
50 static int proto_mtp3  = -1;
51 static module_t *mtp3_module;
52
53 static int hf_mtp3_service_indicator = -1;
54 static int hf_mtp3_network_indicator = -1;
55 static int hf_mtp3_spare = -1;
56 static int hf_mtp3_opc = -1;
57 static int hf_mtp3_dpc = -1;
58 static int hf_mtp3_sls = -1;
59
60 /* Initialize the subtree pointers */
61 static gint ett_mtp3 = -1;
62 static gint ett_mtp3_sio = -1;
63 static gint ett_mtp3_label = -1;
64
65 static dissector_table_t mtp3_sio_dissector_table;
66
67 #define ITU_STANDARD   1
68 #define ANSI_STANDARD  2
69
70 static gint mtp3_standard = ITU_STANDARD;
71  
72 #define ITU_SIO_OFFSET 0
73 #define ITU_SIO_LENGTH 1
74 #define ITU_ROUTING_LABEL_OFFSET 1
75 #define ITU_ROUTING_LABEL_LENGTH 4
76 #define ITU_MTP_PAYLOAD_OFFSET 5
77
78 #define SERVICE_INDICATOR_MASK 0x0F
79 #define SPARE_MASK 0x30
80 #define NETWORK_INDICATOR_MASK 0xC0
81 #define DPC_MASK 0x00003FFF
82 #define OPC_MASK 0x0FFFC000
83 #define SLS_MASK 0xF0000000
84
85 static const value_string service_indicator_code_vals[] = {
86         { 0x0,  "Signalling network management message" },
87         { 0x1,  "Signalling network testing and maintenance message" },
88         { 0x2,  "Spare" },
89         { 0x3,  "SCCP" },
90         { 0x4,  "TUP" },
91         { 0x5,  "ISUP" },
92         { 0x6,  "DUP (call and circuit related messages)" },
93         { 0x7,  "DUP (facility registration and cancellation message)" },
94         { 0x8,  "MTP testing user part" },
95         { 0x9,  "Spare" },
96         { 0xa,  "Spare" },
97         { 0xb,  "Spare" },
98         { 0xc,  "Spare" },
99         { 0xd,  "Spare" },
100         { 0xe,  "Spare" },
101         { 0xf,  "Spare" },
102         { 0,    NULL }
103 };
104
105 static const value_string network_indicator_vals[] = {
106         { 0x0,  "International network" },
107         { 0x1,  "Spare (for international use only)" },
108         { 0x2,  "National network" },
109         { 0x3,  "Reserved for national use" },
110         { 0,    NULL }
111 };
112
113 static void
114 dissect_mtp3_sio(tvbuff_t *tvb, proto_tree *mtp3_tree)
115 {
116   guint8 sio;
117   proto_item *sio_item;
118   proto_tree *sio_tree;
119   
120   sio_item = proto_tree_add_text(mtp3_tree, tvb, ITU_SIO_OFFSET, ITU_SIO_LENGTH, "Service information octet");    
121   sio_tree = proto_item_add_subtree(sio_item, ett_mtp3_sio);
122
123   sio = tvb_get_guint8(tvb, ITU_SIO_OFFSET);
124   proto_tree_add_uint(sio_tree, hf_mtp3_network_indicator,
125                       tvb, ITU_SIO_OFFSET, ITU_SIO_LENGTH,
126                       sio);
127   proto_tree_add_uint(sio_tree, hf_mtp3_spare,
128                       tvb, ITU_SIO_OFFSET, ITU_SIO_LENGTH,
129                       sio);
130   proto_tree_add_uint(sio_tree, hf_mtp3_service_indicator,
131                       tvb, ITU_SIO_OFFSET, ITU_SIO_LENGTH,
132                       sio);
133 }
134
135 static void
136 dissect_mtp3_routing_label(tvbuff_t *tvb, proto_tree *mtp3_tree)
137 {
138   guint32 label;
139   proto_item *label_item;
140   proto_tree *label_tree;
141   
142   label_item = proto_tree_add_text(mtp3_tree, tvb, ITU_ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, "Routing label");    
143   label_tree = proto_item_add_subtree(label_item, ett_mtp3_label);
144
145   label = tvb_get_letohl(tvb, ITU_ROUTING_LABEL_OFFSET);
146   proto_tree_add_uint(label_tree, hf_mtp3_dpc,
147                       tvb, ITU_ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH,
148                       label);
149   proto_tree_add_uint(label_tree, hf_mtp3_opc,
150                       tvb, ITU_ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH,
151                       label);
152   proto_tree_add_uint(label_tree, hf_mtp3_sls,
153                       tvb, ITU_ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH,
154                       label);
155 }
156
157 static void
158 dissect_mtp3_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
159 {
160   guint8 sio;
161   guint8 service_indicator;
162   tvbuff_t *payload_tvb;
163
164   sio = tvb_get_guint8(tvb, ITU_SIO_OFFSET);
165   service_indicator = sio & SERVICE_INDICATOR_MASK;
166   payload_tvb = tvb_new_subset(tvb, ITU_MTP_PAYLOAD_OFFSET, -1, -1);
167   if (!dissector_try_port(mtp3_sio_dissector_table, service_indicator, payload_tvb, pinfo, tree)) {
168     proto_tree_add_text(tree, payload_tvb, 0, tvb_length(payload_tvb),
169                         "Payload (%u byte%s)",
170                         tvb_length(payload_tvb), plurality(tvb_length(payload_tvb), "", "s")); 
171   }
172 }
173
174 /* Code to actually dissect the packets */
175 static void
176 dissect_mtp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
177 {
178
179   /* Set up structures needed to add the protocol subtree and manage it */
180   proto_item *mtp3_item;
181   proto_tree *mtp3_tree;
182
183   /* Make entries in Protocol column and Info column on summary display */
184   if (check_col(pinfo->fd, COL_PROTOCOL)) 
185     col_set_str(pinfo->fd, COL_PROTOCOL, "MTP3");    
186   if (check_col(pinfo->fd, COL_INFO)) 
187     col_clear(pinfo->fd, COL_INFO);
188
189   /* In the interest of speed, if "tree" is NULL, don't do any work not
190      necessary to generate protocol tree items. */
191
192   if (tree) {
193
194     /* create display subtree for the protocol */
195     mtp3_item = proto_tree_add_item(tree, proto_mtp3, tvb, 0, tvb_length(tvb), FALSE);    
196     mtp3_tree = proto_item_add_subtree(mtp3_item, ett_mtp3);
197     
198     /* dissect the packet */
199     dissect_mtp3_sio(tvb, mtp3_tree);
200     dissect_mtp3_routing_label(tvb, mtp3_tree);
201     dissect_mtp3_payload(tvb, pinfo, tree);    
202   }
203 }
204
205 void
206 proto_register_mtp3(void)
207 {                 
208   
209   /* Setup list of header fields  See Section 1.6.1 for details*/
210   static hf_register_info hf[] = {
211     { &hf_mtp3_service_indicator,
212       { "Service indicator",
213         "mtp3.service_indicator",
214         FT_UINT8, BASE_HEX, VALS(service_indicator_code_vals), SERVICE_INDICATOR_MASK,          
215         "", HFILL }}, 
216     { &hf_mtp3_network_indicator,
217       { "Network indicator",
218         "mtp3.network_indicator",
219         FT_UINT8, BASE_HEX, VALS(network_indicator_vals), NETWORK_INDICATOR_MASK,          
220         "", HFILL }}, 
221     { &hf_mtp3_spare,
222       { "Spare",
223         "mtp3.spare",
224         FT_UINT8, BASE_HEX, NULL, SPARE_MASK,          
225         "", HFILL }}, 
226     { &hf_mtp3_opc,
227       { "OPC",
228         "mtp3.opc",
229         FT_UINT32, BASE_DEC, NULL, OPC_MASK,          
230         "", HFILL }}, 
231     { &hf_mtp3_dpc,
232       { "DPC",
233         "mtp3.dpc",
234         FT_UINT32, BASE_DEC, NULL, DPC_MASK,          
235         "", HFILL }}, 
236     { &hf_mtp3_sls,
237       { "SLS",
238         "mtp3.sls",
239         FT_UINT32, BASE_DEC, NULL, SLS_MASK,          
240         "", HFILL }}, 
241   };
242   
243   /* Setup protocol subtree array */
244   static gint *ett[] = {
245     &ett_mtp3,
246     &ett_mtp3_sio,
247     &ett_mtp3_label
248   };
249
250   static enum_val_t mtp3_options[] = {
251     {"ITU",  ITU_STANDARD},
252     /*    {"ANSI", ANSI_STANDARD}, */
253     {NULL, 0}
254   };
255   
256   /* Register the protocol name and description */
257   proto_mtp3 = proto_register_protocol("Message Transfer Part Level 3",
258                                        "MTP3", "mtp3");
259   
260   /* Required function calls to register the header fields and subtrees used */
261   proto_register_field_array(proto_mtp3, hf, array_length(hf));
262   proto_register_subtree_array(ett, array_length(ett));
263
264   /* Register the dissector */
265   register_dissector("mtp3", dissect_mtp3, proto_mtp3);
266
267   mtp3_sio_dissector_table = register_dissector_table("mtp3.service_indicator");
268   
269   mtp3_module = prefs_register_protocol(proto_mtp3, NULL);
270
271   prefs_register_enum_preference(mtp3_module, 
272                                  "mtp3_standard",
273                                  "MTP3 standard",
274                                  "MTP3 standard", 
275                                  &mtp3_standard,
276                                  mtp3_options, FALSE);
277 }