/src/wireshark/epan/dissectors/packet-gsm_a_rp.c
Line | Count | Source |
1 | | /* packet-gsm_a_rp.c |
2 | | * Routines for GSM A Interface RP dissection - SMS GSM layer 3 |
3 | | * |
4 | | * Copyright 2003, Michael Lum <mlum [AT] telostech.com> |
5 | | * In association with Telos Technology Inc. |
6 | | * |
7 | | * Title 3GPP Other |
8 | | * |
9 | | * Reference [5] |
10 | | * Point-to-Point (PP) Short Message Service (SMS) |
11 | | * support on mobile radio interface |
12 | | * (3GPP TS 24.011 version 4.1.1 Release 4) |
13 | | * |
14 | | * Wireshark - Network traffic analyzer |
15 | | * By Gerald Combs <gerald@wireshark.org> |
16 | | * Copyright 1998 Gerald Combs |
17 | | * |
18 | | * SPDX-License-Identifier: GPL-2.0-or-later |
19 | | */ |
20 | | |
21 | | #include "config.h" |
22 | | |
23 | | #include <epan/packet.h> |
24 | | #include <epan/expert.h> |
25 | | #include <epan/proto_data.h> |
26 | | #include <epan/tfs.h> |
27 | | #include <wsutil/wsjson.h> |
28 | | #include <wsutil/array.h> |
29 | | |
30 | | #include "packet-gsm_a_common.h" |
31 | | #include "packet-media-type.h" |
32 | | |
33 | | void proto_register_gsm_a_rp(void); |
34 | | void proto_reg_handoff_gsm_a_rp(void); |
35 | | |
36 | | /* PROTOTYPES/FORWARDS */ |
37 | | |
38 | | static const value_string gsm_rp_msg_strings[] = { |
39 | | { 0x00, "RP-DATA (MS to Network)" }, |
40 | | { 0x01, "RP-DATA (Network to MS)" }, |
41 | | { 0x02, "RP-ACK (MS to Network)" }, |
42 | | { 0x03, "RP-ACK (Network to MS)" }, |
43 | | { 0x04, "RP-ERROR (MS to Network)" }, |
44 | | { 0x05, "RP-ERROR (Network to MS)" }, |
45 | | { 0x06, "RP-SMMA (MS to Network)" }, |
46 | | { 0, NULL } |
47 | | }; |
48 | | |
49 | | typedef enum |
50 | | { |
51 | | /* Short Message Service Information Elements [5] 8.2 */ |
52 | | DE_RP_MESSAGE_REF, /* RP-Message Reference */ |
53 | | DE_RP_ORIG_ADDR, /* RP-Originator Address */ |
54 | | DE_RP_DEST_ADDR, /* RP-Destination Address */ |
55 | | DE_RP_USER_DATA, /* RP-User Data */ |
56 | | DE_RP_CAUSE, /* RP-Cause */ |
57 | | DE_RP_NONE /* NONE */ |
58 | | } |
59 | | rp_elem_idx_t; |
60 | | |
61 | | static const value_string gsm_rp_elem_strings[] = { |
62 | | /* Short Message Service RP Information Elements [5] 8.2 */ |
63 | | { DE_RP_MESSAGE_REF, "RP-Message Reference" }, |
64 | | { DE_RP_ORIG_ADDR, "RP-Originator Address" }, |
65 | | { DE_RP_DEST_ADDR, "RP-Destination Address" }, |
66 | | { DE_RP_USER_DATA, "RP-User Data" }, |
67 | | { DE_RP_CAUSE, "RP-Cause" }, |
68 | | { 0, NULL } |
69 | | }; |
70 | | value_string_ext gsm_rp_elem_strings_ext = VALUE_STRING_EXT_INIT(gsm_rp_elem_strings); |
71 | | |
72 | | /* Initialize the protocol and registered fields */ |
73 | | static int proto_a_rp; |
74 | | |
75 | | static int hf_gsm_a_rp_msg_type; |
76 | | int hf_gsm_a_rp_elem_id; |
77 | | /* Generated from convert_proto_tree_add_text.pl */ |
78 | | static int hf_gsm_a_rp_tpdu; |
79 | | static int hf_gsm_a_rp_extension; |
80 | | static int hf_gsm_a_rp_diagnostic_field; |
81 | | static int hf_gsm_a_rp_cause; |
82 | | static int hf_gsm_a_rp_message_elements; |
83 | | static int hf_gsm_a_rp_rp_message_reference; |
84 | | |
85 | | /* Initialize the subtree pointers */ |
86 | | static int ett_rp_msg; |
87 | | |
88 | | static expert_field ei_gsm_a_rp_extraneous_data; |
89 | | static expert_field ei_gsm_a_rp_missing_mandatory_element; |
90 | | |
91 | | static dissector_handle_t gsm_sms_handle; /* SMS TPDU */ |
92 | | static dissector_handle_t gsm_a_dtap_handle; |
93 | | |
94 | | static int proto_json; |
95 | | |
96 | 112 | #define NUM_GSM_RP_ELEM array_length(gsm_rp_elem_strings) |
97 | | int ett_gsm_rp_elem[NUM_GSM_RP_ELEM]; |
98 | | |
99 | | /* |
100 | | * [5] 8.2.3 |
101 | | */ |
102 | | static uint16_t |
103 | | de_rp_message_ref(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, uint32_t offset, unsigned len _U_, char *add_string _U_, int string_len _U_) |
104 | 26 | { |
105 | 26 | uint32_t curr_offset; |
106 | | |
107 | 26 | curr_offset = offset; |
108 | | |
109 | 26 | proto_tree_add_item(tree, hf_gsm_a_rp_rp_message_reference, tvb, curr_offset, 1, ENC_BIG_ENDIAN); |
110 | | |
111 | 26 | curr_offset++; |
112 | | |
113 | | /* no length check possible */ |
114 | | |
115 | 26 | return curr_offset - offset; |
116 | 26 | } |
117 | | |
118 | | /* |
119 | | * [5] 8.2.5.1 |
120 | | */ |
121 | | static uint16_t |
122 | | de_rp_orig_addr(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, uint32_t offset, unsigned len, char *add_string, int string_len) |
123 | 5 | { |
124 | 5 | return de_clg_party_bcd_num(tvb, tree, pinfo, offset, len, add_string, string_len); |
125 | 5 | } |
126 | | |
127 | | /* |
128 | | * [5] 8.2.5.2 |
129 | | */ |
130 | | static uint16_t |
131 | | de_rp_dest_addr(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, uint32_t offset, unsigned len, char *add_string, int string_len) |
132 | 6 | { |
133 | 6 | return de_cld_party_bcd_num(tvb, tree, pinfo, offset, len, add_string, string_len); |
134 | 6 | } |
135 | | |
136 | | /* |
137 | | * [5] 8.2.5.3 |
138 | | */ |
139 | | static uint16_t |
140 | | de_rp_user_data(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t offset, unsigned len, char *add_string _U_, int string_len _U_) |
141 | 11 | { |
142 | 11 | uint32_t curr_offset; |
143 | 11 | tvbuff_t *tpdu_tvb; |
144 | | |
145 | 11 | curr_offset = offset; |
146 | | |
147 | 11 | proto_tree_add_bytes_format(tree, hf_gsm_a_rp_tpdu, tvb, curr_offset, len, NULL, "TPDU (not displayed)"); |
148 | | |
149 | | /* |
150 | | * dissect the embedded TPDU message |
151 | | */ |
152 | 11 | tpdu_tvb = tvb_new_subset_length(tvb, curr_offset, len); |
153 | | |
154 | 11 | call_dissector_only(gsm_sms_handle, tpdu_tvb, pinfo, proto_tree_get_parent_tree(tree), NULL); |
155 | | |
156 | 11 | curr_offset += len; |
157 | | |
158 | 11 | EXTRANEOUS_DATA_CHECK(len, curr_offset - offset, pinfo, &ei_gsm_a_rp_extraneous_data); |
159 | | |
160 | 11 | return curr_offset - offset; |
161 | 11 | } |
162 | | |
163 | | /* |
164 | | * [5] 8.2.5.4 |
165 | | */ |
166 | | static const value_string gsm_rp_cause_vals[] = { |
167 | | { 1, "Unassigned (unallocated) number" }, |
168 | | { 8, "Operator determined barring" }, |
169 | | { 10, "Call barred" }, |
170 | | { 11, "Reserved" }, |
171 | | { 21, "Short message transfer rejected" }, |
172 | | { 22, "Memory capacity exceeded" }, |
173 | | { 27, "Destination out of order" }, |
174 | | { 28, "Unidentified subscriber" }, |
175 | | { 29, "Facility rejected" }, |
176 | | { 30, "Unknown subscriber" }, |
177 | | { 38, "Network out of order" }, |
178 | | { 41, "Temporary failure" }, |
179 | | { 42, "Congestion" }, |
180 | | { 47, "Resources unavailable, unspecified" }, |
181 | | { 50, "Requested facility not subscribed" }, |
182 | | { 69, "Requested facility not implemented" }, |
183 | | { 81, "Invalid short message transfer reference value" }, |
184 | | { 95, "Semantically incorrect message" }, |
185 | | { 96, "Invalid mandatory information" }, |
186 | | { 97, "Message type non-existent or not implemented" }, |
187 | | { 98, "Message not compatible with short message protocol state" }, |
188 | | { 99, "Information element non-existent or not implemented" }, |
189 | | { 111, "Protocol error, unspecified" }, |
190 | | { 127, "Interworking, unspecified" }, |
191 | | { 0, NULL } |
192 | | }; |
193 | | |
194 | | static value_string_ext gsm_rp_cause_vals_ext = VALUE_STRING_EXT_INIT(gsm_rp_cause_vals); |
195 | | |
196 | | static const true_false_string tfs_extended_no_extension = { "Extended", "No extension"}; |
197 | | |
198 | | static uint16_t |
199 | | de_rp_cause(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, uint32_t offset, unsigned len, char *add_string, int string_len) |
200 | 5 | { |
201 | 5 | uint8_t oct; |
202 | 5 | uint32_t curr_offset; |
203 | | |
204 | 5 | curr_offset = offset; |
205 | | |
206 | 5 | oct = tvb_get_uint8(tvb, curr_offset); |
207 | | |
208 | 5 | proto_tree_add_item(tree, hf_gsm_a_rp_extension, tvb, curr_offset, 1, ENC_NA); |
209 | 5 | proto_tree_add_item(tree, hf_gsm_a_rp_cause, tvb, curr_offset, 1, ENC_BIG_ENDIAN); |
210 | | |
211 | 5 | curr_offset++; |
212 | | |
213 | 5 | if (add_string) |
214 | 5 | snprintf(add_string, string_len, " - (%u) %s", oct & 0x7f, val_to_str_ext_const(oct & 0x7f, &gsm_rp_cause_vals_ext, "Reserved")); |
215 | | |
216 | 5 | NO_MORE_DATA_CHECK(len); |
217 | | |
218 | 3 | proto_tree_add_item(tree, hf_gsm_a_rp_diagnostic_field, tvb, curr_offset, len - (curr_offset - offset), ENC_NA); |
219 | | |
220 | 3 | curr_offset += len - (curr_offset - offset); |
221 | | |
222 | 3 | EXTRANEOUS_DATA_CHECK(len, curr_offset - offset, pinfo, &ei_gsm_a_rp_extraneous_data); |
223 | | |
224 | 3 | return curr_offset - offset; |
225 | 5 | } |
226 | | |
227 | | uint16_t (* const rp_elem_fcn[])(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t offset, unsigned len, char *add_string, int string_len) = { |
228 | | /* Short Message Service Information Elements [5] 8.2 */ |
229 | | de_rp_message_ref, /* RP-Message Reference */ |
230 | | de_rp_orig_addr, /* RP-Originator Address */ |
231 | | de_rp_dest_addr, /* RP-Destination Address */ |
232 | | de_rp_user_data, /* RP-User Data */ |
233 | | de_rp_cause, /* RP-Cause */ |
234 | | NULL, /* NONE */ |
235 | | }; |
236 | | |
237 | | /* MESSAGE FUNCTIONS */ |
238 | | |
239 | | /* |
240 | | * [5] 7.3.1.1 |
241 | | */ |
242 | | void |
243 | | rp_data_n_ms(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t offset, unsigned len) |
244 | 3 | { |
245 | 3 | uint32_t curr_offset; |
246 | 3 | uint32_t consumed; |
247 | 3 | unsigned curr_len; |
248 | | |
249 | 3 | curr_offset = offset; |
250 | 3 | curr_len = len; |
251 | | |
252 | 3 | pinfo->p2p_dir = P2P_DIR_SENT; |
253 | | |
254 | 3 | ELEM_MAND_V(GSM_A_PDU_TYPE_RP, DE_RP_MESSAGE_REF, NULL, ei_gsm_a_rp_missing_mandatory_element); |
255 | | |
256 | 3 | ELEM_MAND_LV(GSM_A_PDU_TYPE_RP, DE_RP_ORIG_ADDR, NULL, ei_gsm_a_rp_missing_mandatory_element); |
257 | | |
258 | 3 | ELEM_MAND_LV(GSM_A_PDU_TYPE_RP, DE_RP_DEST_ADDR, NULL, ei_gsm_a_rp_missing_mandatory_element); |
259 | | |
260 | 3 | ELEM_MAND_LV(GSM_A_PDU_TYPE_RP, DE_RP_USER_DATA, NULL, ei_gsm_a_rp_missing_mandatory_element); |
261 | | |
262 | 3 | EXTRANEOUS_DATA_CHECK(curr_len, 0, pinfo, &ei_gsm_a_rp_extraneous_data); |
263 | 3 | } |
264 | | |
265 | | /* |
266 | | * [5] 7.3.1.2 |
267 | | */ |
268 | | static void |
269 | | rp_data_ms_n(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t offset, unsigned len) |
270 | 10 | { |
271 | 10 | uint32_t curr_offset; |
272 | 10 | uint32_t consumed; |
273 | 10 | unsigned curr_len; |
274 | | |
275 | 10 | curr_offset = offset; |
276 | 10 | curr_len = len; |
277 | | |
278 | 10 | pinfo->p2p_dir = P2P_DIR_RECV; |
279 | | |
280 | 10 | ELEM_MAND_V(GSM_A_PDU_TYPE_RP, DE_RP_MESSAGE_REF, NULL, ei_gsm_a_rp_missing_mandatory_element); |
281 | | |
282 | 10 | ELEM_MAND_LV(GSM_A_PDU_TYPE_RP, DE_RP_ORIG_ADDR, NULL, ei_gsm_a_rp_missing_mandatory_element); |
283 | | |
284 | 10 | ELEM_MAND_LV(GSM_A_PDU_TYPE_RP, DE_RP_DEST_ADDR, NULL, ei_gsm_a_rp_missing_mandatory_element); |
285 | | |
286 | 10 | ELEM_MAND_LV(GSM_A_PDU_TYPE_RP, DE_RP_USER_DATA, NULL, ei_gsm_a_rp_missing_mandatory_element); |
287 | | |
288 | 10 | EXTRANEOUS_DATA_CHECK(curr_len, 0, pinfo, &ei_gsm_a_rp_extraneous_data); |
289 | 10 | } |
290 | | |
291 | | /* |
292 | | * [5] 7.3.2 |
293 | | */ |
294 | | static void |
295 | | rp_smma(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, uint32_t offset, unsigned len) |
296 | 2 | { |
297 | 2 | uint32_t curr_offset; |
298 | 2 | uint32_t consumed; |
299 | 2 | unsigned curr_len; |
300 | | |
301 | 2 | curr_offset = offset; |
302 | 2 | curr_len = len; |
303 | | |
304 | 2 | ELEM_MAND_V(GSM_A_PDU_TYPE_RP, DE_RP_MESSAGE_REF, NULL, ei_gsm_a_rp_missing_mandatory_element); |
305 | | |
306 | 2 | EXTRANEOUS_DATA_CHECK(curr_len, 0, pinfo, &ei_gsm_a_rp_extraneous_data); |
307 | 2 | } |
308 | | |
309 | | /* |
310 | | * [5] 7.3.3 |
311 | | */ |
312 | | static void |
313 | | rp_ack_n_ms(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t offset, unsigned len) |
314 | 0 | { |
315 | 0 | uint32_t curr_offset; |
316 | 0 | uint32_t consumed; |
317 | 0 | unsigned curr_len; |
318 | |
|
319 | 0 | curr_offset = offset; |
320 | 0 | curr_len = len; |
321 | |
|
322 | 0 | pinfo->p2p_dir = P2P_DIR_SENT; |
323 | |
|
324 | 0 | ELEM_MAND_V(GSM_A_PDU_TYPE_RP, DE_RP_MESSAGE_REF, NULL, ei_gsm_a_rp_missing_mandatory_element); |
325 | |
|
326 | 0 | ELEM_OPT_TLV(0x41, GSM_A_PDU_TYPE_RP, DE_RP_USER_DATA, NULL); |
327 | |
|
328 | 0 | EXTRANEOUS_DATA_CHECK(curr_len, 0, pinfo, &ei_gsm_a_rp_extraneous_data); |
329 | 0 | } |
330 | | |
331 | | /* |
332 | | * [5] 7.3.3 |
333 | | */ |
334 | | static void |
335 | | rp_ack_ms_n(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t offset, unsigned len) |
336 | 4 | { |
337 | 4 | uint32_t curr_offset; |
338 | 4 | uint32_t consumed; |
339 | 4 | unsigned curr_len; |
340 | | |
341 | 4 | curr_offset = offset; |
342 | 4 | curr_len = len; |
343 | | |
344 | 4 | pinfo->p2p_dir = P2P_DIR_RECV; |
345 | | |
346 | 4 | ELEM_MAND_V(GSM_A_PDU_TYPE_RP, DE_RP_MESSAGE_REF, NULL, ei_gsm_a_rp_missing_mandatory_element); |
347 | | |
348 | 4 | ELEM_OPT_TLV(0x41, GSM_A_PDU_TYPE_RP, DE_RP_USER_DATA, NULL); |
349 | | |
350 | 3 | EXTRANEOUS_DATA_CHECK(curr_len, 0, pinfo, &ei_gsm_a_rp_extraneous_data); |
351 | 3 | } |
352 | | |
353 | | /* |
354 | | * [5] 7.3.4 |
355 | | */ |
356 | | static void |
357 | | rp_error_n_ms(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t offset, unsigned len) |
358 | 3 | { |
359 | 3 | uint32_t curr_offset; |
360 | 3 | uint32_t consumed; |
361 | 3 | unsigned curr_len; |
362 | | |
363 | 3 | curr_offset = offset; |
364 | 3 | curr_len = len; |
365 | | |
366 | 3 | pinfo->p2p_dir = P2P_DIR_SENT; |
367 | | |
368 | 3 | ELEM_MAND_V(GSM_A_PDU_TYPE_RP, DE_RP_MESSAGE_REF, NULL, ei_gsm_a_rp_missing_mandatory_element); |
369 | | |
370 | 3 | ELEM_MAND_LV(GSM_A_PDU_TYPE_RP, DE_RP_CAUSE, NULL, ei_gsm_a_rp_missing_mandatory_element); |
371 | | |
372 | 3 | ELEM_OPT_TLV(0x41, GSM_A_PDU_TYPE_RP, DE_RP_USER_DATA, NULL); |
373 | | |
374 | 2 | EXTRANEOUS_DATA_CHECK(curr_len, 0, pinfo, &ei_gsm_a_rp_extraneous_data); |
375 | 2 | } |
376 | | |
377 | | /* |
378 | | * [5] 7.3.4 |
379 | | */ |
380 | | static void |
381 | | rp_error_ms_n(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, uint32_t offset, unsigned len) |
382 | 4 | { |
383 | 4 | uint32_t curr_offset; |
384 | 4 | uint32_t consumed; |
385 | 4 | unsigned curr_len; |
386 | | |
387 | 4 | curr_offset = offset; |
388 | 4 | curr_len = len; |
389 | | |
390 | 4 | pinfo->p2p_dir = P2P_DIR_RECV; |
391 | | |
392 | 4 | ELEM_MAND_V(GSM_A_PDU_TYPE_RP, DE_RP_MESSAGE_REF, NULL, ei_gsm_a_rp_missing_mandatory_element); |
393 | | |
394 | 4 | ELEM_MAND_LV(GSM_A_PDU_TYPE_RP, DE_RP_CAUSE, NULL, ei_gsm_a_rp_missing_mandatory_element); |
395 | | |
396 | 4 | ELEM_OPT_TLV(0x41, GSM_A_PDU_TYPE_RP, DE_RP_USER_DATA, NULL); |
397 | | |
398 | 3 | EXTRANEOUS_DATA_CHECK(curr_len, 0, pinfo, &ei_gsm_a_rp_extraneous_data); |
399 | 3 | } |
400 | | |
401 | 144 | #define NUM_GSM_RP_MSG array_length(gsm_rp_msg_strings) |
402 | | static int ett_gsm_rp_msg[NUM_GSM_RP_MSG]; |
403 | | static void (* const rp_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, uint32_t offset, unsigned len) = { |
404 | | rp_data_ms_n, /* RP-DATA (MS to Network) */ |
405 | | rp_data_n_ms, /* RP-DATA (Network to MS) */ |
406 | | rp_ack_ms_n, /* RP-ACK (MS to Network) */ |
407 | | rp_ack_n_ms, /* RP-ACK (Network to MS) */ |
408 | | rp_error_ms_n, /* RP-ERROR (MS to Network) */ |
409 | | rp_error_n_ms, /* RP-ERROR (Network to MS) */ |
410 | | rp_smma, /* RP-SMMA (MS to Network) */ |
411 | | NULL, /* NONE */ |
412 | | }; |
413 | | |
414 | | /* GENERIC DISSECTOR FUNCTIONS */ |
415 | | |
416 | | static int |
417 | | dissect_rp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
418 | 29 | { |
419 | 29 | uint8_t oct; |
420 | 29 | uint32_t offset, saved_offset; |
421 | 29 | uint32_t len; |
422 | 29 | int idx; |
423 | 29 | proto_item *rp_item = NULL; |
424 | 29 | proto_tree *rp_tree = NULL; |
425 | 29 | const char *str; |
426 | | |
427 | 29 | col_append_str(pinfo->cinfo, COL_INFO, "(RP) "); |
428 | | |
429 | 29 | offset = 0; |
430 | 29 | saved_offset = offset; |
431 | | |
432 | 29 | len = tvb_reported_length(tvb); |
433 | | |
434 | | /* |
435 | | * add RP message name |
436 | | */ |
437 | 29 | oct = tvb_get_uint8(tvb, offset++); |
438 | | |
439 | 29 | str = try_val_to_str_idx((uint32_t) oct, gsm_rp_msg_strings, &idx); |
440 | | |
441 | | /* |
442 | | * create the protocol tree |
443 | | */ |
444 | 29 | if (str == NULL) |
445 | 2 | { |
446 | 2 | rp_item = |
447 | 2 | proto_tree_add_protocol_format(tree, proto_a_rp, tvb, 0, len, |
448 | 2 | "GSM A-I/F RP - Unknown RP Message Type (0x%02x)", |
449 | 2 | oct); |
450 | | |
451 | 2 | rp_tree = proto_item_add_subtree(rp_item, ett_rp_msg); |
452 | 2 | } |
453 | 27 | else |
454 | 27 | { |
455 | 27 | rp_item = |
456 | 27 | proto_tree_add_protocol_format(tree, proto_a_rp, tvb, 0, -1, |
457 | 27 | "GSM A-I/F RP - %s", |
458 | 27 | str); |
459 | | |
460 | 27 | rp_tree = proto_item_add_subtree(rp_item, ett_gsm_rp_msg[idx]); |
461 | | |
462 | 27 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str); |
463 | 27 | } |
464 | | |
465 | | /* |
466 | | * add RP message name |
467 | | */ |
468 | 29 | proto_tree_add_uint_format(rp_tree, hf_gsm_a_rp_msg_type, |
469 | 29 | tvb, saved_offset, 1, oct, "Message Type %s", str ? str : "(Unknown)"); |
470 | | |
471 | 29 | if (str == NULL) return offset; |
472 | | |
473 | 27 | if (offset >=len) return offset; |
474 | | |
475 | | /* |
476 | | * decode elements |
477 | | */ |
478 | 26 | if (rp_msg_fcn[idx] == NULL) |
479 | 0 | { |
480 | 0 | proto_tree_add_item(rp_tree, hf_gsm_a_rp_message_elements, tvb, offset, len - offset, ENC_NA); |
481 | 0 | } |
482 | 26 | else |
483 | 26 | { |
484 | 26 | (*rp_msg_fcn[idx])(tvb, rp_tree, pinfo, offset, len - offset); |
485 | 26 | } |
486 | 26 | return tvb_captured_length(tvb); |
487 | 27 | } |
488 | | |
489 | | static int |
490 | | dissect_nf_media_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, media_content_info_t *content_info) |
491 | 0 | { |
492 | 0 | tvbuff_t* json_tvb; |
493 | 0 | int ret; |
494 | 0 | jsmntok_t *tokens, *cur_tok; |
495 | 0 | char *json_data; |
496 | 0 | const char *content_id; |
497 | |
|
498 | 0 | if (!gsm_a_dtap_handle || !content_info || content_info->type > MEDIA_CONTAINER_HTTP_OTHERS || !content_info->content_id) |
499 | 0 | return 0; |
500 | 0 | json_tvb = (tvbuff_t*)p_get_proto_data(pinfo->pool, pinfo, proto_json, 0); |
501 | 0 | if (!json_tvb) |
502 | 0 | return 0; |
503 | 0 | json_data = (char*)tvb_get_string_enc(pinfo->pool, json_tvb, 0, tvb_reported_length(json_tvb), ENC_UTF_8|ENC_NA); |
504 | 0 | ret = json_parse(json_data, NULL, 0); |
505 | 0 | if (ret <= 0) |
506 | 0 | return 0; |
507 | 0 | tokens = wmem_alloc_array(pinfo->pool, jsmntok_t, ret); |
508 | 0 | if (json_parse(json_data, tokens, ret) <= 0) |
509 | 0 | return 0; |
510 | 0 | cur_tok = json_get_object(json_data, tokens, "smsPayload"); |
511 | 0 | if (!cur_tok) |
512 | 0 | return 0; |
513 | 0 | content_id = json_get_string(json_data, cur_tok, "contentId"); |
514 | 0 | if (content_id && !strcmp(content_id, content_info->content_id)) |
515 | 0 | return call_dissector_only(gsm_a_dtap_handle, tvb, pinfo, tree, NULL); |
516 | | |
517 | 0 | return 0; |
518 | 0 | } |
519 | | |
520 | | static int |
521 | | dissect_rp_media_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
522 | 0 | { |
523 | 0 | int ret; |
524 | 0 | media_content_info_t *content_info = (media_content_info_t *)data; |
525 | |
|
526 | 0 | ret = dissect_nf_media_type(tvb, pinfo, tree, content_info); |
527 | 0 | if (!ret) |
528 | 0 | ret = dissect_rp(tvb, pinfo, tree, NULL); |
529 | 0 | return ret; |
530 | 0 | } |
531 | | |
532 | | /* Register the protocol with Wireshark */ |
533 | | void |
534 | | proto_register_gsm_a_rp(void) |
535 | 16 | { |
536 | 16 | unsigned i; |
537 | 16 | unsigned last_offset; |
538 | | |
539 | | /* Setup list of header fields */ |
540 | | |
541 | 16 | static hf_register_info hf[] = { |
542 | 16 | { &hf_gsm_a_rp_msg_type, |
543 | 16 | { "RP Message Type", "gsm_a.rp.msg_type", |
544 | 16 | FT_UINT8, BASE_HEX, VALS(gsm_rp_msg_strings), 0x0, |
545 | 16 | NULL, HFILL } |
546 | 16 | }, |
547 | 16 | { &hf_gsm_a_rp_elem_id, |
548 | 16 | { "Element ID", "gsm_a.rp.elem_id", |
549 | 16 | FT_UINT8, BASE_HEX, NULL, 0, |
550 | 16 | NULL, HFILL } |
551 | 16 | }, |
552 | | |
553 | | /* Generated from convert_proto_tree_add_text.pl */ |
554 | 16 | { &hf_gsm_a_rp_rp_message_reference, { "RP-Message Reference", "gsm_a.rp.rp_message_reference", FT_UINT8, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }}, |
555 | 16 | { &hf_gsm_a_rp_tpdu, { "TPDU", "gsm_a.rp.tpdu", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
556 | 16 | { &hf_gsm_a_rp_extension, { "Extension", "gsm_a.rp.extension", FT_BOOLEAN, 8, TFS(&tfs_extended_no_extension), 0x80, NULL, HFILL }}, |
557 | 16 | { &hf_gsm_a_rp_cause, { "Cause", "gsm_a.rp.cause", FT_UINT8, BASE_DEC|BASE_EXT_STRING, &gsm_rp_cause_vals_ext, 0x7F, NULL, HFILL }}, |
558 | 16 | { &hf_gsm_a_rp_diagnostic_field, { "Diagnostic field", "gsm_a.rp.diagnostic_field", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
559 | 16 | { &hf_gsm_a_rp_message_elements, { "Message Elements", "gsm_a.rp.message_elements", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
560 | 16 | }; |
561 | | |
562 | 16 | static ei_register_info ei[] = { |
563 | 16 | { &ei_gsm_a_rp_extraneous_data, { "gsm_a.rp.extraneous_data", PI_PROTOCOL, PI_NOTE, "Extraneous Data, dissector bug or later version spec (report to wireshark.org)", EXPFILL }}, |
564 | 16 | { &ei_gsm_a_rp_missing_mandatory_element, { "gsm_a.rp.missing_mandatory_element", PI_PROTOCOL, PI_ERROR, "Missing Mandatory element, rest of dissection is suspect", EXPFILL }}, |
565 | 16 | }; |
566 | | |
567 | 16 | expert_module_t* expert_gsm_a_rp; |
568 | | |
569 | | /* Setup protocol subtree array */ |
570 | 16 | #define NUM_INDIVIDUAL_ELEMS 1 |
571 | 16 | int *ett[NUM_INDIVIDUAL_ELEMS + |
572 | 16 | NUM_GSM_RP_MSG + |
573 | 16 | NUM_GSM_RP_ELEM]; |
574 | | |
575 | 16 | ett[0] = &ett_rp_msg; |
576 | | |
577 | 16 | last_offset = NUM_INDIVIDUAL_ELEMS; |
578 | | |
579 | 144 | for (i=0; i < NUM_GSM_RP_MSG; i++, last_offset++) |
580 | 128 | { |
581 | 128 | ett[last_offset] = &ett_gsm_rp_msg[i]; |
582 | 128 | } |
583 | | |
584 | 112 | for (i=0; i < NUM_GSM_RP_ELEM; i++, last_offset++) |
585 | 96 | { |
586 | 96 | ett[last_offset] = &ett_gsm_rp_elem[i]; |
587 | 96 | } |
588 | | |
589 | | /* Register the protocol name and description */ |
590 | | |
591 | 16 | proto_a_rp = proto_register_protocol("GSM A-I/F RP", "GSM RP", "gsm_a.rp"); |
592 | | |
593 | 16 | proto_register_field_array(proto_a_rp, hf, array_length(hf)); |
594 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
595 | 16 | expert_gsm_a_rp = expert_register_protocol(proto_a_rp); |
596 | 16 | expert_register_field_array(expert_gsm_a_rp, ei, array_length(ei)); |
597 | | |
598 | 16 | register_dissector("gsm_a_rp", dissect_rp, proto_a_rp); |
599 | 16 | } |
600 | | |
601 | | void |
602 | | proto_reg_handoff_gsm_a_rp(void) |
603 | 16 | { |
604 | 16 | dissector_handle_t gsm_a_rp_handle; |
605 | | |
606 | 16 | gsm_a_rp_handle = create_dissector_handle(dissect_rp_media_type, proto_a_rp); |
607 | | /* Dissect messages embedded in SIP */ |
608 | 16 | dissector_add_string("media_type","application/vnd.3gpp.sms", gsm_a_rp_handle); |
609 | 16 | gsm_sms_handle = find_dissector_add_dependency("gsm_sms", proto_a_rp); |
610 | 16 | gsm_a_dtap_handle = find_dissector_add_dependency("gsm_a_dtap", proto_a_rp); |
611 | 16 | proto_json = proto_get_id_by_filter_name("json"); |
612 | 16 | } |
613 | | |
614 | | /* |
615 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
616 | | * |
617 | | * Local variables: |
618 | | * c-basic-offset: 8 |
619 | | * tab-width: 8 |
620 | | * indent-tabs-mode: t |
621 | | * End: |
622 | | * |
623 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
624 | | * :indentSize=8:tabSize=8:noTabs=false: |
625 | | */ |