#include <string.h> and/or #include <stdio.h> not needed.
[obnox/wireshark/wip.git] / asn1 / s1ap / packet-s1ap-template.c
1 /* packet-s1ap.c
2  * Routines for E-UTRAN S1 Application Protocol (S1AP) packet dissection
3  * Copyright 2007-2009, Anders Broman <anders.broman@ericsson.com>
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  * Based on the RANAP dissector
26  *
27  * References: 3GPP TS 36.413 V8.5.0 (2009-03)
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <glib.h>
35 #include <epan/packet.h>
36
37 #include <ctype.h>
38 #include <epan/strutil.h>
39 #include <epan/asn1.h>
40 #include <epan/prefs.h>
41 #include <epan/sctpppids.h>
42
43 #include "packet-ber.h"
44 #include "packet-per.h"
45 #include "packet-e212.h"
46 #include "packet-sccp.h"
47 #include "packet-lte-rrc.h"
48
49 #ifdef _MSC_VER
50 /* disable: "warning C4146: unary minus operator applied to unsigned type, result still unsigned" */
51 #pragma warning(disable:4146)
52 #endif
53
54 #define PNAME  "S1 Application Protocol"
55 #define PSNAME "S1AP"
56 #define PFNAME "s1ap"
57
58 /* Dissector will use SCTP PPID 18 or SCTP port. IANA assigned port = 36412 */
59 #define SCTP_PORT_S1AP  36412
60
61 static dissector_handle_t nas_eps_handle;
62
63 #include "packet-s1ap-val.h"
64
65 /* Initialize the protocol and registered fields */
66 static int proto_s1ap = -1;
67
68 static int hf_s1ap_transportLayerAddressIPv4 = -1;
69 static int hf_s1ap_transportLayerAddressIPv6 = -1;
70 #include "packet-s1ap-hf.c"
71
72 /* Initialize the subtree pointers */
73 static int ett_s1ap = -1;
74 static int ett_s1ap_TransportLayerAddress = -1;
75 static int ett_s1ap_ToTargetTransparentContainer = -1;
76 static int ett_s1ap_ToSourceTransparentContainer = -1;
77 static int ett_s1ap_RRCContainer = -1;
78
79 #include "packet-s1ap-ett.c"
80
81 enum{
82         INITIATING_MESSAGE,
83         SUCCESSFUL_OUTCOME,
84         UNSUCCESSFUL_OUTCOME
85 };
86
87 /* Global variables */
88 static guint32 ProcedureCode;
89 static guint32 ProtocolIE_ID;
90 static guint32 ProtocolExtensionID;
91 static guint gbl_s1apSctpPort=SCTP_PORT_S1AP;
92 static guint32 handover_type_value;
93 static guint32 message_type;
94
95 /* Dissector tables */
96 static dissector_table_t s1ap_ies_dissector_table;
97 static dissector_table_t s1ap_ies_p1_dissector_table;
98 static dissector_table_t s1ap_ies_p2_dissector_table;
99 static dissector_table_t s1ap_extension_dissector_table;
100 static dissector_table_t s1ap_proc_imsg_dissector_table;
101 static dissector_table_t s1ap_proc_sout_dissector_table;
102 static dissector_table_t s1ap_proc_uout_dissector_table;
103
104 static int dissect_ProtocolIEFieldValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
105 /* Currently not used
106 static int dissect_ProtocolIEFieldPairFirstValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
107 static int dissect_ProtocolIEFieldPairSecondValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
108 */
109 static int dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
110 static int dissect_InitiatingMessageValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
111 static int dissect_SuccessfulOutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
112 static int dissect_UnsuccessfulOutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
113
114 static int dissect_SourceeNB_ToTargeteNB_TransparentContainer_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
115 static int dissect_TargeteNB_ToSourceeNB_TransparentContainer_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
116 static int dissect_SourceRNC_ToTargetRNC_TransparentContainer_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
117 static int dissect_TargetRNC_ToSourceRNC_TransparentContainer_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
118 static int dissect_SourceBSS_ToTargetBSS_TransparentContainer_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
119 static int dissect_TargetBSS_ToSourceBSS_TransparentContainer_PDU(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
120
121 #include "packet-s1ap-fn.c"
122
123 static int dissect_ProtocolIEFieldValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
124 {
125   return (dissector_try_port(s1ap_ies_dissector_table, ProtocolIE_ID, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
126 }
127 /* Currently not used
128 static int dissect_ProtocolIEFieldPairFirstValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
129 {
130   return (dissector_try_port(s1ap_ies_p1_dissector_table, ProtocolIE_ID, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
131 }
132
133 static int dissect_ProtocolIEFieldPairSecondValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
134 {
135   return (dissector_try_port(s1ap_ies_p2_dissector_table, ProtocolIE_ID, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
136 }
137 */
138
139 static int dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
140 {
141   return (dissector_try_port(s1ap_extension_dissector_table, ProtocolExtensionID, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
142 }
143
144 static int dissect_InitiatingMessageValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
145 {
146   return (dissector_try_port(s1ap_proc_imsg_dissector_table, ProcedureCode, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
147 }
148
149 static int dissect_SuccessfulOutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
150 {
151   return (dissector_try_port(s1ap_proc_sout_dissector_table, ProcedureCode, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
152 }
153
154 static int dissect_UnsuccessfulOutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
155 {
156   return (dissector_try_port(s1ap_proc_uout_dissector_table, ProcedureCode, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
157 }
158
159
160 static void
161 dissect_s1ap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
162 {
163         proto_item      *s1ap_item = NULL;
164         proto_tree      *s1ap_tree = NULL;
165
166         /* make entry in the Protocol column on summary display */
167         col_set_str(pinfo->cinfo, COL_PROTOCOL, "S1AP");
168
169         /* create the s1ap protocol tree */
170         s1ap_item = proto_tree_add_item(tree, proto_s1ap, tvb, 0, -1, FALSE);
171         s1ap_tree = proto_item_add_subtree(s1ap_item, ett_s1ap);
172         
173         dissect_S1AP_PDU_PDU(tvb, pinfo, s1ap_tree);
174 }
175
176 /*--- proto_reg_handoff_s1ap ---------------------------------------*/
177 void
178 proto_reg_handoff_s1ap(void)
179 {
180         static gboolean Initialized=FALSE;
181         static dissector_handle_t s1ap_handle;
182         static guint SctpPort;
183
184         s1ap_handle = find_dissector("s1ap");
185
186         if (!Initialized) {
187                 nas_eps_handle = find_dissector("nas-eps");
188                 dissector_add_handle("sctp.port", s1ap_handle);   /* for "decode-as"  */
189                 dissector_add("sctp.ppi", S1AP_PAYLOAD_PROTOCOL_ID,   s1ap_handle);
190                 Initialized=TRUE;
191 #include "packet-s1ap-dis-tab.c"
192         } else {
193                 if (SctpPort != 0) {
194                         dissector_delete("sctp.port", SctpPort, s1ap_handle);
195                 }
196         }
197
198         SctpPort=gbl_s1apSctpPort;
199         if (SctpPort != 0) {
200                 dissector_add("sctp.port", SctpPort, s1ap_handle);
201         }
202 }
203
204 /*--- proto_register_s1ap -------------------------------------------*/
205 void proto_register_s1ap(void) {
206
207   /* List of fields */
208
209   static hf_register_info hf[] = {
210     { &hf_s1ap_transportLayerAddressIPv4,
211       { "transportLayerAddress(IPv4)", "s1ap.transportLayerAddressIPv4",
212         FT_IPv4, BASE_NONE, NULL, 0,
213         NULL, HFILL }},
214     { &hf_s1ap_transportLayerAddressIPv6,
215       { "transportLayerAddress(IPv6)", "s1ap.transportLayerAddressIPv6",
216         FT_IPv4, BASE_NONE, NULL, 0,
217         NULL, HFILL }},
218
219 #include "packet-s1ap-hfarr.c"
220   };
221
222   /* List of subtrees */
223   static gint *ett[] = {
224                   &ett_s1ap,
225                   &ett_s1ap_TransportLayerAddress,
226                   &ett_s1ap_ToTargetTransparentContainer,
227                   &ett_s1ap_ToSourceTransparentContainer,
228                   &ett_s1ap_RRCContainer,
229 #include "packet-s1ap-ettarr.c"
230   };
231
232   module_t *s1ap_module;
233
234   /* Register protocol */
235   proto_s1ap = proto_register_protocol(PNAME, PSNAME, PFNAME);
236   /* Register fields and subtrees */
237   proto_register_field_array(proto_s1ap, hf, array_length(hf));
238   proto_register_subtree_array(ett, array_length(ett));
239  
240   /* Register dissector */
241   register_dissector("s1ap", dissect_s1ap, proto_s1ap);
242
243   /* Register dissector tables */
244   s1ap_ies_dissector_table = register_dissector_table("s1ap.ies", "S1AP-PROTOCOL-IES", FT_UINT32, BASE_DEC);
245   s1ap_ies_p1_dissector_table = register_dissector_table("s1ap.ies.pair.first", "S1AP-PROTOCOL-IES-PAIR FirstValue", FT_UINT32, BASE_DEC);
246   s1ap_ies_p2_dissector_table = register_dissector_table("s1ap.ies.pair.second", "S1AP-PROTOCOL-IES-PAIR SecondValue", FT_UINT32, BASE_DEC);
247   s1ap_extension_dissector_table = register_dissector_table("s1ap.extension", "S1AP-PROTOCOL-EXTENSION", FT_UINT32, BASE_DEC);
248   s1ap_proc_imsg_dissector_table = register_dissector_table("s1ap.proc.imsg", "S1AP-ELEMENTARY-PROCEDURE InitiatingMessage", FT_UINT32, BASE_DEC);
249   s1ap_proc_sout_dissector_table = register_dissector_table("s1ap.proc.sout", "S1AP-ELEMENTARY-PROCEDURE SuccessfulOutcome", FT_UINT32, BASE_DEC);
250   s1ap_proc_uout_dissector_table = register_dissector_table("s1ap.proc.uout", "S1AP-ELEMENTARY-PROCEDURE UnsuccessfulOutcome", FT_UINT32, BASE_DEC);
251   
252   /* Register configuration options for ports */
253   s1ap_module = prefs_register_protocol(proto_s1ap, proto_reg_handoff_s1ap);
254
255   prefs_register_uint_preference(s1ap_module, "sctp.port",
256                                  "S1AP SCTP Port",
257                                  "Set the SCTP port for S1AP messages",
258                                  10,
259                                  &gbl_s1apSctpPort);
260
261 }
262
263
264
265
266