epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-gsm_sms.c
blob4c7947f0a1b5a6e2279c2951646f099f6ecc44b9
1 /* packet-gsm_sms.c
2 * Routines for GSM SMS TPDU (GSM 03.40) dissection
4 * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
5 * In association with Telos Technology Inc.
7 * TPDU User-Data unpack routines from GNOKII.
9 * Reference [1]
10 * Universal Mobile Telecommunications System (UMTS);
11 * Technical realization of Short Message Service (SMS)
12 * (3GPP TS 23.040 version 5.4.0 Release 5)
14 * Header field support for TPDU Parameters added by
15 * Abhik Sarkar.
17 * Wireshark - Network traffic analyzer
18 * By Gerald Combs <gerald@wireshark.org>
19 * Copyright 1998 Gerald Combs
21 * SPDX-License-Identifier: GPL-2.0-or-later
24 #include "config.h"
27 #include <epan/packet.h>
28 #include <epan/tfs.h>
29 #include <epan/expert.h>
30 #include <epan/prefs.h>
31 #include <epan/reassemble.h>
33 #include <epan/proto_data.h>
34 #include "packet-e164.h"
35 #include <epan/asn1.h>
36 #include "packet-gsm_sms.h"
37 #include "packet-gsm_map.h"
38 #include "packet-sip.h"
40 static int proto_gsm_map;
41 static int proto_sip;
43 void proto_register_gsm_sms(void);
44 void proto_reg_handoff_gsm_sms(void);
46 #define MAX_SMS_FRAG_LEN 134
48 /* PROTOTYPES/FORWARDS */
49 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
50 if ((sdc_len) < (sdc_min_len)) \
51 { \
52 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_short_data, tvb, \
53 offset, (sdc_len)); \
54 return; \
57 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
58 if ((edc_len) != (edc_eq_len)) \
59 { \
60 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_unexpected_data_length, tvb, \
61 offset, (edc_len)); \
62 return; \
65 static const char *gsm_sms_proto_name = "GSM SMS TPDU (GSM 03.40)";
66 static const char *gsm_sms_proto_name_short = "GSM SMS";
68 /* Initialize the subtree pointers */
69 static int ett_gsm_sms;
70 static int ett_pid;
71 static int ett_pi;
72 static int ett_fcs;
73 static int ett_vp;
74 static int ett_scts;
75 static int ett_dt;
76 static int ett_st;
77 static int ett_addr;
78 static int ett_dcs;
79 static int ett_ud;
80 static int ett_udh;
82 static int ett_udh_tfm;
83 static int ett_udh_tfc;
85 /* Initialize the protocol and registered fields */
86 static int proto_gsm_sms;
88 static int hf_gsm_sms_coding_group_bits2;
89 static int hf_gsm_sms_coding_group_bits4;
90 static int hf_gsm_sms_ud_multiple_messages_msg_id;
91 static int hf_gsm_sms_ud_multiple_messages_msg_parts;
92 static int hf_gsm_sms_ud_multiple_messages_msg_part;
94 /* TPDU Parameters */
95 static int hf_gsm_sms_tp_mti_up;
96 static int hf_gsm_sms_tp_mti_down;
97 static int hf_gsm_sms_tp_mms;
98 static int hf_gsm_sms_tp_lp;
99 static int hf_gsm_sms_tp_vpf;
100 static int hf_gsm_sms_tp_sri;
101 static int hf_gsm_sms_tp_srr;
102 static int hf_gsm_sms_tp_mr;
103 static int hf_gsm_sms_tp_oa;
104 static int hf_gsm_sms_tp_da;
105 static int hf_gsm_sms_tp_pid;
106 static int hf_gsm_sms_tp_dcs;
107 static int hf_gsm_sms_tp_ra;
108 static int hf_gsm_sms_tp_digits;
109 static int hf_gsm_sms_tp_rp;
110 static int hf_gsm_sms_tp_udhi;
111 static int hf_gsm_sms_tp_rd;
112 static int hf_gsm_sms_tp_srq;
113 static int hf_gsm_sms_text;
114 static int hf_gsm_sms_body;
115 static int hf_gsm_sms_tp_fail_cause;
116 #if 0
117 static int hf_gsm_sms_tp_scts;
118 static int hf_gsm_sms_tp_vp;
119 static int hf_gsm_sms_tp_dt;
120 static int hf_gsm_sms_tp_st;
121 static int hf_gsm_sms_tp_mn;
122 static int hf_gsm_sms_tp_ct;
123 static int hf_gsm_sms_tp_cdl;
124 static int hf_gsm_sms_tp_cd;
125 static int hf_gsm_sms_tp_ud;
126 #endif
127 static int hf_gsm_sms_tp_parameter_indicator;
128 static int hf_gsm_sms_tp_extension;
129 static int hf_gsm_sms_tp_reserved;
130 static int hf_gsm_sms_tp_udl_present;
131 static int hf_gsm_sms_tp_dcs_present;
132 static int hf_gsm_sms_tp_pid_present;
133 static int hf_gsm_sms_dis_field_addr_extension;
134 static int hf_gsm_sms_dis_field_addr_num_type;
135 static int hf_gsm_sms_dis_field_addr_num_plan;
136 static int hf_gsm_sms_tp_pid_format_subsequent_bits;
137 static int hf_gsm_sms_tp_pid_telematic_interworking;
138 static int hf_gsm_sms_tp_pid_device_type;
139 static int hf_gsm_sms_tp_pid_sm_al_proto;
140 static int hf_gsm_sms_tp_pid_message_type;
141 static int hf_gsm_sms_tp_pid_reserved;
142 static int hf_gsm_sms_tp_pid_undefined;
143 static int hf_gsm_sms_tp_pid_sc_specific_use;
144 static int hf_gsm_sms_tp_pid_sc_specific;
145 static int hf_gsm_sms_dcs_text_compressed;
146 static int hf_gsm_sms_dcs_message_class_defined;
147 static int hf_gsm_sms_dcs_character_set;
148 static int hf_gsm_sms_dcs_message_class;
149 static int hf_gsm_sms_dcs_indication_sense;
150 static int hf_gsm_sms_dcs_reserved04;
151 static int hf_gsm_sms_dcs_message_waiting;
152 static int hf_gsm_sms_dcs_reserved08;
153 static int hf_gsm_sms_dcs_message_coding;
154 static int hf_gsm_sms_vp_extension;
155 static int hf_gsm_sms_vp_extension_ignored;
156 static int hf_gsm_sms_vp_single_shot_sm;
157 static int hf_gsm_sms_vp_reserved;
158 static int hf_gsm_sms_vp_validity_period_format;
159 static int hf_gsm_sms_vp_validity_period;
160 static int hf_gsm_sms_dis_field_definition;
161 static int hf_gsm_sms_dis_field_st_error;
162 static int hf_gsm_sms_dis_field_st_reason[4];
163 static int hf_gsm_sms_tp_user_data_length;
164 static int hf_gsm_sms_tp_command_type;
165 static int hf_gsm_sms_tp_message_number;
166 static int hf_gsm_sms_tp_command_data;
167 static int hf_gsm_sms_tp_command_data_length;
168 static int hf_gsm_sms_msg_ind_type_and_stor;
169 static int hf_gsm_sms_msg_profile_id;
170 static int hf_gsm_sms_ext_msg_ind_type;
171 static int hf_gsm_sms_msg_ind_type;
172 static int hf_gsm_sms_msg_count;
173 static int hf_gsm_sms_destination_port8;
174 static int hf_gsm_sms_originator_port8;
175 static int hf_gsm_sms_destination_port16;
176 static int hf_gsm_sms_originator_port16;
177 static int hf_gsm_sms_status_report;
178 static int hf_gsm_sms_status_report_short_msg;
179 static int hf_gsm_sms_status_report_permanent_error;
180 static int hf_gsm_sms_status_report_temp_error_no_attempt;
181 static int hf_gsm_sms_status_report_temp_error_transfer;
182 static int hf_gsm_sms_status_report_active;
183 static int hf_gsm_sms_status_report_original_udh;
184 static int hf_gsm_sms_udh_created;
185 static int hf_gsm_sms_formatting_mode;
186 static int hf_gsm_sms_formatting_mode_alignment;
187 static int hf_gsm_sms_formatting_mode_font_size;
188 static int hf_gsm_sms_formatting_mode_style_bold;
189 static int hf_gsm_sms_formatting_mode_style_italic;
190 static int hf_gsm_sms_formatting_mode_style_underlined;
191 static int hf_gsm_sms_formatting_mode_style_strikethrough;
192 static int hf_gsm_sms_ie_identifier;
193 static int hf_gsm_sms_scts_year;
194 static int hf_gsm_sms_scts_month;
195 static int hf_gsm_sms_scts_day;
196 static int hf_gsm_sms_scts_hour;
197 static int hf_gsm_sms_scts_minutes;
198 static int hf_gsm_sms_scts_seconds;
199 static int hf_gsm_sms_scts_timezone;
200 static int hf_gsm_sms_vp_validity_period_hour;
201 static int hf_gsm_sms_vp_validity_period_minutes;
202 static int hf_gsm_sms_vp_validity_period_seconds;
204 /* Generated from convert_proto_tree_add_text.pl */
205 static int hf_gsm_sms_dis_field_udh_user_data_header_length;
206 static int hf_gsm_sms_compressed_data;
207 static int hf_gsm_sms_dis_iei_la_large_animation;
208 static int hf_gsm_sms_dis_iei_vp_variable_picture;
209 static int hf_gsm_sms_dis_iei_vp_horizontal_dimension;
210 static int hf_gsm_sms_dis_iei_vp_position;
211 static int hf_gsm_sms_dis_iei_sp_small_picture;
212 static int hf_gsm_sms_dis_iei_tf_background_colour;
213 static int hf_gsm_sms_dis_iei_pa_position;
214 static int hf_gsm_sms_dis_iei_sa_position;
215 static int hf_gsm_sms_dis_iei_ps_position;
216 static int hf_gsm_sms_dis_field_ud_iei_length;
217 static int hf_gsm_sms_dis_iei_upi_num_corresponding_objects;
218 static int hf_gsm_sms_dis_iei_lp_large_picture;
219 static int hf_gsm_sms_dis_iei_la_position;
220 static int hf_gsm_sms_dis_iei_sa_small_animation;
221 static int hf_gsm_sms_dis_iei_tf_start_position;
222 static int hf_gsm_sms_dis_iei_lp_position;
223 static int hf_gsm_sms_gsm_7_bit_default_alphabet;
224 static int hf_gsm_sms_dis_iei_ps_sound_number;
225 static int hf_gsm_sms_ie_data;
226 static int hf_gsm_sms_dis_iei_vp_vertical_dimension;
227 static int hf_gsm_sms_dis_iei_tf_foreground_colour;
228 static int hf_gsm_sms_dis_iei_uds_user_defined_sound;
229 static int hf_gsm_sms_dis_iei_sp_position;
230 static int hf_gsm_sms_dis_field_addr_length;
231 static int hf_gsm_sms_dis_iei_uds_position;
232 static int hf_gsm_sms_dis_iei_tf_length;
233 static int hf_gsm_sms_dis_iei_pa_animation_number;
234 static int hf_gsm_sms_dis_iei_lang_single_shift;
235 static int hf_gsm_sms_dis_iei_lang_locking_shift;
236 static int hf_gsm_sms_dis_field_udh_gsm_mask00;
237 static int hf_gsm_sms_dis_field_udh_gsm_mask01;
238 static int hf_gsm_sms_dis_field_udh_gsm_mask03;
239 static int hf_gsm_sms_dis_field_udh_gsm_mask07;
240 static int hf_gsm_sms_dis_field_udh_gsm_mask0f;
241 static int hf_gsm_sms_dis_field_udh_gsm_mask1f;
242 static int hf_gsm_sms_dis_field_udh_gsm_mask3f;
243 static int hf_gsm_sms_dis_field_udh_ascii_mask00;
244 static int hf_gsm_sms_dis_field_udh_ascii_mask80;
245 static int hf_gsm_sms_dis_field_udh_ascii_maskc0;
246 static int hf_gsm_sms_dis_field_udh_ascii_maske0;
247 static int hf_gsm_sms_dis_field_udh_ascii_maskf0;
248 static int hf_gsm_sms_dis_field_udh_ascii_maskf8;
249 static int hf_gsm_sms_dis_field_udh_ascii_maskfc;
252 static expert_field ei_gsm_sms_short_data;
253 static expert_field ei_gsm_sms_unexpected_data_length;
254 static expert_field ei_gsm_sms_message_dissector_not_implemented;
256 static bool reassemble_sms = true;
257 static bool reassemble_sms_with_lower_layers_info = true;
258 static proto_tree *g_tree;
260 /* 3GPP TS 23.038 version 7.0.0 Release 7
261 * The TP-Data-Coding-Scheme field, defined in 3GPP TS 23.040 [4],
262 * indicates the data coding scheme of the TP-UD field, and may indicate a message class.
263 * Any reserved codings shall be assumed to be the GSM 7 bit default alphabet
264 * (the same as codepoint 00000000) by a receiving entity.
265 * The octet is used according to a coding group which is indicated in bits 7..4.
268 /* Coding Group Bits */
269 static const value_string gsm_sms_coding_group_bits_vals[] = {
270 { 0, "General Data Coding indication" }, /* 00xx */
271 { 1, "General Data Coding indication" }, /* 00xx */
272 { 2, "General Data Coding indication" }, /* 00xx */
273 { 3, "General Data Coding indication" }, /* 00xx */
274 { 4, "Message Marked for Automatic Deletion Group" }, /* 01xx */
275 { 5, "Message Marked for Automatic Deletion Group" }, /* 01xx */
276 { 6, "Message Marked for Automatic Deletion Group" }, /* 01xx */
277 { 7, "Message Marked for Automatic Deletion Group" }, /* 01xx */
278 { 8, "Reserved coding groups" }, /* 1000..1011 */
279 { 9, "Reserved coding groups" }, /* 1000..1011 */
280 { 10, "Reserved coding groups" }, /* 1000..1011 */
281 { 11, "Reserved coding groups" }, /* 1000..1011 */
282 { 12, "Message Waiting Indication Group: Discard Message" }, /* 1100 */
283 { 13, "Message Waiting Indication Group: Store Message" }, /* 1101 */
284 { 14, "Message Waiting Indication Group: Store Message" }, /* 1110 */
285 { 15, "Data coding/message class" }, /* 1111 */
286 { 0, NULL },
288 static value_string_ext gsm_sms_coding_group_bits_vals_ext = VALUE_STRING_EXT_INIT(gsm_sms_coding_group_bits_vals);
290 static dissector_table_t gsm_sms_dissector_tbl;
291 /* Short Message reassembly */
292 static reassembly_table g_sm_reassembly_table;
293 static wmem_multimap_t *g_sm_fragment_params_table;
294 static int ett_gsm_sms_ud_fragment;
295 static int ett_gsm_sms_ud_fragments;
297 * Short Message fragment handling
299 static int hf_gsm_sms_ud_fragments;
300 static int hf_gsm_sms_ud_fragment;
301 static int hf_gsm_sms_ud_fragment_overlap;
302 static int hf_gsm_sms_ud_fragment_overlap_conflicts;
303 static int hf_gsm_sms_ud_fragment_multiple_tails;
304 static int hf_gsm_sms_ud_fragment_too_long_fragment;
305 static int hf_gsm_sms_ud_fragment_error;
306 static int hf_gsm_sms_ud_fragment_count;
307 static int hf_gsm_sms_ud_reassembled_in;
308 static int hf_gsm_sms_ud_reassembled_length;
310 static const fragment_items sm_frag_items = {
311 /* Fragment subtrees */
312 &ett_gsm_sms_ud_fragment,
313 &ett_gsm_sms_ud_fragments,
314 /* Fragment fields */
315 &hf_gsm_sms_ud_fragments,
316 &hf_gsm_sms_ud_fragment,
317 &hf_gsm_sms_ud_fragment_overlap,
318 &hf_gsm_sms_ud_fragment_overlap_conflicts,
319 &hf_gsm_sms_ud_fragment_multiple_tails,
320 &hf_gsm_sms_ud_fragment_too_long_fragment,
321 &hf_gsm_sms_ud_fragment_error,
322 &hf_gsm_sms_ud_fragment_count,
323 /* Reassembled in field */
324 &hf_gsm_sms_ud_reassembled_in,
325 /* Reassembled length field */
326 &hf_gsm_sms_ud_reassembled_length,
327 /* Reassembled data field */
328 NULL,
329 /* Tag */
330 "Short Message fragments"
333 typedef struct {
334 uint32_t length;
335 uint8_t udl;
336 uint8_t fill_bits;
337 } sm_fragment_params;
339 typedef struct {
340 const char *addr_info; /* TP-OA or TP-DA + optional lower layer info */
341 int p2p_dir;
342 address src;
343 address dst;
344 uint32_t id;
345 } sm_fragment_params_key;
347 static unsigned
348 sm_fragment_params_hash(const void *k)
350 const sm_fragment_params_key* key = (const sm_fragment_params_key*) k;
351 unsigned hash_val;
353 hash_val = (wmem_str_hash(key->addr_info) ^ key->id) + key->p2p_dir;
355 return hash_val;
358 static gboolean
359 sm_fragment_params_equal(const void *v1, const void *v2)
361 const sm_fragment_params_key *key1 = (const sm_fragment_params_key*)v1;
362 const sm_fragment_params_key *key2 = (const sm_fragment_params_key*)v2;
364 return (key1->id == key2->id) &&
365 (key1->p2p_dir == key2->p2p_dir) &&
366 !g_strcmp0(key1->addr_info, key2->addr_info) &&
367 addresses_equal(&key1->src, &key2->src) &&
368 addresses_equal(&key1->dst, &key2->dst);
371 typedef struct {
372 const char *addr_info; /* TP-OA or TP-DA + optional lower layer info */
373 int p2p_dir;
374 address src;
375 address dst;
376 uint32_t id;
377 } sm_fragment_key;
379 static unsigned
380 sm_fragment_hash(const void *k)
382 const sm_fragment_key* key = (const sm_fragment_key*) k;
383 unsigned hash_val;
385 if (!key || !key->addr_info)
386 return 0;
388 hash_val = (wmem_str_hash(key->addr_info) ^ key->id) + key->p2p_dir;
390 return hash_val;
393 static int
394 sm_fragment_equal(const void *k1, const void *k2)
396 const sm_fragment_key* key1 = (const sm_fragment_key*) k1;
397 const sm_fragment_key* key2 = (const sm_fragment_key*) k2;
399 if (!key1 || !key2)
400 return false;
402 return (key1->id == key2->id) &&
403 (key1->p2p_dir == key2->p2p_dir) &&
404 !g_strcmp0(key1->addr_info, key2->addr_info) &&
405 addresses_equal(&key1->src, &key2->src) &&
406 addresses_equal(&key1->dst, &key2->dst);
409 static void *
410 sm_fragment_temporary_key(const packet_info *pinfo,
411 const uint32_t id, const void *data)
413 const char* addr = (const char*)data;
414 sm_fragment_key *key;
416 if (addr == NULL)
417 return NULL;
419 key = g_slice_new(sm_fragment_key);
420 key->addr_info = addr;
421 key->p2p_dir = pinfo->p2p_dir;
422 copy_address_shallow(&key->src, &pinfo->src);
423 copy_address_shallow(&key->dst, &pinfo->dst);
424 key->id = id;
426 return (void *)key;
429 static void *
430 sm_fragment_persistent_key(const packet_info *pinfo,
431 const uint32_t id, const void *data)
433 const char* addr = (const char*)data;
434 sm_fragment_key *key = g_slice_new(sm_fragment_key);
436 if (addr == NULL)
437 return NULL;
439 key->addr_info = wmem_strdup(NULL, addr);
440 key->p2p_dir = pinfo->p2p_dir;
441 copy_address(&key->src, &pinfo->src);
442 copy_address(&key->dst, &pinfo->dst);
443 key->id = id;
445 return (void *)key;
448 static void
449 sm_fragment_free_temporary_key(void *ptr)
451 sm_fragment_key *key = (sm_fragment_key *)ptr;
452 g_slice_free(sm_fragment_key, key);
455 static void
456 sm_fragment_free_persistent_key(void *ptr)
458 sm_fragment_key *key = (sm_fragment_key *)ptr;
460 if(key) {
461 wmem_free(NULL, (void*)key->addr_info);
462 free_address(&key->src);
463 free_address(&key->dst);
464 g_slice_free(sm_fragment_key, key);
468 static const reassembly_table_functions
469 sm_reassembly_table_functions = {
470 sm_fragment_hash,
471 sm_fragment_equal,
472 sm_fragment_temporary_key,
473 sm_fragment_persistent_key,
474 sm_fragment_free_temporary_key,
475 sm_fragment_free_persistent_key
479 * this is the GSM 03.40 definition with the bit 2
480 * set to 1 for uplink messages
482 static const value_string msg_type_strings[] = {
483 { 0, "SMS-DELIVER" },
484 { 4, "SMS-DELIVER REPORT" },
485 { 5, "SMS-SUBMIT" },
486 { 1, "SMS-SUBMIT REPORT" },
487 { 2, "SMS-STATUS REPORT" },
488 { 6, "SMS-COMMAND" },
489 { 3, "Reserved" },
490 { 7, "Reserved" },
491 { 0, NULL },
494 static const value_string msg_type_strings_sc_to_ms[] = {
495 { 0, "SMS-DELIVER" },
496 { 1, "SMS-SUBMIT REPORT" },
497 { 2, "SMS-STATUS REPORT" },
498 { 3, "Reserved" },
499 { 0, NULL },
502 static const value_string msg_type_strings_ms_to_sc[] = {
503 { 0, "SMS-DELIVER REPORT" },
504 { 1, "SMS-SUBMIT" },
505 { 2, "SMS-COMMAND" },
506 { 3, "Reserved" },
507 { 0, NULL },
510 /* 9.2.3.3 TP-Validity-Period-Format (TP-VPF) */
511 static const value_string vp_type_strings[] = {
512 { 0, "TP-VP field not present"},
513 { 2, "TP-VP field present - relative format"},
514 { 1, "TP-VP field present - enhanced format"},
515 { 3, "TP-VP field present - absolute format"},
516 { 0, NULL },
519 static const true_false_string mms_bool_strings = {
520 "No more messages are waiting for the MS in this SC",
521 "More messages are waiting for the MS in this SC"
524 static const true_false_string lp_bool_strings = {
525 "The message has either been forwarded or is a spawned message",
526 "The message has not been forwarded and is not a spawned message"
529 static const true_false_string sri_bool_strings = {
530 "A status report shall be returned to the SME",
531 "A status report shall not be returned to the SME"
534 static const true_false_string srr_bool_strings = {
535 "A status report is requested",
536 "A status report is not requested"
539 static const true_false_string udhi_bool_strings = {
540 "The beginning of the TP UD field contains a Header in addition to the short message",
541 "The TP UD field contains only the short message"
544 static const true_false_string rp_bool_strings = {
545 "TP Reply Path parameter is set in this SMS SUBMIT/DELIVER",
546 "TP Reply Path parameter is not set in this SMS SUBMIT/DELIVER"
549 static const true_false_string rd_bool_strings = {
550 "Instruct SC to reject duplicates",
551 "Instruct SC to accept duplicates"
554 static const true_false_string srq_bool_strings = {
555 "The SMS STATUS REPORT is the result of an SMS COMMAND e.g. an Enquiry.",
556 "SMS STATUS REPORT is the result of a SMS SUBMIT."
559 static const true_false_string tfs_extended_no_extension = {
560 "Extended",
561 "No extension"
564 static const true_false_string tfs_no_extension_extended = {
565 "No extension",
566 "Extended"
570 #define NUM_UDH_IEIS 256
571 static int ett_udh_ieis[NUM_UDH_IEIS];
573 #define MAX_ADDR_SIZE 20
575 static const value_string dis_field_addr_num_types_vals[] = {
576 {0, "Unknown"},
577 {1, "International"},
578 {2, "National"},
579 {3, "Network specific"},
580 {4, "Subscriber"},
581 {5, "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)"},
582 {6, "Abbreviated number"},
583 {7, "Reserved for extension"},
584 {0, NULL }
587 static const value_string dis_field_addr_numbering_plan_vals[] = {
588 {0x0, "Unknown"},
589 {0x1, "ISDN/telephone (E.164/E.163)"},
590 {0x3, "Data numbering plan (X.121)"},
591 {0x4, "Telex numbering plan"},
592 {0x5, "Service Centre Specific plan"},
593 {0x6, "Service Centre Specific plan"},
594 {0x8, "National numbering plan"},
595 {0x9, "Private numbering plan"},
596 {0xa, "ERMES numbering plan (ETSI DE/PS 3 01-3)"},
597 {0xf, "Reserved for extension"},
598 {0, NULL }
601 void
602 dis_field_addr(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t *offset_p, const char *title)
604 proto_item *item;
605 proto_tree *subtree;
606 uint8_t oct, nt_mp;
607 uint32_t offset;
608 uint32_t numdigocts;
609 uint32_t length, addrlength;
610 char *addrstr;
612 offset = *offset_p;
614 addrlength = tvb_get_uint8(tvb, offset);
615 numdigocts = (addrlength + 1) / 2;
617 length = tvb_reported_length_remaining(tvb, offset);
619 if (length <= numdigocts)
621 proto_tree_add_expert_format(tree, pinfo, &ei_gsm_sms_short_data,
622 tvb, offset, length, "%s: Short Data (?)", title);
624 *offset_p += length;
625 return;
628 subtree = proto_tree_add_subtree(tree, tvb,
629 offset, numdigocts + 2, ett_addr, &item, title);
631 proto_tree_add_uint_format_value(subtree, hf_gsm_sms_dis_field_addr_length,
632 tvb, offset, 1,
633 addrlength, "%d address digits", addrlength);
635 offset++;
636 oct = tvb_get_uint8(tvb, offset);
637 nt_mp = oct & 0x7f;
639 proto_tree_add_item(subtree, hf_gsm_sms_dis_field_addr_extension, tvb, offset, 1, ENC_NA);
640 proto_tree_add_item(subtree, hf_gsm_sms_dis_field_addr_num_type, tvb, offset, 1, ENC_BIG_ENDIAN);
641 proto_tree_add_item(subtree, hf_gsm_sms_dis_field_addr_num_plan, tvb, offset, 1, ENC_BIG_ENDIAN);
642 offset++;
644 switch ((oct & 0x70) >> 4)
646 case 0x05: /* "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)" */
647 addrlength = (addrlength << 2) / 7;
648 addrstr = tvb_get_ts_23_038_7bits_string_packed(pinfo->pool, tvb, offset << 3,
649 (addrlength > MAX_ADDR_SIZE) ? MAX_ADDR_SIZE : addrlength);
650 break;
651 default:
652 addrstr = tvb_get_string_enc(pinfo->pool, tvb, offset, numdigocts, ENC_KEYPAD_ABC_TBCD|ENC_LITTLE_ENDIAN);
653 break;
656 if (g_ascii_strncasecmp(title, "TP-O", 4) == 0) {
657 proto_tree_add_string(subtree, hf_gsm_sms_tp_oa, tvb,
658 offset, numdigocts, addrstr);
659 if (((nt_mp >> 4) == 1) && ((nt_mp & 0x0f) == 1)) {
660 /* if Type of number international and number plan is E.164*/
661 dissect_e164_msisdn(tvb, subtree, offset, numdigocts, E164_ENC_BCD);
663 p_add_proto_data(pinfo->pool, pinfo, proto_gsm_sms, 0,
664 wmem_strdup(pinfo->pool, addrstr));
665 } else if (g_ascii_strncasecmp(title, "TP-D", 4) == 0) {
666 proto_tree_add_string(subtree, hf_gsm_sms_tp_da, tvb,
667 offset, numdigocts, addrstr);
668 if (((nt_mp >> 4) == 1) && ((nt_mp & 0x0f) == 1)) {
669 /* if Type of number international and number plan is E.164*/
670 dissect_e164_msisdn(tvb, subtree, offset, numdigocts, E164_ENC_BCD);
672 p_add_proto_data(pinfo->pool, pinfo, proto_gsm_sms, 0,
673 wmem_strdup(pinfo->pool, addrstr));
674 } else if (g_ascii_strncasecmp(title, "TP-R", 4) == 0) {
675 proto_tree_add_string(subtree, hf_gsm_sms_tp_ra, tvb,
676 offset, numdigocts, addrstr);
677 } else {
678 proto_tree_add_string(subtree, hf_gsm_sms_tp_digits, tvb,
679 offset, numdigocts, addrstr);
682 proto_item_append_text(item, " - (%s)", addrstr);
684 *offset_p = offset + numdigocts;
687 /* 9.2.3.7 */
688 /* use dis_field_addr() */
690 /* 9.2.3.8 */
691 /* use dis_field_addr() */
693 /* 9.2.3.9 */
694 static const true_false_string tfs_telematic_interworking = { "Yes", "no telematic interworking, but SME-to-SME protocol" };
696 static const range_string tp_pid_device_type_rvals[] = {
697 { 0x00, 0x00, "implicit - device type is specific to this SC, or can be concluded on the basis of the address" },
698 { 0x01, 0x01, "telex (or teletex reduced to telex format)" },
699 { 0x02, 0x02, "group 3 telefax" },
700 { 0x03, 0x03, "group 4 telefax" },
701 { 0x04, 0x04, "voice telephone (i.e. conversion to speech)" },
702 { 0x05, 0x05, "ERMES (European Radio Messaging System)" },
703 { 0x06, 0x06, "National Paging system (known to the SC)" },
704 { 0x07, 0x07, "Videotex (T.100 [20] /T.101 [21])" },
705 { 0x08, 0x08, "teletex, carrier unspecified" },
706 { 0x09, 0x09, "teletex, in PSPDN" },
707 { 0x0A, 0x0A, "teletex, in CSPDN" },
708 { 0x0B, 0x0B, "teletex, in analog PSTN" },
709 { 0x0C, 0x0C, "teletex, in digital ISDN" },
710 { 0x0D, 0x0D, "UCI (Universal Computer Interface, ETSI DE/PS 3 01-3)" },
711 { 0x0E, 0x0F, "Reserved" },
712 { 0x10, 0x10, "a message handling facility (known to the SC)" },
713 { 0x11, 0x11, "any public X.400-based message handling system" },
714 { 0x12, 0x12, "Internet Electronic Mail" },
715 { 0x13, 0x17, "Reserved" },
716 { 0x18, 0x1E, "values specific to each SC" },
717 { 0x1F, 0x1F, "GSM/UMTS mobile station" },
718 { 0, 0, NULL }
721 static const value_string pid_message_type_vals[] = {
722 {0x00, "Short Message Type 0"},
723 {0x01, "Replace Short Message Type 1"},
724 {0x02, "Replace Short Message Type 2"},
725 {0x03, "Replace Short Message Type 3"},
726 {0x04, "Replace Short Message Type 4"},
727 {0x05, "Replace Short Message Type 5"},
728 {0x06, "Replace Short Message Type 6"},
729 {0x07, "Replace Short Message Type 7"},
730 {0x08, "Device Triggering Short Message"},
731 {0x1e, "Enhanced Message Service (Obsolete)"},
732 {0x1f, "Return Call Message"},
733 {0x3c, "ANSI-136 R-DATA"},
734 {0x3d, "ME Data download"},
735 {0x3e, "ME De-personalization Short Message"},
736 {0x3f, "(U)SIM Data download"},
737 {0, NULL }
740 static void
741 dis_field_pid(tvbuff_t *tvb, proto_tree *tree, uint32_t offset, uint8_t oct)
743 proto_item *item;
744 proto_tree *subtree;
746 item = proto_tree_add_item(tree, hf_gsm_sms_tp_pid, tvb, offset, 1, ENC_BIG_ENDIAN);
747 subtree = proto_item_add_subtree(item, ett_pid);
749 switch ((oct & 0xc0) >> 6)
751 case 0:
752 proto_tree_add_item(subtree, hf_gsm_sms_tp_pid_format_subsequent_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
753 proto_tree_add_item(subtree, hf_gsm_sms_tp_pid_telematic_interworking, tvb, offset, 1, ENC_NA);
755 if (oct & 0x20)
757 proto_tree_add_item(subtree, hf_gsm_sms_tp_pid_device_type, tvb, offset, 1, ENC_BIG_ENDIAN);
759 else
761 proto_tree_add_item(subtree, hf_gsm_sms_tp_pid_sm_al_proto, tvb, offset, 1, ENC_BIG_ENDIAN);
763 break;
765 case 1:
766 proto_tree_add_item(subtree, hf_gsm_sms_tp_pid_format_subsequent_bits, tvb, offset, 1, ENC_BIG_ENDIAN);
767 proto_tree_add_item(subtree, hf_gsm_sms_tp_pid_message_type, tvb, offset, 1, ENC_BIG_ENDIAN);
768 break;
770 case 2:
771 proto_tree_add_item(subtree, hf_gsm_sms_tp_pid_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
772 proto_tree_add_item(subtree, hf_gsm_sms_tp_pid_undefined, tvb, offset, 1, ENC_BIG_ENDIAN);
773 break;
775 case 3:
776 proto_tree_add_item(subtree, hf_gsm_sms_tp_pid_sc_specific_use, tvb, offset, 1, ENC_BIG_ENDIAN);
777 proto_tree_add_item(subtree, hf_gsm_sms_tp_pid_sc_specific, tvb, offset, 1, ENC_BIG_ENDIAN);
778 break;
782 /* 9.2.3.10 */
783 static const value_string dcs_character_set_vals[] = {
784 {0x00, "GSM 7 bit default alphabet"},
785 {0x01, "8 bit data"},
786 {0x02, "UCS2 (16 bit)/UTF-16"},
787 {0x03, "Reserved"},
788 {0, NULL }
791 static const value_string dcs_message_class_vals[] = {
792 {0x00, "Class 0"},
793 {0x01, "Class 1 Default meaning: ME-specific"},
794 {0x02, "Class 2 (U)SIM specific message"},
795 {0x03, "Class 3 Default meaning: TE-specific"},
796 {0, NULL }
799 static const value_string dcs_message_waiting_vals[] = {
800 {0x00, "Voicemail"},
801 {0x01, "Fax"},
802 {0x02, "Electronic Mail"},
803 {0x03, "Other"},
804 {0, NULL }
807 static const true_false_string tfs_indication_sense = { "Set Indication Active", "Set Indication Inactive"};
808 static const true_false_string tfs_message_coding = { "8 bit data", "GSM 7 bit default alphabet"};
809 static const true_false_string tfs_compressed_not_compressed = { "Compressed", "Not compressed"};
810 static const true_false_string tfs_message_class_defined = { "Defined below", "Reserved, no message class"};
812 static void
813 dis_field_dcs(tvbuff_t *tvb, proto_tree *tree, uint32_t offset, uint8_t oct,
814 enum character_set *cset, bool *compressed)
816 proto_item *item;
817 proto_tree *subtree;
818 bool default_5_bits;
819 bool default_3_bits;
820 bool default_data;
822 *cset = OTHER;
823 *compressed = false;
825 item = proto_tree_add_item(tree, hf_gsm_sms_tp_dcs, tvb, offset, 1, ENC_BIG_ENDIAN);
827 subtree = proto_item_add_subtree(item, ett_dcs);
828 if (oct&0x80) {
829 proto_tree_add_item(subtree, hf_gsm_sms_coding_group_bits4, tvb, offset, 1, ENC_BIG_ENDIAN);
830 } else {
831 proto_tree_add_item(subtree, hf_gsm_sms_coding_group_bits2, tvb, offset, 1, ENC_BIG_ENDIAN);
834 if (oct == 0x00)
836 proto_tree_add_item(subtree, hf_gsm_sms_gsm_7_bit_default_alphabet, tvb, offset, 1, ENC_NA);
838 *cset = GSM_7BITS;
839 return;
842 default_5_bits = false;
843 default_3_bits = false;
844 default_data = false;
846 switch ((oct & 0xc0) >> 6)
848 case 0:
849 default_5_bits = true;
850 break;
852 case 1:
853 default_5_bits = true;
854 break;
856 case 2:
857 /* Reserved coding groups */
858 return;
860 case 3:
861 switch ((oct & 0x30) >> 4)
863 case 0x00:
864 default_3_bits = true;
865 *cset = GSM_7BITS;
866 break;
867 case 0x01:
868 default_3_bits = true;
869 *cset = GSM_7BITS;
870 break;
871 case 0x02:
872 default_3_bits = true;
873 *cset = UCS2;
874 break;
875 case 0x03:
876 default_data = true;
877 break;
879 break;
882 if (default_5_bits)
884 *compressed = (oct & 0x20) >> 5;
885 proto_tree_add_item(subtree, hf_gsm_sms_dcs_text_compressed, tvb, offset, 1, ENC_NA);
886 proto_tree_add_item(subtree, hf_gsm_sms_dcs_message_class_defined, tvb, offset, 1, ENC_NA);
888 switch ((oct & 0x0c) >> 2)
890 case 0x00:
891 *cset = GSM_7BITS;
892 break;
893 case 0x01:
894 *cset = OTHER;
895 break;
896 case 0x02:
897 *cset = UCS2;
898 break;
899 case 0x03:
900 /* Reserved */
901 break;
904 proto_tree_add_item(subtree, hf_gsm_sms_dcs_character_set, tvb, offset, 1, ENC_BIG_ENDIAN);
905 proto_tree_add_item(subtree, hf_gsm_sms_dcs_message_class, tvb, offset, 1, ENC_BIG_ENDIAN);
907 else if (default_3_bits)
909 proto_tree_add_item(subtree, hf_gsm_sms_dcs_indication_sense, tvb, offset, 1, ENC_NA);
910 proto_tree_add_item(subtree, hf_gsm_sms_dcs_reserved04, tvb, offset, 1, ENC_BIG_ENDIAN);
911 proto_tree_add_item(subtree, hf_gsm_sms_dcs_message_waiting, tvb, offset, 1, ENC_BIG_ENDIAN);
913 else if (default_data)
915 *cset = (oct & 0x04) ? OTHER : GSM_7BITS;
916 proto_tree_add_item(subtree, hf_gsm_sms_dcs_reserved08, tvb, offset, 1, ENC_BIG_ENDIAN);
917 proto_tree_add_item(subtree, hf_gsm_sms_dcs_message_coding, tvb, offset, 1, ENC_NA);
918 proto_tree_add_item(subtree, hf_gsm_sms_dcs_message_class, tvb, offset, 1, ENC_BIG_ENDIAN);
922 static void
923 dis_field_scts_aux(tvbuff_t *tvb, proto_tree *tree, uint32_t offset)
925 uint8_t oct;
926 uint16_t value;
927 char sign;
929 oct = tvb_get_uint8(tvb, offset);
930 value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
931 proto_tree_add_uint(tree, hf_gsm_sms_scts_year, tvb, offset, 1, value);
932 offset++;
933 oct = tvb_get_uint8(tvb, offset);
934 value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
935 proto_tree_add_uint(tree, hf_gsm_sms_scts_month, tvb, offset, 1, value);
936 offset++;
937 oct = tvb_get_uint8(tvb, offset);
938 value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
939 proto_tree_add_uint(tree, hf_gsm_sms_scts_day, tvb, offset, 1, value);
940 offset++;
941 oct = tvb_get_uint8(tvb, offset);
942 value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
943 proto_tree_add_uint(tree, hf_gsm_sms_scts_hour, tvb, offset, 1, value);
944 offset++;
945 oct = tvb_get_uint8(tvb, offset);
946 value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
947 proto_tree_add_uint(tree, hf_gsm_sms_scts_minutes, tvb, offset, 1, value);
948 offset++;
949 oct = tvb_get_uint8(tvb, offset);
950 value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
951 proto_tree_add_uint(tree, hf_gsm_sms_scts_seconds, tvb, offset, 1, value);
952 offset++;
954 oct = tvb_get_uint8(tvb, offset);
956 sign = (oct & 0x08)?'-':'+';
957 oct = (oct >> 4) + (oct & 0x07) * 10;
959 proto_tree_add_uint_format_value(tree, hf_gsm_sms_scts_timezone, tvb, offset, 1,
960 oct, "GMT %c %d hours %d minutes",
961 sign, oct / 4, oct % 4 * 15);
964 /* 9.2.3.11 */
965 static void
966 dis_field_scts(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t *offset_p)
968 proto_tree *subtree;
969 uint32_t offset;
970 uint32_t length;
973 offset = *offset_p;
975 length = tvb_reported_length_remaining(tvb, offset);
977 if (length < 7)
979 proto_tree_add_expert_format(tree, pinfo, &ei_gsm_sms_short_data,
980 tvb, offset, length,
981 "TP-Service-Centre-Time-Stamp: Short Data (?)");
983 *offset_p += length;
984 return;
987 subtree = proto_tree_add_subtree(tree, tvb,
988 offset, 7, ett_scts, NULL,
989 "TP-Service-Centre-Time-Stamp");
991 dis_field_scts_aux(tvb, subtree, *offset_p);
993 *offset_p += 7;
996 /* 9.2.3.12 */
997 static const value_string vp_validity_period_format_vals[] = {
998 {0x00, "None specified"},
999 {0x01, "Relative"},
1000 {0x02, "Relative"},
1001 {0x03, "Relative"},
1002 {0x04, "Reserved"},
1003 {0x05, "Reserved"},
1004 {0x06, "Reserved"},
1005 {0x07, "Reserved"},
1006 {0, NULL }
1009 static void
1010 dis_field_vp(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t *offset_p, uint8_t vp_form)
1012 proto_tree *subtree;
1013 uint32_t offset;
1014 uint32_t length;
1015 uint8_t oct;
1016 uint8_t loc_form;
1017 uint16_t value;
1018 uint32_t mins, hours;
1019 bool done;
1022 if (vp_form == 0x00) return;
1024 offset = *offset_p;
1025 subtree = tree;
1027 done = false;
1030 switch (vp_form)
1032 case 1:
1033 length = tvb_reported_length_remaining(tvb, offset);
1035 if (length < 7)
1037 proto_tree_add_expert_format(tree, pinfo, &ei_gsm_sms_short_data,
1038 tvb, offset, length,
1039 "TP-Validity-Period: Short Data (?)");
1041 *offset_p += length;
1042 return;
1045 subtree = proto_tree_add_subtree(tree, tvb, offset, 7, ett_vp, NULL, "TP-Validity-Period");
1047 oct = tvb_get_uint8(tvb, offset);
1049 proto_tree_add_item(subtree, hf_gsm_sms_vp_extension, tvb, offset, 1, ENC_NA);
1050 if (oct & 0x80)
1052 proto_tree_add_item(subtree, hf_gsm_sms_vp_extension_ignored, tvb, offset + 1, 6, ENC_NA);
1053 *offset_p += 7;
1054 return;
1057 proto_tree_add_item(subtree, hf_gsm_sms_vp_single_shot_sm, tvb, offset, 1, ENC_NA);
1058 proto_tree_add_item(subtree, hf_gsm_sms_vp_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
1059 proto_tree_add_item(subtree, hf_gsm_sms_vp_validity_period_format, tvb, offset, 1, ENC_BIG_ENDIAN);
1061 loc_form = oct & 0x7;
1062 switch (loc_form)
1064 case 0x00:
1065 done = true;
1066 break;
1068 case 0x01:
1069 offset++;
1070 /* go around again */
1071 vp_form = 2;
1072 break;
1074 case 0x02:
1075 offset++;
1076 oct = tvb_get_uint8(tvb, offset);
1077 proto_tree_add_uint_format_value(subtree, hf_gsm_sms_vp_validity_period, tvb, offset, 1,
1078 oct, "%d seconds", oct);
1079 done = true;
1080 break;
1082 case 0x03:
1083 offset++;
1084 oct = tvb_get_uint8(tvb, offset);
1085 value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
1086 proto_tree_add_uint(subtree, hf_gsm_sms_vp_validity_period_hour, tvb, offset, 1, value);
1087 offset++;
1088 oct = tvb_get_uint8(tvb, offset);
1089 value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
1090 proto_tree_add_uint(subtree, hf_gsm_sms_vp_validity_period_minutes, tvb, offset, 1, value);
1091 offset++;
1092 oct = tvb_get_uint8(tvb, offset);
1093 value = (oct & 0x0f)*10 + ((oct & 0xf0) >> 4);
1094 proto_tree_add_uint(subtree, hf_gsm_sms_vp_validity_period_seconds, tvb, offset, 1, value);
1095 offset++;
1096 done = true;
1097 break;
1099 default:
1100 done = true;
1101 break;
1103 break;
1105 case 2:
1106 oct = tvb_get_uint8(tvb, offset);
1108 if (oct <= 143)
1110 mins = (oct + 1) * 5;
1111 if (mins >= 60)
1113 hours = mins / 60;
1114 mins %= 60;
1116 proto_tree_add_uint_format_value(subtree, hf_gsm_sms_vp_validity_period, tvb, offset, 1,
1117 oct, "%d hours %d minutes", hours, mins);
1119 else
1121 proto_tree_add_uint_format_value(subtree, hf_gsm_sms_vp_validity_period, tvb, offset, 1,
1122 oct, "%d minutes", mins);
1125 else if ((oct >= 144) &&
1126 (oct <= 167))
1128 mins = (oct - 143) * 30;
1129 hours = 12 + (mins / 60);
1130 mins %= 60;
1132 proto_tree_add_uint_format_value(subtree, hf_gsm_sms_vp_validity_period, tvb, offset, 1,
1133 oct, "%d hours %d minutes", hours, mins);
1135 else if ((oct >= 168) &&
1136 (oct <= 196))
1138 proto_tree_add_uint_format_value(subtree, hf_gsm_sms_vp_validity_period, tvb, offset, 1,
1139 oct, "%d day(s)", oct - 166);
1141 else if (oct >= 197)
1143 proto_tree_add_uint_format_value(subtree, hf_gsm_sms_vp_validity_period, tvb, offset, 1,
1144 oct, "%d week(s)", oct - 192);
1147 done = true;
1148 break;
1150 case 3:
1151 length = tvb_reported_length_remaining(tvb, offset);
1153 if (length < 7)
1155 proto_tree_add_expert_format(tree, pinfo, &ei_gsm_sms_short_data,
1156 tvb, offset, length,
1157 "TP-Validity-Period: Short Data (?)");
1159 *offset_p += length;
1160 return;
1163 subtree = proto_tree_add_subtree(tree, tvb,
1164 offset, 7, ett_vp, NULL,
1165 "TP-Validity-Period: absolute");
1167 dis_field_scts_aux(tvb, subtree, *offset_p);
1169 done = true;
1170 break;
1173 while (!done);
1175 if (vp_form == 2)
1177 (*offset_p)++;
1179 else
1181 *offset_p += 7;
1185 /* 9.2.3.13 */
1186 static void
1187 dis_field_dt(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t *offset_p)
1189 proto_tree *subtree;
1190 uint32_t offset;
1191 uint32_t length;
1194 offset = *offset_p;
1196 length = tvb_reported_length_remaining(tvb, offset);
1198 if (length < 7)
1200 proto_tree_add_expert_format(tree, pinfo, &ei_gsm_sms_short_data,
1201 tvb, offset, length,
1202 "TP-Discharge-Time: Short Data (?)");
1204 *offset_p += length;
1205 return;
1208 subtree = proto_tree_add_subtree(tree, tvb,
1209 offset, 7, ett_dt, NULL,
1210 "TP-Discharge-Time");
1212 dis_field_scts_aux(tvb, subtree, *offset_p);
1214 *offset_p += 7;
1217 /* 9.2.3.14 */
1218 /* use dis_field_addr() */
1220 /* 9.2.3.15 TP-Status (TP-ST) */
1221 static const value_string dis_field_st_error_vals[] = {
1222 { 0x00, "No error, short message transaction completed" },
1223 { 0x01, "Temporary error, SC still trying to transfer SM" },
1224 { 0x02, "Permanent error, SC is not making any more transfer attempts" },
1225 { 0x03, "Temporary error, SC is not making any more transfer attempts" },
1226 { 0x00, NULL },
1229 static const range_string dis_field_st_error00_reason_rvals[] = {
1230 { 0x00, 0x00, "Short message received by the SME" },
1231 { 0x01, 0x01, "Short message forwarded by the SC to the SME but the SC is unable to confirm delivery" },
1232 { 0x02, 0x02, "Short message replaced by the SC Reserved values" },
1233 { 0x03, 0x0F, "Reserved" },
1234 { 0x10, 0x1F, "Values specific to each SC" },
1235 { 0x00, 0x00, NULL },
1238 static const range_string dis_field_st_error01_reason_rvals[] = {
1239 { 0x00, 0x00, "Congestion" },
1240 { 0x01, 0x01, "SME busy" },
1241 { 0x02, 0x02, "No response from SME" },
1242 { 0x03, 0x03, "Service rejected" },
1243 { 0x04, 0x04, "Quality of service not available" },
1244 { 0x05, 0x05, "Error in SME" },
1245 { 0x06, 0x0F, "Reserved" },
1246 { 0x10, 0x1F, "Values specific to each SC" },
1247 { 0x00, 0x00, NULL },
1250 static const range_string dis_field_st_error10_reason_rvals[] = {
1251 { 0x00, 0x00, "Remote procedure error" },
1252 { 0x01, 0x01, "Incompatible destination" },
1253 { 0x02, 0x02, "Connection rejected by SME" },
1254 { 0x03, 0x03, "Not obtainable" },
1255 { 0x04, 0x04, "Quality of service not available" },
1256 { 0x05, 0x05, "No interworking available" },
1257 { 0x06, 0x06, "SM Validity Period Expired" },
1258 { 0x07, 0x07, "SM Deleted by originating SME" },
1259 { 0x08, 0x08, "SM Deleted by SC Administration" },
1260 { 0x09, 0x09, "SM does not exist (The SM may have previously existed in the SC but the SC no longer has knowledge of it or the SM may never have previously existed in the SC)" },
1261 { 0x0A, 0x0F, "Reserved" },
1262 { 0x10, 0x1f, "Values specific to each SC" },
1263 { 0x00, 0x00, NULL },
1266 static const range_string dis_field_st_error11_reason_rvals[] = {
1267 { 0x00, 0x00, "Congestion" },
1268 { 0x01, 0x01, "SME busy" },
1269 { 0x02, 0x02, "No response from SME" },
1270 { 0x03, 0x03, "Service rejected" },
1271 { 0x04, 0x04, "Quality of service not available" },
1272 { 0x05, 0x05, "Error in SME" },
1273 { 0x06, 0x0F, "Reserved" },
1274 { 0x10, 0x1F, "Values specific to each SC" },
1275 { 0x00, 0x00, NULL },
1278 static const true_false_string tfs_dis_field_definition = { "Reserved", "as follows" };
1280 static void
1281 dis_field_st(tvbuff_t *tvb, proto_tree *tree, uint32_t offset)
1283 proto_tree *subtree;
1284 uint32_t error;
1286 subtree = proto_tree_add_subtree(tree, tvb,
1287 offset, 1, ett_st, NULL, "TP-Status");
1289 proto_tree_add_item(subtree, hf_gsm_sms_dis_field_definition, tvb, offset, 1, ENC_NA);
1290 proto_tree_add_item_ret_uint(subtree, hf_gsm_sms_dis_field_st_error,
1291 tvb, offset, 1, ENC_BIG_ENDIAN, &error);
1293 /* Shall not happen as we use mask 0x60 (2 bits high) to get the value */
1294 DISSECTOR_ASSERT(error < array_length(hf_gsm_sms_dis_field_st_reason));
1295 proto_tree_add_item(subtree, hf_gsm_sms_dis_field_st_reason[error],
1296 tvb, offset, 1, ENC_BIG_ENDIAN);
1299 /* 9.2.3.16 */
1300 #define DIS_FIELD_UDL(m_tree, m_offset) \
1301 proto_tree_add_uint_format_value(m_tree, hf_gsm_sms_tp_user_data_length, tvb, m_offset, 1, oct, \
1302 "(%d) %s", oct, oct ? "depends on Data-Coding-Scheme" : "no User-Data");
1304 /* 9.2.3.17 */
1305 #define DIS_FIELD_RP(m_tree, hf, m_offset) \
1306 proto_tree_add_item(m_tree, hf, tvb, m_offset, 1, ENC_NA);
1308 /* 9.2.3.18 */
1309 #define DIS_FIELD_MN(m_tree, m_offset) \
1310 proto_tree_add_item(m_tree, hf_gsm_sms_tp_message_number, tvb, m_offset, 1, ENC_BIG_ENDIAN);
1312 /* 9.2.3.19 */
1313 static const range_string tp_command_type_rvals[] = {
1314 { 0x00, 0x00, "Enquiry relating to previously submitted short message" },
1315 { 0x01, 0x01, "Cancel Status Report Request relating to previously submitted short message" },
1316 { 0x02, 0x02, "Delete previously submitted Short Message" },
1317 { 0x03, 0x03, "Enable Status Report Request relating to previously submitted short message" },
1318 { 0x04, 0x1F, "Reserved unspecified" },
1319 { 0x20, 0xDF, "Undefined" },
1320 { 0xE0, 0xFF, "Values specific for each SC" },
1321 { 0x00, 0x00, NULL },
1324 #define DIS_FIELD_CT(m_tree, m_offset) \
1325 proto_tree_add_item(m_tree, hf_gsm_sms_tp_command_type, tvb, m_offset, 1, ENC_BIG_ENDIAN);
1327 /* 9.2.3.20 */
1328 #define DIS_FIELD_CDL(m_tree, m_offset) \
1329 if (oct) \
1330 proto_tree_add_item(m_tree, hf_gsm_sms_tp_command_data_length, tvb, m_offset, 1, ENC_BIG_ENDIAN); \
1331 else \
1332 proto_tree_add_uint_format_value(m_tree, hf_gsm_sms_tp_command_data_length, tvb, m_offset, 1, 0, "(0) no Command-Data"); \
1334 /* 9.2.3.21 */
1335 /* done in-line in the message functions */
1338 * 9.2.3.22 TP-Failure-Cause (TP-FCS)
1342 static const range_string gsm_sms_tp_failure_cause_values[] = {
1343 { 0x00, 0x7F, "Reserved" },
1344 /* 80 - 8F TP-PID errors */
1345 { 0x80, 0x80, "Telematic interworking not supported" },
1346 { 0x81, 0x81, "Short message Type 0 not supported" },
1347 { 0x82, 0x82, "Cannot replace short message" },
1348 { 0x83, 0x8E, "Reserved" },
1349 { 0x8F, 0x8F, "Unspecified TP-PID error" },
1350 /* 90 - 9F TP-DCS errors */
1351 { 0x90, 0x90, "Data coding scheme (alphabet) not supported" },
1352 { 0x91, 0x91, "Message class not supported" },
1353 { 0x92, 0x9E, "Reserved" },
1354 { 0x9F, 0x9F, "Unspecified TP-DCS error" },
1355 /* A0 - AF TP-Command Errors */
1356 { 0xA0, 0xA0, "Command cannot be actioned" },
1357 { 0xA1, 0xA1, "Command unsupported" },
1358 { 0xA2, 0xAE, "Reserved" },
1359 { 0xAF, 0xAF, "Unspecified TP-Command error" },
1360 { 0xB0, 0xB0, "TPDU not supported" },
1361 { 0xB1, 0xBF, "Reserved" },
1362 { 0xC0, 0xC0, "SC busy" },
1363 { 0xC1, 0xC1, "No SC subscription" },
1364 { 0xC2, 0xC2, "SC system failure" },
1365 { 0xC3, 0xC3, "Invalid SME address" },
1366 { 0xC4, 0xC4, "Destination SME barred" },
1367 { 0xC5, 0xC5, "SM Rejected-Duplicate SM" },
1368 { 0xC6, 0xC6, "TP-VPF not supported" },
1369 { 0xC7, 0xC7, "TP-VP not supported" },
1370 { 0xC8, 0xCF, "Reserved" },
1371 { 0xD0, 0xD0, "(U)SIM SMS storage full" },
1372 { 0xD1, 0xD1, "No SMS storage capability in (U)SIM" },
1373 { 0xD2, 0xD2, "Error in MS" },
1374 { 0xD3, 0xD3, "Memory Capacity Exceeded" },
1375 { 0xD4, 0xD4, "(U)SIM Application Toolkit Busy" },
1376 { 0xD5, 0xD5, "(U)SIM data download error" },
1377 { 0xD6, 0xDF, "Reserved" },
1378 { 0xE0, 0xFE, "Value specific to an application" },
1379 { 0xFF, 0xFF, "Unspecified error cause" },
1380 { 0, 0, NULL }
1383 static void
1384 dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, uint32_t offset, uint8_t oct _U_)
1386 proto_tree_add_item(tree, hf_gsm_sms_tp_fail_cause, tvb, offset, 1, ENC_BIG_ENDIAN);
1389 /* 9.2.3.23 */
1390 #if 0
1391 static const true_false_string tfs_user_data_header_indicator = { "The beginning of the TP-UD field contains a Header in addition to the short message",
1392 "The TP-UD field contains only the short message" };
1393 #endif
1395 #define DIS_FIELD_UDHI(m_tree, hf, m_offset) \
1396 proto_tree_add_item(m_tree, hf, tvb, m_offset, 1, ENC_BIG_ENDIAN);
1398 /* 9.2.3.24.1 */
1399 static void
1400 dis_iei_csm8(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields)
1402 uint8_t oct;
1404 EXACT_DATA_CHECK(length, 3);
1405 oct = tvb_get_uint8(tvb, offset);
1406 p_udh_fields->sm_id = oct;
1407 proto_tree_add_uint (tree, hf_gsm_sms_ud_multiple_messages_msg_id,
1408 tvb, offset, 1, oct);
1409 offset++;
1411 oct = tvb_get_uint8(tvb, offset);
1412 p_udh_fields->frags = oct;
1413 proto_tree_add_uint (tree, hf_gsm_sms_ud_multiple_messages_msg_parts,
1414 tvb, offset, 1, oct);
1415 offset++;
1416 oct = tvb_get_uint8(tvb, offset);
1417 p_udh_fields->frag = oct;
1418 proto_tree_add_uint (tree,
1419 hf_gsm_sms_ud_multiple_messages_msg_part,
1420 tvb, offset, 1, oct);
1424 /* 9.2.3.24.2 Special SMS Message Indication */
1425 static const true_false_string gsm_sms_msg_type_and_stor_value = {
1426 "Store message after updating indication",
1427 "Discard message after updating indication"
1430 static const value_string gsm_sms_profile_id_vals[] = {
1431 { 0, "Profile ID 1" },
1432 { 1, "Profile ID 2" },
1433 { 2, "Profile ID 3" },
1434 { 3, "Profile ID 4" },
1435 { 0, NULL },
1438 static const range_string gsm_sms_ext_msg_ind_type_vals[] = {
1439 { 0, 0, "No extended message indication type" },
1440 { 1, 1, "Video Message Waiting" },
1441 { 2, 7, "Reserved" },
1442 { 0, 0, NULL }
1445 static const value_string gsm_sms_msg_ind_type_vals[] = {
1446 { 0, "Voice Message Waiting" },
1447 { 1, "Fax Message Waiting" },
1448 { 2, "Electronic Mail Message Waiting" },
1449 { 3, "Extended Message Type Waiting" },
1450 { 0, NULL },
1453 static void
1454 dis_iei_spe_sms_msg_ind(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset,
1455 uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1457 EXACT_DATA_CHECK(length, 2);
1459 proto_tree_add_item(tree, hf_gsm_sms_msg_ind_type_and_stor, tvb, offset, 1, ENC_BIG_ENDIAN);
1460 proto_tree_add_item(tree, hf_gsm_sms_msg_profile_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1461 proto_tree_add_item(tree, hf_gsm_sms_ext_msg_ind_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1462 proto_tree_add_item(tree, hf_gsm_sms_msg_ind_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1463 proto_tree_add_item(tree, hf_gsm_sms_msg_count, tvb, offset+1, 1, ENC_BIG_ENDIAN);
1466 /* 9.2.3.24.3 */
1467 static const range_string gsm_sms_8bit_port_values[] = {
1468 { 0, 239, "Reserved" },
1469 { 240, 255, "Available for allocation by applications" },
1470 { 0, 0, NULL }
1473 static void
1474 dis_iei_apa_8bit(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields)
1476 EXACT_DATA_CHECK(length, 2);
1478 p_udh_fields->port_dst = tvb_get_uint8(tvb, offset);
1479 proto_tree_add_item(tree, hf_gsm_sms_destination_port8, tvb, offset, 1, ENC_BIG_ENDIAN);
1480 offset++;
1481 p_udh_fields->port_src = tvb_get_uint8(tvb, offset);
1482 proto_tree_add_item(tree, hf_gsm_sms_originator_port8, tvb, offset, 1, ENC_BIG_ENDIAN);
1485 /* 9.2.3.24.4 */
1486 static const range_string gsm_sms_16bit_port_values[] = {
1487 { 0, 15999, "UDP/TCP port numbers assigned by IANA without the need to refer to 3GPP" },
1488 { 16000, 16999, "Available for allocation by SMS applications without the need to refer to 3GPP or IANA" },
1489 { 17000, 49151, "UDP/TCP port numbers assigned by IANA" },
1490 { 49152, 65535, "Reserved for future allocation by 3GPP" },
1491 { 0, 0, NULL }
1494 static void
1495 dis_iei_apa_16bit(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields)
1497 EXACT_DATA_CHECK(length, 4);
1499 p_udh_fields->port_dst = tvb_get_ntohs(tvb, offset);
1500 proto_tree_add_item(tree, hf_gsm_sms_destination_port16, tvb, offset, 2, ENC_BIG_ENDIAN);
1501 offset += 2;
1502 p_udh_fields->port_src = tvb_get_ntohs(tvb, offset);
1503 proto_tree_add_item(tree, hf_gsm_sms_originator_port16, tvb, offset, 2, ENC_BIG_ENDIAN);
1506 /* 9.2.3.24.5 */
1507 static const true_false_string tfs_status_report_active = { "A Status Report generated by this Short Message, due to a permanent error or last temporary error, cancels the SRR of the rest of the Short Messages in a concatenated message",
1508 "No activation" };
1510 static void
1511 dis_iei_scp(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1513 static int * const status_flags[] = {
1514 &hf_gsm_sms_status_report_short_msg,
1515 &hf_gsm_sms_status_report_permanent_error,
1516 &hf_gsm_sms_status_report_temp_error_no_attempt,
1517 &hf_gsm_sms_status_report_temp_error_transfer,
1518 &hf_gsm_sms_status_report_active,
1519 &hf_gsm_sms_status_report_original_udh,
1520 NULL
1523 EXACT_DATA_CHECK(length, 1);
1525 proto_tree_add_bitmask(tree, tvb, offset, hf_gsm_sms_status_report, ett_st, status_flags, ENC_NA);
1528 /* 9.2.3.24.6 */
1529 static const value_string udh_created_vals[] = {
1530 {0x01, "Original sender (valid in case of Status Report)"},
1531 {0x02, "Original receiver (valid in case of Status Report)"},
1532 {0x03, "SMSC (can occur in any message or report)"},
1533 {0, NULL }
1536 static void
1537 dis_iei_udh_si(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1539 EXACT_DATA_CHECK(length, 1);
1541 proto_tree_add_item(tree, hf_gsm_sms_udh_created, tvb, offset, 1, ENC_BIG_ENDIAN);
1544 /* 9.2.3.24.8 */
1545 static void
1546 dis_iei_csm16(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields)
1548 uint8_t oct;
1549 uint16_t oct_ref;
1551 EXACT_DATA_CHECK(length, 4);
1552 oct_ref = tvb_get_ntohs(tvb, offset);
1553 p_udh_fields->sm_id = oct_ref;
1554 proto_tree_add_uint (tree,
1555 hf_gsm_sms_ud_multiple_messages_msg_id,
1556 tvb, offset, 2, oct_ref);
1557 offset+=2;
1558 oct = tvb_get_uint8(tvb, offset);
1559 p_udh_fields->frags = oct;
1560 proto_tree_add_uint (tree,
1561 hf_gsm_sms_ud_multiple_messages_msg_parts,
1562 tvb , offset , 1, oct);
1564 offset++;
1565 oct = tvb_get_uint8(tvb, offset);
1566 p_udh_fields->frag = oct;
1567 proto_tree_add_uint (tree,
1568 hf_gsm_sms_ud_multiple_messages_msg_part,
1569 tvb, offset, 1, oct);
1572 static const value_string text_color_values[] = {
1573 { 0x00, "Black" },
1574 { 0x01, "Dark Grey" },
1575 { 0x02, "Dark Red" },
1576 { 0x03, "Dark Yellow" },
1577 { 0x04, "Dark Green" },
1578 { 0x05, "Dark Cyan" },
1579 { 0x06, "Dark Blue" },
1580 { 0x07, "Dark Magenta" },
1581 { 0x08, "Grey" },
1582 { 0x09, "White" },
1583 { 0x0A, "Bright Red" },
1584 { 0x0B, "Bright Yellow" },
1585 { 0x0C, "Bright Green" },
1586 { 0x0D, "Bright Cyan" },
1587 { 0x0E, "Bright Blue" },
1588 { 0x0F, "Bright Magenta" },
1589 { 0, NULL }
1591 static value_string_ext text_color_values_ext = VALUE_STRING_EXT_INIT(text_color_values);
1593 static const value_string alignment_values[] = {
1594 { 0x00, "Left" },
1595 { 0x01, "Center" },
1596 { 0x02, "Right" },
1597 { 0x03, "Language dependent" },
1598 { 0, NULL }
1601 static const value_string font_size_values[] = {
1602 { 0x00, "Normal" },
1603 { 0x01, "Large" },
1604 { 0x02, "Small" },
1605 { 0x03, "Reserved" },
1606 { 0, NULL }
1609 /* 9.2.3.24.10.1.1 */
1610 static void
1611 dis_iei_tf(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1613 proto_tree* subtree_colour;
1615 static int * const format_flags[] = {
1616 &hf_gsm_sms_formatting_mode_alignment,
1617 &hf_gsm_sms_formatting_mode_font_size,
1618 &hf_gsm_sms_formatting_mode_style_bold,
1619 &hf_gsm_sms_formatting_mode_style_italic,
1620 &hf_gsm_sms_formatting_mode_style_underlined,
1621 &hf_gsm_sms_formatting_mode_style_strikethrough,
1622 NULL
1625 SHORT_DATA_CHECK(length, 3);
1627 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_tf_start_position, tvb, offset, 1, ENC_BIG_ENDIAN);
1628 offset++;
1630 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_tf_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1631 offset++;
1633 proto_tree_add_bitmask(tree, tvb, offset, hf_gsm_sms_formatting_mode, ett_udh_tfm, format_flags, ENC_NA);
1634 offset++;
1636 if (length > 3)
1638 subtree_colour = proto_tree_add_subtree(tree, tvb, offset, 1, ett_udh_tfc, NULL, "Text Colour");
1640 proto_tree_add_item(subtree_colour, hf_gsm_sms_dis_iei_tf_foreground_colour, tvb, offset, 1, ENC_BIG_ENDIAN);
1642 proto_tree_add_item(subtree_colour, hf_gsm_sms_dis_iei_tf_background_colour, tvb, offset, 1, ENC_BIG_ENDIAN);
1646 /* 9.2.3.24.10.1.2 */
1647 static void
1648 dis_iei_ps(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1650 EXACT_DATA_CHECK(length, 2);
1652 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_ps_position, tvb, offset, 1, ENC_BIG_ENDIAN);
1653 offset++;
1655 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_ps_sound_number, tvb, offset, 1, ENC_BIG_ENDIAN);
1658 /* 9.2.3.24.10.1.3 */
1659 static void
1660 dis_iei_uds(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1662 SHORT_DATA_CHECK(length, 2);
1664 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_uds_position, tvb, offset, 1, ENC_BIG_ENDIAN);
1665 offset++;
1667 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_uds_user_defined_sound, tvb, offset, length - 1, ENC_NA);
1671 /* 9.2.3.24.10.1.4 */
1672 static void
1673 dis_iei_pa(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1675 EXACT_DATA_CHECK(length, 2);
1677 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_pa_position, tvb, offset, 1, ENC_BIG_ENDIAN);
1678 offset++;
1680 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_pa_animation_number, tvb, offset, 1, ENC_BIG_ENDIAN);
1684 /* 9.2.3.24.10.1.5 */
1685 static void
1686 dis_iei_la(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1688 SHORT_DATA_CHECK(length, 2);
1690 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_la_position, tvb, offset, 1, ENC_BIG_ENDIAN);
1691 offset++;
1693 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_la_large_animation, tvb, offset, length - 1, ENC_NA);
1696 /* 9.2.3.24.10.1.6 */
1697 static void
1698 dis_iei_sa(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1700 SHORT_DATA_CHECK(length, 2);
1702 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_sa_position, tvb, offset, 1, ENC_BIG_ENDIAN);
1703 offset++;
1705 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_sa_small_animation, tvb, offset, length - 1, ENC_NA);
1709 /* 9.2.3.24.10.1.7 */
1710 static void
1711 dis_iei_lp(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1713 SHORT_DATA_CHECK(length, 2);
1715 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_lp_position, tvb, offset, 1, ENC_BIG_ENDIAN);
1716 offset++;
1718 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_lp_large_picture, tvb, offset, length - 1, ENC_NA);
1721 /* 9.2.3.24.10.1.8 */
1722 static void
1723 dis_iei_sp(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1725 SHORT_DATA_CHECK(length, 2);
1727 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_sp_position, tvb, offset, 1, ENC_BIG_ENDIAN);
1728 offset++;
1730 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_sp_small_picture, tvb, offset, length - 1, ENC_NA);
1734 /* 9.2.3.24.10.1.9 */
1735 static void
1736 dis_iei_vp(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1738 SHORT_DATA_CHECK(length, 4);
1740 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_vp_position, tvb, offset, 1, ENC_BIG_ENDIAN);
1741 offset++;
1743 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_vp_horizontal_dimension, tvb, offset, 1, ENC_BIG_ENDIAN);
1744 offset++;
1746 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_vp_vertical_dimension, tvb, offset, 1, ENC_BIG_ENDIAN);
1747 offset++;
1749 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_vp_variable_picture, tvb, offset, length - 3, ENC_NA);
1752 /* 9.2.3.24.10.1.10 */
1753 static void
1754 dis_iei_upi(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1756 EXACT_DATA_CHECK(length, 1);
1758 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_upi_num_corresponding_objects, tvb, offset, 1, ENC_BIG_ENDIAN);
1759 offset++;
1762 /* TS 123.038 V17.0.0 (2022-04), Table 6.2.1.4.1 */
1763 static const value_string lang_single_shift_vals[] = {
1764 { 0x01, "Turkish" },
1765 { 0x02, "Spanish" },
1766 { 0x03, "Portuguese" },
1767 { 0x04, "Bengali" },
1768 { 0x05, "Gujarati" },
1769 { 0x06, "Hindi" },
1770 { 0x07, "Kannada" },
1771 { 0x08, "Malayalam" },
1772 { 0x09, "Oriya" },
1773 { 0x0A, "Punjabi" },
1774 { 0x0B, "Tamil" },
1775 { 0x0C, "Telugu" },
1776 { 0x0D, "Urdu" },
1777 { 0, NULL }
1780 /* 9.2.3.24.15 */
1781 static void
1782 dis_iei_lang_ss(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1784 EXACT_DATA_CHECK(length, 1);
1786 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_lang_single_shift, tvb, offset, 1, ENC_BIG_ENDIAN);
1789 /* TS 123.038 V17.0.0 (2022-04), Table 6.2.1.4.1 */
1790 static const value_string lang_locking_shift_vals[] = {
1791 { 0x01, "Turkish" },
1792 // { 0x02, "Spanish" }, Not defined, fallback to GSM 7 bit alphabet
1793 { 0x03, "Portuguese" },
1794 { 0x04, "Bengali" },
1795 { 0x05, "Gujarati" },
1796 { 0x06, "Hindi" },
1797 { 0x07, "Kannada" },
1798 { 0x08, "Malayalam" },
1799 { 0x09, "Oriya" },
1800 { 0x0A, "Punjabi" },
1801 { 0x0B, "Tamil" },
1802 { 0x0C, "Telugu" },
1803 { 0x0D, "Urdu" },
1804 { 0, NULL }
1807 /* 9.2.3.24.16 */
1808 static void
1809 dis_iei_lang_ls(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields _U_)
1811 EXACT_DATA_CHECK(length, 1);
1813 proto_tree_add_item(tree, hf_gsm_sms_dis_iei_lang_locking_shift, tvb, offset, 1, ENC_BIG_ENDIAN);
1817 * 9.2.3.24 TP-User Data (TP-UD)
1818 * Information Element Identifier octet
1821 /* TS 123 040 V17.2.0 (2022-05) */
1822 static const range_string gsm_sms_tp_ud_ie_id_rvals[] = {
1823 { 0x00, 0x00, "Concatenated short messages, 8-bit reference number (SMS Control)" },
1824 { 0x01, 0x01, "Special SMS Message Indication (SMS Control)" },
1825 { 0x02, 0x02, "Reserved N/A" },
1826 { 0x03, 0x03, "Value not used to avoid misinterpretation as <LF> character N/A" },
1827 { 0x04, 0x04, "Application port addressing scheme, 8 bit address (SMS Control)" },
1828 { 0x05, 0x05, "Application port addressing scheme, 16 bit address (SMS Control)" },
1829 { 0x06, 0x06, "SMSC Control Parameters (SMS Control)" },
1830 { 0x07, 0x07, "UDH Source Indicator (SMS Control)" },
1831 { 0x08, 0x08, "Concatenated short message, 16-bit reference number (SMS Control)" },
1832 { 0x09, 0x09, "Wireless Control Message Protocol (SMS Control)" },
1833 { 0x0A, 0x0A, "Text Formatting (EMS Control)" },
1834 { 0x0B, 0x0B, "Predefined Sound (EMS Content)" },
1835 { 0x0C, 0x0C, "User Defined Sound (iMelody max 128 bytes) (EMS Content)" },
1836 { 0x0D, 0x0D, "Predefined Animation (EMS Content)" },
1837 { 0x0E, 0x0E, "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)" },
1838 { 0x0F, 0x0F, "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)" },
1839 { 0x10, 0x10, "Large Picture (32*32 = 128 bytes) (EMS Content)" },
1840 { 0x11, 0x11, "Small Picture (16*16 = 32 bytes) (EMS Content)" },
1841 { 0x12, 0x12, "Variable Picture (EMS Content)" },
1842 { 0x13, 0x13, "User prompt indicator (EMS Control)" },
1843 { 0x14, 0x14, "Extended Object (EMS Content)" },
1844 { 0x15, 0x15, "Reused Extended Object (EMS Control)" },
1845 { 0x16, 0x16, "Compression Control (EMS Control)" },
1846 { 0x17, 0x17, "Object Distribution Indicator (EMS Control)" },
1847 { 0x18, 0x18, "Standard WVG object (EMS Content)" },
1848 { 0x19, 0x19, "Character Size WVG object (EMS Content)" },
1849 { 0x1A, 0x1A, "Extended Object Data Request Command (EMS Control)" },
1850 { 0x1B, 0x1F, "Reserved for future EMS features (see subclause 3.10) N/A" },
1851 { 0x20, 0x20, "RFC 822 E-Mail Header (SMS Control)" },
1852 { 0x21, 0x21, "Hyperlink format element (SMS Control)" },
1853 { 0x22, 0x22, "Reply Address Element (SMS Control)" },
1854 { 0x23, 0x23, "Enhanced Voice Mail Information (SMS Control)" },
1855 { 0x24, 0x24, "National Language Single Shift (SMS Control)" },
1856 { 0x25, 0x25, "National Language Locking Shift (SMS Control)" },
1857 { 0x26, 0x6F, "Reserved for future use N/A" },
1858 { 0x70, 0x7F, "(U)SIM Toolkit Security Headers (SMS Control)" },
1859 { 0x80, 0x9F, "SME to SME specific use (SMS Control)" },
1860 { 0xA0, 0xBF, "Reserved for future use N/A" },
1861 { 0xC0, 0xDF, "SC specific use (SMS Control)" },
1862 { 0xE0, 0xFF, "Reserved for future use N/A" },
1863 { 0x00, 0x00, NULL },
1866 static void
1867 dis_field_ud_iei(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields)
1869 void (*iei_fcn)(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t offset, uint8_t length, gsm_sms_udh_fields_t *p_udh_fields);
1870 uint8_t oct;
1871 proto_tree *subtree;
1872 uint8_t iei_len;
1875 while (length >= 2)
1877 iei_fcn = NULL;
1879 oct = tvb_get_uint8(tvb, offset);
1881 switch (oct)
1883 case 0x00:
1884 iei_fcn = dis_iei_csm8;
1885 break;
1886 case 0x01:
1887 iei_fcn = dis_iei_spe_sms_msg_ind;
1888 break;
1889 case 0x04:
1890 iei_fcn = dis_iei_apa_8bit;
1891 break;
1892 case 0x05:
1893 iei_fcn = dis_iei_apa_16bit;
1894 break;
1895 case 0x06:
1896 iei_fcn = dis_iei_scp;
1897 break;
1898 case 0x07:
1899 iei_fcn = dis_iei_udh_si;
1900 break;
1901 case 0x08:
1902 iei_fcn = dis_iei_csm16;
1903 break;
1904 case 0x0A:
1905 iei_fcn = dis_iei_tf;
1906 break;
1907 case 0x0B:
1908 iei_fcn = dis_iei_ps;
1909 break;
1910 case 0x0C:
1911 iei_fcn = dis_iei_uds;
1912 break;
1913 case 0x0D:
1914 iei_fcn = dis_iei_pa;
1915 break;
1916 case 0x0E:
1917 iei_fcn = dis_iei_la;
1918 break;
1919 case 0x0F:
1920 iei_fcn = dis_iei_sa;
1921 break;
1922 case 0x10:
1923 iei_fcn = dis_iei_lp;
1924 break;
1925 case 0x11:
1926 iei_fcn = dis_iei_sp;
1927 break;
1928 case 0x12:
1929 iei_fcn = dis_iei_vp;
1930 break;
1931 case 0x13:
1932 iei_fcn = dis_iei_upi;
1933 break;
1934 case 0x24:
1935 iei_fcn = dis_iei_lang_ss;
1936 break;
1937 case 0x25:
1938 iei_fcn = dis_iei_lang_ls;
1939 break;
1942 iei_len = tvb_get_uint8(tvb, offset + 1);
1944 subtree = proto_tree_add_subtree_format(tree,
1945 tvb, offset, iei_len + 2,
1946 ett_udh_ieis[oct], NULL, "IE: %s",
1947 rval_to_str_const(oct, gsm_sms_tp_ud_ie_id_rvals, "Reserved"));
1949 proto_tree_add_item(subtree, hf_gsm_sms_ie_identifier, tvb, offset, 1, ENC_BIG_ENDIAN);
1950 offset++;
1952 proto_tree_add_item(subtree, hf_gsm_sms_dis_field_ud_iei_length, tvb, offset, 1, ENC_BIG_ENDIAN);
1953 offset++;
1955 if (iei_len > 0)
1957 if (iei_fcn == NULL)
1959 proto_tree_add_item(subtree, hf_gsm_sms_ie_data, tvb, offset, iei_len, ENC_NA);
1961 else
1963 iei_fcn(tvb, pinfo, subtree, offset, iei_len, p_udh_fields);
1967 length -= 2 + iei_len;
1968 offset += iei_len;
1972 void
1973 dis_field_udh(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, uint32_t *offset, uint32_t *length,
1974 uint8_t *udl, enum character_set cset, uint8_t *fill_bits, gsm_sms_udh_fields_t *p_udh_fields)
1976 uint8_t oct;
1977 proto_tree *udh_subtree;
1978 static const int* fill_bits_mask_gsm[7] = { &hf_gsm_sms_dis_field_udh_gsm_mask00, &hf_gsm_sms_dis_field_udh_gsm_mask01, &hf_gsm_sms_dis_field_udh_gsm_mask03,
1979 &hf_gsm_sms_dis_field_udh_gsm_mask07, &hf_gsm_sms_dis_field_udh_gsm_mask0f, &hf_gsm_sms_dis_field_udh_gsm_mask1f,
1980 &hf_gsm_sms_dis_field_udh_gsm_mask3f };
1981 static const int* fill_bits_mask_ascii[7] = {&hf_gsm_sms_dis_field_udh_ascii_mask00, &hf_gsm_sms_dis_field_udh_ascii_mask80, &hf_gsm_sms_dis_field_udh_ascii_maskc0,
1982 &hf_gsm_sms_dis_field_udh_ascii_maske0, &hf_gsm_sms_dis_field_udh_ascii_maskf0, &hf_gsm_sms_dis_field_udh_ascii_maskf8,
1983 &hf_gsm_sms_dis_field_udh_ascii_maskfc };
1985 /* step over header */
1987 oct = tvb_get_uint8(tvb, *offset);
1989 udh_subtree =
1990 proto_tree_add_subtree(tree, tvb,
1991 *offset, oct + 1,
1992 ett_udh, NULL, "User-Data Header");
1994 proto_tree_add_item(udh_subtree, hf_gsm_sms_dis_field_udh_user_data_header_length, tvb, *offset, 1, ENC_BIG_ENDIAN);
1996 (*offset)++;
1997 (*length)--;
1999 dis_field_ud_iei(tvb, pinfo, udh_subtree, *offset, oct, p_udh_fields);
2001 *offset += oct;
2002 *length -= oct;
2004 if (cset == GSM_7BITS || cset == ASCII_7BITS)
2006 /* step over fill bits ? */
2008 *fill_bits = 6 - ((oct * 8) % 7);
2009 *udl -= (((oct + 1)*8) + *fill_bits) / 7;
2010 if (*fill_bits)
2013 if (cset == GSM_7BITS)
2015 proto_tree_add_item(udh_subtree, *fill_bits_mask_gsm[*fill_bits], tvb, *offset, 1, ENC_NA);
2017 else
2019 proto_tree_add_item(udh_subtree, *fill_bits_mask_ascii[*fill_bits], tvb, *offset, 1, ENC_NA);
2021 /* Note: Could add an expert item here if ((oct & fill_bits_mask[*fill_bits]) != 0) */
2024 else
2026 *udl -= oct + 1;
2030 /* 9.2.3.24 */
2031 #define SMS_MAX_MESSAGE_SIZE 160
2032 static void
2033 dis_field_ud(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset,
2034 uint32_t length, bool udhi, uint8_t udl, enum character_set cset,
2035 bool compressed, gsm_sms_data_t *data)
2037 proto_tree *subtree;
2038 tvbuff_t *sm_tvb = NULL;
2039 fragment_head *fd_sm = NULL;
2040 uint8_t fill_bits;
2041 uint32_t total_sms_len, i;
2043 bool reassembled = false;
2044 uint32_t reassembled_in = 0;
2045 bool is_fragmented = false;
2046 bool save_fragmented = false, try_gsm_sms_ud_reassemble = false;
2048 sm_fragment_params *p_frag_params;
2049 sm_fragment_params_key *p_frag_params_key, frag_params_key;
2050 const char *addr_info, *addr;
2051 gsm_sms_udh_fields_t udh_fields;
2053 memset(&udh_fields, 0, sizeof(udh_fields));
2054 fill_bits = 0;
2056 addr = (char*)p_get_proto_data(pinfo->pool, pinfo, proto_gsm_sms, 0);
2057 if (addr == NULL)
2058 addr = "";
2059 /* check if lower layers provide additional info */
2060 if (reassemble_sms_with_lower_layers_info) {
2061 wmem_strbuf_t *addr_info_strbuf = wmem_strbuf_new(pinfo->pool, addr);
2062 if (proto_is_frame_protocol(pinfo->layers, "gsm_map")) {
2063 gsm_map_packet_info_t *gsm_map_packet_info;
2064 wmem_strbuf_append(addr_info_strbuf, "MAP");
2065 if ((gsm_map_packet_info = (gsm_map_packet_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_gsm_map, 0)) != NULL) {
2066 if (gsm_map_packet_info->sm_rp_oa_id == GSM_MAP_SM_RP_OA_MSISDN)
2067 wmem_strbuf_append(addr_info_strbuf, gsm_map_packet_info->sm_rp_oa_str);
2068 else if (gsm_map_packet_info->sm_rp_da_id == GSM_MAP_SM_RP_DA_IMSI)
2069 wmem_strbuf_append(addr_info_strbuf, gsm_map_packet_info->sm_rp_da_str);
2070 else if (gsm_map_packet_info->sm_rp_da_id == GSM_MAP_SM_RP_DA_LMSI)
2071 wmem_strbuf_append(addr_info_strbuf, gsm_map_packet_info->sm_rp_da_str);
2072 else /* no identity provided by GSM MAP layer, use TCAP OTID as last resort */
2073 wmem_strbuf_append_printf(addr_info_strbuf, "TCAP%u", gsm_map_packet_info->tcap_src_tid);
2075 } else if (proto_is_frame_protocol(pinfo->layers, "sip")) {
2076 sip_info_value_t *sip_info;
2077 wmem_list_frame_t *frame;
2078 uint8_t curr_layer_num;
2079 wmem_strbuf_append(addr_info_strbuf, "SIP");
2080 curr_layer_num = pinfo->curr_layer_num-1;
2081 frame = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
2082 while (frame && (proto_sip != (int) GPOINTER_TO_UINT(wmem_list_frame_data(frame)))) {
2083 frame = wmem_list_frame_prev(frame);
2084 curr_layer_num--;
2086 if ((sip_info = (sip_info_value_t*)p_get_proto_data(pinfo->pool, pinfo, proto_sip, curr_layer_num)) != NULL) {
2087 if (sip_info->tap_from_addr)
2088 wmem_strbuf_append(addr_info_strbuf, sip_info->tap_from_addr);
2089 if (sip_info->tap_to_addr)
2090 wmem_strbuf_append(addr_info_strbuf, sip_info->tap_to_addr);
2092 } else if (proto_is_frame_protocol(pinfo->layers, "gsm_a.rp")) {
2093 wmem_strbuf_append(addr_info_strbuf, "RP");
2094 } else if (proto_is_frame_protocol(pinfo->layers, "etsi_cat")) {
2095 wmem_strbuf_append(addr_info_strbuf, "CAT");
2096 } else if (proto_is_frame_protocol(pinfo->layers, "mbim")) {
2097 wmem_strbuf_append(addr_info_strbuf, "MBIM");
2099 addr_info = wmem_strbuf_finalize(addr_info_strbuf);
2100 } else {
2101 addr_info = addr;
2104 subtree =
2105 proto_tree_add_subtree(tree, tvb,
2106 offset, length,
2107 ett_ud, NULL, "TP-User-Data");
2109 if (data && data->stk_packing_required)
2111 cset = GSM_7BITS_UNPACKED;
2114 if (udhi)
2116 dis_field_udh(tvb, pinfo, subtree, &offset, &length, &udl, compressed ? OTHER : cset, &fill_bits, &udh_fields);
2119 if (udh_fields.frags > 1)
2120 is_fragmented = true;
2122 if ( is_fragmented && reassemble_sms)
2124 try_gsm_sms_ud_reassemble = true;
2125 save_fragmented = pinfo->fragmented;
2126 pinfo->fragmented = true;
2127 fd_sm = fragment_add_seq_check (&g_sm_reassembly_table, tvb, offset,
2128 pinfo,
2129 udh_fields.sm_id, /* uint32_t ID for fragments belonging together */
2130 addr_info,
2131 udh_fields.frag-1, /* uint32_t fragment sequence number */
2132 length, /* uint32_t fragment length */
2133 (udh_fields.frag != udh_fields.frags)); /* More fragments? */
2134 if (fd_sm)
2136 reassembled = true;
2137 reassembled_in = fd_sm->reassembled_in;
2140 sm_tvb = process_reassembled_data(tvb, offset, pinfo,
2141 "Reassembled Short Message", fd_sm, &sm_frag_items,
2142 NULL, subtree);
2144 if(reassembled && pinfo->num == reassembled_in)
2146 /* Reassembled */
2147 col_append_str (pinfo->cinfo, COL_INFO,
2148 " (Short Message Reassembled)");
2150 else
2152 /* Not last packet of reassembled Short Message */
2153 col_append_fstr (pinfo->cinfo, COL_INFO,
2154 " (Short Message fragment %u of %u)", udh_fields.frag, udh_fields.frags);
2157 if (!PINFO_FD_VISITED(pinfo)) {
2158 /* Store udl and length for later decoding of reassembled SMS */
2159 p_frag_params_key = wmem_new(wmem_file_scope(), sm_fragment_params_key);
2160 p_frag_params_key->addr_info = wmem_strdup(wmem_file_scope(), addr_info);
2161 p_frag_params_key->p2p_dir = pinfo->p2p_dir;
2162 copy_address_wmem(wmem_file_scope(), &p_frag_params_key->src, &pinfo->src);
2163 copy_address_wmem(wmem_file_scope(), &p_frag_params_key->dst, &pinfo->dst);
2164 p_frag_params_key->id = (udh_fields.sm_id<<16)|(udh_fields.frag-1);
2165 p_frag_params = wmem_new0(wmem_file_scope(), sm_fragment_params);
2166 p_frag_params->udl = udl;
2167 p_frag_params->fill_bits = fill_bits;
2168 p_frag_params->length = length;
2169 wmem_multimap_insert32(g_sm_fragment_params_table, p_frag_params_key, pinfo->num, p_frag_params);
2171 } /* Else: not fragmented */
2172 if (! sm_tvb) /* One single Short Message, or not reassembled */
2173 sm_tvb = tvb_new_subset_remaining (tvb, offset);
2175 if (compressed)
2177 proto_tree_add_item(subtree, hf_gsm_sms_compressed_data, tvb, offset, length, ENC_NA);
2179 else
2181 if (cset == GSM_7BITS_UNPACKED)
2184 * STK requires SMS packing by the terminal; this means
2185 * that the string here is *not* packet 7 bits per
2186 * character, but is unpacked, with each character in
2187 * an octet, with the expectation that the recipient
2188 * will pack it before sending it on the network.
2190 * Per 3GPP 31.111 chapter 6.4.10:
2191 * It shall use the SMS default 7-bit coded alphabet
2192 * as defined in TS 23.038 with bit 8 set to 0
2194 * I.e., bit 8 of each octet should be 0.
2196 if(!(reassembled && pinfo->num == reassembled_in))
2198 proto_tree_add_item(subtree, hf_gsm_sms_text, tvb, offset,
2199 length, ENC_3GPP_TS_23_038_7BITS_UNPACKED);
2201 else
2203 total_sms_len = 0;
2204 for(i = 0 ; i < udh_fields.frags; i++)
2206 frag_params_key.addr_info = addr_info;
2207 frag_params_key.p2p_dir = pinfo->p2p_dir;
2208 copy_address_shallow(&frag_params_key.src, &pinfo->src);
2209 copy_address_shallow(&frag_params_key.dst, &pinfo->dst);
2210 frag_params_key.id = (udh_fields.sm_id<<16)|i;
2211 p_frag_params = (sm_fragment_params*)wmem_multimap_lookup32_le(g_sm_fragment_params_table,
2212 &frag_params_key, pinfo->num);
2214 if (p_frag_params) {
2215 proto_tree_add_item(subtree, hf_gsm_sms_text, sm_tvb, total_sms_len,
2216 p_frag_params->length, ENC_3GPP_TS_23_038_7BITS_UNPACKED);
2217 total_sms_len += p_frag_params->length;
2222 else if (cset == GSM_7BITS)
2224 if(!(reassembled && pinfo->num == reassembled_in))
2226 /* Show unassembled SMS */
2227 proto_tree_add_ts_23_038_7bits_packed_item(subtree, hf_gsm_sms_text, tvb, (offset<<3)+fill_bits,
2228 (udl > SMS_MAX_MESSAGE_SIZE ? SMS_MAX_MESSAGE_SIZE : udl));
2230 else
2232 /* Show reassembled SMS. We show each fragment separately
2233 * so that the text doesn't get truncated when we add it to
2234 * the tree.
2236 total_sms_len = 0;
2237 for(i = 0 ; i < udh_fields.frags; i++)
2239 frag_params_key.addr_info = addr_info;
2240 frag_params_key.p2p_dir = pinfo->p2p_dir;
2241 copy_address_shallow(&frag_params_key.src, &pinfo->src);
2242 copy_address_shallow(&frag_params_key.dst, &pinfo->dst);
2243 frag_params_key.id = (udh_fields.sm_id<<16)|i;
2244 p_frag_params = (sm_fragment_params*)wmem_multimap_lookup32_le(g_sm_fragment_params_table,
2245 &frag_params_key, pinfo->num);
2247 if (p_frag_params) {
2248 proto_tree_add_ts_23_038_7bits_packed_item(subtree, hf_gsm_sms_text, sm_tvb,
2249 (total_sms_len<<3)+p_frag_params->fill_bits,
2250 (p_frag_params->udl > SMS_MAX_MESSAGE_SIZE ? SMS_MAX_MESSAGE_SIZE : p_frag_params->udl));
2252 total_sms_len += p_frag_params->length;
2257 else if (cset == OTHER)
2259 if (!is_fragmented || (reassembled && pinfo->num == reassembled_in)) {
2260 if (! dissector_try_uint(gsm_sms_dissector_tbl, udh_fields.port_src, sm_tvb, pinfo, subtree))
2262 if (! dissector_try_uint(gsm_sms_dissector_tbl, udh_fields.port_dst,sm_tvb, pinfo, subtree))
2264 proto_tree_add_item(subtree, hf_gsm_sms_body, sm_tvb, 0, tvb_reported_length(sm_tvb), ENC_NA);
2267 } else {
2268 proto_tree_add_item(subtree, hf_gsm_sms_body, tvb, offset, length, ENC_NA);
2271 else if (cset == UCS2)
2274 unsigned rep_len = tvb_reported_length(sm_tvb);
2276 if (!(reassembled && pinfo->num == reassembled_in))
2278 /* Show unreassembled SMS
2279 * Decode as ENC_UTF_16 instead of UCS2 because Android and iOS smartphones
2280 * encode emoji characters as UTF-16 big endian and although the UTF-16
2281 * is not specified in the 3GPP 23.038 (GSM 03.38) it seems to be widely supported
2283 proto_tree_add_item(subtree, hf_gsm_sms_text, sm_tvb,
2284 0, rep_len, ENC_UTF_16|ENC_BIG_ENDIAN);
2285 } else {
2286 /* Show reassembled SMS. We show each fragment separately
2287 * so that the text doesn't get truncated when we add it to
2288 * the tree.
2290 total_sms_len = 0;
2291 for(i = 0 ; i < udh_fields.frags; i++)
2293 frag_params_key.addr_info = addr_info;
2294 frag_params_key.p2p_dir = pinfo->p2p_dir;
2295 copy_address_shallow(&frag_params_key.src, &pinfo->src);
2296 copy_address_shallow(&frag_params_key.dst, &pinfo->dst);
2297 frag_params_key.id = (udh_fields.sm_id<<16)|i;
2298 p_frag_params = (sm_fragment_params*)wmem_multimap_lookup32_le(g_sm_fragment_params_table,
2299 &frag_params_key, pinfo->num);
2301 if (p_frag_params) {
2302 /* Decode as ENC_UTF_16 instead of UCS2 because Android and iOS smartphones
2303 * encode emoji characters as UTF-16 big endian and although the UTF-16
2304 * is not specified in the 3GPP 23.038 (GSM 03.38) it seems to be widely supported
2306 proto_tree_add_item(subtree, hf_gsm_sms_text, sm_tvb, total_sms_len,
2307 (p_frag_params->udl > SMS_MAX_MESSAGE_SIZE ? SMS_MAX_MESSAGE_SIZE : p_frag_params->udl),
2308 ENC_UTF_16|ENC_BIG_ENDIAN);
2310 total_sms_len += p_frag_params->length;
2318 if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */
2319 pinfo->fragmented = save_fragmented;
2322 /* 9.2.3.27 */
2323 static void
2324 dis_field_pi(tvbuff_t *tvb, proto_tree *tree, uint32_t offset)
2326 static int * const pi_flags[] = {
2327 &hf_gsm_sms_tp_extension,
2328 &hf_gsm_sms_tp_reserved,
2329 &hf_gsm_sms_tp_udl_present,
2330 &hf_gsm_sms_tp_dcs_present,
2331 &hf_gsm_sms_tp_pid_present,
2332 NULL
2335 proto_tree_add_bitmask(tree, tvb, offset, hf_gsm_sms_tp_parameter_indicator, ett_pi, pi_flags, ENC_NA);
2339 * Ref. GSM 03.40
2340 * Section 9.2.2
2342 static void
2343 dis_msg_deliver(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset, gsm_sms_data_t *data)
2345 uint32_t saved_offset;
2346 uint32_t length;
2347 uint8_t oct;
2348 uint8_t udl;
2349 enum character_set cset;
2350 bool compressed;
2351 bool udhi;
2353 saved_offset = offset;
2354 length = tvb_reported_length_remaining(tvb, offset);
2356 oct = tvb_get_uint8(tvb, offset);
2357 udhi = oct & 0x40;
2359 proto_tree_add_item(tree, hf_gsm_sms_tp_rp, tvb, offset, 1, ENC_BIG_ENDIAN);
2360 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
2361 proto_tree_add_item(tree, hf_gsm_sms_tp_sri, tvb, offset, 1, ENC_BIG_ENDIAN);
2362 proto_tree_add_item(tree, hf_gsm_sms_tp_lp, tvb, offset, 1, ENC_BIG_ENDIAN);
2363 proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, ENC_BIG_ENDIAN);
2364 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, ENC_BIG_ENDIAN);
2366 offset++;
2368 dis_field_addr(tvb, pinfo, tree, &offset, "TP-Originating-Address");
2370 oct = tvb_get_uint8(tvb, offset);
2372 dis_field_pid(tvb, tree, offset, oct);
2374 offset++;
2375 oct = tvb_get_uint8(tvb, offset);
2377 dis_field_dcs(tvb, tree, offset, oct, &cset, &compressed);
2379 offset++;
2380 dis_field_scts(tvb, pinfo, tree, &offset);
2382 oct = tvb_get_uint8(tvb, offset);
2383 udl = oct;
2385 DIS_FIELD_UDL(tree, offset);
2387 if (udl > 0)
2389 offset++;
2391 dis_field_ud(tvb, pinfo, tree, offset, length - (offset - saved_offset), udhi, udl,
2392 cset, compressed, data);
2397 * Ref. GSM 03.40
2398 * Section 9.2.2
2400 static void
2401 dis_msg_deliver_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset, gsm_sms_data_t *data)
2403 uint32_t saved_offset;
2404 uint32_t length;
2405 uint8_t oct;
2406 uint8_t pi;
2407 uint8_t udl;
2408 enum character_set cset = OTHER;
2409 bool compressed = false;
2410 bool udhi;
2413 udl = 0;
2414 saved_offset = offset;
2415 length = tvb_reported_length_remaining(tvb, offset);
2417 oct = tvb_get_uint8(tvb, offset);
2418 udhi = oct & 0x40;
2420 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
2421 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, ENC_BIG_ENDIAN);
2423 if (length < 2)
2425 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_short_data,
2426 tvb, offset, length);
2427 return;
2431 * there does not seem to be a way to determine that this
2432 * deliver report is from an RP-ERROR or RP-ACK other
2433 * than to look at the next octet
2435 * FCS values are 0x80 and higher
2436 * PI uses bit 7 as an extension indicator
2438 * will assume that if bit 7 is set then this octet
2439 * is an FCS otherwise PI
2441 offset++;
2442 oct = tvb_get_uint8(tvb, offset);
2444 if (oct & 0x80)
2446 dis_field_fcs(tvb, tree, offset, oct);
2447 offset++;
2450 pi = tvb_get_uint8(tvb, offset);
2452 dis_field_pi(tvb, tree, offset);
2454 if (pi & 0x01)
2456 if (length <= (offset - saved_offset))
2458 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_short_data,
2459 tvb, offset, -1);
2460 return;
2463 offset++;
2464 oct = tvb_get_uint8(tvb, offset);
2466 dis_field_pid(tvb, tree, offset, oct);
2469 if (pi & 0x02)
2471 if (length <= (offset - saved_offset))
2473 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_short_data,
2474 tvb, offset, -1);
2475 return;
2478 offset++;
2479 oct = tvb_get_uint8(tvb, offset);
2481 dis_field_dcs(tvb, tree, offset, oct, &cset, &compressed);
2484 if (pi & 0x04)
2486 if (length <= (offset - saved_offset))
2488 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_short_data,
2489 tvb, offset, -1);
2490 return;
2493 offset++;
2494 oct = tvb_get_uint8(tvb, offset);
2495 udl = oct;
2497 DIS_FIELD_UDL(tree, offset);
2500 if (udl > 0)
2502 offset++;
2504 dis_field_ud(tvb, pinfo, tree, offset, length - (offset - saved_offset), udhi, udl,
2505 cset, compressed, data);
2510 * Ref. GSM 03.40
2511 * Section 9.2.2
2513 static void
2514 dis_msg_submit(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset, gsm_sms_data_t *data)
2516 uint32_t saved_offset;
2517 uint32_t length;
2518 uint8_t oct;
2519 uint8_t vp_form;
2520 uint8_t udl;
2521 enum character_set cset;
2522 bool compressed;
2523 bool udhi;
2526 saved_offset = offset;
2527 length = tvb_reported_length_remaining(tvb, offset);
2529 oct = tvb_get_uint8(tvb, offset);
2530 udhi = oct & 0x40;
2531 vp_form = ((oct & 0x18) >> 3);
2533 proto_tree_add_item(tree, hf_gsm_sms_tp_rp, tvb, offset, 1, ENC_BIG_ENDIAN);
2534 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
2535 proto_tree_add_item(tree, hf_gsm_sms_tp_srr, tvb, offset, 1, ENC_BIG_ENDIAN);
2536 proto_tree_add_item(tree, hf_gsm_sms_tp_vpf, tvb, offset, 1, ENC_BIG_ENDIAN);
2537 proto_tree_add_item(tree, hf_gsm_sms_tp_rd, tvb, offset, 1, ENC_BIG_ENDIAN);
2538 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, ENC_BIG_ENDIAN);
2540 offset++;
2542 proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, ENC_BIG_ENDIAN);
2544 offset++;
2546 dis_field_addr(tvb, pinfo, tree, &offset, "TP-Destination-Address");
2548 oct = tvb_get_uint8(tvb, offset);
2550 dis_field_pid(tvb, tree, offset, oct);
2552 offset++;
2553 oct = tvb_get_uint8(tvb, offset);
2555 dis_field_dcs(tvb, tree, offset, oct, &cset, &compressed);
2557 offset++;
2558 dis_field_vp(tvb, pinfo, tree, &offset, vp_form);
2560 oct = tvb_get_uint8(tvb, offset);
2561 udl = oct;
2563 DIS_FIELD_UDL(tree, offset);
2565 if (udl > 0)
2567 offset++;
2569 dis_field_ud(tvb, pinfo, tree, offset, length - (offset - saved_offset), udhi, udl,
2570 cset, compressed, data);
2575 * Ref. GSM 03.40
2576 * Section 9.2.2
2578 static void
2579 dis_msg_submit_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset, gsm_sms_data_t *data)
2581 uint32_t saved_offset;
2582 uint32_t length;
2583 uint8_t oct;
2584 uint8_t pi;
2585 uint8_t udl;
2586 enum character_set cset = OTHER;
2587 bool compressed = false;
2588 bool udhi;
2591 udl = 0;
2592 saved_offset = offset;
2593 length = tvb_reported_length_remaining(tvb, offset);
2595 oct = tvb_get_uint8(tvb, offset);
2596 udhi = oct & 0x40;
2598 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
2599 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, ENC_BIG_ENDIAN);
2602 * there does not seem to be a way to determine that this
2603 * deliver report is from an RP-ERROR or RP-ACK other
2604 * than to look at the next octet
2606 * FCS values are 0x80 and higher
2607 * PI uses bit 7 as an extension indicator
2609 * will assume that if bit 7 is set then this octet
2610 * is an FCS otherwise PI
2612 offset++;
2613 oct = tvb_get_uint8(tvb, offset);
2615 if (oct & 0x80)
2617 dis_field_fcs(tvb, tree, offset, oct);
2618 offset++;
2621 pi = tvb_get_uint8(tvb, offset);
2622 dis_field_pi(tvb, tree, offset);
2623 offset++;
2625 dis_field_scts(tvb, pinfo, tree, &offset);
2627 if (pi & 0x01) {
2628 if (length <= (offset - saved_offset)) {
2629 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_short_data,
2630 tvb, offset, -1);
2631 return;
2634 oct = tvb_get_uint8(tvb, offset);
2636 dis_field_pid(tvb, tree, offset, oct);
2637 offset++;
2640 if (pi & 0x02)
2642 if (length <= (offset - saved_offset))
2644 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_short_data,
2645 tvb, offset, -1);
2646 return;
2649 oct = tvb_get_uint8(tvb, offset);
2651 dis_field_dcs(tvb, tree, offset, oct, &cset, &compressed);
2652 offset++;
2655 if (pi & 0x04)
2657 if (length <= (offset - saved_offset))
2659 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_short_data,
2660 tvb, offset, -1);
2661 return;
2664 oct = tvb_get_uint8(tvb, offset);
2665 udl = oct;
2667 DIS_FIELD_UDL(tree, offset);
2668 offset++;
2671 if (udl > 0)
2673 dis_field_ud(tvb, pinfo, tree, offset, length - (offset - saved_offset), udhi, udl,
2674 cset, compressed, data);
2679 * Ref. GSM 03.40
2680 * Section 9.2.2
2682 static void
2683 dis_msg_status_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset, gsm_sms_data_t *data)
2685 uint32_t saved_offset;
2686 uint32_t length;
2687 uint8_t oct;
2688 uint8_t pi;
2689 uint8_t udl;
2690 enum character_set cset = OTHER;
2691 bool compressed = false;
2692 bool udhi;
2695 udl = 0;
2696 saved_offset = offset;
2697 length = tvb_reported_length_remaining(tvb, offset);
2699 oct = tvb_get_uint8(tvb, offset);
2700 udhi = oct & 0x40;
2702 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
2703 proto_tree_add_item(tree, hf_gsm_sms_tp_srq, tvb, offset, 1, ENC_BIG_ENDIAN);
2704 proto_tree_add_item(tree, hf_gsm_sms_tp_lp, tvb, offset, 1, ENC_BIG_ENDIAN);
2705 proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, ENC_BIG_ENDIAN);
2706 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, ENC_BIG_ENDIAN);
2708 offset++;
2710 proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, ENC_BIG_ENDIAN);
2712 offset++;
2714 dis_field_addr(tvb, pinfo, tree, &offset, "TP-Recipient-Address");
2716 dis_field_scts(tvb, pinfo, tree, &offset);
2718 dis_field_dt(tvb, pinfo, tree, &offset);
2720 dis_field_st(tvb, tree, offset);
2722 offset++;
2723 /* Parameter indicating the presence of any of
2724 * the optional parameters which follow
2725 * 4) Mandatory if any of the optional parameters following TP-PI is present,
2726 * otherwise optional.
2728 if (length <= (offset - saved_offset))
2730 return;
2733 /* Read Parameter Indicator byte */
2734 pi = tvb_get_uint8(tvb, offset);
2735 dis_field_pi(tvb, tree, offset);
2736 offset++;
2738 /* TODO: (9.2.3.27) If a Reserved bit is set to "1" then the receiving entity shall ignore the setting */
2740 if (pi & 0x01)
2742 if (length <= (offset - saved_offset))
2744 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_short_data,
2745 tvb, offset, -1);
2746 return;
2749 oct = tvb_get_uint8(tvb, offset);
2750 dis_field_pid(tvb, tree, offset, oct);
2751 offset++;
2754 if (pi & 0x02)
2756 if (length <= (offset - saved_offset))
2758 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_short_data,
2759 tvb, offset, -1);
2760 return;
2763 oct = tvb_get_uint8(tvb, offset);
2764 dis_field_dcs(tvb, tree, offset, oct, &cset, &compressed);
2765 offset++;
2768 if (pi & 0x04)
2770 if (length <= (offset - saved_offset))
2772 proto_tree_add_expert(tree, pinfo, &ei_gsm_sms_short_data,
2773 tvb, offset, -1);
2774 return;
2777 oct = tvb_get_uint8(tvb, offset);
2778 udl = oct;
2780 DIS_FIELD_UDL(tree, offset);
2781 offset++;
2784 if (udl > 0)
2786 dis_field_ud(tvb, pinfo, tree, offset, length - (offset - saved_offset), udhi, udl,
2787 cset, compressed, data);
2792 * Ref. GSM 03.40
2793 * Section 9.2.2
2795 static void
2796 dis_msg_command(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, uint32_t offset, gsm_sms_data_t *data _U_)
2798 uint8_t oct;
2799 uint8_t cdl;
2801 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
2802 proto_tree_add_item(tree, hf_gsm_sms_tp_srr, tvb, offset, 1, ENC_BIG_ENDIAN);
2803 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, ENC_BIG_ENDIAN);
2805 offset++;
2807 proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, ENC_BIG_ENDIAN);
2809 offset++;
2810 oct = tvb_get_uint8(tvb, offset);
2812 dis_field_pid(tvb, tree, offset, oct);
2814 offset++;
2816 DIS_FIELD_CT(tree, offset);
2818 offset++;
2820 DIS_FIELD_MN(tree, offset);
2822 offset++;
2824 dis_field_addr(tvb, pinfo, tree, &offset, "TP-Destination-Address");
2826 oct = tvb_get_uint8(tvb, offset);
2827 cdl = oct;
2829 DIS_FIELD_CDL(tree, offset);
2831 if (cdl > 0)
2833 offset++;
2835 proto_tree_add_item(tree, hf_gsm_sms_tp_command_data, tvb, offset, cdl, ENC_NA);
2839 #if 0
2840 #define NUM_MSGS array_length(msg_type_strings)
2841 static int ett_msgs[NUM_MSGS];
2842 #endif
2844 static void (*gsm_sms_msg_fcn[])(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, uint32_t offset, gsm_sms_data_t *data) = {
2845 dis_msg_deliver, /* SMS-DELIVER */
2846 dis_msg_deliver_report, /* SMS-DELIVER REPORT */
2847 dis_msg_submit, /* SMS-SUBMIT */
2848 dis_msg_submit_report, /* SMS-SUBMIT REPORT */
2849 dis_msg_status_report, /* SMS-STATUS REPORT */
2850 dis_msg_command, /* SMS-COMMAND */
2851 NULL, /* Reserved */
2852 NULL, /* Reserved */
2853 NULL, /* NONE */
2856 /* GENERIC DISSECTOR FUNCTIONS */
2858 static int
2859 dissect_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
2861 void (*msg_fcn)(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2862 uint32_t offset, gsm_sms_data_t *gsm_data) = NULL;
2863 uint32_t offset;
2864 uint8_t msg_type;
2865 uint8_t oct;
2866 int idx;
2867 const char *str = NULL;
2868 /*int ett_msg_idx;*/
2869 gsm_sms_data_t *gsm_data = (gsm_sms_data_t*) data;
2871 col_set_str(pinfo->cinfo, COL_PROTOCOL, gsm_sms_proto_name_short);
2873 /* In the interest of speed, if "tree" is NULL, don't do any work not
2874 * necessary to generate protocol tree items.
2876 if (tree || reassemble_sms)
2878 proto_item *gsm_sms_item;
2879 proto_tree *gsm_sms_tree;
2881 g_tree = tree;
2883 offset = 0;
2885 oct = tvb_get_uint8(tvb, offset);
2887 oct &= 0x03;
2888 msg_type = oct;
2891 * convert the 2 bit value to one based on direction
2893 msg_type |= ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x04 : 0x00);
2895 str = try_val_to_str_idx(msg_type, msg_type_strings, &idx);
2898 * create the GSM_SMS protocol tree
2900 gsm_sms_item =
2901 proto_tree_add_protocol_format(tree, proto_gsm_sms, tvb, 0, -1,
2902 "%s %s",
2903 gsm_sms_proto_name,
2904 (str == NULL) ? "Unknown message identifier" : str);
2906 gsm_sms_tree =
2907 proto_item_add_subtree(gsm_sms_item, ett_gsm_sms);
2909 if ((str == NULL) ||
2910 (msg_type == 0x03) ||
2911 (msg_type == 0x07))
2913 return tvb_captured_length(tvb);
2915 else
2917 /*ett_msg_idx = ett_msgs[idx];*/ /* XXX: Not actually used */
2918 msg_fcn = gsm_sms_msg_fcn[idx];
2921 if (msg_fcn == NULL)
2923 proto_tree_add_expert(gsm_sms_tree, pinfo, &ei_gsm_sms_message_dissector_not_implemented,
2924 tvb, offset, -1);
2926 else
2928 (*msg_fcn)(tvb, pinfo, gsm_sms_tree, offset, gsm_data);
2931 return tvb_captured_length(tvb);
2935 /* Register the protocol with Wireshark */
2936 void
2937 proto_register_gsm_sms(void)
2939 unsigned i;
2940 unsigned last_offset;
2941 module_t *gsm_sms_module; /* Preferences for GSM SMS UD */
2942 expert_module_t* expert_gsm_sms;
2944 /* Setup list of header fields */
2945 static hf_register_info hf[] =
2947 { &hf_gsm_sms_coding_group_bits2,
2948 { "Coding Group Bits", "gsm_sms.coding_group_bits2",
2949 FT_UINT8, BASE_DEC | BASE_EXT_STRING, &gsm_sms_coding_group_bits_vals_ext, 0xc0,
2950 NULL, HFILL }
2952 { &hf_gsm_sms_coding_group_bits4,
2953 { "Coding Group Bits", "gsm_sms.coding_group_bits4",
2954 FT_UINT8, BASE_DEC | BASE_EXT_STRING, &gsm_sms_coding_group_bits_vals_ext, 0xf0,
2955 NULL, HFILL }
2959 * Short Message fragment reassembly
2961 { &hf_gsm_sms_ud_fragments,
2962 { "Short Message fragments", "gsm_sms.fragments",
2963 FT_NONE, BASE_NONE, NULL, 0x00,
2964 "GSM Short Message fragments", HFILL }
2966 { &hf_gsm_sms_ud_fragment,
2967 { "Short Message fragment", "gsm_sms.fragment",
2968 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
2969 "GSM Short Message fragment", HFILL }
2971 { &hf_gsm_sms_ud_fragment_overlap,
2972 { "Short Message fragment overlap", "gsm_sms.fragment.overlap",
2973 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2974 "GSM Short Message fragment overlaps with other fragment(s)", HFILL }
2976 { &hf_gsm_sms_ud_fragment_overlap_conflicts,
2977 { "Short Message fragment overlapping with conflicting data", "gsm_sms.fragment.overlap.conflicts",
2978 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2979 "GSM Short Message fragment overlaps with conflicting data", HFILL }
2981 { &hf_gsm_sms_ud_fragment_multiple_tails,
2982 { "Short Message has multiple tail fragments", "gsm_sms.fragment.multiple_tails",
2983 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2984 "GSM Short Message fragment has multiple tail fragments", HFILL }
2986 { &hf_gsm_sms_ud_fragment_too_long_fragment,
2987 { "Short Message fragment too long", "gsm_sms.fragment.too_long_fragment",
2988 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2989 "GSM Short Message fragment data goes beyond the packet end", HFILL }
2991 { &hf_gsm_sms_ud_fragment_error,
2992 { "Short Message defragmentation error", "gsm_sms.fragment.error",
2993 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
2994 "GSM Short Message defragmentation error due to illegal fragments", HFILL }
2996 { &hf_gsm_sms_ud_fragment_count,
2997 { "Short Message fragment count", "gsm_sms.fragment.count",
2998 FT_UINT32, BASE_DEC, NULL, 0x00,
2999 NULL, HFILL }
3001 { &hf_gsm_sms_ud_reassembled_in,
3002 { "Reassembled in", "gsm_sms.reassembled.in",
3003 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3004 "GSM Short Message has been reassembled in this packet.", HFILL }
3006 { &hf_gsm_sms_ud_reassembled_length,
3007 { "Reassembled Short Message length", "gsm_sms.reassembled.length",
3008 FT_UINT32, BASE_DEC, NULL, 0x00,
3009 "The total length of the reassembled payload", HFILL }
3011 { &hf_gsm_sms_ud_multiple_messages_msg_id,
3012 { "Message identifier", "gsm_sms.udh.mm.msg_id",
3013 FT_UINT16, BASE_DEC, NULL, 0x00,
3014 "Identification of the message", HFILL }
3016 { &hf_gsm_sms_ud_multiple_messages_msg_parts,
3017 { "Message parts", "gsm_sms.udh.mm.msg_parts",
3018 FT_UINT8, BASE_DEC, NULL, 0x00,
3019 "Total number of message parts (fragments)", HFILL }
3021 { &hf_gsm_sms_ud_multiple_messages_msg_part,
3022 { "Message part number", "gsm_sms.udh.mm.msg_part",
3023 FT_UINT8, BASE_DEC, NULL, 0x00,
3024 "Message part (fragment) sequence number", HFILL }
3026 /* TPDU parameters */
3027 { &hf_gsm_sms_tp_mti_up,
3028 { "TP-MTI", "gsm_sms.tp-mti",
3029 FT_UINT8, BASE_DEC, VALS(msg_type_strings_ms_to_sc), 0x03,
3030 "TP-Message-Type-Indicator (in the direction MS to SC)", HFILL }
3032 { &hf_gsm_sms_tp_mti_down,
3033 { "TP-MTI", "gsm_sms.tp-mti",
3034 FT_UINT8, BASE_DEC, VALS(msg_type_strings_sc_to_ms), 0x03,
3035 "TP-Message-Type-Indicator (in the direction SC to MS)", HFILL }
3037 { &hf_gsm_sms_tp_oa,
3038 { "TP-OA Digits", "gsm_sms.tp-oa",
3039 FT_STRING, BASE_NONE, NULL, 0x00,
3040 "TP-Originating-Address Digits", HFILL }
3042 { &hf_gsm_sms_tp_da,
3043 { "TP-DA Digits", "gsm_sms.tp-da",
3044 FT_STRING, BASE_NONE, NULL, 0x00,
3045 "TP-Destination-Address Digits", HFILL }
3047 { &hf_gsm_sms_tp_ra,
3048 { "TP-RA Digits", "gsm_sms.tp-ra",
3049 FT_STRING, BASE_NONE, NULL, 0x00,
3050 "TP-Recipient-Address Digits", HFILL }
3052 { &hf_gsm_sms_tp_digits,
3053 { "Digits", "gsm_sms.tp-digits",
3054 FT_STRING, BASE_NONE, NULL, 0x00,
3055 "TP (Unknown) Digits", HFILL }
3057 { &hf_gsm_sms_tp_pid,
3058 { "TP-PID", "gsm_sms.tp-pid",
3059 FT_UINT8, BASE_DEC, NULL, 0x00,
3060 "TP-Protocol-Identifier", HFILL }
3062 { &hf_gsm_sms_tp_dcs,
3063 { "TP-DCS", "gsm_sms.tp-dcs",
3064 FT_UINT8, BASE_DEC, NULL, 0x00,
3065 "TP-Data-Coding-Scheme", HFILL }
3067 { &hf_gsm_sms_tp_mr,
3068 { "TP-MR", "gsm_sms.tp-mr",
3069 FT_UINT8, BASE_DEC, NULL, 0x00,
3070 "TP-Message-Reference", HFILL }
3072 { &hf_gsm_sms_tp_mms,
3073 { "TP-MMS", "gsm_sms.tp-mms",
3074 FT_BOOLEAN, 8, TFS(&mms_bool_strings), 0x04,
3075 "TP-More-Messages-to-Send", HFILL }
3077 { &hf_gsm_sms_tp_lp,
3078 { "TP-LP", "gsm_sms.tp-lp",
3079 FT_BOOLEAN, 8, TFS(&lp_bool_strings), 0x08,
3080 "TP-Loop-Prevention", HFILL }
3082 { &hf_gsm_sms_tp_sri,
3083 { "TP-SRI", "gsm_sms.tp-sri",
3084 FT_BOOLEAN, 8, TFS(&sri_bool_strings), 0x20,
3085 "TP-Status-Report-Indication", HFILL }
3087 { &hf_gsm_sms_tp_srr,
3088 { "TP-SRR", "gsm_sms.tp-srr",
3089 FT_BOOLEAN, 8, TFS(&srr_bool_strings), 0x20,
3090 "TP-Status-Report-Request", HFILL }
3092 { &hf_gsm_sms_tp_udhi,
3093 { "TP-UDHI", "gsm_sms.tp-udhi",
3094 FT_BOOLEAN, 8, TFS(&udhi_bool_strings), 0x40,
3095 "TP-User-Data-Header-Indicator", HFILL }
3097 { &hf_gsm_sms_tp_rp,
3098 { "TP-RP", "gsm_sms.tp-rp",
3099 FT_BOOLEAN, 8, TFS(&rp_bool_strings), 0x80,
3100 "TP-Reply-Path", HFILL }
3102 { &hf_gsm_sms_tp_vpf,
3103 { "TP-VPF", "gsm_sms.tp-vpf",
3104 FT_UINT8, BASE_DEC, VALS(vp_type_strings), 0x18,
3105 "TP-Validity-Period-Format", HFILL }
3107 { &hf_gsm_sms_tp_rd,
3108 { "TP-RD", "gsm_sms.tp-rd",
3109 FT_BOOLEAN, 8, TFS(&rd_bool_strings), 0x04,
3110 "TP-Reject-Duplicates", HFILL }
3112 { &hf_gsm_sms_tp_srq,
3113 { "TP-SRQ", "gsm_sms.tp-srq",
3114 FT_BOOLEAN, 8, TFS(&srq_bool_strings), 0x20,
3115 "TP-Status-Report-Qualifier", HFILL }
3117 { &hf_gsm_sms_text,
3118 { "SMS text", "gsm_sms.sms_text",
3119 FT_STRING, BASE_NONE, NULL, 0x00,
3120 "The text of the SMS", HFILL }
3122 { &hf_gsm_sms_body,
3123 { "SMS body", "gsm_sms.sms_body",
3124 FT_BYTES, BASE_NONE, NULL, 0x00,
3125 NULL, HFILL }
3127 { &hf_gsm_sms_tp_fail_cause,
3128 { "TP-Failure-Cause (TP-FCS)", "gsm_sms.tp-fcs",
3129 FT_UINT8, BASE_HEX_DEC|BASE_RANGE_STRING, RVALS(gsm_sms_tp_failure_cause_values), 0x0,
3130 "TP-Validity-Period-Format", HFILL }
3132 { &hf_gsm_sms_dis_field_addr_extension,
3133 { "Extension", "gsm_sms.dis_field_addr.extension",
3134 FT_BOOLEAN, 8, TFS(&tfs_no_extension_extended), 0x80,
3135 NULL, HFILL }
3137 { &hf_gsm_sms_dis_field_addr_num_type,
3138 { "Type of number", "gsm_sms.dis_field_addr.num_type",
3139 FT_UINT8, BASE_DEC, VALS(dis_field_addr_num_types_vals), 0x70,
3140 NULL, HFILL }
3142 { &hf_gsm_sms_dis_field_addr_num_plan,
3143 { "Numbering plan", "gsm_sms.dis_field_addr.num_plan",
3144 FT_UINT8, BASE_DEC, VALS(dis_field_addr_numbering_plan_vals), 0x0F,
3145 NULL, HFILL }
3147 { &hf_gsm_sms_tp_parameter_indicator,
3148 { "TP-Parameter-Indicator", "gsm_sms.tp.parameter_indicator",
3149 FT_UINT8, BASE_HEX, NULL, 0x0,
3150 NULL, HFILL }
3152 { &hf_gsm_sms_tp_extension,
3153 { "Extension", "gsm_sms.tp.extension",
3154 FT_BOOLEAN, 8, TFS(&tfs_extended_no_extension), 0x80,
3155 NULL, HFILL }
3157 { &hf_gsm_sms_tp_reserved,
3158 { "Reserved", "gsm_sms.tp.reserved",
3159 FT_UINT8, BASE_DEC, NULL, 0x78,
3160 NULL, HFILL }
3162 { &hf_gsm_sms_tp_udl_present,
3163 { "TP-UDL", "gsm_sms.tp.udl.present",
3164 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x04,
3165 NULL, HFILL }
3167 { &hf_gsm_sms_tp_dcs_present,
3168 { "TP-DCS", "gsm_sms.tp.dcs.present",
3169 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x02,
3170 NULL, HFILL }
3172 { &hf_gsm_sms_tp_pid_present,
3173 { "TP-PID", "gsm_sms.tp.pid.present",
3174 FT_BOOLEAN, 8, TFS(&tfs_present_not_present), 0x01,
3175 NULL, HFILL }
3177 { &hf_gsm_sms_tp_pid_format_subsequent_bits,
3178 { "Defines formatting for subsequent bits", "gsm_sms.tp.pid.format_subsequent_bits",
3179 FT_UINT8, BASE_HEX, NULL, 0xC0,
3180 NULL, HFILL }
3182 { &hf_gsm_sms_tp_pid_telematic_interworking,
3183 { "Telematic interworking", "gsm_sms.tp.pid.telematic_interworking",
3184 FT_BOOLEAN, 8, TFS(&tfs_telematic_interworking), 0x20,
3185 NULL, HFILL }
3187 { &hf_gsm_sms_tp_pid_device_type,
3188 { "Device type", "gsm_sms.tp.pid.device_type",
3189 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(tp_pid_device_type_rvals), 0x1F,
3190 NULL, HFILL }
3192 { &hf_gsm_sms_tp_pid_sm_al_proto,
3193 { "The SM-AL protocol being used between the SME and the MS", "gsm_sms.tp.pid.sm_al_proto",
3194 FT_UINT8, BASE_DEC, NULL, 0x1F,
3195 NULL, HFILL }
3197 { &hf_gsm_sms_tp_pid_message_type,
3198 { "Message type", "gsm_sms.tp.pid.message_type",
3199 FT_UINT8, BASE_DEC, VALS(pid_message_type_vals), 0x3F,
3200 NULL, HFILL }
3202 { &hf_gsm_sms_tp_pid_reserved,
3203 { "Reserved", "gsm_sms.tp.pid.reserved",
3204 FT_UINT8, BASE_HEX, NULL, 0xC0,
3205 NULL, HFILL }
3207 { &hf_gsm_sms_tp_pid_undefined,
3208 { "Undefined", "gsm_sms.tp.pid.undefined",
3209 FT_UINT8, BASE_HEX, NULL, 0x3F,
3210 NULL, HFILL }
3212 { &hf_gsm_sms_tp_pid_sc_specific_use,
3213 { "Bits 0-5 for SC specific use", "gsm_sms.tp.pid.sc_specific_use",
3214 FT_UINT8, BASE_HEX, NULL, 0xC0,
3215 NULL, HFILL }
3217 { &hf_gsm_sms_tp_pid_sc_specific,
3218 { "SC specific", "gsm_sms.tp.pid.sc_specific",
3219 FT_UINT8, BASE_HEX, NULL, 0x3F,
3220 NULL, HFILL }
3222 { &hf_gsm_sms_dcs_text_compressed,
3223 { "Text", "gsm_sms.dcs.text_compressed",
3224 FT_BOOLEAN, 8, TFS(&tfs_compressed_not_compressed), 0x20,
3225 NULL, HFILL }
3227 { &hf_gsm_sms_dcs_message_class_defined,
3228 { "Message Class", "gsm_sms.dcs.message_class_defined",
3229 FT_BOOLEAN, 8, TFS(&tfs_message_class_defined), 0x10,
3230 NULL, HFILL }
3232 { &hf_gsm_sms_dcs_character_set,
3233 { "Character Set", "gsm_sms.dcs.character_set",
3234 FT_UINT8, BASE_HEX, VALS(dcs_character_set_vals), 0x0C,
3235 NULL, HFILL }
3237 { &hf_gsm_sms_dcs_message_class,
3238 { "Message Class", "gsm_sms.dcs.message_class",
3239 FT_UINT8, BASE_HEX, VALS(dcs_message_class_vals), 0x03,
3240 NULL, HFILL }
3242 { &hf_gsm_sms_dcs_indication_sense,
3243 { "Indication Sense", "gsm_sms.dcs.indication_sense",
3244 FT_BOOLEAN, 8, TFS(&tfs_indication_sense), 0x08,
3245 NULL, HFILL }
3247 { &hf_gsm_sms_dcs_reserved04,
3248 { "Reserved", "gsm_sms.dcs.reserved",
3249 FT_UINT8, BASE_DEC, NULL, 0x04,
3250 NULL, HFILL }
3252 { &hf_gsm_sms_dcs_reserved08,
3253 { "Reserved", "gsm_sms.dcs.reserved",
3254 FT_UINT8, BASE_DEC, NULL, 0x08,
3255 NULL, HFILL }
3257 { &hf_gsm_sms_dcs_message_waiting,
3258 { "Message Waiting", "gsm_sms.dcs.message_waiting",
3259 FT_UINT8, BASE_HEX, VALS(dcs_message_waiting_vals), 0x03,
3260 NULL, HFILL }
3262 { &hf_gsm_sms_dcs_message_coding,
3263 { "Message coding", "gsm_sms.dcs.message_coding",
3264 FT_BOOLEAN, 8, TFS(&tfs_message_coding), 0x04,
3265 NULL, HFILL }
3267 { &hf_gsm_sms_vp_extension,
3268 { "Extension", "gsm_sms.vp.extension",
3269 FT_BOOLEAN, 8, TFS(&tfs_extended_no_extension), 0x80,
3270 NULL, HFILL }
3272 { &hf_gsm_sms_vp_extension_ignored,
3273 { "Extension not implemented, ignored", "gsm_sms.vp.extension_ignored",
3274 FT_NONE, BASE_NONE, NULL, 0x0,
3275 NULL, HFILL }
3277 { &hf_gsm_sms_vp_single_shot_sm,
3278 { "Single shot SM", "gsm_sms.vp.single_shot_sm",
3279 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x40,
3280 NULL, HFILL }
3282 { &hf_gsm_sms_vp_reserved,
3283 { "Reserved", "gsm_sms.vp.reserved",
3284 FT_UINT8, BASE_HEX, NULL, 0x38,
3285 NULL, HFILL }
3287 { &hf_gsm_sms_vp_validity_period_format,
3288 { "Validity Period Format", "gsm_sms.vp.validity_period_format",
3289 FT_UINT8, BASE_DEC, VALS(vp_validity_period_format_vals), 0x07,
3290 NULL, HFILL }
3292 { &hf_gsm_sms_vp_validity_period,
3293 { "TP-Validity-Period", "gsm_sms.vp.validity_period",
3294 FT_UINT8, BASE_DEC, NULL, 0x0,
3295 NULL, HFILL }
3297 { &hf_gsm_sms_dis_field_definition,
3298 { "Definition of bits 0-6", "gsm_sms.dis_field.definition",
3299 FT_BOOLEAN, 8, TFS(&tfs_dis_field_definition), 0x80,
3300 NULL, HFILL }
3302 { &hf_gsm_sms_dis_field_st_error,
3303 { "Error", "gsm_sms.dis_field.st_error",
3304 FT_UINT8, BASE_DEC, VALS(dis_field_st_error_vals), 0x60,
3305 NULL, HFILL }
3307 { &hf_gsm_sms_dis_field_st_reason[0],
3308 { "Reason", "gsm_sms.dis.field_st_reason",
3309 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(dis_field_st_error00_reason_rvals), 0x1F,
3310 NULL, HFILL }
3312 { &hf_gsm_sms_dis_field_st_reason[1],
3313 { "Reason", "gsm_sms.dis.field_st_reason",
3314 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(dis_field_st_error01_reason_rvals), 0x1F,
3315 NULL, HFILL }
3317 { &hf_gsm_sms_dis_field_st_reason[2],
3318 { "Reason", "gsm_sms.dis.field_st_reason",
3319 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(dis_field_st_error10_reason_rvals), 0x1F,
3320 NULL, HFILL }
3322 { &hf_gsm_sms_dis_field_st_reason[3],
3323 { "Reason", "gsm_sms.dis.field_st_reason",
3324 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(dis_field_st_error11_reason_rvals), 0x1F,
3325 NULL, HFILL }
3327 { &hf_gsm_sms_tp_user_data_length,
3328 { "TP-User-Data-Length", "gsm_sms.tp.user_data_length",
3329 FT_UINT8, BASE_DEC, NULL, 0x0,
3330 NULL, HFILL }
3332 { &hf_gsm_sms_tp_message_number,
3333 { "TP-Message-Number", "gsm_sms.tp.message_number",
3334 FT_UINT8, BASE_DEC, NULL, 0x0,
3335 NULL, HFILL }
3337 { &hf_gsm_sms_tp_command_type,
3338 { "TP-Command-Type", "gsm_sms.tp.command_type",
3339 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(tp_command_type_rvals), 0x0,
3340 NULL, HFILL }
3342 { &hf_gsm_sms_tp_command_data,
3343 { "TP-Command-Data", "gsm_sms.tp.command_data",
3344 FT_NONE, BASE_NONE, NULL, 0x0,
3345 NULL, HFILL }
3347 { &hf_gsm_sms_tp_command_data_length,
3348 { "TP-Command-Data-Length", "gsm_sms.tp.command_data_length",
3349 FT_UINT8, BASE_DEC, NULL, 0x0,
3350 NULL, HFILL }
3352 { &hf_gsm_sms_msg_ind_type_and_stor,
3353 { "Message Indication type and Storage", "gsm_sms.msg_ind_type_and_stor",
3354 FT_BOOLEAN, 8, TFS(&gsm_sms_msg_type_and_stor_value), 0x80,
3355 NULL, HFILL }
3357 { &hf_gsm_sms_msg_profile_id,
3358 { "Multiple Subscriber Profile", "gsm_sms.profile_id",
3359 FT_UINT8, BASE_DEC, VALS(gsm_sms_profile_id_vals), 0x60,
3360 NULL, HFILL }
3362 { &hf_gsm_sms_ext_msg_ind_type,
3363 { "Extended Message Indication Type", "gsm_sms.ext_msg_ind_type",
3364 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(gsm_sms_ext_msg_ind_type_vals), 0x1c,
3365 NULL, HFILL }
3367 { &hf_gsm_sms_msg_ind_type,
3368 { "Message Indication Type", "gsm_sms.msg_ind_type",
3369 FT_UINT8, BASE_DEC, VALS(gsm_sms_msg_ind_type_vals), 0x03,
3370 NULL, HFILL }
3372 { &hf_gsm_sms_msg_count,
3373 { "Message Count", "gsm_sms.msg_count",
3374 FT_UINT8, BASE_DEC, NULL, 0x0,
3375 NULL, HFILL }
3377 { &hf_gsm_sms_destination_port8,
3378 { "Destination port", "gsm_sms.destination_port",
3379 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(gsm_sms_8bit_port_values), 0x0,
3380 NULL, HFILL }
3382 { &hf_gsm_sms_originator_port8,
3383 { "Originator port", "gsm_sms.originator_port",
3384 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(gsm_sms_8bit_port_values), 0x0,
3385 NULL, HFILL }
3387 { &hf_gsm_sms_destination_port16,
3388 { "Destination port", "gsm_sms.destination_port",
3389 FT_UINT16, BASE_DEC|BASE_RANGE_STRING, RVALS(gsm_sms_16bit_port_values), 0x0,
3390 NULL, HFILL }
3392 { &hf_gsm_sms_originator_port16,
3393 { "Originator port", "gsm_sms.originator_port",
3394 FT_UINT16, BASE_DEC|BASE_RANGE_STRING, RVALS(gsm_sms_16bit_port_values), 0x0,
3395 NULL, HFILL }
3397 { &hf_gsm_sms_status_report,
3398 { "Status Report", "gsm_sms.status_report",
3399 FT_UINT8, BASE_HEX, NULL, 0x0,
3400 NULL, HFILL }
3402 { &hf_gsm_sms_status_report_short_msg,
3403 { "Status Report for short message transaction completed", "gsm_sms.status_report.short_msg",
3404 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x01,
3405 NULL, HFILL }
3407 { &hf_gsm_sms_status_report_permanent_error,
3408 { "Status Report for permanent error when SC is not making any more transfer attempts", "gsm_sms.status_report.permanent_error",
3409 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x02,
3410 NULL, HFILL }
3412 { &hf_gsm_sms_status_report_temp_error_no_attempt,
3413 { "Status Report for temporary error when SC is not making any more transfer attempts", "gsm_sms.status_report.temp_error_no_attempt",
3414 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
3415 NULL, HFILL }
3417 { &hf_gsm_sms_status_report_temp_error_transfer,
3418 { "Status Report for temporary error when SC is still trying to transfer SM", "gsm_sms.status_report.temp_error_transfer",
3419 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
3420 NULL, HFILL }
3422 { &hf_gsm_sms_status_report_active,
3423 { "Single shot SM", "gsm_sms.status_report.active",
3424 FT_BOOLEAN, 8, TFS(&tfs_status_report_active), 0x40,
3425 NULL, HFILL }
3427 { &hf_gsm_sms_status_report_original_udh,
3428 { "Include original UDH into the Status Report", "gsm_sms.status_report.original_udh",
3429 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x80,
3430 NULL, HFILL }
3432 { &hf_gsm_sms_udh_created,
3433 { "The following part of the UDH is created by", "gsm_sms.udh_created",
3434 FT_UINT8, BASE_DEC, VALS(udh_created_vals), 0x0,
3435 NULL, HFILL }
3437 { &hf_gsm_sms_formatting_mode,
3438 { "Formatting mode", "gsm_sms.formatting_mode",
3439 FT_UINT8, BASE_HEX, NULL, 0x0,
3440 NULL, HFILL }
3442 { &hf_gsm_sms_formatting_mode_alignment,
3443 { "Alignment", "gsm_sms.formatting_mode.alignment",
3444 FT_UINT8, BASE_DEC, VALS(alignment_values), 0x03,
3445 NULL, HFILL }
3447 { &hf_gsm_sms_formatting_mode_font_size,
3448 { "Font Size", "gsm_sms.formatting_mode.font_size",
3449 FT_UINT8, BASE_DEC, VALS(font_size_values), 0x0C,
3450 NULL, HFILL }
3452 { &hf_gsm_sms_formatting_mode_style_bold,
3453 { "Style bold", "gsm_sms.formatting_mode.style_bold",
3454 FT_BOOLEAN, 8, TFS(&tfs_on_off), 0x10,
3455 NULL, HFILL }
3457 { &hf_gsm_sms_formatting_mode_style_italic,
3458 { "Style Italic", "gsm_sms.formatting_mode.style_italic",
3459 FT_BOOLEAN, 8, TFS(&tfs_on_off), 0x20,
3460 NULL, HFILL }
3462 { &hf_gsm_sms_formatting_mode_style_underlined,
3463 { "Style Underlined", "gsm_sms.formatting_mode.style_underlined",
3464 FT_BOOLEAN, 8, TFS(&tfs_on_off), 0x40,
3465 NULL, HFILL }
3467 { &hf_gsm_sms_formatting_mode_style_strikethrough,
3468 { "Style Strikethrough", "gsm_sms.formatting_mode.style_strikethrough",
3469 FT_BOOLEAN, 8, TFS(&tfs_on_off), 0x80,
3470 NULL, HFILL }
3472 { &hf_gsm_sms_ie_identifier,
3473 { "Information Element Identifier", "gsm_sms.ie_identifier",
3474 FT_UINT8, BASE_HEX, NULL, 0x0,
3475 NULL, HFILL }
3477 { &hf_gsm_sms_scts_year,
3478 { "Year", "gsm_sms.scts.year",
3479 FT_UINT8, BASE_DEC, NULL, 0x0,
3480 NULL, HFILL }
3482 { &hf_gsm_sms_scts_month,
3483 { "Month", "gsm_sms.scts.month",
3484 FT_UINT8, BASE_DEC, NULL, 0x0,
3485 NULL, HFILL }
3487 { &hf_gsm_sms_scts_day,
3488 { "Day", "gsm_sms.scts.day",
3489 FT_UINT8, BASE_DEC, NULL, 0x0,
3490 NULL, HFILL }
3492 { &hf_gsm_sms_scts_hour,
3493 { "Hour", "gsm_sms.scts.hour",
3494 FT_UINT8, BASE_DEC, NULL, 0x0,
3495 NULL, HFILL }
3497 { &hf_gsm_sms_scts_minutes,
3498 { "Minutes", "gsm_sms.scts.minutes",
3499 FT_UINT8, BASE_DEC, NULL, 0x0,
3500 NULL, HFILL }
3502 { &hf_gsm_sms_scts_seconds,
3503 { "Seconds", "gsm_sms.scts.seconds",
3504 FT_UINT8, BASE_DEC, NULL, 0x0,
3505 NULL, HFILL }
3507 { &hf_gsm_sms_scts_timezone,
3508 { "Timezone", "gsm_sms.scts.timezone",
3509 FT_UINT8, BASE_DEC, NULL, 0x0,
3510 NULL, HFILL }
3512 { &hf_gsm_sms_vp_validity_period_hour,
3513 { "Hour", "gsm_sms.vp.validity_period.hour",
3514 FT_UINT8, BASE_DEC, NULL, 0x0,
3515 NULL, HFILL }
3517 { &hf_gsm_sms_vp_validity_period_minutes,
3518 { "Minutes", "gsm_sms.vp.validity_period.minutes",
3519 FT_UINT8, BASE_DEC, NULL, 0x0,
3520 NULL, HFILL }
3522 { &hf_gsm_sms_vp_validity_period_seconds,
3523 { "Seconds", "gsm_sms.vp.validity_period.seconds",
3524 FT_UINT8, BASE_DEC, NULL, 0x0,
3525 NULL, HFILL }
3528 /* Generated from convert_proto_tree_add_text.pl */
3529 { &hf_gsm_sms_dis_field_addr_length, { "Length", "gsm_sms.dis_field_addr.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3530 { &hf_gsm_sms_gsm_7_bit_default_alphabet, { "Special case, GSM 7 bit default alphabet", "gsm_sms.gsm_7_bit_default_alphabet", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3531 { &hf_gsm_sms_dis_iei_tf_start_position, { "Start position of the text formatting", "gsm_sms.dis_iei_tf.start_position", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3532 { &hf_gsm_sms_dis_iei_tf_length, { "Text formatting length", "gsm_sms.dis_iei_tf.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3533 { &hf_gsm_sms_dis_iei_tf_foreground_colour, { "Foreground Colour", "gsm_sms.dis_iei_tf.foreground_colour", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &text_color_values_ext, 0x0F, NULL, HFILL }},
3534 { &hf_gsm_sms_dis_iei_tf_background_colour, { "Background Colour", "gsm_sms.dis_iei_tf.background_colour", FT_UINT8, BASE_HEX|BASE_EXT_STRING, &text_color_values_ext, 0xF0, NULL, HFILL }},
3535 { &hf_gsm_sms_dis_iei_ps_position, { "Position", "gsm_sms.dis_iei_ps.position", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3536 { &hf_gsm_sms_dis_iei_ps_sound_number, { "Sound number", "gsm_sms.dis_iei_ps.sound_number", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3537 { &hf_gsm_sms_dis_iei_uds_position, { "Position", "gsm_sms.dis_iei_uds.position", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3538 { &hf_gsm_sms_dis_iei_uds_user_defined_sound, { "User Defined Sound", "gsm_sms.dis_iei_uds.user_defined_sound", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3539 { &hf_gsm_sms_dis_iei_pa_position, { "Position", "gsm_sms.dis_iei_pa.position", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3540 { &hf_gsm_sms_dis_iei_pa_animation_number, { "Animation number", "gsm_sms.dis_iei_pa.animation_number", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3541 { &hf_gsm_sms_dis_iei_la_position, { "Position", "gsm_sms.dis_iei_la.position", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3542 { &hf_gsm_sms_dis_iei_la_large_animation, { "Large Animation", "gsm_sms.dis_iei_la.large_animation", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3543 { &hf_gsm_sms_dis_iei_sa_position, { "Position", "gsm_sms.dis_iei_sa.position", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3544 { &hf_gsm_sms_dis_iei_sa_small_animation, { "Small Animation", "gsm_sms.dis_iei_sa.small_animation", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3545 { &hf_gsm_sms_dis_iei_lp_position, { "Position", "gsm_sms.dis_iei_lp.position", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3546 { &hf_gsm_sms_dis_iei_lp_large_picture, { "Large Picture", "gsm_sms.dis_iei_lp.large_picture", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3547 { &hf_gsm_sms_dis_iei_sp_position, { "Position", "gsm_sms.dis_iei_sp.position", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3548 { &hf_gsm_sms_dis_iei_sp_small_picture, { "Small Picture", "gsm_sms.dis_iei_sp.small_picture", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3549 { &hf_gsm_sms_dis_iei_vp_position, { "position", "gsm_sms.dis_iei_vp.position", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3550 { &hf_gsm_sms_dis_iei_vp_horizontal_dimension, { "Horizontal dimension", "gsm_sms.dis_iei_vp.horizontal_dimension", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3551 { &hf_gsm_sms_dis_iei_vp_vertical_dimension, { "Vertical dimension", "gsm_sms.dis_iei_vp.vertical_dimension", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3552 { &hf_gsm_sms_dis_iei_vp_variable_picture, { "Variable Picture", "gsm_sms.dis_iei_vp.variable_picture", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3553 { &hf_gsm_sms_dis_iei_upi_num_corresponding_objects, { "Number of corresponding objects", "gsm_sms.dis_iei_upi.num_corresponding_objects", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3554 { &hf_gsm_sms_dis_iei_lang_single_shift, { "Language (Single Shift)", "gsm_sms.dis_iei_lang.single_shift", FT_UINT8, BASE_DEC, VALS(lang_single_shift_vals), 0x0, NULL, HFILL }},
3555 { &hf_gsm_sms_dis_iei_lang_locking_shift, { "Language (Locking Shift)", "gsm_sms.dis_iei_lang.locking_shift", FT_UINT8, BASE_DEC, VALS(lang_locking_shift_vals), 0x0, NULL, HFILL }},
3556 { &hf_gsm_sms_dis_field_ud_iei_length, { "Length", "gsm_sms.dis_field_ud_iei.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3557 { &hf_gsm_sms_ie_data, { "IE Data", "gsm_sms.ie_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3558 { &hf_gsm_sms_dis_field_udh_user_data_header_length, { "User Data Header Length", "gsm_sms.dis_field_udh.user_data_header_length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3559 { &hf_gsm_sms_compressed_data, { "Compressed data", "gsm_sms.compressed_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3560 { &hf_gsm_sms_dis_field_udh_gsm_mask00, { "Fill bits", "gsm_sms.dis_field_udh.gsm.fill_bits", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
3561 { &hf_gsm_sms_dis_field_udh_gsm_mask01, { "Fill bits", "gsm_sms.dis_field_udh.gsm.fill_bits", FT_UINT8, BASE_HEX, NULL, 0x01, NULL, HFILL }},
3562 { &hf_gsm_sms_dis_field_udh_gsm_mask03, { "Fill bits", "gsm_sms.dis_field_udh.gsm.fill_bits", FT_UINT8, BASE_HEX, NULL, 0x03, NULL, HFILL }},
3563 { &hf_gsm_sms_dis_field_udh_gsm_mask07, { "Fill bits", "gsm_sms.dis_field_udh.gsm.fill_bits", FT_UINT8, BASE_HEX, NULL, 0x07, NULL, HFILL }},
3564 { &hf_gsm_sms_dis_field_udh_gsm_mask0f, { "Fill bits", "gsm_sms.dis_field_udh.gsm.fill_bits", FT_UINT8, BASE_HEX, NULL, 0x0F, NULL, HFILL }},
3565 { &hf_gsm_sms_dis_field_udh_gsm_mask1f, { "Fill bits", "gsm_sms.dis_field_udh.gsm.fill_bits", FT_UINT8, BASE_HEX, NULL, 0x1F, NULL, HFILL }},
3566 { &hf_gsm_sms_dis_field_udh_gsm_mask3f, { "Fill bits", "gsm_sms.dis_field_udh.gsm.fill_bits", FT_UINT8, BASE_HEX, NULL, 0x3F, NULL, HFILL }},
3567 { &hf_gsm_sms_dis_field_udh_ascii_mask00, { "Fill bits", "gsm_sms.dis_field_udh.ascii.fill_bits", FT_UINT8, BASE_HEX, NULL, 0x00, NULL, HFILL }},
3568 { &hf_gsm_sms_dis_field_udh_ascii_mask80, { "Fill bits", "gsm_sms.dis_field_udh.ascii.fill_bits", FT_UINT8, BASE_HEX, NULL, 0x80, NULL, HFILL }},
3569 { &hf_gsm_sms_dis_field_udh_ascii_maskc0, { "Fill bits", "gsm_sms.dis_field_udh.ascii.fill_bits", FT_UINT8, BASE_HEX, NULL, 0xC0, NULL, HFILL }},
3570 { &hf_gsm_sms_dis_field_udh_ascii_maske0, { "Fill bits", "gsm_sms.dis_field_udh.ascii.fill_bits", FT_UINT8, BASE_HEX, NULL, 0xE0, NULL, HFILL }},
3571 { &hf_gsm_sms_dis_field_udh_ascii_maskf0, { "Fill bits", "gsm_sms.dis_field_udh.ascii.fill_bits", FT_UINT8, BASE_HEX, NULL, 0xF0, NULL, HFILL }},
3572 { &hf_gsm_sms_dis_field_udh_ascii_maskf8, { "Fill bits", "gsm_sms.dis_field_udh.ascii.fill_bits", FT_UINT8, BASE_HEX, NULL, 0xF8, NULL, HFILL }},
3573 { &hf_gsm_sms_dis_field_udh_ascii_maskfc, { "Fill bits", "gsm_sms.dis_field_udh.ascii.fill_bits", FT_UINT8, BASE_HEX, NULL, 0xFC, NULL, HFILL }},
3576 static ei_register_info ei[] = {
3577 { &ei_gsm_sms_short_data, { "gsm_sms.short_data", PI_MALFORMED, PI_ERROR, "Short Data (?)", EXPFILL }},
3578 { &ei_gsm_sms_unexpected_data_length, { "gsm_sms.unexpected_data_length", PI_MALFORMED, PI_ERROR, "Unexpected Data Length", EXPFILL }},
3579 { &ei_gsm_sms_message_dissector_not_implemented, { "gsm_sms.message_dissector_not_implemented", PI_UNDECODED, PI_WARN, "Message dissector not implemented", EXPFILL }},
3582 /* Setup protocol subtree array */
3583 #define NUM_INDIVIDUAL_PARMS 14
3584 int *ett[NUM_INDIVIDUAL_PARMS/*+NUM_MSGS*/+NUM_UDH_IEIS+2];
3586 ett[0] = &ett_gsm_sms;
3587 ett[1] = &ett_pid;
3588 ett[2] = &ett_pi;
3589 ett[3] = &ett_fcs;
3590 ett[4] = &ett_vp;
3591 ett[5] = &ett_scts;
3592 ett[6] = &ett_dt;
3593 ett[7] = &ett_st;
3594 ett[8] = &ett_addr;
3595 ett[9] = &ett_dcs;
3596 ett[10] = &ett_ud;
3597 ett[11] = &ett_udh;
3598 ett[12] = &ett_udh_tfm;
3599 ett[13] = &ett_udh_tfc;
3601 last_offset = NUM_INDIVIDUAL_PARMS;
3603 #if 0
3604 for (i=0; i < NUM_MSGS; i++, last_offset++)
3606 ett[last_offset] = &ett_msgs[i];
3608 #endif
3610 for (i=0; i < NUM_UDH_IEIS; i++, last_offset++)
3612 ett[last_offset] = &ett_udh_ieis[i];
3615 ett[last_offset++] = &ett_gsm_sms_ud_fragment;
3616 ett[last_offset] = &ett_gsm_sms_ud_fragments;
3618 /* Register the protocol name and description */
3620 proto_gsm_sms = proto_register_protocol(gsm_sms_proto_name, gsm_sms_proto_name_short, "gsm_sms");
3622 proto_register_field_array(proto_gsm_sms, hf, array_length(hf));
3623 proto_register_subtree_array(ett, array_length(ett));
3624 expert_gsm_sms = expert_register_protocol(proto_gsm_sms);
3625 expert_register_field_array(expert_gsm_sms, ei, array_length(ei));
3627 gsm_sms_dissector_tbl = register_dissector_table("gsm_sms.udh.port",
3628 "GSM SMS port IE in UDH", proto_gsm_sms, FT_UINT16, BASE_DEC);
3630 gsm_sms_module = prefs_register_protocol (proto_gsm_sms, NULL);
3632 prefs_register_obsolete_preference(gsm_sms_module,
3633 "try_dissect_message_fragment");
3634 prefs_register_bool_preference(gsm_sms_module, "reassemble",
3635 "Reassemble fragmented SMS",
3636 "Whether the dissector should reassemble SMS spanning multiple packets",
3637 &reassemble_sms);
3638 prefs_register_bool_preference(gsm_sms_module, "reassemble_with_lower_layers_info",
3639 "Use lower layers info for SMS reassembly",
3640 "Whether the dissector should take into account info coming "
3641 "from lower layers (like GSM-MAP) to perform SMS reassembly",
3642 &reassemble_sms_with_lower_layers_info);
3644 register_dissector("gsm_sms", dissect_gsm_sms, proto_gsm_sms);
3646 g_sm_fragment_params_table = wmem_multimap_new_autoreset(wmem_epan_scope(), wmem_file_scope(),
3647 sm_fragment_params_hash, sm_fragment_params_equal);
3649 reassembly_table_register(&g_sm_reassembly_table,
3650 &sm_reassembly_table_functions);
3654 void
3655 proto_reg_handoff_gsm_sms(void)
3657 proto_gsm_map = proto_get_id_by_filter_name("gsm_map");
3658 proto_sip = proto_get_id_by_filter_name("sip");
3662 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3664 * Local variables:
3665 * c-basic-offset: 4
3666 * tab-width: 8
3667 * indent-tabs-mode: nil
3668 * End:
3670 * vi: set shiftwidth=4 tabstop=8 expandtab:
3671 * :indentSize=4:tabSize=8:noTabs=true: