Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-gsm_sms_ud.c
blob6fe1b157001ccadb66ea6c9a569d212a0b8dd6a7
1 /* packet-gsm_sms_ud.c
2 * Routines for GSM SMS TP-UD (GSM 03.40) dissection
4 * Refer to the AUTHORS file or the AUTHORS section in the man page
5 * for contacting the author(s) of this file.
7 * Separated from the SMPP dissector by Chris Wilson.
9 * UDH and WSP dissection of SMS message, Short Message reassembly,
10 * "Decode Short Message with Port Number UDH as CL-WSP" preference,
11 * "Always try subdissection of 1st fragment" preference,
12 * provided by Olivier Biot.
14 * Note on SMS Message reassembly
15 * ------------------------------
16 * The current Short Message reassembly is possible thanks to the
17 * message identifier (8 or 16 bit identifier). It is able to reassemble
18 * short messages that are sent over either the same SMPP connection or
19 * distinct SMPP connections. Normally the reassembly code is able to deal
20 * with duplicate message identifiers since the fragment_add_seq_check()
21 * call is used.
23 * The SMS TP-UD preference "always try subdissection of 1st fragment" allows
24 * a subdissector to be called for the first Short Message fragment,
25 * even if reassembly is not possible. This way partial dissection
26 * is still possible. This preference is switched off by default.
28 * Note on Short Message decoding as CL-WSP
29 * ----------------------------------------
30 * The SMS TP-UD preference "port_number_udh_means_wsp" is switched off
31 * by default. If it is enabled, then any Short Message with a Port Number
32 * UDH will be decoded as CL-WSP if:
33 * - The Short Message is not segmented
34 * - The entire segmented Short Message is reassembled
35 * - It is the 1st segment of an unreassembled Short Message (if the
36 * "always try subdissection of 1st fragment" preference is enabled)
38 * Wireshark - Network traffic analyzer
39 * By Gerald Combs <gerald@wireshark.org>
40 * Copyright 1998 Gerald Combs
42 * SPDX-License-Identifier: GPL-2.0-or-later
45 #include "config.h"
47 #include <epan/packet.h>
49 #include <epan/prefs.h>
50 #include <epan/reassemble.h>
51 #include "packet-gsm_sms.h"
52 #include "packet-smpp.h"
54 void proto_register_gsm_sms_ud(void);
55 void proto_reg_handoff_gsm_sms_ud(void);
57 static int proto_gsm_sms_ud;
60 * Short Message fragment handling
62 static int hf_gsm_sms_ud_fragments;
63 static int hf_gsm_sms_ud_fragment;
64 static int hf_gsm_sms_ud_fragment_overlap;
65 static int hf_gsm_sms_ud_fragment_overlap_conflicts;
66 static int hf_gsm_sms_ud_fragment_multiple_tails;
67 static int hf_gsm_sms_ud_fragment_too_long_fragment;
68 static int hf_gsm_sms_ud_fragment_error;
69 static int hf_gsm_sms_ud_fragment_count;
70 static int hf_gsm_sms_ud_reassembled_in;
71 static int hf_gsm_sms_ud_reassembled_length;
72 static int hf_gsm_sms_ud_short_msg;
74 static int ett_gsm_sms;
75 static int ett_gsm_sms_ud_fragment;
76 static int ett_gsm_sms_ud_fragments;
78 /* Subdissector declarations */
79 static dissector_table_t gsm_sms_dissector_table;
81 /* Short Message reassembly */
82 static reassembly_table sm_reassembly_table;
84 static const fragment_items sm_frag_items = {
85 /* Fragment subtrees */
86 &ett_gsm_sms_ud_fragment,
87 &ett_gsm_sms_ud_fragments,
88 /* Fragment fields */
89 &hf_gsm_sms_ud_fragments,
90 &hf_gsm_sms_ud_fragment,
91 &hf_gsm_sms_ud_fragment_overlap,
92 &hf_gsm_sms_ud_fragment_overlap_conflicts,
93 &hf_gsm_sms_ud_fragment_multiple_tails,
94 &hf_gsm_sms_ud_fragment_too_long_fragment,
95 &hf_gsm_sms_ud_fragment_error,
96 &hf_gsm_sms_ud_fragment_count,
97 /* Reassembled in field */
98 &hf_gsm_sms_ud_reassembled_in,
99 /* Reassembled length field */
100 &hf_gsm_sms_ud_reassembled_length,
101 /* Reassembled data field */
102 NULL,
103 /* Tag */
104 "Short Message fragments"
107 /* Dissect all SM data as WSP if the UDH contains a Port Number IE */
108 static bool port_number_udh_means_wsp;
110 /* Always try dissecting the 1st fragment of a SM,
111 * even if it is not reassembled */
112 static bool try_dissect_1st_frag;
114 /* Prevent subdissectors changing column data */
115 static bool prevent_subdissectors_changing_columns;
117 static dissector_handle_t wsp_handle;
119 /* Parse Short Message. This function is only called from the SMPP
120 * dissector if the UDH present, or if the UDH fields were obtained
121 * elsewhere in SMPP TLVs.
122 * Call WSP dissector if port matches WSP traffic.
124 static void
125 parse_gsm_sms_ud_message(proto_tree *sm_tree, tvbuff_t *tvb, packet_info *pinfo, smpp_data_t *smpp_data)
127 tvbuff_t *sm_tvb = NULL;
128 proto_tree *top_tree;
129 unsigned sm_len = tvb_reported_length(tvb);
130 uint32_t i = 0;
131 /* Multiple Messages UDH */
132 bool is_fragmented = false;
133 fragment_head *fd_sm = NULL;
134 bool save_fragmented = false;
135 bool try_gsm_sms_ud_reassemble = false;
136 /* SMS Message reassembly */
137 bool reassembled = false;
138 uint32_t reassembled_in = 0;
140 gsm_sms_udh_fields_t *udh_fields = NULL;
141 if (smpp_data) {
142 udh_fields = smpp_data->udh_fields;
145 top_tree = proto_tree_get_parent_tree(sm_tree);
147 if (!udh_fields) {
148 udh_fields = wmem_new0(pinfo->pool, gsm_sms_udh_fields_t);
151 if (smpp_data && smpp_data->udhi) {
152 /* XXX: We don't handle different encodings in this dissector yet,
153 * so just treat everything as 8-bit binary encoding. */
154 uint8_t fill_bits = 0;
155 uint8_t udl = sm_len;
156 dis_field_udh(tvb, pinfo, sm_tree, &i, &sm_len, &udl, OTHER, &fill_bits, udh_fields);
159 if (tvb_reported_length_remaining(tvb, i) <= 0)
160 return; /* No more data */
162 if (udh_fields->frags > 1) {
163 is_fragmented = true;
167 * Try reassembling the packets.
168 * XXX - fragment numbers are 1-origin, but the fragment number
169 * field could be 0.
170 * Should we flag a fragmented message with a fragment number field
171 * of 0?
172 * What if the fragment count is 0? Should we flag that as well?
174 if (is_fragmented && udh_fields->frag != 0 && udh_fields->frags != 0 &&
175 tvb_bytes_exist(tvb, i, sm_len)) {
176 try_gsm_sms_ud_reassemble = true;
177 save_fragmented = pinfo->fragmented;
178 pinfo->fragmented = true;
179 fd_sm = fragment_add_seq_check(&sm_reassembly_table,
180 tvb, i,
181 pinfo,
182 udh_fields->sm_id, /* uint32_t ID for fragments belonging together */
183 NULL,
184 udh_fields->frag-1, /* uint32_t fragment sequence number */
185 sm_len, /* uint32_t fragment length */
186 (udh_fields->frag != udh_fields->frags)); /* More fragments? */
187 if (fd_sm) {
188 reassembled = true;
189 reassembled_in = fd_sm->reassembled_in;
191 sm_tvb = process_reassembled_data(tvb, i, pinfo,
192 "Reassembled Short Message", fd_sm, &sm_frag_items,
193 NULL, sm_tree);
194 if (reassembled) { /* Reassembled */
195 col_append_str(pinfo->cinfo, COL_INFO,
196 " (Short Message Reassembled)");
197 } else {
198 /* Not last packet of reassembled Short Message */
199 col_append_fstr(pinfo->cinfo, COL_INFO,
200 " (Short Message fragment %u of %u)", udh_fields->frag, udh_fields->frags);
202 } /* Else: not fragmented */
204 if (! sm_tvb) /* One single Short Message, or not reassembled */
205 sm_tvb = tvb_new_subset_remaining(tvb, i);
206 /* Try calling a subdissector */
207 if (sm_tvb) {
208 if ((reassembled && pinfo->num == reassembled_in)
209 || udh_fields->frag==0 || (udh_fields->frag==1 && try_dissect_1st_frag)) {
210 /* Try calling a subdissector only if:
211 * - the Short Message is reassembled in this very packet,
212 * - the Short Message consists of only one "fragment",
213 * - the preference "Always Try Dissection for 1st SM fragment"
214 * is switched on, and this is the SM's 1st fragment. */
215 if (udh_fields->port_src || udh_fields->port_dst) {
216 bool disallow_write = false; /* true if we changed writability
217 of the columns of the summary */
218 if (prevent_subdissectors_changing_columns && col_get_writable(pinfo->cinfo, -1)) {
219 disallow_write = true;
220 col_set_writable(pinfo->cinfo, -1, false);
223 if (port_number_udh_means_wsp) {
224 call_dissector(wsp_handle, sm_tvb, pinfo, top_tree);
225 } else {
226 if (! dissector_try_uint(gsm_sms_dissector_table, udh_fields->port_src,
227 sm_tvb, pinfo, top_tree)) {
228 if (! dissector_try_uint(gsm_sms_dissector_table, udh_fields->port_dst,
229 sm_tvb, pinfo, top_tree)) {
230 if (sm_tree) { /* Only display if needed */
231 proto_tree_add_item(sm_tree, hf_gsm_sms_ud_short_msg, sm_tvb, 0, -1, ENC_NA);
237 if (disallow_write)
238 col_set_writable(pinfo->cinfo, -1, true);
239 } else { /* No ports IE */
240 proto_tree_add_item(sm_tree, hf_gsm_sms_ud_short_msg, sm_tvb, 0, -1, ENC_NA);
242 } else {
243 /* The packet is not reassembled,
244 * or it is reassembled in another packet */
245 proto_tree_add_bytes_format(sm_tree, hf_gsm_sms_ud_short_msg, sm_tvb, 0, -1,
246 NULL, "Unreassembled Short Message fragment %u of %u",
247 udh_fields->frag, udh_fields->frags);
251 if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */
252 pinfo->fragmented = save_fragmented;
253 return;
256 static int
257 dissect_gsm_sms_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
259 proto_item *ti;
260 proto_tree *subtree;
261 smpp_data_t *smpp_data = NULL;
263 if (data) {
264 smpp_data = (smpp_data_t*)data;
267 ti = proto_tree_add_item(tree, proto_gsm_sms_ud, tvb, 0, -1, ENC_NA);
268 subtree = proto_item_add_subtree(ti, ett_gsm_sms);
269 parse_gsm_sms_ud_message(subtree, tvb, pinfo, smpp_data);
270 return tvb_captured_length(tvb);
273 /* Register the protocol with Wireshark */
274 void
275 proto_register_gsm_sms_ud(void)
277 module_t *gsm_sms_ud_module; /* Preferences for GSM SMS UD */
279 /* Setup list of header fields */
280 static hf_register_info hf[] = {
282 * Short Message fragment reassembly
284 { &hf_gsm_sms_ud_fragments,
285 { "Short Message fragments", "gsm_sms_ud.fragments",
286 FT_NONE, BASE_NONE, NULL, 0x00,
287 "GSM Short Message fragments",
288 HFILL
291 { &hf_gsm_sms_ud_fragment,
292 { "Short Message fragment", "gsm_sms_ud.fragment",
293 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
294 "GSM Short Message fragment",
295 HFILL
298 { &hf_gsm_sms_ud_fragment_overlap,
299 { "Short Message fragment overlap", "gsm_sms_ud.fragment.overlap",
300 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
301 "GSM Short Message fragment overlaps with other fragment(s)",
302 HFILL
305 { &hf_gsm_sms_ud_fragment_overlap_conflicts,
306 { "Short Message fragment overlapping with conflicting data",
307 "gsm_sms_ud.fragment.overlap.conflicts",
308 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
309 "GSM Short Message fragment overlaps with conflicting data",
310 HFILL
313 { &hf_gsm_sms_ud_fragment_multiple_tails,
314 { "Short Message has multiple tail fragments",
315 "gsm_sms_ud.fragment.multiple_tails",
316 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
317 "GSM Short Message fragment has multiple tail fragments",
318 HFILL
321 { &hf_gsm_sms_ud_fragment_too_long_fragment,
322 { "Short Message fragment too long",
323 "gsm_sms_ud.fragment.too_long_fragment",
324 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
325 "GSM Short Message fragment data goes beyond the packet end",
326 HFILL
329 { &hf_gsm_sms_ud_fragment_error,
330 { "Short Message defragmentation error", "gsm_sms_ud.fragment.error",
331 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
332 "GSM Short Message defragmentation error due to illegal fragments",
333 HFILL
336 { &hf_gsm_sms_ud_fragment_count,
337 { "Short Message fragment count", "gsm_sms_ud.fragment.count",
338 FT_UINT32, BASE_DEC, NULL, 0x00,
339 NULL,
340 HFILL
343 { &hf_gsm_sms_ud_reassembled_in,
344 { "Reassembled in",
345 "gsm_sms_ud.reassembled.in",
346 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
347 "GSM Short Message has been reassembled in this packet.",
348 HFILL
351 { &hf_gsm_sms_ud_reassembled_length,
352 { "Reassembled Short Message length",
353 "gsm_sms_ud.reassembled.length",
354 FT_UINT32, BASE_DEC, NULL, 0x00,
355 "The total length of the reassembled payload",
356 HFILL
359 { &hf_gsm_sms_ud_short_msg,
360 { "Short Message body",
361 "gsm_sms_ud.short_msg",
362 FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL
367 static int *ett[] = {
368 &ett_gsm_sms,
369 &ett_gsm_sms_ud_fragment,
370 &ett_gsm_sms_ud_fragments,
372 /* Register the protocol name and description */
373 proto_gsm_sms_ud = proto_register_protocol("GSM Short Message Service User Data", "GSM SMS UD", "gsm_sms_ud");
375 /* Required function calls to register header fields and subtrees used */
376 proto_register_field_array(proto_gsm_sms_ud, hf, array_length(hf));
377 proto_register_subtree_array(ett, array_length(ett));
379 /* Subdissector code */
380 gsm_sms_dissector_table = register_dissector_table("gsm_sms_ud.udh.port",
381 "GSM SMS port IE in UDH", proto_gsm_sms_ud, FT_UINT16, BASE_DEC);
383 /* Preferences for GSM SMS UD */
384 gsm_sms_ud_module = prefs_register_protocol(proto_gsm_sms_ud, NULL);
385 /* For reading older preference files with "smpp-gsm-sms." preferences */
386 prefs_register_module_alias("smpp-gsm-sms", gsm_sms_ud_module);
387 prefs_register_bool_preference(gsm_sms_ud_module,
388 "port_number_udh_means_wsp",
389 "Port Number IE in UDH always triggers CL-WSP dissection",
390 "Always decode a GSM Short Message as Connectionless WSP "
391 "if a Port Number Information Element is present "
392 "in the SMS User Data Header.",
393 &port_number_udh_means_wsp);
394 prefs_register_bool_preference(gsm_sms_ud_module, "try_dissect_1st_fragment",
395 "Always try subdissection of 1st Short Message fragment",
396 "Always try subdissection of the 1st fragment of a fragmented "
397 "GSM Short Message. If reassembly is possible, the Short Message "
398 "may be dissected twice (once as a short frame, once in its "
399 "entirety).",
400 &try_dissect_1st_frag);
401 prefs_register_bool_preference(gsm_sms_ud_module, "prevent_dissectors_chg_cols",
402 "Prevent sub-dissectors from changing column data",
403 "Prevent sub-dissectors from replacing column data with their "
404 "own. Eg. Prevent WSP dissector overwriting SMPP information.",
405 &prevent_subdissectors_changing_columns);
407 register_dissector("gsm_sms_ud", dissect_gsm_sms_ud, proto_gsm_sms_ud);
409 reassembly_table_register(&sm_reassembly_table,
410 &addresses_reassembly_table_functions);
413 void
414 proto_reg_handoff_gsm_sms_ud(void)
416 wsp_handle = find_dissector_add_dependency("wsp-cl", proto_gsm_sms_ud);
417 DISSECTOR_ASSERT(wsp_handle);
421 * Editor modelines - https://www.wireshark.org/tools/modelines.html
423 * Local variables:
424 * c-basic-offset: 4
425 * tab-width: 8
426 * indent-tabs-mode: nil
427 * End:
429 * vi: set shiftwidth=4 tabstop=8 expandtab:
430 * :indentSize=4:tabSize=8:noTabs=true: