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.
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
19 * Wireshark - Network traffic analyzer
20 * By Gerald Combs <gerald@wireshark.org>
21 * Copyright 1998 Gerald Combs
23 * This program is free software; you can redistribute it and/or
24 * modify it under the terms of the GNU General Public License
25 * as published by the Free Software Foundation; either version 2
26 * of the License, or (at your option) any later version.
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the Free Software
35 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
44 #include <epan/packet.h>
45 #include <epan/prefs.h>
46 #include <epan/reassemble.h>
48 #include "packet-gsm_sms.h"
50 #define MAX_SMS_FRAG_LEN 134
52 /* PROTOTYPES/FORWARDS */
54 #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
55 if ((edc_len) > (edc_max_len)) \
57 proto_tree_add_text(tree, tvb, \
58 offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
61 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
62 if ((sdc_len) < (sdc_min_len)) \
64 proto_tree_add_text(tree, tvb, \
65 offset, (sdc_len), "Short Data (?)"); \
69 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
70 if ((edc_len) != (edc_eq_len)) \
72 proto_tree_add_text(tree, tvb, \
73 offset, (edc_len), "Unexpected Data Length"); \
77 #define SMS_SHIFTMASK(m_val, m_bitmask, m_sval); \
79 int _temp_val = m_val; \
80 int _temp_bm = m_bitmask; \
81 while (_temp_bm && !(_temp_bm & 0x01)) \
83 _temp_bm = _temp_bm >> 1; \
84 _temp_val = _temp_val >> 1; \
90 static const char *gsm_sms_proto_name = "GSM SMS TPDU (GSM 03.40)";
91 static const char *gsm_sms_proto_name_short = "GSM SMS";
93 /* Initialize the subtree pointers */
94 static gint ett_gsm_sms = -1;
95 static gint ett_pid = -1;
96 static gint ett_pi = -1;
97 static gint ett_fcs = -1;
98 static gint ett_vp = -1;
99 static gint ett_scts = -1;
100 static gint ett_dt = -1;
101 static gint ett_st = -1;
102 static gint ett_addr = -1;
103 static gint ett_dcs = -1;
104 static gint ett_ud = -1;
105 static gint ett_udh = -1;
107 static gint ett_udh_tfm = -1;
108 static gint ett_udh_tfc = -1;
110 /* Initialize the protocol and registered fields */
111 static int proto_gsm_sms = -1;
113 static gint hf_gsm_sms_coding_group_bits2 = -1;
114 static gint hf_gsm_sms_coding_group_bits4 = -1;
115 static gint hf_gsm_sms_ud_multiple_messages_msg_id = -1;
116 static gint hf_gsm_sms_ud_multiple_messages_msg_parts = -1;
117 static gint hf_gsm_sms_ud_multiple_messages_msg_part = -1;
119 /* TPDU Parameters */
120 static gint hf_gsm_sms_tp_mti_up = -1;
121 static gint hf_gsm_sms_tp_mti_down = -1;
122 static gint hf_gsm_sms_tp_mms = -1;
123 static gint hf_gsm_sms_tp_vpf = -1;
124 static gint hf_gsm_sms_tp_sri = -1;
125 static gint hf_gsm_sms_tp_srr = -1;
126 static gint hf_gsm_sms_tp_mr = -1;
127 static gint hf_gsm_sms_tp_oa = -1;
128 static gint hf_gsm_sms_tp_da = -1;
129 static gint hf_gsm_sms_tp_pid = -1;
130 static gint hf_gsm_sms_tp_dcs = -1;
131 static gint hf_gsm_sms_tp_ra = -1;
132 static gint hf_gsm_sms_tp_rp = -1;
133 static gint hf_gsm_sms_tp_udhi = -1;
134 static gint hf_gsm_sms_tp_rd = -1;
135 static gint hf_gsm_sms_tp_srq = -1;
136 static gint hf_gsm_sms_text = -1;
137 static gint hf_gsm_sms_tp_fail_cause = -1;
139 static gint hf_gsm_sms_tp_scts = -1;
140 static gint hf_gsm_sms_tp_vp = -1;
141 static gint hf_gsm_sms_tp_dt = -1;
142 static gint hf_gsm_sms_tp_st = -1;
143 static gint hf_gsm_sms_tp_udl = -1;
144 static gint hf_gsm_sms_tp_mn = -1;
145 static gint hf_gsm_sms_tp_ct = -1;
146 static gint hf_gsm_sms_tp_cdl = -1;
147 static gint hf_gsm_sms_tp_cd = -1;
148 static gint hf_gsm_sms_tp_ud = -1;
151 static gboolean reassemble_sms = TRUE;
152 static char bigbuf[1024];
153 static packet_info *g_pinfo;
154 static proto_tree *g_tree;
156 /* 3GPP TS 23.038 version 7.0.0 Release 7
157 * The TP-Data-Coding-Scheme field, defined in 3GPP TS 23.040 [4],
158 * indicates the data coding scheme of the TP-UD field, and may indicate a message class.
159 * Any reserved codings shall be assumed to be the GSM 7 bit default alphabet
160 * (the same as codepoint 00000000) by a receiving entity.
161 * The octet is used according to a coding group which is indicated in bits 7..4.
164 /* Coding Group Bits */
165 static const value_string gsm_sms_coding_group_bits_vals[] = {
166 { 0, "General Data Coding indication" }, /* 00xx */
167 { 1, "General Data Coding indication" }, /* 00xx */
168 { 2, "General Data Coding indication" }, /* 00xx */
169 { 3, "General Data Coding indication" }, /* 00xx */
170 { 4, "Message Marked for Automatic Deletion Group" }, /* 01xx */
171 { 5, "Message Marked for Automatic Deletion Group" }, /* 01xx */
172 { 6, "Message Marked for Automatic Deletion Group" }, /* 01xx */
173 { 7, "Message Marked for Automatic Deletion Group" }, /* 01xx */
174 { 8, "Reserved coding groups" }, /* 1000..1011 */
175 { 9, "Reserved coding groups" }, /* 1000..1011 */
176 { 10, "Reserved coding groups" }, /* 1000..1011 */
177 { 11, "Reserved coding groups" }, /* 1000..1011 */
178 { 12, "Message Waiting Indication Group: Discard Message" }, /* 1100 */
179 { 13, "Message Waiting Indication Group: Store Message" }, /* 1101 */
180 { 14, "Message Waiting Indication Group: Store Message" }, /* 1110 */
181 { 15, "Data coding/message class" }, /* 1111 */
185 static guint16 g_sm_id;
186 static guint16 g_frags;
187 static guint16 g_frag;
189 static guint16 g_port_src;
190 static guint16 g_port_dst;
191 static gboolean g_is_wsp;
193 static dissector_table_t gsm_sms_dissector_tbl;
194 /* Short Message reassembly */
195 static GHashTable *g_sm_fragment_table = NULL;
196 static GHashTable *g_sm_reassembled_table = NULL;
197 static GHashTable *g_sm_fragment_params_table = NULL;
198 static gint ett_gsm_sms_ud_fragment = -1;
199 static gint ett_gsm_sms_ud_fragments = -1;
201 * Short Message fragment handling
203 static int hf_gsm_sms_ud_fragments = -1;
204 static int hf_gsm_sms_ud_fragment = -1;
205 static int hf_gsm_sms_ud_fragment_overlap = -1;
206 static int hf_gsm_sms_ud_fragment_overlap_conflicts = -1;
207 static int hf_gsm_sms_ud_fragment_multiple_tails = -1;
208 static int hf_gsm_sms_ud_fragment_too_long_fragment = -1;
209 static int hf_gsm_sms_ud_fragment_error = -1;
210 static int hf_gsm_sms_ud_fragment_count = -1;
211 static int hf_gsm_sms_ud_reassembled_in = -1;
212 static int hf_gsm_sms_ud_reassembled_length = -1;
214 static const fragment_items sm_frag_items = {
215 /* Fragment subtrees */
216 &ett_gsm_sms_ud_fragment,
217 &ett_gsm_sms_ud_fragments,
218 /* Fragment fields */
219 &hf_gsm_sms_ud_fragments,
220 &hf_gsm_sms_ud_fragment,
221 &hf_gsm_sms_ud_fragment_overlap,
222 &hf_gsm_sms_ud_fragment_overlap_conflicts,
223 &hf_gsm_sms_ud_fragment_multiple_tails,
224 &hf_gsm_sms_ud_fragment_too_long_fragment,
225 &hf_gsm_sms_ud_fragment_error,
226 &hf_gsm_sms_ud_fragment_count,
227 /* Reassembled in field */
228 &hf_gsm_sms_ud_reassembled_in,
229 /* Reassembled length field */
230 &hf_gsm_sms_ud_reassembled_length,
231 /* Reassembled data field */
234 "Short Message fragments"
240 } sm_fragment_params;
243 gsm_sms_defragment_init (void)
245 fragment_table_init (&g_sm_fragment_table);
246 reassembled_table_init(&g_sm_reassembled_table);
247 if (g_sm_fragment_params_table) {
248 g_hash_table_destroy(g_sm_fragment_params_table);
250 g_sm_fragment_params_table = g_hash_table_new(g_direct_hash, g_direct_equal);
254 * this is the GSM 03.40 definition with the bit 2
255 * set to 1 for uplink messages
257 static const value_string msg_type_strings[] = {
258 { 0, "SMS-DELIVER" },
259 { 4, "SMS-DELIVER REPORT" },
261 { 1, "SMS-SUBMIT REPORT" },
262 { 2, "SMS-STATUS REPORT" },
263 { 6, "SMS-COMMAND" },
269 static const value_string msg_type_strings_sc_to_ms[] = {
270 { 0, "SMS-DELIVER" },
271 { 1, "SMS-SUBMIT REPORT" },
272 { 2, "SMS-STATUS REPORT" },
277 static const value_string msg_type_strings_ms_to_sc[] = {
278 { 0, "SMS-DELIVER REPORT" },
280 { 2, "SMS-COMMAND" },
285 /* 9.2.3.3 TP-Validity-Period-Format (TP-VPF) */
286 static const value_string vp_type_strings[] = {
287 { 0, "TP-VP field not present"},
288 { 2, "TP-VP field present - relative format"},
289 { 1, "TP-VP field present - enhanced format"},
290 { 3, "TP-VP field present - absolute format"},
294 static const true_false_string mms_bool_strings = {
295 "No more messages are waiting for the MS in this SC",
296 "More messages are waiting for the MS in this SC"
299 static const true_false_string sri_bool_strings = {
300 "A status report shall be returned to the SME",
301 "A status report shall not be returned to the SME"
304 static const true_false_string srr_bool_strings = {
305 "A status report is requested",
306 "A status report is not requested"
309 static const true_false_string udhi_bool_strings = {
310 "The beginning of the TP UD field contains a Header in addition to the short message",
311 "The TP UD field contains only the short message"
314 static const true_false_string rp_bool_strings = {
315 "TP Reply Path parameter is set in this SMS SUBMIT/DELIVER",
316 "TP Reply Path parameter is not set in this SMS SUBMIT/DELIVER"
319 static const true_false_string rd_bool_strings = {
320 "Instruct SC to reject duplicates",
321 "Instruct SC to accept duplicates"
324 static const true_false_string srq_bool_strings = {
325 "The SMS STATUS REPORT is the result of an SMS COMMAND e.g. an Enquiry.",
326 "SMS STATUS REPORT is the result of a SMS SUBMIT."
329 #define NUM_UDH_IEIS 256
330 static gint ett_udh_ieis[NUM_UDH_IEIS];
332 #define MAX_ADDR_SIZE 20
334 dis_field_addr(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, const gchar *title)
336 static gchar digit_table[] = {"0123456789*#abc\0"};
338 proto_tree *subtree = NULL;
339 const gchar *str = NULL;
345 char addrbuf[MAX_ADDR_SIZE+1];
350 oct = tvb_get_guint8(tvb, offset);
351 numdigocts = (oct + 1) / 2;
353 length = tvb_length_remaining(tvb, offset);
355 if (length <= numdigocts)
357 proto_tree_add_text(tree,
359 "%s: Short Data (?)",
366 item = proto_tree_add_text(tree, tvb,
367 offset, numdigocts + 2, "%s",
370 subtree = proto_item_add_subtree(item, ett_addr);
372 proto_tree_add_text(subtree,
374 "Length: %d address digits",
378 oct = tvb_get_guint8(tvb, offset);
380 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
381 proto_tree_add_text(subtree, tvb,
385 (oct & 0x80) ? "No extension" : "Extended");
387 switch ((oct & 0x70) >> 4)
389 case 0x00: str = "Unknown"; break;
390 case 0x01: str = "International"; break;
391 case 0x02: str = "National"; break;
392 case 0x03: str = "Network specific"; break;
393 case 0x04: str = "Subscriber"; break;
394 case 0x05: str = "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)"; break;
395 case 0x06: str = "Abbreviated number"; break;
396 case 0x07: str = "Reserved for extension"; break;
397 default: str = "Unknown, reserved (?)"; break;
400 other_decode_bitfield_value(bigbuf, oct, 0x70, 8);
401 proto_tree_add_text(subtree,
403 "%s : Type of number: (%d) %s",
410 case 0x00: str = "Unknown"; break;
411 case 0x01: str = "ISDN/telephone (E.164/E.163)"; break;
412 case 0x03: str = "Data numbering plan (X.121)"; break;
413 case 0x04: str = "Telex numbering plan"; break;
414 case 0x05: str = "Service Centre Specific plan"; break;
415 case 0x06: str = "Service Centre Specific plan"; break;
416 case 0x08: str = "National numbering plan"; break;
417 case 0x09: str = "Private numbering plan"; break;
418 case 0x0a: str = "ERMES numbering plan (ETSI DE/PS 3 01-3)"; break;
419 case 0x0f: str = "Reserved for extension"; break;
420 default: str = "Unknown, reserved (?)"; break;
423 other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
424 proto_tree_add_text(subtree,
426 "%s : Numbering plan: (%d) %s",
434 switch ((oct & 0x70) >> 4)
436 case 0x05: /* "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)" */
437 i = gsm_sms_char_7bit_unpack(0, numdigocts, MAX_ADDR_SIZE, tvb_get_ptr(tvb, offset, numdigocts), addrbuf);
439 addrstr = gsm_sms_chars_to_utf8(addrbuf, i);
442 addrstr = ep_alloc(numdigocts*2 + 1);
443 for (i = 0; i < numdigocts; i++)
445 oct = tvb_get_guint8(tvb, offset + i);
447 addrstr[j++] = digit_table[oct & 0x0f];
448 addrstr[j++] = digit_table[(oct & 0xf0) >> 4];
454 if (g_ascii_strncasecmp(title, "TP-O", 4) == 0) {
455 proto_tree_add_string(subtree, hf_gsm_sms_tp_oa, tvb,
456 offset, numdigocts, addrstr);
457 } else if (g_ascii_strncasecmp(title, "TP-D", 4) == 0) {
458 proto_tree_add_string(subtree, hf_gsm_sms_tp_da, tvb,
459 offset, numdigocts, addrstr);
460 } else if (g_ascii_strncasecmp(title, "TP-R", 4) == 0) {
461 proto_tree_add_string(subtree, hf_gsm_sms_tp_ra, tvb,
462 offset, numdigocts, addrstr);
464 proto_tree_add_text(subtree, tvb,
465 offset, numdigocts, "Digits: %s", addrstr);
468 proto_item_append_text(item, " - (%s)", addrstr);
470 *offset_p = offset + numdigocts;
474 /* use dis_field_addr() */
477 /* use dis_field_addr() */
481 dis_field_pid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
484 proto_tree *subtree = NULL;
487 const gchar *str = NULL;
490 item = proto_tree_add_item(tree, hf_gsm_sms_tp_pid, tvb, offset, 1, ENC_BIG_ENDIAN);
492 subtree = proto_item_add_subtree(item, ett_pid);
494 form = (oct & 0xc0) >> 6;
499 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
500 proto_tree_add_text(subtree, tvb,
502 "%s : defines formatting for subsequent bits",
505 other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
506 proto_tree_add_text(subtree, tvb,
511 "telematic interworking" :
512 "no telematic interworking, but SME-to-SME protocol");
516 telematic = oct & 0x1f;
520 case 0x00: str = "implicit - device type is specific to this SC, or can be concluded on the basis of the address"; break;
521 case 0x01: str = "telex (or teletex reduced to telex format)"; break;
522 case 0x02: str = "group 3 telefax"; break;
523 case 0x03: str = "group 4 telefax"; break;
524 case 0x04: str = "voice telephone (i.e. conversion to speech)"; break;
525 case 0x05: str = "ERMES (European Radio Messaging System)"; break;
526 case 0x06: str = "National Paging system (known to the SC)"; break;
527 case 0x07: str = "Videotex (T.100 [20] /T.101 [21])"; break;
528 case 0x08: str = "teletex, carrier unspecified"; break;
529 case 0x09: str = "teletex, in PSPDN"; break;
530 case 0x0a: str = "teletex, in CSPDN"; break;
531 case 0x0b: str = "teletex, in analog PSTN"; break;
532 case 0x0c: str = "teletex, in digital ISDN"; break;
533 case 0x0d: str = "UCI (Universal Computer Interface, ETSI DE/PS 3 01-3)"; break;
534 case 0x10: str = "a message handling facility (known to the SC)"; break;
535 case 0x11: str = "any public X.400-based message handling system"; break;
536 case 0x12: str = "Internet Electronic Mail"; break;
537 case 0x1f: str = "A GSM/UMTS mobile station"; break;
539 if ((telematic >= 0x18) &&
542 str = "values specific to each SC";
551 other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
552 proto_tree_add_text(subtree, tvb,
554 "%s : device type: (%d) %s",
561 other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
562 proto_tree_add_text(subtree, tvb,
564 "%s : the SM-AL protocol being used between the SME and the MS (%d)",
571 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
572 proto_tree_add_text(subtree, tvb,
574 "%s : defines formatting for subsequent bits",
579 case 0x00: str = "Short Message Type 0"; break;
580 case 0x01: str = "Replace Short Message Type 1"; break;
581 case 0x02: str = "Replace Short Message Type 2"; break;
582 case 0x03: str = "Replace Short Message Type 3"; break;
583 case 0x04: str = "Replace Short Message Type 4"; break;
584 case 0x05: str = "Replace Short Message Type 5"; break;
585 case 0x06: str = "Replace Short Message Type 6"; break;
586 case 0x07: str = "Replace Short Message Type 7"; break;
587 case 0x1e: str = "Enhanced Message Service (Obsolete)"; break;
588 case 0x1f: str = "Return Call Message"; break;
589 case 0x3c: str = "ANSI-136 R-DATA"; break;
590 case 0x3d: str = "ME Data download"; break;
591 case 0x3e: str = "ME De-personalization Short Message"; break;
592 case 0x3f: str = "(U)SIM Data download"; break;
594 str = "Reserved"; break;
597 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
598 proto_tree_add_text(subtree, tvb,
607 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
608 proto_tree_add_text(subtree, tvb,
613 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
614 proto_tree_add_text(subtree, tvb,
621 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
622 proto_tree_add_text(subtree, tvb,
624 "%s : bits 0-5 for SC specific use",
627 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
628 proto_tree_add_text(subtree, tvb,
638 dis_field_dcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct,
639 gboolean *seven_bit, gboolean *eight_bit, gboolean *ucs2, gboolean *compressed)
642 proto_tree *subtree = NULL;
644 const gchar *str = NULL;
645 gboolean default_5_bits;
646 gboolean default_3_bits;
647 gboolean default_data;
655 item = proto_tree_add_item(tree, hf_gsm_sms_tp_dcs, tvb, offset, 1, ENC_BIG_ENDIAN);
657 subtree = proto_item_add_subtree(item, ett_dcs);
659 proto_tree_add_item(subtree, hf_gsm_sms_coding_group_bits4, tvb, offset, 1, ENC_BIG_ENDIAN);
661 proto_tree_add_item(subtree, hf_gsm_sms_coding_group_bits2, tvb, offset, 1, ENC_BIG_ENDIAN);
666 proto_tree_add_text(subtree, tvb,
668 "Special case, GSM 7 bit default alphabet");
674 default_5_bits = FALSE;
675 default_3_bits = FALSE;
676 default_data = FALSE;
677 form = (oct & 0xc0) >> 6;
682 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
683 proto_tree_add_text(subtree, tvb,
685 "%s : General Data Coding indication",
688 default_5_bits = TRUE;
692 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
693 proto_tree_add_text(subtree, tvb,
695 "%s : Message Marked for Automatic Deletion Group",
698 default_5_bits = TRUE;
702 /* use top four bits */
703 other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
704 proto_tree_add_text(subtree, tvb,
706 "%s : Reserved coding groups",
711 switch ((oct & 0x30) >> 4)
713 case 0x00: str = "Message Waiting Indication Group: Discard Message (GSM 7 bit default alphabet)";
714 default_3_bits = TRUE;
717 case 0x01: str = "Message Waiting Indication Group: Store Message (GSM 7 bit default alphabet)";
718 default_3_bits = TRUE;
721 case 0x02: str = "Message Waiting Indication Group: Store Message (uncompressed UCS2 alphabet)";
722 default_3_bits = TRUE;
724 case 0x03: str = "Data coding/message class";
729 /* use top four bits */
730 other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
731 proto_tree_add_text(subtree, tvb,
741 other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
742 proto_tree_add_text(subtree, tvb,
744 "%s : Text is %scompressed",
746 (oct & 0x20) ? "" : "not ");
748 *compressed = (oct & 0x20) >> 5;
750 other_decode_bitfield_value(bigbuf, oct, 0x10, 8);
751 proto_tree_add_text(subtree, tvb,
755 (oct & 0x10) ? "Message class is defined below" :
756 "Reserved, no message class");
758 switch ((oct & 0x0c) >> 2)
760 case 0x00: str = "GSM 7 bit default alphabet";
763 case 0x01: str = "8 bit data";
766 case 0x02: str = "UCS2 (16 bit)";
769 case 0x03: str = "Reserved"; break;
772 other_decode_bitfield_value(bigbuf, oct, 0x0c, 8);
773 proto_tree_add_text(subtree, tvb,
775 "%s : Character set: %s",
781 case 0x00: str = "Class 0"; break;
782 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
783 case 0x02: str = "Class 2 (U)SIM specific message"; break;
784 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
787 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
788 proto_tree_add_text(subtree, tvb,
790 "%s : Message Class: %s%s",
793 (oct & 0x10) ? "" : " (reserved)");
795 else if (default_3_bits)
797 other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
798 proto_tree_add_text(subtree, tvb,
800 "%s : Indication Sense: %s",
802 (oct & 0x08) ? "Set Indication Active" : "Set Indication Inactive");
804 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
805 proto_tree_add_text(subtree, tvb,
812 case 0x00: str = "Voicemail Message Waiting"; break;
813 case 0x01: str = "Fax Message Waiting"; break;
814 case 0x02: str = "Electronic Mail Message Waiting"; break;
815 case 0x03: str = "Other Message Waiting"; break;
818 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
819 proto_tree_add_text(subtree, tvb,
825 else if (default_data)
827 other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
828 proto_tree_add_text(subtree, tvb,
833 *seven_bit = !(*eight_bit = (oct & 0x04) ? TRUE : FALSE);
835 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
836 proto_tree_add_text(subtree, tvb,
838 "%s : Message coding: %s",
840 (*eight_bit) ? "8 bit data" : "GSM 7 bit default alphabet");
844 case 0x00: str = "Class 0"; break;
845 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
846 case 0x02: str = "Class 2 (U)SIM specific message"; break;
847 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
850 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
851 proto_tree_add_text(subtree, tvb,
853 "%s : Message Class: %s",
860 dis_field_scts_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
862 guint8 oct, oct2, oct3;
866 oct = tvb_get_guint8(tvb, offset);
867 oct2 = tvb_get_guint8(tvb, offset+1);
868 oct3 = tvb_get_guint8(tvb, offset+2);
870 proto_tree_add_text(tree,
872 "Year %d%d, Month %d%d, Day %d%d",
882 oct = tvb_get_guint8(tvb, offset);
883 oct2 = tvb_get_guint8(tvb, offset+1);
884 oct3 = tvb_get_guint8(tvb, offset+2);
886 proto_tree_add_text(tree,
888 "Hour %d%d, Minutes %d%d, Seconds %d%d",
898 oct = tvb_get_guint8(tvb, offset);
900 sign = (oct & 0x08)?'-':'+';
901 oct = (oct >> 4) + (oct & 0x07) * 10;
903 proto_tree_add_text(tree,
905 "Timezone: GMT %c %d hours %d minutes",
906 sign, oct / 4, oct % 4 * 15);
911 dis_field_scts(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
914 proto_tree *subtree = NULL;
921 length = tvb_length_remaining(tvb, offset);
925 proto_tree_add_text(tree,
927 "TP-Service-Centre-Time-Stamp: Short Data (?)");
934 proto_tree_add_text(tree, tvb,
936 "TP-Service-Centre-Time-Stamp");
938 subtree = proto_item_add_subtree(item, ett_scts);
940 dis_field_scts_aux(tvb, subtree, *offset_p);
947 dis_field_vp(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, guint8 vp_form)
950 proto_tree *subtree = NULL;
953 guint8 oct, oct2, oct3;
959 if (vp_form == 0x00) return;
970 length = tvb_length_remaining(tvb, offset);
974 proto_tree_add_text(tree,
976 "TP-Validity-Period: Short Data (?)");
983 proto_tree_add_text(tree, tvb,
985 "TP-Validity-Period");
987 subtree = proto_item_add_subtree(item, ett_vp);
989 oct = tvb_get_guint8(tvb, offset);
991 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
992 proto_tree_add_text(subtree, tvb,
996 (oct & 0x80) ? "Extended" : "No extension");
1000 proto_tree_add_text(subtree,
1002 "Extension not implemented, ignored");
1008 other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
1009 proto_tree_add_text(subtree, tvb,
1013 (oct & 0x40) ? "Single shot SM" : "Not single shot SM");
1015 other_decode_bitfield_value(bigbuf, oct, 0x38, 8);
1016 proto_tree_add_text(subtree, tvb,
1021 loc_form = oct & 0x7;
1026 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1027 proto_tree_add_text(subtree, tvb,
1029 "%s : No Validity Period specified",
1036 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1037 proto_tree_add_text(subtree, tvb,
1039 "%s : Validity Period Format: relative",
1043 /* go around again */
1048 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1049 proto_tree_add_text(subtree, tvb,
1051 "%s : Validity Period Format: relative",
1055 oct = tvb_get_guint8(tvb, offset);
1057 proto_tree_add_text(subtree, tvb,
1066 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1067 proto_tree_add_text(subtree, tvb,
1069 "%s : Validity Period Format: relative",
1073 oct = tvb_get_guint8(tvb, offset);
1074 oct2 = tvb_get_guint8(tvb, offset+1);
1075 oct3 = tvb_get_guint8(tvb, offset+2);
1077 proto_tree_add_text(subtree,
1079 "Hour %d%d, Minutes %d%d, Seconds %d%d",
1085 (oct3 & 0xf0) >> 4);
1091 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1092 proto_tree_add_text(subtree, tvb,
1094 "%s : Validity Period Format: Reserved",
1103 oct = tvb_get_guint8(tvb, offset);
1107 mins = (oct + 1) * 5;
1113 proto_tree_add_text(subtree, tvb,
1115 "TP-Validity-Period: %d hours %d minutes",
1121 proto_tree_add_text(subtree, tvb,
1123 "TP-Validity-Period: %d minutes",
1127 else if ((oct >= 144) &&
1130 mins = (oct - 143) * 30;
1131 hours = 12 + (mins / 60);
1134 proto_tree_add_text(subtree, tvb,
1136 "TP-Validity-Period: %d hours %d minutes",
1140 else if ((oct >= 168) &&
1143 proto_tree_add_text(subtree, tvb,
1145 "TP-Validity-Period: %d day(s)",
1148 else if (oct >= 197)
1150 proto_tree_add_text(subtree, tvb,
1152 "TP-Validity-Period: %d week(s)",
1160 length = tvb_length_remaining(tvb, offset);
1164 proto_tree_add_text(tree,
1165 tvb, offset, length,
1166 "TP-Validity-Period: Short Data (?)");
1168 *offset_p += length;
1173 proto_tree_add_text(tree, tvb,
1175 "TP-Validity-Period: absolute");
1177 subtree = proto_item_add_subtree(item, ett_vp);
1179 dis_field_scts_aux(tvb, subtree, *offset_p);
1199 dis_field_dt(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
1202 proto_tree *subtree = NULL;
1209 length = tvb_length_remaining(tvb, offset);
1213 proto_tree_add_text(tree,
1214 tvb, offset, length,
1215 "TP-Discharge-Time: Short Data (?)");
1217 *offset_p += length;
1222 proto_tree_add_text(tree, tvb,
1224 "TP-Discharge-Time");
1226 subtree = proto_item_add_subtree(item, ett_dt);
1228 dis_field_scts_aux(tvb, subtree, *offset_p);
1234 /* use dis_field_addr() */
1238 dis_field_st(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1240 static const gchar *sc_complete = "Short message transaction completed";
1241 static const gchar *sc_temporary = "Temporary error, SC still trying to transfer SM";
1242 static const gchar *sc_perm = "Permanent error, SC is not making any more transfer attempts";
1243 static const gchar *sc_tempfin = "Temporary error, SC is not making any more transfer attempts";
1245 proto_tree *subtree = NULL;
1247 const gchar *str = NULL;
1248 const gchar *str2 = NULL;
1252 proto_tree_add_text(tree, tvb,
1256 subtree = proto_item_add_subtree(item, ett_st);
1258 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1259 proto_tree_add_text(subtree, tvb,
1261 "%s : Definition of bits 0-6: %s",
1263 (oct & 0x80) ? "Reserved" : "as follows");
1269 case 0x00: str2 = sc_complete; str = "Short message received by the SME"; break;
1270 case 0x01: str2 = sc_complete; str = "Short message forwarded by the SC to the SME but the SC is unable to confirm delivery"; break;
1271 case 0x02: str2 = sc_complete; str = "Short message replaced by the SC Reserved values"; break;
1273 case 0x20: str2 = sc_temporary; str = "Congestion"; break;
1274 case 0x21: str2 = sc_temporary; str = "SME busy"; break;
1275 case 0x22: str2 = sc_temporary; str = "No response from SME"; break;
1276 case 0x23: str2 = sc_temporary; str = "Service rejected"; break;
1277 case 0x24: str2 = sc_temporary; str = "Quality of service not available"; break;
1278 case 0x25: str2 = sc_temporary; str = "Error in SME"; break;
1280 case 0x40: str2 = sc_perm; str = "Remote procedure error"; break;
1281 case 0x41: str2 = sc_perm; str = "Incompatible destination"; break;
1282 case 0x42: str2 = sc_perm; str = "Connection rejected by SME"; break;
1283 case 0x43: str2 = sc_perm; str = "Not obtainable"; break;
1284 case 0x44: str2 = sc_perm; str = "Quality of service not available"; break;
1285 case 0x45: str2 = sc_perm; str = "No interworking available"; break;
1286 case 0x46: str2 = sc_perm; str = "SM Validity Period Expired"; break;
1287 case 0x47: str2 = sc_perm; str = "SM Deleted by originating SME"; break;
1288 case 0x48: str2 = sc_perm; str = "SM Deleted by SC Administration"; break;
1289 case 0x49: str2 = sc_perm; str = "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)"; break;
1291 case 0x60: str2 = sc_tempfin; str = "Congestion"; break;
1292 case 0x61: str2 = sc_tempfin; str = "SME busy"; break;
1293 case 0x62: str2 = sc_tempfin; str = "No response from SME"; break;
1294 case 0x63: str2 = sc_tempfin; str = "Service rejected"; break;
1295 case 0x64: str2 = sc_tempfin; str = "Quality of service not available"; break;
1296 case 0x65: str2 = sc_tempfin; str = "Error in SME"; break;
1299 if ((value >= 0x03) &&
1305 else if ((value >= 0x10) &&
1309 str = "Values specific to each SC";
1311 else if ((value >= 0x26) &&
1314 str2 = sc_temporary;
1317 else if ((value >= 0x30) &&
1320 str2 = sc_temporary;
1321 str = "Values specific to each SC";
1323 else if ((value >= 0x4a) &&
1329 else if ((value >= 0x50) &&
1333 str = "Values specific to each SC";
1335 else if ((value >= 0x66) &&
1341 else if ((value >= 0x70) &&
1345 str = "Values specific to each SC";
1350 other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
1351 proto_tree_add_text(subtree, tvb,
1361 #define DIS_FIELD_UDL(m_tree, m_offset) \
1363 proto_tree_add_text(m_tree, tvb, \
1365 "TP-User-Data-Length: (%d) %s", \
1367 oct ? "depends on Data-Coding-Scheme" : "no User-Data");\
1371 #define DIS_FIELD_RP(m_tree, m_bitmask, m_offset) \
1373 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1374 proto_tree_add_text(m_tree, tvb, \
1376 "%s : TP-Reply-Path: parameter is %sset in this SMS-SUBMIT/DELIVER", \
1378 (oct & m_bitmask) ? "" : "not "); \
1382 #define DIS_FIELD_MN(m_tree, m_offset) \
1384 proto_tree_add_text(m_tree, tvb, \
1386 "TP-Message-Number: %d", \
1391 #define DIS_FIELD_CT(m_tree, m_offset) \
1395 case 0: str = "Enquiry relating to previously submitted short message"; break; \
1396 case 1: str = "Cancel Status Report Request relating to previously submitted short message"; break; \
1397 case 2: str = "Delete previously submitted Short Message"; break; \
1398 case 3: str = "Enable Status Report Request relating to previously submitted short message"; break; \
1400 if ((oct >= 0x04) && \
1403 str = "Reserved unspecified"; \
1405 else if (oct >= 0xe0) \
1407 str = "Values specific for each SC"; \
1411 str = "undefined"; \
1415 proto_tree_add_text(m_tree, tvb, \
1417 "TP-Command-Type: (%d), %s", \
1423 #define DIS_FIELD_CDL(m_tree, m_offset) \
1425 proto_tree_add_text(m_tree, tvb, \
1427 "TP-Command-Data-Length: (%d)%s", \
1429 oct ? "" : " no Command-Data");\
1433 /* done in-line in the message functions */
1436 * 9.2.3.22 TP-Failure-Cause (TP-FCS)
1440 static const value_string gsm_sms_tp_failure_cause_values[] = {
1441 /* 00 - 7F Reserved */
1442 /* 80 - 8F TP-PID errors */
1443 { 0x80, "Telematic interworking not supported" },
1444 { 0x81, "Short message Type 0 not supported" },
1445 { 0x82, "Cannot replace short message" },
1446 /* 83 - 8E Reserved */
1447 { 0x83, "Reserved" },
1448 { 0x84, "Reserved" },
1449 { 0x85, "Reserved" },
1450 { 0x86, "Reserved" },
1451 { 0x87, "Reserved" },
1452 { 0x88, "Reserved" },
1453 { 0x89, "Reserved" },
1454 { 0x8a, "Reserved" },
1455 { 0x8b, "Reserved" },
1456 { 0x8c, "Reserved" },
1457 { 0x8d, "Reserved" },
1458 { 0x8e, "Reserved" },
1460 { 0x8F, "Unspecified TP-PID error" },
1461 /* 90 - 9F TP-DCS errors */
1462 { 0x90, "Data coding scheme (alphabet) not supported" },
1463 { 0x91, "Message class not supported" },
1464 /* 92 - 9E Reserved */
1465 { 0x92, "Reserved" },
1466 { 0x93, "Reserved" },
1467 { 0x94, "Reserved" },
1468 { 0x95, "Reserved" },
1469 { 0x96, "Reserved" },
1470 { 0x97, "Reserved" },
1471 { 0x98, "Reserved" },
1472 { 0x99, "Reserved" },
1473 { 0x9a, "Reserved" },
1474 { 0x9b, "Reserved" },
1475 { 0x9c, "Reserved" },
1476 { 0x9d, "Reserved" },
1477 { 0x9e, "Reserved" },
1479 { 0x9F, "Unspecified TP-DCS error" },
1480 /* A0 - AF TP-Command Errors */
1481 { 0xA0, "Command cannot be actioned" },
1482 { 0xA1, "Command unsupported" },
1483 /* A2 - AE Reserved */
1484 { 0xa2, "Reserved" },
1485 { 0xa3, "Reserved" },
1486 { 0xa4, "Reserved" },
1487 { 0xa5, "Reserved" },
1488 { 0xa6, "Reserved" },
1489 { 0xa7, "Reserved" },
1490 { 0xa8, "Reserved" },
1491 { 0xa9, "Reserved" },
1492 { 0xaa, "Reserved" },
1493 { 0xab, "Reserved" },
1494 { 0xac, "Reserved" },
1495 { 0xad, "Reserved" },
1496 { 0xae, "Reserved" },
1498 { 0xAF, "Unspecified TP-Command error" },
1499 { 0xB0, "TPDU not supported" },
1500 /* B1 - BF Reserved */
1501 { 0xb1, "Reserved" },
1502 { 0xb2, "Reserved" },
1503 { 0xb3, "Reserved" },
1504 { 0xb4, "Reserved" },
1505 { 0xb5, "Reserved" },
1506 { 0xb6, "Reserved" },
1507 { 0xb7, "Reserved" },
1508 { 0xb8, "Reserved" },
1509 { 0xb9, "Reserved" },
1510 { 0xba, "Reserved" },
1511 { 0xbb, "Reserved" },
1512 { 0xbc, "Reserved" },
1513 { 0xbd, "Reserved" },
1514 { 0xbe, "Reserved" },
1515 { 0xbf, "Reserved" },
1517 { 0xC0, "SC busy" },
1518 { 0xC1, "No SC subscription" },
1519 { 0xC2, "SC system failure" },
1520 { 0xC3, "Invalid SME address" },
1521 { 0xC4, "Destination SME barred" },
1522 { 0xC5, "SM Rejected-Duplicate SM" },
1523 { 0xC6, "TP-VPF not supported" },
1524 { 0xC7, "TP-VP not supported" },
1525 /* C8 - CF Reserved */
1526 { 0xc8, "Reserved" },
1527 { 0xc9, "Reserved" },
1528 { 0xca, "Reserved" },
1529 { 0xcb, "Reserved" },
1530 { 0xcc, "Reserved" },
1531 { 0xcd, "Reserved" },
1532 { 0xce, "Reserved" },
1533 { 0xcf, "Reserved" },
1535 { 0xD0, "(U)SIM SMS storage full" },
1536 { 0xD1, "No SMS storage capability in (U)SIM" },
1537 { 0xD2, "Error in MS" },
1538 { 0xD3, "Memory Capacity Exceeded" },
1539 { 0xD4, "(U)SIM Application Toolkit Busy" },
1540 { 0xD5, "(U)SIM data download error" },
1541 /* D6 - DF Reserved */
1542 { 0xd6, "Reserved" },
1543 { 0xd7, "Reserved" },
1544 { 0xd8, "Reserved" },
1545 { 0xd9, "Reserved" },
1546 { 0xda, "Reserved" },
1547 { 0xdb, "Reserved" },
1548 { 0xdc, "Reserved" },
1549 { 0xdd, "Reserved" },
1550 { 0xde, "Reserved" },
1551 { 0xdf, "Reserved" },
1553 /* E0 - FE Values specific to an application */
1554 { 0xe0, "Value specific to an application" },
1555 { 0xe1, "Value specific to an application" },
1556 { 0xe2, "Value specific to an application" },
1557 { 0xe3, "Value specific to an application" },
1558 { 0xe4, "Value specific to an application" },
1559 { 0xe5, "Value specific to an application" },
1560 { 0xe6, "Value specific to an application" },
1561 { 0xe7, "Value specific to an application" },
1562 { 0xe8, "Value specific to an application" },
1563 { 0xe9, "Value specific to an application" },
1564 { 0xea, "Value specific to an application" },
1565 { 0xeb, "Value specific to an application" },
1566 { 0xec, "Value specific to an application" },
1567 { 0xed, "Value specific to an application" },
1568 { 0xee, "Value specific to an application" },
1569 { 0xef, "Value specific to an application" },
1570 { 0xf0, "Value specific to an application" },
1571 { 0xf1, "Value specific to an application" },
1572 { 0xf2, "Value specific to an application" },
1573 { 0xf3, "Value specific to an application" },
1574 { 0xf4, "Value specific to an application" },
1575 { 0xf5, "Value specific to an application" },
1576 { 0xf6, "Value specific to an application" },
1577 { 0xf7, "Value specific to an application" },
1578 { 0xf8, "Value specific to an application" },
1579 { 0xf9, "Value specific to an application" },
1580 { 0xfa, "Value specific to an application" },
1581 { 0xfb, "Value specific to an application" },
1582 { 0xfc, "Value specific to an application" },
1583 { 0xfd, "Value specific to an application" },
1584 { 0xfe, "Value specific to an application" },
1586 { 0xFF, "Unspecified error cause" },
1589 static value_string_ext gsm_sms_tp_failure_cause_values_ext = VALUE_STRING_EXT_INIT(gsm_sms_tp_failure_cause_values);
1592 dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct _U_)
1594 proto_tree_add_item(tree, hf_gsm_sms_tp_fail_cause, tvb, offset, 1, ENC_BIG_ENDIAN);
1598 #define DIS_FIELD_UDHI(m_tree, m_bitmask, m_offset, m_udhi) \
1600 SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, m_udhi); \
1601 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1602 proto_tree_add_text(m_tree, tvb, \
1604 "%s : TP-User-Data-Header-Indicator: %s short message", \
1607 "The beginning of the TP-UD field contains a Header in addition to the" : \
1608 "The TP-UD field contains only the"); \
1616 #define GN_BYTE_MASK ((1 << bits) - 1)
1619 gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length,
1620 const guint8 *input, unsigned char *output)
1622 unsigned char *out_num = output; /* Current pointer to the output buffer */
1623 const guint8 *in_num = input; /* Current pointer to the input buffer */
1624 unsigned char rest = 0x00;
1627 bits = offset ? offset : 7;
1629 while ((unsigned int)(in_num - input) < in_length)
1631 *out_num = ((*in_num & GN_BYTE_MASK) << (7 - bits)) | rest;
1632 rest = *in_num >> bits;
1634 /* If we don't start from 0th bit, we shouldn't go to the
1635 next char. Under *out_num we have now 0 and under Rest -
1636 _first_ part of the char. */
1637 if ((in_num != input) || (bits == 7)) out_num++;
1640 if ((unsigned int)(out_num - output) >= out_length) break;
1642 /* After reading 7 octets we have read 7 full characters but
1643 we have 7 bits as well. This is the next character */
1657 return (int)(out_num - output);
1660 #define GN_CHAR_ALPHABET_SIZE 128
1662 #define GN_CHAR_ESCAPE 0x1b
1664 static gunichar gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
1666 /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
1667 /* Fixed to use unicode */
1668 /* Characters in hex position 10, [12 to 1a] and 24 are not present on
1669 latin1 charset, so we cannot reproduce on the screen, however they are
1670 greek symbol not present even on my Nokia */
1672 '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
1673 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
1674 0x394, '_', 0x3a6, 0x393, 0x39b, 0x3a9, 0x3a0, 0x3a8,
1675 0x3a3, 0x398, 0x39e, 0xa0, 0xc6, 0xe6, 0xdf, 0xc9,
1676 ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
1677 '(', ')', '*', '+', ',', '-', '.', '/',
1678 '0', '1', '2', '3', '4', '5', '6', '7',
1679 '8', '9', ':', ';', '<', '=', '>', '?',
1680 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
1681 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
1682 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
1683 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
1684 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
1685 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
1686 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
1687 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
1691 char_is_escape(unsigned char value)
1693 return (value == GN_CHAR_ESCAPE);
1697 char_def_alphabet_ext_decode(unsigned char value)
1701 case 0x0a: return 0x0c; /* form feed */
1702 case 0x14: return '^';
1703 case 0x28: return '{';
1704 case 0x29: return '}';
1705 case 0x2f: return '\\';
1706 case 0x3c: return '[';
1707 case 0x3d: return '~';
1708 case 0x3e: return ']';
1709 case 0x40: return '|';
1710 case 0x65: return 0x20ac; /* euro */
1711 default: return '?'; /* invalid character */
1716 char_def_alphabet_decode(unsigned char value)
1718 if (value < GN_CHAR_ALPHABET_SIZE)
1720 return gsm_default_alphabet[value];
1729 gsm_sms_chars_to_utf8(const unsigned char* src, int len)
1735 /* Scan the input string to see how long the output string will be */
1736 for (outlen = 0, j = 0; j < len; j++)
1738 if (char_is_escape(src[j])) {
1741 c = '?'; /* escape with nothing following it - error */
1743 c = char_def_alphabet_ext_decode(src[j]);
1746 c = char_def_alphabet_decode(src[j]);
1747 outlen += g_unichar_to_utf8(c,NULL);
1750 /* Now allocate a buffer for the output string and fill it in */
1751 outbuf = ep_alloc(outlen + 1);
1752 for (i = 0, j = 0; j < len; j++)
1754 if (char_is_escape(src[j])) {
1757 c = '?'; /* escape with nothing following it - error */
1759 c = char_def_alphabet_ext_decode(src[j]);
1762 c = char_def_alphabet_decode(src[j]);
1763 i += g_unichar_to_utf8(c,&(outbuf[i]));
1775 dis_iei_csm8(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1779 EXACT_DATA_CHECK(length, 3);
1780 oct = tvb_get_guint8(tvb, offset);
1782 proto_tree_add_uint (tree,
1783 hf_gsm_sms_ud_multiple_messages_msg_id,
1784 tvb, offset, 1, g_sm_id);
1787 oct = tvb_get_guint8(tvb, offset);
1789 proto_tree_add_uint (tree,
1790 hf_gsm_sms_ud_multiple_messages_msg_parts,
1791 tvb , offset , 1, g_frags);
1793 oct = tvb_get_guint8(tvb, offset);
1795 proto_tree_add_uint (tree,
1796 hf_gsm_sms_ud_multiple_messages_msg_part,
1797 tvb, offset, 1, g_frag);
1801 /* TODO 9.2.3.24.2 Special SMS Message Indication */
1805 dis_iei_apa_8bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1807 const gchar *str = NULL;
1811 EXACT_DATA_CHECK(length, 2);
1813 oct = tvb_get_guint8(tvb, offset);
1821 str = "Available for allocation by applications";
1824 proto_tree_add_text(tree,
1826 "Destination port: %d, %s",
1831 oct = tvb_get_guint8(tvb, offset);
1839 str = "Available for allocation by applications";
1842 proto_tree_add_text(tree,
1844 "Originator port: %d, %s",
1851 dis_iei_apa_16bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1853 const gchar *str = NULL;
1857 EXACT_DATA_CHECK(length, 4);
1859 value = tvb_get_ntohs(tvb, offset);
1863 str = "As allocated by IANA (http://www.IANA.com/)";
1865 else if (value < 17000)
1867 str = "Available for allocation by applications";
1874 proto_tree_add_text(tree,
1876 "Destination port: %d, %s",
1881 value = tvb_get_ntohs(tvb, offset);
1885 str = "As allocated by IANA (http://www.IANA.com/)";
1887 else if (value < 17000)
1889 str = "Available for allocation by applications";
1896 proto_tree_add_text(tree,
1898 "Originator port: %d, %s",
1907 dis_iei_scp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1911 EXACT_DATA_CHECK(length, 1);
1913 oct = tvb_get_guint8(tvb, offset);
1917 proto_tree_add_text(tree,
1919 "Status Report for short message transaction completed");
1923 proto_tree_add_text(tree,
1925 "No Status Report for short message transaction completed");
1930 proto_tree_add_text(tree,
1932 "Status Report for permanent error when SC is not making any more transfer attempts");
1936 proto_tree_add_text(tree,
1938 "No Status Report for permanent error when SC is not making any more transfer attempts");
1943 proto_tree_add_text(tree,
1945 "Status Report for temporary error when SC is not making any more transfer attempts");
1949 proto_tree_add_text(tree,
1951 "No Status Report for temporary error when SC is not making any more transfer attempts");
1957 proto_tree_add_text(tree,
1959 "Status Report for temporary error when SC is still trying to transfer SM");
1963 proto_tree_add_text(tree,
1965 "No Status Report for temporary error when SC is still trying to transfer SM");
1971 proto_tree_add_text(tree,
1973 "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");
1977 proto_tree_add_text(tree,
1985 proto_tree_add_text(tree,
1987 "Include original UDH into the Status Report");
1991 proto_tree_add_text(tree,
1993 "Do not include original UDH into the Status Report");
2000 dis_iei_udh_si(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2004 EXACT_DATA_CHECK(length, 1);
2006 oct = tvb_get_guint8(tvb, offset);
2011 proto_tree_add_text(tree,
2013 "The following part of the UDH is created by the original sender (valid in case of Status Report)");
2016 proto_tree_add_text(tree,
2018 "The following part of the UDH is created by the original receiver (valid in case of Status Report)");
2021 proto_tree_add_text(tree,
2023 "The following part of the UDH is created by the SMSC (can occur in any message or report)");
2026 proto_tree_add_text(tree,
2028 "The following part of the UDH is created by %d" , oct);
2034 dis_iei_csm16(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2039 EXACT_DATA_CHECK(length, 4);
2040 oct_ref = tvb_get_ntohs(tvb, offset);
2042 proto_tree_add_uint (tree,
2043 hf_gsm_sms_ud_multiple_messages_msg_id,
2044 tvb, offset, 2, g_sm_id);
2046 oct = tvb_get_guint8(tvb, offset);
2048 proto_tree_add_uint (tree,
2049 hf_gsm_sms_ud_multiple_messages_msg_parts,
2050 tvb , offset , 1, g_frags);
2053 oct = tvb_get_guint8(tvb, offset);
2055 proto_tree_add_uint (tree,
2056 hf_gsm_sms_ud_multiple_messages_msg_part,
2057 tvb, offset, 1, g_frag);
2060 static const value_string text_color_values[] = {
2062 { 0x01, "Dark Grey" },
2063 { 0x02, "Dark Red" },
2064 { 0x03, "Dark Yellow" },
2065 { 0x04, "Dark Green" },
2066 { 0x05, "Dark Cyan" },
2067 { 0x06, "Dark Blue" },
2068 { 0x07, "Dark Magenta" },
2071 { 0x0A, "Bright Red" },
2072 { 0x0B, "Bright Yellow" },
2073 { 0x0C, "Bright Green" },
2074 { 0x0D, "Bright Cyan" },
2075 { 0x0E, "Bright Blue" },
2076 { 0x0F, "Bright Magenta" },
2080 /* 9.2.3.24.10.1.1 */
2082 dis_iei_tf(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2084 const gchar *str = NULL;
2087 proto_item *item_colour;
2088 proto_tree *subtree = NULL;
2089 proto_tree *subtree_colour = NULL;
2092 EXACT_DATA_CHECK(length, 4);
2093 oct = tvb_get_guint8(tvb, offset);
2095 proto_tree_add_text(tree, tvb, offset, 1,
2096 "Start position of the text formatting: %d", oct);
2099 oct = tvb_get_guint8(tvb, offset);
2101 proto_tree_add_text(tree, tvb, offset, 1, "Text formatting length: %d",
2105 oct = tvb_get_guint8(tvb, offset);
2107 item = proto_tree_add_text(tree, tvb, offset, 1, "formatting mode");
2109 subtree = proto_item_add_subtree(item, ett_udh_tfm);
2122 str = "Language dependent";
2126 proto_tree_add_text(subtree, tvb, offset, 1, "Alignment : %d %s",
2129 switch((oct >> 2) & 0x03)
2145 proto_tree_add_text(subtree, tvb, offset, 1, "Font Size : %d %s",
2146 (oct >> 2) & 0x03 , str);
2152 proto_tree_add_text(subtree, tvb, offset, 1, "Style bold : %d %s",
2159 proto_tree_add_text(subtree, tvb, offset, 1, "Style Italic : %d %s",
2166 proto_tree_add_text(subtree, tvb, offset, 1, "Style Underlined : %d %s",
2173 proto_tree_add_text(subtree, tvb, offset, 1, "Style Strikethrough : %d %s",
2177 oct = tvb_get_guint8(tvb, offset);
2178 item_colour = proto_tree_add_text(tree, tvb, offset, 1, "Text Colour");
2180 subtree_colour = proto_item_add_subtree(item_colour, ett_udh_tfc);
2183 str = val_to_str_const(oct & 0x0f, text_color_values, "Unknown");
2184 proto_tree_add_text(subtree_colour, tvb, offset, 1,
2185 "Foreground Colour : 0x%x %s",
2188 str = val_to_str_const((oct >> 4) & 0x0f, text_color_values, "Unknown");
2189 proto_tree_add_text(subtree_colour,
2191 "Background Colour : 0x%x %s",
2192 (oct >> 4) & 0x0f , str);
2196 /* 9.2.3.24.10.1.2 */
2198 dis_iei_ps(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2202 EXACT_DATA_CHECK(length, 2);
2203 oct = tvb_get_guint8(tvb, offset);
2205 proto_tree_add_text(tree,
2211 oct = tvb_get_guint8(tvb, offset);
2213 proto_tree_add_text(tree,
2219 /* 9.2.3.24.10.1.3 */
2221 dis_iei_uds(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2225 SHORT_DATA_CHECK(length, 2);
2226 oct = tvb_get_guint8(tvb, offset);
2228 proto_tree_add_text(tree,
2234 proto_tree_add_text(tree,
2235 tvb, offset, length - 1,
2236 "User Defined Sound ");
2240 /* 9.2.3.24.10.1.4 */
2242 dis_iei_pa(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2246 EXACT_DATA_CHECK(length, 2);
2247 oct = tvb_get_guint8(tvb, offset);
2249 proto_tree_add_text(tree,
2255 oct = tvb_get_guint8(tvb, offset);
2257 proto_tree_add_text(tree,
2259 "animation number: %d",
2264 /* 9.2.3.24.10.1.5 */
2266 dis_iei_la(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2270 SHORT_DATA_CHECK(length, 2);
2271 oct = tvb_get_guint8(tvb, offset);
2273 proto_tree_add_text(tree,
2279 proto_tree_add_text(tree,
2280 tvb, offset, length - 1,
2281 "Large Animation ");
2284 /* 9.2.3.24.10.1.6 */
2286 dis_iei_sa(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2290 SHORT_DATA_CHECK(length, 2);
2291 oct = tvb_get_guint8(tvb, offset);
2293 proto_tree_add_text(tree,
2299 proto_tree_add_text(tree,
2300 tvb, offset, length - 1,
2301 "Small Animation ");
2305 /* 9.2.3.24.10.1.7 */
2307 dis_iei_lp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2311 SHORT_DATA_CHECK(length, 2);
2312 oct = tvb_get_guint8(tvb, offset);
2314 proto_tree_add_text(tree,
2320 proto_tree_add_text(tree,
2321 tvb, offset, length - 1,
2325 /* 9.2.3.24.10.1.8 */
2327 dis_iei_sp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2331 SHORT_DATA_CHECK(length, 2);
2332 oct = tvb_get_guint8(tvb, offset);
2334 proto_tree_add_text(tree,
2340 proto_tree_add_text(tree,
2341 tvb, offset, length - 1,
2346 /* 9.2.3.24.10.1.9 */
2348 dis_iei_vp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2352 SHORT_DATA_CHECK(length, 4);
2353 oct = tvb_get_guint8(tvb, offset);
2355 proto_tree_add_text(tree,
2361 oct = tvb_get_guint8(tvb, offset);
2362 proto_tree_add_text(tree,
2364 "Horizontal dimension: %d",
2368 oct = tvb_get_guint8(tvb, offset);
2369 proto_tree_add_text(tree,
2371 "Vertical dimension: %d",
2375 proto_tree_add_text(tree,
2376 tvb, offset, length - 3,
2377 "Variable Picture ");
2380 /* 9.2.3.24.10.1.10 */
2382 dis_iei_upi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2386 EXACT_DATA_CHECK(length, 1);
2387 oct = tvb_get_guint8(tvb, offset);
2389 proto_tree_add_text(tree,
2391 "Number of corresponding objects: %d",
2398 * 9.2.3.24 TP-User Data (TP-UD)
2399 * Information Element Identifier octet
2403 /* TS 123 040 V9.3.0 (2010-10) */
2404 static const value_string gsm_sms_tp_ud_ie_id_vals[] = {
2405 { 0x00, "Concatenated short messages, 8-bit reference number (SMS Control)" },
2406 { 0x01, "Special SMS Message Indication (SMS Control)" },
2407 { 0x02, "Reserved" },
2408 { 0x03, "Value not used to avoid misinterpretation as <LF> character" },
2409 { 0x04, "Application port addressing scheme, 8 bit address (SMS Control)" },
2410 { 0x05, "Application port addressing scheme, 16 bit address (SMS Control)" },
2411 { 0x06, "SMSC Control Parameters (SMS Control)" },
2412 { 0x07, "UDH Source Indicator (SMS Control)" },
2413 { 0x08, "Concatenated short message, 16-bit reference number (SMS Control)" },
2414 { 0x09, "Wireless Control Message Protocol (SMS Control)" },
2415 { 0x0A, "Text Formatting (EMS Control)" },
2416 { 0x0B, "Predefined Sound (EMS Content)" },
2417 { 0x0C, "User Defined Sound (iMelody max 128 bytes) (EMS Content)" },
2418 { 0x0D, "Predefined Animation (EMS Content)" },
2419 { 0x0E, "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)" },
2420 { 0x0F, "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)" },
2421 { 0x10, "Large Picture (32*32 = 128 bytes) (EMS Content)" },
2422 { 0x11, "Small Picture (16*16 = 32 bytes) (EMS Content)" },
2423 { 0x12, "Variable Picture (EMS Content)" },
2424 { 0x13, "User prompt indicator (EMS Control)" },
2425 { 0x14, "Extended Object (EMS Content)" },
2426 { 0x15, "Reused Extended Object (EMS Control)" },
2427 { 0x16, "Compression Control (EMS Control)" },
2428 { 0x17, "Object Distribution Indicator (EMS Control)" },
2429 { 0x18, "Standard WVG object (EMS Content)" },
2430 { 0x19, "Character Size WVG object (EMS Content)" },
2431 { 0x1A, "Extended Object Data Request Command (EMS Control)" },
2432 /*1B-1F Reserved for future EMS features (see subclause 3.10) */
2433 { 0x20, "RFC 822 E-Mail Header (SMS Control)" },
2434 { 0x21, "Hyperlink format element (SMS Control)" },s
2435 { 0x22, "Reply Address Element (SMS Control)" },
2436 { 0x23, "Enhanced Voice Mail Information (SMS Control)" },
2437 { 0x24, "National Language Single Shift (SMS Control)" },
2438 { 0x25, "National Language Locking Shift (SMS Control)" },
2439 /*26-6F Reserved for future use */
2440 /*70-7F (U)SIM Toolkit Security Headers (SMS Control) */
2441 /*80-9F SME to SME specific use (SMS Control) */
2442 /*A0-BF Reserved for future use */
2443 /*C0-DF SC specific use (SMS Control) */
2444 /*E0-FF Reserved for future use */
2450 dis_field_ud_iei(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2452 void (*iei_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length);
2455 proto_tree *subtree = NULL;
2456 const gchar *str = NULL;
2464 oct = tvb_get_guint8(tvb, offset);
2468 case 0x00: str = "Concatenated short messages, 8-bit reference number (SMS Control)"; iei_fcn = dis_iei_csm8; break;
2469 case 0x01: str = "Special SMS Message Indication (SMS Control)"; break;
2470 case 0x02: str = "Reserved N/A"; break;
2471 case 0x03: str = "Value not used to avoid misinterpretation as <LF> character N/A"; break;
2472 case 0x04: str = "Application port addressing scheme, 8 bit address (SMS Control)"; iei_fcn = dis_iei_apa_8bit; break;
2473 case 0x05: str = "Application port addressing scheme, 16 bit address (SMS Control)"; iei_fcn = dis_iei_apa_16bit; break;
2474 case 0x06: str = "SMSC Control Parameters (SMS Control)"; iei_fcn = dis_iei_scp; break;
2475 case 0x07: str = "UDH Source Indicator (SMS Control)"; iei_fcn = dis_iei_udh_si; break;
2476 case 0x08: str = "Concatenated short message, 16-bit reference number (SMS Control)"; iei_fcn = dis_iei_csm16; break;
2477 case 0x09: str = "Wireless Control Message Protocol (SMS Control)"; break;
2478 case 0x0A: str = "Text Formatting (EMS Control)"; iei_fcn = dis_iei_tf;break;
2479 case 0x0B: str = "Predefined Sound (EMS Content)"; iei_fcn = dis_iei_ps;break;
2480 case 0x0C: str = "User Defined Sound (iMelody max 128 bytes) (EMS Content)"; iei_fcn = dis_iei_uds;break;
2481 case 0x0D: str = "Predefined Animation (EMS Content)"; iei_fcn = dis_iei_pa;break;
2482 case 0x0E: str = "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)"; iei_fcn = dis_iei_la;break;
2483 case 0x0F: str = "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)"; iei_fcn = dis_iei_sa;break;
2484 case 0x10: str = "Large Picture (32*32 = 128 bytes) (EMS Content)"; iei_fcn = dis_iei_lp;break;
2485 case 0x11: str = "Small Picture (16*16 = 32 bytes) (EMS Content)"; iei_fcn = dis_iei_sp;break;
2486 case 0x12: str = "Variable Picture (EMS Content)"; iei_fcn = dis_iei_vp;break;
2487 case 0x13: str = "User prompt indicator (EMS Control)"; iei_fcn = dis_iei_upi;break;
2488 case 0x14: str = "Extended Object (EMS Content)"; break;
2489 case 0x15: str = "Reused Extended Object (EMS Control)"; break;
2490 case 0x16: str = "Compression Control (EMS Control)"; break;
2491 case 0x17: str = "Object Distribution Indicator (EMS Control)"; break;
2492 case 0x18: str = "Standard WVG object (EMS Content)"; break;
2493 case 0x19: str = "Character Size WVG object (EMS Content)"; break;
2494 case 0x1A: str = "Extended Object Data Request Command (EMS Control)"; break;
2495 case 0x20: str = "RFC 822 E-Mail Header (SMS Control)"; break;
2496 case 0x21: str = "Hyperlink format element (SMS Control)"; break;
2497 case 0x22: str = "Reply Address Element (SMS Control)"; break;
2499 if ((oct >= 0x1b) &&
2502 str = "Reserved for future EMS features (see subclause 3.10) N/A"; break;
2504 else if ((oct >= 0x23) &&
2507 str = "Reserved for future use N/A"; break;
2509 else if ((oct >= 0x70) &&
2512 str = "(U)SIM Toolkit Security Headers (SMS Control)"; break;
2514 else if ((oct >= 0x80) &&
2517 str = "SME to SME specific use (SMS Control)"; break;
2519 else if ((oct >= 0xa0) &&
2522 str = "Reserved for future use N/A"; break;
2524 else if ((oct >= 0xc0) &&
2527 str = "SC specific use (SMS Control)"; break;
2531 str = "Reserved for future use N/A"; break;
2535 iei_len = tvb_get_guint8(tvb, offset + 1);
2538 proto_tree_add_text(tree,
2539 tvb, offset, iei_len + 2,
2543 subtree = proto_item_add_subtree(item, ett_udh_ieis[oct]);
2545 proto_tree_add_text(subtree,
2547 "Information Element Identifier: 0x%02X",
2552 proto_tree_add_text(subtree,
2561 if (iei_fcn == NULL)
2563 proto_tree_add_text(subtree,
2564 tvb, offset, iei_len,
2569 iei_fcn(tvb, subtree, offset, iei_len);
2573 length -= 2 + iei_len;
2579 #define SMS_MAX_MESSAGE_SIZE 160
2580 static char messagebuf[SMS_MAX_MESSAGE_SIZE+1];
2582 dis_field_ud(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 length, gboolean udhi, guint8 udl,
2583 gboolean seven_bit, gboolean eight_bit, gboolean ucs2, gboolean compressed)
2585 static guint8 fill_bits_mask[7] =
2586 { 0x0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f };
2588 proto_item *udh_item;
2589 proto_tree *subtree = NULL;
2590 proto_tree *udh_subtree = NULL;
2591 tvbuff_t *sm_tvb = NULL;
2592 fragment_data *fd_sm = NULL;
2595 guint32 out_len, total_sms_len, len_sms, length_ucs2, i;
2597 proto_item *ucs2_item;
2598 gchar *utf8_text = NULL;
2599 gchar save_byte = 0, save_byte2 = 0;
2601 GError *l_conv_error = NULL;
2603 gboolean reassembled = FALSE;
2604 guint32 reassembled_in = 0;
2605 gboolean is_fragmented = FALSE;
2606 gboolean save_fragmented = FALSE, try_gsm_sms_ud_reassemble = FALSE;
2609 sm_fragment_params *p_frag_params;
2614 proto_tree_add_text(tree, tvb,
2617 subtree = proto_item_add_subtree(item, ett_ud);
2619 oct = tvb_get_guint8(tvb, offset);
2624 /* step over header */
2627 proto_tree_add_text(subtree, tvb,
2629 "User-Data Header");
2631 udh_subtree = proto_item_add_subtree(udh_item, ett_udh);
2633 proto_tree_add_text(udh_subtree,
2635 "User Data Header Length (%u)",
2642 dis_field_ud_iei(tvb, udh_subtree, offset, oct);
2650 /* step over fill bits ? */
2652 fill_bits = 6 - ((oct * 8) % 7);
2655 oct = tvb_get_guint8(tvb, offset);
2657 other_decode_bitfield_value(bigbuf, oct, fill_bits_mask[fill_bits], 8);
2658 proto_tree_add_text(udh_subtree,
2662 /* Note: Could add an expert item here if ((oct & fill_bits_mask[fill_bits]) != 0) */
2668 is_fragmented = TRUE;
2670 if ( is_fragmented && reassemble_sms)
2672 try_gsm_sms_ud_reassemble = TRUE;
2673 save_fragmented = g_pinfo->fragmented;
2674 g_pinfo->fragmented = TRUE;
2675 fd_sm = fragment_add_seq_check (tvb, offset, g_pinfo,
2676 g_sm_id, /* guint32 ID for fragments belonging together */
2677 g_sm_fragment_table, /* list of message fragments */
2678 g_sm_reassembled_table, /* list of reassembled messages */
2679 g_frag-1, /* guint32 fragment sequence number */
2680 length, /* guint32 fragment length */
2681 (g_frag != g_frags)); /* More fragments? */
2685 reassembled_in = fd_sm->reassembled_in;
2688 sm_tvb = process_reassembled_data(tvb, offset, g_pinfo,
2689 "Reassembled Short Message", fd_sm, &sm_frag_items,
2692 if(reassembled && g_pinfo->fd->num == reassembled_in)
2695 col_append_str (g_pinfo->cinfo, COL_INFO,
2696 " (Short Message Reassembled)");
2700 /* Not last packet of reassembled Short Message */
2701 col_append_fstr (g_pinfo->cinfo, COL_INFO,
2702 " (Short Message fragment %u of %u)", g_frag, g_frags);
2705 /* Store udl and length for later decoding of reassembled SMS */
2706 p_frag_params = se_alloc0(sizeof(sm_fragment_params));
2707 p_frag_params->udl = udl;
2708 p_frag_params->length = length;
2709 g_hash_table_insert(g_sm_fragment_params_table,
2710 GUINT_TO_POINTER((guint)((g_sm_id<<16)|(g_frag-1))),
2712 } /* Else: not fragmented */
2713 if (! sm_tvb) /* One single Short Message, or not reassembled */
2714 sm_tvb = tvb_new_subset_remaining (tvb, offset);
2718 proto_tree_add_text(subtree, tvb, offset, length, "Compressed data");
2724 if(!(reassembled && g_pinfo->fd->num == reassembled_in))
2726 /* Show unassembled SMS */
2728 gsm_sms_char_7bit_unpack(fill_bits, length ,
2729 (udl > SMS_MAX_MESSAGE_SIZE ? SMS_MAX_MESSAGE_SIZE : udl),
2730 tvb_get_ptr(tvb , offset , length) , messagebuf);
2731 messagebuf[out_len] = '\0';
2732 proto_tree_add_unicode_string(subtree, hf_gsm_sms_text, tvb, offset,
2734 gsm_sms_chars_to_utf8(messagebuf, out_len));
2738 /* Show reassembled SMS. We show each fragment separately
2739 * so that the text doesn't get truncated when we add it to
2743 for(i = 0 ; i < g_frags; i++)
2745 p_frag_params = (sm_fragment_params*)g_hash_table_lookup(g_sm_fragment_params_table,
2746 GUINT_TO_POINTER((guint)((g_sm_id<<16)|i)));
2748 if (p_frag_params) {
2750 gsm_sms_char_7bit_unpack(fill_bits, p_frag_params->length,
2751 (p_frag_params->udl > SMS_MAX_MESSAGE_SIZE ? SMS_MAX_MESSAGE_SIZE : p_frag_params->udl),
2752 tvb_get_ptr(sm_tvb, total_sms_len, p_frag_params->length), messagebuf);
2754 messagebuf[out_len] = '\0';
2755 proto_tree_add_unicode_string(subtree, hf_gsm_sms_text, sm_tvb,
2756 total_sms_len, p_frag_params->length,
2757 gsm_sms_chars_to_utf8(messagebuf, out_len));
2759 total_sms_len += p_frag_params->length;
2766 /*proto_tree_add_text(subtree, tvb , offset , length, "%s",
2767 tvb_format_text(tvb, offset, length)); */
2768 if (! dissector_try_uint(gsm_sms_dissector_tbl, g_port_src, sm_tvb, g_pinfo, subtree))
2770 if (! dissector_try_uint(gsm_sms_dissector_tbl, g_port_dst,sm_tvb, g_pinfo, subtree))
2773 { /* Only display if needed */
2774 proto_tree_add_text (subtree, sm_tvb, 0, -1,
2775 "Short Message body");
2782 /* XXX, use tvb_get_ephemeral_unicode_string(.., ENC_BIG_ENDIAN); */
2783 if ((cd = g_iconv_open("UTF-8","UCS-2BE")) != (GIConv)-1)
2785 guint8 rep_len = tvb_reported_length(sm_tvb);
2787 if(!(reassembled && g_pinfo->fd->num == reassembled_in))
2789 /* Show unreassembled SMS */
2790 utf8_text = g_convert_with_iconv(tvb_get_ptr(sm_tvb, 0, rep_len), rep_len , cd , NULL , NULL , &l_conv_error);
2792 ucs2_item = proto_tree_add_unicode_string(subtree, hf_gsm_sms_text, tvb,
2793 offset, length, utf8_text);
2795 ucs2_item = proto_tree_add_text(subtree, tvb, offset, length, "Failed to decode UCS2!");
2797 PROTO_ITEM_SET_GENERATED(ucs2_item);
2799 /* Show reassembled SMS. We show each fragment separately
2800 * so that the text doesn't get truncated when we add it to
2803 utf8_text = g_convert_with_iconv(tvb_get_ptr(sm_tvb, 0, rep_len), rep_len , cd , NULL , NULL , &l_conv_error);
2806 len_sms = (int)strlen(utf8_text);
2807 num_labels = len_sms / MAX_SMS_FRAG_LEN;
2808 num_labels += (len_sms % MAX_SMS_FRAG_LEN) ? 1 : 0;
2809 for(i = 0; i < num_labels;i++) {
2810 if(i * MAX_SMS_FRAG_LEN < len_sms) {
2811 /* set '\0' to byte number 134 text_node MAX size*/
2812 save_byte = utf8_text[i * MAX_SMS_FRAG_LEN];
2813 save_byte2 = utf8_text[i * MAX_SMS_FRAG_LEN + 1];
2816 utf8_text[i * MAX_SMS_FRAG_LEN] = '\0';
2817 utf8_text[i * MAX_SMS_FRAG_LEN + 1] = '\0';
2820 length_ucs2 = MAX_SMS_FRAG_LEN;
2822 length_ucs2 = len_sms % MAX_SMS_FRAG_LEN;
2824 ucs2_item = proto_tree_add_unicode_string(subtree, hf_gsm_sms_text, sm_tvb,
2825 i * MAX_SMS_FRAG_LEN, length_ucs2,
2826 &utf8_text[i * MAX_SMS_FRAG_LEN]);
2827 PROTO_ITEM_SET_GENERATED(ucs2_item);
2829 /* return the save byte to utf8 buffer*/
2830 if(i * MAX_SMS_FRAG_LEN < len_sms) {
2831 utf8_text[i * MAX_SMS_FRAG_LEN] = save_byte;
2832 utf8_text[i * MAX_SMS_FRAG_LEN + 1] = save_byte2;
2836 ucs2_item = proto_tree_add_text(subtree, tvb, offset, length, "Failed to decode UCS2!");
2837 PROTO_ITEM_SET_GENERATED(ucs2_item);
2844 ustr = tvb_get_ephemeral_unicode_string(tvb, offset, length, ENC_BIG_ENDIAN);
2845 proto_tree_add_text(subtree, tvb, offset, length, "%s", ustr);
2850 if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */
2851 g_pinfo->fragmented = save_fragmented;
2856 dis_field_pi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
2859 proto_tree *subtree = NULL;
2863 proto_tree_add_text(tree, tvb,
2865 "TP-Parameter-Indicator");
2867 subtree = proto_item_add_subtree(item, ett_pi);
2869 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
2870 proto_tree_add_text(subtree, tvb,
2874 (oct & 0x80) ? "Extended" : "No extension");
2876 other_decode_bitfield_value(bigbuf, oct, 0x78, 8);
2877 proto_tree_add_text(subtree, tvb,
2882 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
2883 proto_tree_add_text(subtree, tvb,
2885 "%s : TP-UDL %spresent",
2887 (oct & 0x04) ? "" : "not ");
2889 other_decode_bitfield_value(bigbuf, oct, 0x02, 8);
2890 proto_tree_add_text(subtree, tvb,
2892 "%s : TP-DCS %spresent",
2894 (oct & 0x02) ? "" : "not ");
2896 other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
2897 proto_tree_add_text(subtree, tvb,
2899 "%s : TP-PID %spresent",
2901 (oct & 0x01) ? "" : "not ");
2909 dis_msg_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2911 guint32 saved_offset;
2918 gboolean compressed;
2921 saved_offset = offset;
2922 length = tvb_length_remaining(tvb, offset);
2924 oct = tvb_get_guint8(tvb, offset);
2927 proto_tree_add_item(tree, hf_gsm_sms_tp_rp, tvb, offset, 1, ENC_BIG_ENDIAN);
2928 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
2929 proto_tree_add_item(tree, hf_gsm_sms_tp_sri, tvb, offset, 1, ENC_BIG_ENDIAN);
2930 proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, ENC_BIG_ENDIAN);
2931 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, ENC_BIG_ENDIAN);
2935 dis_field_addr(tvb, tree, &offset, "TP-Originating-Address");
2937 oct = tvb_get_guint8(tvb, offset);
2939 dis_field_pid(tvb, tree, offset, oct);
2942 oct = tvb_get_guint8(tvb, offset);
2944 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2947 dis_field_scts(tvb, tree, &offset);
2949 oct = tvb_get_guint8(tvb, offset);
2952 DIS_FIELD_UDL(tree, offset);
2958 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2959 seven_bit, eight_bit, ucs2, compressed);
2968 dis_msg_deliver_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2970 guint32 saved_offset;
2975 gboolean seven_bit = FALSE;
2976 gboolean eight_bit = FALSE;
2977 gboolean ucs2 = FALSE;
2978 gboolean compressed = FALSE;
2983 saved_offset = offset;
2984 length = tvb_length_remaining(tvb, offset);
2986 oct = tvb_get_guint8(tvb, offset);
2989 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
2990 proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, ENC_BIG_ENDIAN);
2991 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, ENC_BIG_ENDIAN);
2995 proto_tree_add_text(tree,
2996 tvb, offset, length,
3002 * there does not seem to be a way to determine that this
3003 * deliver report is from an RP-ERROR or RP-ACK other
3004 * than to look at the next octet
3006 * FCS values are 0x80 and higher
3007 * PI uses bit 7 as an extension indicator
3009 * will assume that if bit 7 is set then this octet
3010 * is an FCS otherwise PI
3013 oct = tvb_get_guint8(tvb, offset);
3017 dis_field_fcs(tvb, tree, offset, oct);
3021 pi = tvb_get_guint8(tvb, offset);
3023 dis_field_pi(tvb, tree, offset, pi);
3027 if (length <= (offset - saved_offset))
3029 proto_tree_add_text(tree,
3036 oct = tvb_get_guint8(tvb, offset);
3038 dis_field_pid(tvb, tree, offset, oct);
3043 if (length <= (offset - saved_offset))
3045 proto_tree_add_text(tree,
3052 oct = tvb_get_guint8(tvb, offset);
3054 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3059 if (length <= (offset - saved_offset))
3061 proto_tree_add_text(tree,
3068 oct = tvb_get_guint8(tvb, offset);
3071 DIS_FIELD_UDL(tree, offset);
3078 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3079 seven_bit, eight_bit, ucs2, compressed);
3088 dis_msg_submit(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3090 guint32 saved_offset;
3098 gboolean compressed;
3102 saved_offset = offset;
3103 length = tvb_length_remaining(tvb, offset);
3105 oct = tvb_get_guint8(tvb, offset);
3107 vp_form = ((oct & 0x18) >> 3);
3109 proto_tree_add_item(tree, hf_gsm_sms_tp_rp, tvb, offset, 1, ENC_BIG_ENDIAN);
3110 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
3111 proto_tree_add_item(tree, hf_gsm_sms_tp_srr, tvb, offset, 1, ENC_BIG_ENDIAN);
3112 proto_tree_add_item(tree, hf_gsm_sms_tp_vpf, tvb, offset, 1, ENC_BIG_ENDIAN);
3113 proto_tree_add_item(tree, hf_gsm_sms_tp_rd, tvb, offset, 1, ENC_BIG_ENDIAN);
3114 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, ENC_BIG_ENDIAN);
3118 proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, ENC_BIG_ENDIAN);
3122 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
3124 oct = tvb_get_guint8(tvb, offset);
3126 dis_field_pid(tvb, tree, offset, oct);
3129 oct = tvb_get_guint8(tvb, offset);
3131 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3134 dis_field_vp(tvb, tree, &offset, vp_form);
3136 oct = tvb_get_guint8(tvb, offset);
3139 DIS_FIELD_UDL(tree, offset);
3145 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3146 seven_bit, eight_bit, ucs2, compressed);
3155 dis_msg_submit_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3157 guint32 saved_offset;
3162 gboolean seven_bit = FALSE;
3163 gboolean eight_bit = FALSE;
3164 gboolean ucs2 = FALSE;
3165 gboolean compressed = FALSE;
3170 saved_offset = offset;
3171 length = tvb_length_remaining(tvb, offset);
3173 oct = tvb_get_guint8(tvb, offset);
3176 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
3177 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, ENC_BIG_ENDIAN);
3180 * there does not seem to be a way to determine that this
3181 * deliver report is from an RP-ERROR or RP-ACK other
3182 * than to look at the next octet
3184 * FCS values are 0x80 and higher
3185 * PI uses bit 7 as an extension indicator
3187 * will assume that if bit 7 is set then this octet
3188 * is an FCS otherwise PI
3191 oct = tvb_get_guint8(tvb, offset);
3195 dis_field_fcs(tvb, tree, offset, oct);
3199 pi = tvb_get_guint8(tvb, offset);
3201 dis_field_pi(tvb, tree, offset, pi);
3204 dis_field_scts(tvb, tree, &offset);
3207 if (length <= (offset - saved_offset)) {
3208 proto_tree_add_text(tree,
3214 oct = tvb_get_guint8(tvb, offset);
3216 dis_field_pid(tvb, tree, offset, oct);
3222 if (length <= (offset - saved_offset))
3224 proto_tree_add_text(tree,
3230 oct = tvb_get_guint8(tvb, offset);
3232 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3238 if (length <= (offset - saved_offset))
3240 proto_tree_add_text(tree,
3246 oct = tvb_get_guint8(tvb, offset);
3249 DIS_FIELD_UDL(tree, offset);
3255 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3256 seven_bit, eight_bit, ucs2, compressed);
3265 dis_msg_status_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3267 guint32 saved_offset;
3272 gboolean seven_bit = FALSE;
3273 gboolean eight_bit = FALSE;
3274 gboolean ucs2 = FALSE;
3275 gboolean compressed = FALSE;
3280 saved_offset = offset;
3281 length = tvb_length_remaining(tvb, offset);
3283 oct = tvb_get_guint8(tvb, offset);
3286 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
3287 proto_tree_add_item(tree, hf_gsm_sms_tp_srq, tvb, offset, 1, ENC_BIG_ENDIAN);
3288 proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, ENC_BIG_ENDIAN);
3289 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, ENC_BIG_ENDIAN);
3293 proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, ENC_BIG_ENDIAN);
3297 dis_field_addr(tvb, tree, &offset, "TP-Recipient-Address");
3299 dis_field_scts(tvb, tree, &offset);
3301 dis_field_dt(tvb, tree, &offset);
3303 oct = tvb_get_guint8(tvb, offset);
3305 dis_field_st(tvb, tree, offset, oct);
3308 /* Parameter indicating the presence of any of
3309 * the optional parameters which follow
3310 * 4) Mandatory if any of the optional parameters following TP-PI is present,
3311 * otherwise optional.
3313 if (length <= (offset - saved_offset))
3317 pi = tvb_get_guint8(tvb, offset);
3319 dis_field_pi(tvb, tree, offset, pi);
3323 if (length <= (offset - saved_offset))
3325 proto_tree_add_text(tree,
3332 oct = tvb_get_guint8(tvb, offset);
3334 dis_field_pid(tvb, tree, offset, oct);
3339 if (length <= (offset - saved_offset))
3341 proto_tree_add_text(tree,
3348 oct = tvb_get_guint8(tvb, offset);
3350 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3355 if (length <= (offset - saved_offset))
3357 proto_tree_add_text(tree,
3364 oct = tvb_get_guint8(tvb, offset);
3367 DIS_FIELD_UDL(tree, offset);
3374 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3375 seven_bit, eight_bit, ucs2, compressed);
3384 dis_msg_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3388 const gchar *str = NULL;
3390 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, ENC_BIG_ENDIAN);
3391 proto_tree_add_item(tree, hf_gsm_sms_tp_srr, tvb, offset, 1, ENC_BIG_ENDIAN);
3392 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, ENC_BIG_ENDIAN);
3396 proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, ENC_BIG_ENDIAN);
3399 oct = tvb_get_guint8(tvb, offset);
3401 dis_field_pid(tvb, tree, offset, oct);
3404 oct = tvb_get_guint8(tvb, offset);
3406 DIS_FIELD_CT(tree, offset);
3409 oct = tvb_get_guint8(tvb, offset);
3411 DIS_FIELD_MN(tree, offset);
3415 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
3417 oct = tvb_get_guint8(tvb, offset);
3420 DIS_FIELD_CDL(tree, offset);
3426 proto_tree_add_text(tree,
3433 #define NUM_MSGS (sizeof(msg_type_strings)/sizeof(value_string))
3434 static gint ett_msgs[NUM_MSGS];
3437 static void (*gsm_sms_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = {
3438 dis_msg_deliver, /* SMS-DELIVER */
3439 dis_msg_deliver_report, /* SMS-DELIVER REPORT */
3440 dis_msg_submit, /* SMS-SUBMIT */
3441 dis_msg_submit_report, /* SMS-SUBMIT REPORT */
3442 dis_msg_status_report, /* SMS-STATUS REPORT */
3443 dis_msg_command, /* SMS-COMMAND */
3444 NULL, /* Reserved */
3445 NULL, /* Reserved */
3449 /* GENERIC DISSECTOR FUNCTIONS */
3452 dissect_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3454 void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = NULL;
3455 proto_item *gsm_sms_item;
3456 proto_tree *gsm_sms_tree = NULL;
3461 const gchar *str = NULL;
3462 /*gint ett_msg_idx;*/
3473 col_set_str(pinfo->cinfo, COL_PROTOCOL, gsm_sms_proto_name_short);
3475 /* In the interest of speed, if "tree" is NULL, don't do any work not
3476 * necessary to generate protocol tree items.
3478 if (tree || reassemble_sms)
3484 oct = tvb_get_guint8(tvb, offset);
3490 * convert the 2 bit value to one based on direction
3492 msg_type |= ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x04 : 0x00);
3494 str = match_strval_idx(msg_type, msg_type_strings, &idx);
3497 * create the GSM_SMS protocol tree
3500 proto_tree_add_protocol_format(tree, proto_gsm_sms, tvb, 0, -1,
3503 (str == NULL) ? "Unknown message identifier" : str);
3506 proto_item_add_subtree(gsm_sms_item, ett_gsm_sms);
3508 if ((str == NULL) ||
3509 (msg_type == 0x03) ||
3516 /*ett_msg_idx = ett_msgs[idx];*/ /* XXX: Not actually used */
3517 msg_fcn = gsm_sms_msg_fcn[idx];
3520 if (msg_fcn == NULL)
3522 proto_tree_add_text(gsm_sms_tree,
3524 "Message dissector not implemented");
3528 (*msg_fcn)(tvb, gsm_sms_tree, offset);
3534 /* Register the protocol with Wireshark */
3536 proto_register_gsm_sms(void)
3540 module_t *gsm_sms_module; /* Preferences for GSM SMS UD */
3542 /* Setup list of header fields */
3543 static hf_register_info hf[] =
3545 { &hf_gsm_sms_coding_group_bits2,
3546 { "Coding Group Bits", "gsm_sms.coding_group_bits2",
3547 FT_UINT8, BASE_DEC, VALS(gsm_sms_coding_group_bits_vals), 0xc0,
3550 { &hf_gsm_sms_coding_group_bits4,
3551 { "Coding Group Bits", "gsm_sms.coding_group_bits4",
3552 FT_UINT8, BASE_DEC, VALS(gsm_sms_coding_group_bits_vals), 0xf0,
3557 * Short Message fragment reassembly
3559 { &hf_gsm_sms_ud_fragments,
3560 { "Short Message fragments", "gsm_sms.fragments",
3561 FT_NONE, BASE_NONE, NULL, 0x00,
3562 "GSM Short Message fragments", HFILL }
3564 { &hf_gsm_sms_ud_fragment,
3565 { "Short Message fragment", "gsm_sms.fragment",
3566 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3567 "GSM Short Message fragment", HFILL }
3569 { &hf_gsm_sms_ud_fragment_overlap,
3570 { "Short Message fragment overlap", "gsm_sms.fragment.overlap",
3571 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3572 "GSM Short Message fragment overlaps with other fragment(s)", HFILL }
3574 { &hf_gsm_sms_ud_fragment_overlap_conflicts,
3575 { "Short Message fragment overlapping with conflicting data", "gsm_sms.fragment.overlap.conflicts",
3576 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3577 "GSM Short Message fragment overlaps with conflicting data", HFILL }
3579 { &hf_gsm_sms_ud_fragment_multiple_tails,
3580 { "Short Message has multiple tail fragments", "gsm_sms.fragment.multiple_tails",
3581 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3582 "GSM Short Message fragment has multiple tail fragments", HFILL }
3584 { &hf_gsm_sms_ud_fragment_too_long_fragment,
3585 { "Short Message fragment too long", "gsm_sms.fragment.too_long_fragment",
3586 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3587 "GSM Short Message fragment data goes beyond the packet end", HFILL }
3589 { &hf_gsm_sms_ud_fragment_error,
3590 { "Short Message defragmentation error", "gsm_sms.fragment.error",
3591 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3592 "GSM Short Message defragmentation error due to illegal fragments", HFILL }
3594 { &hf_gsm_sms_ud_fragment_count,
3595 { "Short Message fragment count", "gsm_sms.fragment.count",
3596 FT_UINT32, BASE_DEC, NULL, 0x00,
3599 { &hf_gsm_sms_ud_reassembled_in,
3600 { "Reassembled in", "gsm_sms.reassembled.in",
3601 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3602 "GSM Short Message has been reassembled in this packet.", HFILL }
3604 { &hf_gsm_sms_ud_reassembled_length,
3605 { "Reassembled Short Message length", "gsm_sms.reassembled.length",
3606 FT_UINT32, BASE_DEC, NULL, 0x00,
3607 "The total length of the reassembled payload", HFILL }
3609 { &hf_gsm_sms_ud_multiple_messages_msg_id,
3610 { "Message identifier", "gsm_sms.udh.mm.msg_id",
3611 FT_UINT16, BASE_DEC, NULL, 0x00,
3612 "Identification of the message", HFILL }
3614 { &hf_gsm_sms_ud_multiple_messages_msg_parts,
3615 { "Message parts", "gsm_sms.udh.mm.msg_parts",
3616 FT_UINT8, BASE_DEC, NULL, 0x00,
3617 "Total number of message parts (fragments)", HFILL }
3619 { &hf_gsm_sms_ud_multiple_messages_msg_part,
3620 { "Message part number", "gsm_sms.udh.mm.msg_part",
3621 FT_UINT8, BASE_DEC, NULL, 0x00,
3622 "Message part (fragment) sequence number", HFILL }
3624 /* TPDU parameters */
3625 { &hf_gsm_sms_tp_mti_up,
3626 { "TP-MTI", "gsm_sms.tp-mti",
3627 FT_UINT8, BASE_DEC, VALS(msg_type_strings_ms_to_sc), 0x03,
3628 "TP-Message-Type-Indicator (in the direction MS to SC)", HFILL }
3630 { &hf_gsm_sms_tp_mti_down,
3631 { "TP-MTI", "gsm_sms.tp-mti",
3632 FT_UINT8, BASE_DEC, VALS(msg_type_strings_sc_to_ms), 0x03,
3633 "TP-Message-Type-Indicator (in the direction SC to MS)", HFILL }
3635 { &hf_gsm_sms_tp_oa,
3636 { "TP-OA Digits", "gsm_sms.tp-oa",
3637 FT_STRING, BASE_NONE, NULL, 0x00,
3638 "TP-Originating-Address Digits", HFILL }
3640 { &hf_gsm_sms_tp_da,
3641 { "TP-DA Digits", "gsm_sms.tp-da",
3642 FT_STRING, BASE_NONE, NULL, 0x00,
3643 "TP-Destination-Address Digits", HFILL }
3645 { &hf_gsm_sms_tp_ra,
3646 { "TP-RA Digits", "gsm_sms.tp-ra",
3647 FT_STRING, BASE_NONE, NULL, 0x00,
3648 "TP-Recipient-Address Digits", HFILL }
3650 { &hf_gsm_sms_tp_pid,
3651 { "TP-PID", "gsm_sms.tp-pid",
3652 FT_UINT8, BASE_DEC, NULL, 0x00,
3653 "TP-Protocol-Identifier", HFILL }
3655 { &hf_gsm_sms_tp_dcs,
3656 { "TP-DCS", "gsm_sms.tp-dcs",
3657 FT_UINT8, BASE_DEC, NULL, 0x00,
3658 "TP-Data-Coding-Scheme", HFILL }
3660 { &hf_gsm_sms_tp_mr,
3661 { "TP-MR", "gsm_sms.tp-mr",
3662 FT_UINT8, BASE_DEC, NULL, 0x00,
3663 "TP-Message-Reference", HFILL }
3665 { &hf_gsm_sms_tp_mms,
3666 { "TP-MMS", "gsm_sms.tp-mms",
3667 FT_BOOLEAN, 8, TFS(&mms_bool_strings), 0x04,
3668 "TP-More-Messages-to-Send", HFILL }
3670 { &hf_gsm_sms_tp_sri,
3671 { "TP-SRI", "gsm_sms.tp-sri",
3672 FT_BOOLEAN, 8, TFS(&sri_bool_strings), 0x20,
3673 "TP-Status-Report-Indication", HFILL }
3675 { &hf_gsm_sms_tp_srr,
3676 { "TP-SRR", "gsm_sms.tp-srr",
3677 FT_BOOLEAN, 8, TFS(&srr_bool_strings), 0x20,
3678 "TP-Status-Report-Request", HFILL }
3680 { &hf_gsm_sms_tp_udhi,
3681 { "TP-UDHI", "gsm_sms.tp-udhi",
3682 FT_BOOLEAN, 8, TFS(&udhi_bool_strings), 0x40,
3683 "TP-User-Data-Header-Indicator", HFILL }
3685 { &hf_gsm_sms_tp_rp,
3686 { "TP-RP", "gsm_sms.tp-rp",
3687 FT_BOOLEAN, 8, TFS(&rp_bool_strings), 0x80,
3688 "TP-Reply-Path", HFILL }
3690 { &hf_gsm_sms_tp_vpf,
3691 { "TP-VPF", "gsm_sms.tp-vpf",
3692 FT_UINT8, BASE_DEC, VALS(vp_type_strings), 0x18,
3693 "TP-Validity-Period-Format", HFILL }
3695 { &hf_gsm_sms_tp_rd,
3696 { "TP-RD", "gsm_sms.tp-rd",
3697 FT_BOOLEAN, 8, TFS(&rd_bool_strings), 0x04,
3698 "TP-Reject-Duplicates", HFILL }
3700 { &hf_gsm_sms_tp_srq,
3701 { "TP-SRQ", "gsm_sms.tp-srq",
3702 FT_BOOLEAN, 8, TFS(&srq_bool_strings), 0x20,
3703 "TP-Status-Report-Qualifier", HFILL }
3706 { "SMS text", "gsm_sms.sms_text",
3707 FT_STRING, BASE_NONE, NULL, 0x00,
3708 "The text of the SMS", HFILL }
3710 { &hf_gsm_sms_tp_fail_cause,
3711 { "TP-Failure-Cause (TP-FCS)", "gsm_sms.tp-fcs",
3712 FT_UINT8, BASE_HEX_DEC|BASE_EXT_STRING, &gsm_sms_tp_failure_cause_values_ext, 0x0,
3713 "TP-Validity-Period-Format", HFILL }
3717 /* Setup protocol subtree array */
3718 #define NUM_INDIVIDUAL_PARMS 12
3719 gint *ett[NUM_INDIVIDUAL_PARMS/*+NUM_MSGS*/+NUM_UDH_IEIS+2];
3721 ett[0] = &ett_gsm_sms;
3734 last_offset = NUM_INDIVIDUAL_PARMS;
3737 for (i=0; i < NUM_MSGS; i++, last_offset++)
3740 ett[last_offset] = &ett_msgs[i];
3744 for (i=0; i < NUM_UDH_IEIS; i++, last_offset++)
3746 ett_udh_ieis[i] = -1;
3747 ett[last_offset] = &ett_udh_ieis[i];
3750 ett[last_offset++] = &ett_gsm_sms_ud_fragment;
3751 ett[last_offset] = &ett_gsm_sms_ud_fragments;
3753 /* Register the protocol name and description */
3756 proto_register_protocol(gsm_sms_proto_name, gsm_sms_proto_name_short, "gsm_sms");
3759 proto_register_field_array(proto_gsm_sms, hf, array_length(hf));
3761 proto_register_subtree_array(ett, array_length(ett));
3763 gsm_sms_dissector_tbl = register_dissector_table("gsm_sms.udh.port",
3764 "GSM SMS port IE in UDH", FT_UINT16, BASE_DEC);
3766 gsm_sms_module = prefs_register_protocol (proto_gsm_sms, NULL);
3768 prefs_register_obsolete_preference(gsm_sms_module,
3769 "try_dissect_message_fragment");
3770 prefs_register_bool_preference (gsm_sms_module, "reassemble",
3771 "Reassemble fragmented SMS",
3772 "Whether the dissector should reassemble SMS spanning multiple packets",
3775 /* register_dissector("gsm_sms", dissect_gsm_sms, proto_gsm_sms); */
3777 /* GSM SMS UD dissector initialization routines */
3778 register_init_routine (gsm_sms_defragment_init);
3783 proto_reg_handoff_gsm_sms(void)
3785 dissector_handle_t gsm_sms_handle;
3787 gsm_sms_handle = create_dissector_handle(dissect_gsm_sms, proto_gsm_sms);
3789 dissector_add_uint("gsm_a.sms_tpdu", 0, gsm_sms_handle);
3790 dissector_add_uint("gsm_map.sms_tpdu", 0, gsm_sms_handle);
3791 dissector_add_uint("etsi_cat.sms_tpdu", 0, gsm_sms_handle);