1 /* packet-sabp-template.c
2 * Routines for UTRAN Iu-BC Interface: Service Area Broadcast Protocol (SABP) packet dissection
3 * Copyright 2007, Tomas Kukosa <tomas.kukosa@siemens.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
11 * Ref: 3GPP TS 25.419 version V9.0.0 (2009-12)
16 #include <epan/packet.h>
18 #include <epan/asn1.h>
19 #include <wsutil/array.h>
21 #include "packet-tcp.h"
22 #include "packet-per.h"
23 #include "packet-e212.h"
24 #include "packet-gsm_map.h"
25 #include "packet-gsm_sms.h"
26 #include <epan/sctpppids.h>
27 #include "packet-cell_broadcast.h"
29 #define PNAME "UTRAN IuBC interface SABP signaling"
33 #include "packet-sabp-val.h"
35 void proto_register_sabp(void);
36 void proto_reg_handoff_sabp(void);
38 /* Initialize the protocol and registered fields */
39 static int proto_sabp
;
41 static int hf_sabp_no_of_pages
;
42 static int hf_sabp_cb_inf_len
;
43 static int hf_sabp_cb_msg_inf_page
;
44 static int hf_sabp_cbs_page_content
;
45 #include "packet-sabp-hf.c"
47 /* Initialize the subtree pointers */
49 static int ett_sabp_e212
;
50 static int ett_sabp_cbs_data_coding
;
51 static int ett_sabp_bcast_msg
;
52 static int ett_sabp_cbs_serial_number
;
53 static int ett_sabp_cbs_new_serial_number
;
54 static int ett_sabp_cbs_page
;
55 static int ett_sabp_cbs_page_content
;
57 #include "packet-sabp-ett.c"
59 /* Global variables */
60 static uint32_t ProcedureCode
;
61 static uint32_t ProtocolIE_ID
;
62 static uint32_t ProtocolExtensionID
;
63 static uint8_t sms_encoding
;
65 #define SABP_PORT 3452
67 /* Dissector tables */
68 static dissector_table_t sabp_ies_dissector_table
;
69 static dissector_table_t sabp_extension_dissector_table
;
70 static dissector_table_t sabp_proc_imsg_dissector_table
;
71 static dissector_table_t sabp_proc_sout_dissector_table
;
72 static dissector_table_t sabp_proc_uout_dissector_table
;
74 static dissector_handle_t sabp_handle
;
75 static dissector_handle_t sabp_tcp_handle
;
77 static int dissect_ProtocolIEFieldValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
78 static int dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
79 static int dissect_InitiatingMessageValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
80 static int dissect_SuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
81 static int dissect_UnsuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *);
82 static void dissect_sabp_cb_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
84 #include "packet-sabp-fn.c"
86 static int dissect_ProtocolIEFieldValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
88 return (dissector_try_uint(sabp_ies_dissector_table
, ProtocolIE_ID
, tvb
, pinfo
, tree
)) ? tvb_captured_length(tvb
) : 0;
91 static int dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
93 return (dissector_try_uint(sabp_extension_dissector_table
, ProtocolExtensionID
, tvb
, pinfo
, tree
)) ? tvb_captured_length(tvb
) : 0;
96 static int dissect_InitiatingMessageValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
98 return (dissector_try_uint(sabp_proc_imsg_dissector_table
, ProcedureCode
, tvb
, pinfo
, tree
)) ? tvb_captured_length(tvb
) : 0;
101 static int dissect_SuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
103 return (dissector_try_uint(sabp_proc_sout_dissector_table
, ProcedureCode
, tvb
, pinfo
, tree
)) ? tvb_captured_length(tvb
) : 0;
106 static int dissect_UnsuccessfulOutcomeValue(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
108 return (dissector_try_uint(sabp_proc_uout_dissector_table
, ProcedureCode
, tvb
, pinfo
, tree
)) ? tvb_captured_length(tvb
) : 0;
112 /* 3GPP TS 23.041 version 11.4.0
116 dissect_sabp_cb_data(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
118 proto_item
*cbs_page_item
;
120 tvbuff_t
*page_tvb
, *unpacked_tvb
;
123 uint8_t nr_pages
, len
, cb_inf_msg_len
;
126 /* Octet 1 Number-of-Pages */
127 nr_pages
= tvb_get_uint8(tvb
, offset
);
128 proto_tree_add_item(tree
, hf_sabp_no_of_pages
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
131 * NOTE: n equal to or less than 15
137 for (n
= 0; n
< nr_pages
; n
++) {
138 subtree
= proto_tree_add_subtree_format(tree
, tvb
, offset
, 83, ett_sabp_cbs_page
, NULL
,
139 "CB page %u data", n
+1);
140 /* octet 2 - 83 CBS-Message-Information-Page 1 */
141 cbs_page_item
= proto_tree_add_item(subtree
, hf_sabp_cb_msg_inf_page
, tvb
, offset
, 82, ENC_NA
);
142 cb_inf_msg_len
= tvb_get_uint8(tvb
,offset
+82);
143 page_tvb
= tvb_new_subset_length(tvb
, offset
, cb_inf_msg_len
);
144 unpacked_tvb
= dissect_cbs_data(sms_encoding
, page_tvb
, subtree
, pinfo
, 0);
145 len
= tvb_captured_length(unpacked_tvb
);
146 if (unpacked_tvb
!= NULL
){
148 proto_tree
*cbs_page_subtree
= proto_item_add_subtree(cbs_page_item
, ett_sabp_cbs_page_content
);
149 proto_tree_add_item(cbs_page_subtree
, hf_sabp_cbs_page_content
, unpacked_tvb
, 0, len
, ENC_UTF_8
);
154 /* 84 CBS-Message-Information-Length 1 */
155 proto_tree_add_item(subtree
, hf_sabp_cb_inf_len
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
161 dissect_sabp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
163 proto_item
*sabp_item
= NULL
;
164 proto_tree
*sabp_tree
= NULL
;
166 /* make entry in the Protocol column on summary display */
167 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, PSNAME
);
169 /* create the sabp protocol tree */
170 sabp_item
= proto_tree_add_item(tree
, proto_sabp
, tvb
, 0, -1, ENC_NA
);
171 sabp_tree
= proto_item_add_subtree(sabp_item
, ett_sabp
);
173 return dissect_SABP_PDU_PDU(tvb
, pinfo
, sabp_tree
, NULL
);
176 /* Note a little bit of a hack assumes length max takes two bytes and that the length starts at byte 4 */
178 dissect_sabp_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
180 uint32_t type_length
, msg_len
;
185 asn1_ctx_init(&asn1_ctx
, ASN1_ENC_PER
, true, pinfo
);
187 tvb_length
= tvb_reported_length(tvb
);
189 if (tvb_length
< 5) {
190 pinfo
->desegment_offset
= 0;
191 pinfo
->desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
192 return tvb_captured_length(tvb
);
195 /* Length should be in the 3:d octet */
197 /* Get the length of the sabp packet. Offset in bits */
199 bit_offset
= dissect_per_length_determinant(tvb
, bit_offset
, &asn1_ctx
, NULL
, -1, &type_length
, &is_fragmented
);
200 bit_offset
+= 8*type_length
;
201 msg_len
= (bit_offset
+ 7) >> 3;
203 /* Next length field will take 1 or 2 bytes; let's ask for the maximum */
206 if (msg_len
> tvb_length
) {
207 pinfo
->desegment_offset
= 0;
208 pinfo
->desegment_len
= msg_len
- tvb_length
;
209 return tvb_captured_length(tvb
);
211 } while (is_fragmented
);
213 return dissect_sabp(tvb
, pinfo
, tree
, data
);
216 /*--- proto_register_sabp -------------------------------------------*/
217 void proto_register_sabp(void) {
221 static hf_register_info hf
[] = {
222 { &hf_sabp_no_of_pages
,
223 { "Number-of-Pages", "sabp.no_of_pages",
224 FT_UINT8
, BASE_DEC
, NULL
, 0,
226 { &hf_sabp_cb_msg_inf_page
,
227 { "CBS-Message-Information-Page", "sabp.cb_msg_inf_page",
228 FT_BYTES
, BASE_NONE
, NULL
, 0,
230 { &hf_sabp_cbs_page_content
,
231 { "CBS Page Content", "sabp.cb_page_content",
232 FT_STRING
, BASE_NONE
, NULL
, 0,
234 { &hf_sabp_cb_inf_len
,
235 { "CBS-Message-Information-Length", "sabp.cb_inf_len",
236 FT_UINT8
, BASE_DEC
, NULL
, 0,
239 #include "packet-sabp-hfarr.c"
242 /* List of subtrees */
243 static int *ett
[] = {
246 &ett_sabp_cbs_data_coding
,
248 &ett_sabp_cbs_serial_number
,
249 &ett_sabp_cbs_new_serial_number
,
251 &ett_sabp_cbs_page_content
,
252 #include "packet-sabp-ettarr.c"
256 /* Register protocol */
257 proto_sabp
= proto_register_protocol(PNAME
, PSNAME
, PFNAME
);
258 /* Register fields and subtrees */
259 proto_register_field_array(proto_sabp
, hf
, array_length(hf
));
260 proto_register_subtree_array(ett
, array_length(ett
));
262 /* Register dissector */
263 sabp_handle
= register_dissector("sabp", dissect_sabp
, proto_sabp
);
264 sabp_tcp_handle
= register_dissector("sabp.tcp", dissect_sabp_tcp
, proto_sabp
);
266 /* Register dissector tables */
267 sabp_ies_dissector_table
= register_dissector_table("sabp.ies", "SABP-PROTOCOL-IES", proto_sabp
, FT_UINT32
, BASE_DEC
);
268 sabp_extension_dissector_table
= register_dissector_table("sabp.extension", "SABP-PROTOCOL-EXTENSION", proto_sabp
, FT_UINT32
, BASE_DEC
);
269 sabp_proc_imsg_dissector_table
= register_dissector_table("sabp.proc.imsg", "SABP-ELEMENTARY-PROCEDURE InitiatingMessage", proto_sabp
, FT_UINT32
, BASE_DEC
);
270 sabp_proc_sout_dissector_table
= register_dissector_table("sabp.proc.sout", "SABP-ELEMENTARY-PROCEDURE SuccessfulOutcome", proto_sabp
, FT_UINT32
, BASE_DEC
);
271 sabp_proc_uout_dissector_table
= register_dissector_table("sabp.proc.uout", "SABP-ELEMENTARY-PROCEDURE UnsuccessfulOutcome", proto_sabp
, FT_UINT32
, BASE_DEC
);
275 /*--- proto_reg_handoff_sabp ---------------------------------------*/
277 proto_reg_handoff_sabp(void)
279 dissector_add_uint_with_preference("udp.port", SABP_PORT
, sabp_handle
);
280 dissector_add_uint_with_preference("tcp.port", SABP_PORT
, sabp_tcp_handle
);
281 dissector_add_uint("sctp.ppi", SABP_PAYLOAD_PROTOCOL_ID
, sabp_handle
);
283 #include "packet-sabp-dis-tab.c"