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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #ifdef HAVE_SYS_TYPES_H
47 # include <sys/types.h>
50 #ifdef HAVE_NETINET_IN_H
51 # include <netinet/in.h>
56 #include <epan/packet.h>
57 #include <epan/prefs.h>
58 #include <epan/reassemble.h>
61 #include "packet-gsm_sms.h"
63 #define MAX_SMS_FRAG_LEN 134
65 /* PROTOTYPES/FORWARDS */
67 #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
68 if ((edc_len) > (edc_max_len)) \
70 proto_tree_add_text(tree, tvb, \
71 offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
74 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
75 if ((sdc_len) < (sdc_min_len)) \
77 proto_tree_add_text(tree, tvb, \
78 offset, (sdc_len), "Short Data (?)"); \
82 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
83 if ((edc_len) != (edc_eq_len)) \
85 proto_tree_add_text(tree, tvb, \
86 offset, (edc_len), "Unexpected Data Length"); \
90 #define SMS_SHIFTMASK(m_val, m_bitmask, m_sval); \
92 int _temp_val = m_val; \
93 int _temp_bm = m_bitmask; \
94 while (_temp_bm && !(_temp_bm & 0x01)) \
96 _temp_bm = _temp_bm >> 1; \
97 _temp_val = _temp_val >> 1; \
103 static const char *gsm_sms_proto_name = "GSM SMS TPDU (GSM 03.40)";
104 static const char *gsm_sms_proto_name_short = "GSM SMS";
106 /* Initialize the subtree pointers */
107 static gint ett_gsm_sms = -1;
108 static gint ett_pid = -1;
109 static gint ett_pi = -1;
110 static gint ett_fcs = -1;
111 static gint ett_vp = -1;
112 static gint ett_scts = -1;
113 static gint ett_dt = -1;
114 static gint ett_st = -1;
115 static gint ett_addr = -1;
116 static gint ett_dcs = -1;
117 static gint ett_ud = -1;
118 static gint ett_udh = -1;
120 static gint ett_udh_tfm = -1;
121 static gint ett_udh_tfc = -1;
123 /* Initialize the protocol and registered fields */
124 static int proto_gsm_sms = -1;
126 static gint hf_gsm_sms_coding_group_bits2 = -1;
127 static gint hf_gsm_sms_coding_group_bits4 = -1;
128 static gint hf_gsm_sms_ud_multiple_messages_msg_id = -1;
129 static gint hf_gsm_sms_ud_multiple_messages_msg_parts = -1;
130 static gint hf_gsm_sms_ud_multiple_messages_msg_part = -1;
132 /* TPDU Parameters */
133 static gint hf_gsm_sms_tp_mti_up = -1;
134 static gint hf_gsm_sms_tp_mti_down = -1;
135 static gint hf_gsm_sms_tp_mms = -1;
136 static gint hf_gsm_sms_tp_vpf = -1;
137 static gint hf_gsm_sms_tp_sri = -1;
138 static gint hf_gsm_sms_tp_srr = -1;
139 static gint hf_gsm_sms_tp_mr = -1;
140 static gint hf_gsm_sms_tp_oa = -1;
141 static gint hf_gsm_sms_tp_da = -1;
142 static gint hf_gsm_sms_tp_pid = -1;
143 static gint hf_gsm_sms_tp_dcs = -1;
144 static gint hf_gsm_sms_tp_ra = -1;
145 static gint hf_gsm_sms_tp_rp = -1;
146 static gint hf_gsm_sms_tp_udhi = -1;
147 static gint hf_gsm_sms_tp_rd = -1;
148 static gint hf_gsm_sms_tp_srq = -1;
150 static gint hf_gsm_sms_tp_scts = -1;
151 static gint hf_gsm_sms_tp_vp = -1;
152 static gint hf_gsm_sms_tp_dt = -1;
153 static gint hf_gsm_sms_tp_st = -1;
154 static gint hf_gsm_sms_tp_udl = -1;
155 static gint hf_gsm_sms_tp_mn = -1;
156 static gint hf_gsm_sms_tp_ct = -1;
157 static gint hf_gsm_sms_tp_cdl = -1;
158 static gint hf_gsm_sms_tp_cd = -1;
159 static gint hf_gsm_sms_tp_ud = -1;
162 static gboolean msg_udh_frag = FALSE;
163 static char bigbuf[1024];
164 static packet_info *g_pinfo;
165 static proto_tree *g_tree;
167 /* 3GPP TS 23.038 version 7.0.0 Release 7
168 * The TP-Data-Coding-Scheme field, defined in 3GPP TS 23.040 [4],
169 * indicates the data coding scheme of the TP-UD field, and may indicate a message class.
170 * Any reserved codings shall be assumed to be the GSM 7 bit default alphabet
171 * (the same as codepoint 00000000) by a receiving entity.
172 * The octet is used according to a coding group which is indicated in bits 7..4.
175 /* Coding Group Bits */
176 static const value_string gsm_sms_coding_group_bits_vals[] = {
177 { 0, "General Data Coding indication" }, /* 00xx */
178 { 1, "General Data Coding indication" }, /* 00xx */
179 { 2, "General Data Coding indication" }, /* 00xx */
180 { 3, "General Data Coding indication" }, /* 00xx */
181 { 4, "Message Marked for Automatic Deletion Group" }, /* 01xx */
182 { 5, "Message Marked for Automatic Deletion Group" }, /* 01xx */
183 { 6, "Message Marked for Automatic Deletion Group" }, /* 01xx */
184 { 7, "Message Marked for Automatic Deletion Group" }, /* 01xx */
185 { 8, "Reserved coding groups" }, /* 1000..1011 */
186 { 9, "Reserved coding groups" }, /* 1000..1011 */
187 { 10, "Reserved coding groups" }, /* 1000..1011 */
188 { 11, "Reserved coding groups" }, /* 1000..1011 */
189 { 12, "Message Waiting Indication Group: Discard Message" },/* 1100 */
190 { 13, "Message Waiting Indication Group: Store Message" }, /* 1101 */
191 { 14, "Message Waiting Indication Group: Store Message" }, /* 1110 */
192 { 15, "Data coding/message class" }, /* 1111 */
202 static gboolean g_is_wsp;
204 static dissector_table_t gsm_sms_dissector_tbl;
205 /* Short Message reassembly */
206 static GHashTable *g_sm_fragment_table = NULL;
207 static GHashTable *g_sm_reassembled_table = NULL;
208 static gint ett_gsm_sms_ud_fragment = -1;
209 static gint ett_gsm_sms_ud_fragments = -1;
211 * Short Message fragment handling
213 static int hf_gsm_sms_ud_fragments = -1;
214 static int hf_gsm_sms_ud_fragment = -1;
215 static int hf_gsm_sms_ud_fragment_overlap = -1;
216 static int hf_gsm_sms_ud_fragment_overlap_conflicts = -1;
217 static int hf_gsm_sms_ud_fragment_multiple_tails = -1;
218 static int hf_gsm_sms_ud_fragment_too_long_fragment = -1;
219 static int hf_gsm_sms_ud_fragment_error = -1;
220 static int hf_gsm_sms_ud_reassembled_in = -1;
222 static const fragment_items sm_frag_items = {
223 /* Fragment subtrees */
224 &ett_gsm_sms_ud_fragment,
225 &ett_gsm_sms_ud_fragments,
226 /* Fragment fields */
227 &hf_gsm_sms_ud_fragments,
228 &hf_gsm_sms_ud_fragment,
229 &hf_gsm_sms_ud_fragment_overlap,
230 &hf_gsm_sms_ud_fragment_overlap_conflicts,
231 &hf_gsm_sms_ud_fragment_multiple_tails,
232 &hf_gsm_sms_ud_fragment_too_long_fragment,
233 &hf_gsm_sms_ud_fragment_error,
234 /* Reassembled in field */
235 &hf_gsm_sms_ud_reassembled_in,
237 "Short Message fragments"
242 gsm_sms_defragment_init (void)
244 fragment_table_init (&g_sm_fragment_table);
245 reassembled_table_init(&g_sm_reassembled_table);
249 * this is the GSM 03.40 definition with the bit 2
250 * set to 1 for uplink messages
252 static const value_string msg_type_strings[] = {
253 { 0, "SMS-DELIVER" },
254 { 4, "SMS-DELIVER REPORT" },
256 { 1, "SMS-SUBMIT REPORT" },
257 { 2, "SMS-STATUS REPORT" },
258 { 6, "SMS-COMMAND" },
264 static const value_string msg_type_strings_sc_to_ms[] = {
265 { 0, "SMS-DELIVER" },
266 { 1, "SMS-SUBMIT REPORT" },
267 { 2, "SMS-STATUS REPORT" },
272 static const value_string msg_type_strings_ms_to_sc[] = {
273 { 0, "SMS-DELIVER REPORT" },
275 { 2, "SMS-COMMAND" },
280 static const value_string vp_type_strings[] = {
281 { 0, "TP VP field not present"},
282 { 1, "TP VP field present - relative format"},
283 { 2, "TP-VP field present - enhanced format"},
284 { 3, "TP VP field present - absolute format"},
288 static const true_false_string mms_bool_strings = {
289 "No more messages are waiting for the MS in this SC",
290 "More messages are waiting for the MS in this SC"
293 static const true_false_string sri_bool_strings = {
294 "A status report shall be returned to the SME",
295 "A status report shall not be returned to the SME"
298 static const true_false_string srr_bool_strings = {
299 "A status report is requested",
300 "A status report is not requested"
303 static const true_false_string udhi_bool_strings = {
304 "The beginning of the TP UD field contains a Header in addition to the short message",
305 "The TP UD field contains only the short message"
308 static const true_false_string rp_bool_strings = {
309 "TP Reply Path parameter is set in this SMS SUBMIT/DELIVER",
310 "TP Reply Path parameter is not set in this SMS SUBMIT/DELIVER"
313 static const true_false_string rd_bool_strings = {
314 "Instruct SC to reject duplicates",
315 "Instruct SC to accept duplicates"
318 static const true_false_string srq_bool_strings = {
319 "The SMS STATUS REPORT is the result of an SMS COMMAND e.g. an Enquiry.",
320 "SMS STATUS REPORT is the result of a SMS SUBMIT."
323 #define NUM_UDH_IEIS 256
324 static gint ett_udh_ieis[NUM_UDH_IEIS];
326 #define MAX_ADDR_SIZE 20
328 dis_field_addr(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, const gchar *title)
330 static gchar digit_table[] = {"0123456789*#abc\0"};
332 proto_tree *subtree = NULL;
333 const gchar *str = NULL;
339 char addrbuf[MAX_ADDR_SIZE+1];
343 oct = tvb_get_guint8(tvb, offset);
344 numdigocts = (oct + 1) / 2;
346 length = tvb_length_remaining(tvb, offset);
348 if (length <= numdigocts)
350 proto_tree_add_text(tree,
352 "%s: Short Data (?)",
359 item = proto_tree_add_text(tree, tvb,
360 offset, numdigocts + 2, "%s",
363 subtree = proto_item_add_subtree(item, ett_addr);
365 proto_tree_add_text(subtree,
367 "Length: %d address digits",
371 oct = tvb_get_guint8(tvb, offset);
373 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
374 proto_tree_add_text(subtree, tvb,
378 (oct & 0x80) ? "No extension" : "Extended");
380 switch ((oct & 0x70) >> 4)
382 case 0x00: str = "Unknown"; break;
383 case 0x01: str = "International"; break;
384 case 0x02: str = "National"; break;
385 case 0x03: str = "Network specific"; break;
386 case 0x04: str = "Subscriber"; break;
387 case 0x05: str = "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)"; break;
388 case 0x06: str = "Abbreviated number"; break;
389 case 0x07: str = "Reserved for extension"; break;
390 default: str = "Unknown, reserved (?)"; break;
393 other_decode_bitfield_value(bigbuf, oct, 0x70, 8);
394 proto_tree_add_text(subtree,
396 "%s : Type of number: (%d) %s",
403 case 0x00: str = "Unknown"; break;
404 case 0x01: str = "ISDN/telephone (E.164/E.163)"; break;
405 case 0x03: str = "Data numbering plan (X.121)"; break;
406 case 0x04: str = "Telex numbering plan"; break;
407 case 0x05: str = "Service Centre Specific plan"; break;
408 case 0x06: str = "Service Centre Specific plan"; break;
409 case 0x08: str = "National numbering plan"; break;
410 case 0x09: str = "Private numbering plan"; break;
411 case 0x0a: str = "ERMES numbering plan (ETSI DE/PS 3 01-3)"; break;
412 case 0x0f: str = "Reserved for extension"; break;
413 default: str = "Unknown, reserved (?)"; break;
416 other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
417 proto_tree_add_text(subtree,
419 "%s : Numbering plan: (%d) %s",
427 switch ((oct & 0x70) >> 4)
429 case 0x05: /* "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)" */
430 i = gsm_sms_char_7bit_unpack(0, numdigocts, MAX_ADDR_SIZE, tvb_get_ptr(tvb, offset, numdigocts), addrbuf);
432 gsm_sms_char_ascii_decode(bigbuf, addrbuf, i);
435 for (i = 0; i < numdigocts; i++)
437 oct = tvb_get_guint8(tvb, offset + i);
439 bigbuf[j++] = digit_table[oct & 0x0f];
440 bigbuf[j++] = digit_table[(oct & 0xf0) >> 4];
446 if (g_ascii_strncasecmp(title, "TP-O", 4) == 0) {
447 proto_tree_add_string(subtree, hf_gsm_sms_tp_oa, tvb,
448 offset, numdigocts, bigbuf);
449 } else if (g_ascii_strncasecmp(title, "TP-D", 4) == 0) {
450 proto_tree_add_string(subtree, hf_gsm_sms_tp_da, tvb,
451 offset, numdigocts, bigbuf);
452 } else if (g_ascii_strncasecmp(title, "TP-R", 4) == 0) {
453 proto_tree_add_string(subtree, hf_gsm_sms_tp_ra, tvb,
454 offset, numdigocts, bigbuf);
456 proto_tree_add_text(subtree,
457 tvb, offset, numdigocts,
462 proto_item_append_text(item, " - (%s)", bigbuf);
464 *offset_p = offset + numdigocts;
468 /* use dis_field_addr() */
471 /* use dis_field_addr() */
475 dis_field_pid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
478 proto_tree *subtree = NULL;
481 const gchar *str = NULL;
485 proto_tree_add_item(tree, hf_gsm_sms_tp_pid, tvb,
488 subtree = proto_item_add_subtree(item, ett_pid);
490 form = (oct & 0xc0) >> 6;
495 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
496 proto_tree_add_text(subtree, tvb,
498 "%s : defines formatting for subsequent bits",
501 other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
502 proto_tree_add_text(subtree, tvb,
507 "telematic interworking" :
508 "no telematic interworking, but SME-to-SME protocol");
512 telematic = oct & 0x1f;
516 case 0x00: str = "implicit - device type is specific to this SC, or can be concluded on the basis of the address"; break;
517 case 0x01: str = "telex (or teletex reduced to telex format)"; break;
518 case 0x02: str = "group 3 telefax"; break;
519 case 0x03: str = "group 4 telefax"; break;
520 case 0x04: str = "voice telephone (i.e. conversion to speech)"; break;
521 case 0x05: str = "ERMES (European Radio Messaging System)"; break;
522 case 0x06: str = "National Paging system (known to the SC)"; break;
523 case 0x07: str = "Videotex (T.100 [20] /T.101 [21])"; break;
524 case 0x08: str = "teletex, carrier unspecified"; break;
525 case 0x09: str = "teletex, in PSPDN"; break;
526 case 0x0a: str = "teletex, in CSPDN"; break;
527 case 0x0b: str = "teletex, in analog PSTN"; break;
528 case 0x0c: str = "teletex, in digital ISDN"; break;
529 case 0x0d: str = "UCI (Universal Computer Interface, ETSI DE/PS 3 01-3)"; break;
530 case 0x10: str = "a message handling facility (known to the SC)"; break;
531 case 0x11: str = "any public X.400-based message handling system"; break;
532 case 0x12: str = "Internet Electronic Mail"; break;
533 case 0x1f: str = "A GSM/UMTS mobile station"; break;
535 if ((telematic >= 0x18) &&
538 str = "values specific to each SC";
547 other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
548 proto_tree_add_text(subtree, tvb,
550 "%s : device type: (%d) %s",
557 other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
558 proto_tree_add_text(subtree, tvb,
560 "%s : the SM-AL protocol being used between the SME and the MS (%d)",
567 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
568 proto_tree_add_text(subtree, tvb,
570 "%s : defines formatting for subsequent bits",
575 case 0x00: str = "Short Message Type 0"; break;
576 case 0x01: str = "Replace Short Message Type 1"; break;
577 case 0x02: str = "Replace Short Message Type 2"; break;
578 case 0x03: str = "Replace Short Message Type 3"; break;
579 case 0x04: str = "Replace Short Message Type 4"; break;
580 case 0x05: str = "Replace Short Message Type 5"; break;
581 case 0x06: str = "Replace Short Message Type 6"; break;
582 case 0x07: str = "Replace Short Message Type 7"; break;
583 case 0x1e: str = "Enhanced Message Service (Obsolete)"; break;
584 case 0x1f: str = "Return Call Message"; break;
585 case 0x3c: str = "ANSI-136 R-DATA"; break;
586 case 0x3d: str = "ME Data download"; break;
587 case 0x3e: str = "ME De-personalization Short Message"; break;
588 case 0x3f: str = "(U)SIM Data download"; break;
590 str = "Reserved"; break;
593 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
594 proto_tree_add_text(subtree, tvb,
603 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
604 proto_tree_add_text(subtree, tvb,
609 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
610 proto_tree_add_text(subtree, tvb,
617 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
618 proto_tree_add_text(subtree, tvb,
620 "%s : bits 0-5 for SC specific use",
623 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
624 proto_tree_add_text(subtree, tvb,
634 dis_field_dcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct,
635 gboolean *seven_bit, gboolean *eight_bit, gboolean *ucs2, gboolean *compressed)
638 proto_tree *subtree = NULL;
640 const gchar *str = NULL;
641 gboolean default_5_bits;
642 gboolean default_3_bits;
643 gboolean default_data;
652 proto_tree_add_item(tree, hf_gsm_sms_tp_dcs, tvb,
655 subtree = proto_item_add_subtree(item, ett_dcs);
657 proto_tree_add_item(subtree, hf_gsm_sms_coding_group_bits4, tvb, offset, 1, FALSE);
659 proto_tree_add_item(subtree, hf_gsm_sms_coding_group_bits2, tvb, offset, 1, FALSE);
664 proto_tree_add_text(subtree, tvb,
666 "Special case, GSM 7 bit default alphabet");
672 default_5_bits = FALSE;
673 default_3_bits = FALSE;
674 default_data = FALSE;
675 form = (oct & 0xc0) >> 6;
680 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
681 proto_tree_add_text(subtree, tvb,
683 "%s : General Data Coding indication",
686 default_5_bits = TRUE;
690 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
691 proto_tree_add_text(subtree, tvb,
693 "%s : Message Marked for Automatic Deletion Group",
696 default_5_bits = TRUE;
700 /* use top four bits */
701 other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
702 proto_tree_add_text(subtree, tvb,
704 "%s : Reserved coding groups",
709 switch ((oct & 0x30) >> 4)
711 case 0x00: str = "Message Waiting Indication Group: Discard Message (GSM 7 bit default alphabet)";
712 default_3_bits = TRUE;
715 case 0x01: str = "Message Waiting Indication Group: Store Message (GSM 7 bit default alphabet)";
716 default_3_bits = TRUE;
719 case 0x02: str = "Message Waiting Indication Group: Store Message (uncompressed UCS2 alphabet)";
720 default_3_bits = TRUE;
722 case 0x03: str = "Data coding/message class";
727 /* use top four bits */
728 other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
729 proto_tree_add_text(subtree, tvb,
739 other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
740 proto_tree_add_text(subtree, tvb,
742 "%s : Text is %scompressed",
744 (oct & 0x20) ? "" : "not ");
746 *compressed = (oct & 0x20) >> 5;
748 other_decode_bitfield_value(bigbuf, oct, 0x10, 8);
749 proto_tree_add_text(subtree, tvb,
753 (oct & 0x10) ? "Message class is defined below" :
754 "Reserved, no message class");
756 switch ((oct & 0x0c) >> 2)
758 case 0x00: str = "GSM 7 bit default alphabet";
761 case 0x01: str = "8 bit data";
764 case 0x02: str = "UCS2 (16 bit)";
767 case 0x03: str = "Reserved"; break;
770 other_decode_bitfield_value(bigbuf, oct, 0x0c, 8);
771 proto_tree_add_text(subtree, tvb,
773 "%s : Character set: %s",
779 case 0x00: str = "Class 0"; break;
780 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
781 case 0x02: str = "Class 2 (U)SIM specific message"; break;
782 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
785 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
786 proto_tree_add_text(subtree, tvb,
788 "%s : Message Class: %s%s",
791 (oct & 0x10) ? "" : " (reserved)");
793 else if (default_3_bits)
795 other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
796 proto_tree_add_text(subtree, tvb,
798 "%s : Indication Sense: %s",
800 (oct & 0x08) ? "Set Indication Active" : "Set Indication Inactive");
802 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
803 proto_tree_add_text(subtree, tvb,
810 case 0x00: str = "Voicemail Message Waiting"; break;
811 case 0x01: str = "Fax Message Waiting"; break;
812 case 0x02: str = "Electronic Mail Message Waiting"; break;
813 case 0x03: str = "Other Message Waiting"; break;
816 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
817 proto_tree_add_text(subtree, tvb,
823 else if (default_data)
825 other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
826 proto_tree_add_text(subtree, tvb,
831 *seven_bit = !(*eight_bit = (oct & 0x04) ? TRUE : FALSE);
833 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
834 proto_tree_add_text(subtree, tvb,
836 "%s : Message coding: %s",
838 (*eight_bit) ? "8 bit data" : "GSM 7 bit default alphabet");
842 case 0x00: str = "Class 0"; break;
843 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
844 case 0x02: str = "Class 2 (U)SIM specific message"; break;
845 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
848 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
849 proto_tree_add_text(subtree, tvb,
851 "%s : Message Class: %s",
858 dis_field_scts_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
860 guint8 oct, oct2, oct3;
864 oct = tvb_get_guint8(tvb, offset);
865 oct2 = tvb_get_guint8(tvb, offset+1);
866 oct3 = tvb_get_guint8(tvb, offset+2);
868 proto_tree_add_text(tree,
870 "Year %d%d, Month %d%d, Day %d%d",
880 oct = tvb_get_guint8(tvb, offset);
881 oct2 = tvb_get_guint8(tvb, offset+1);
882 oct3 = tvb_get_guint8(tvb, offset+2);
884 proto_tree_add_text(tree,
886 "Hour %d%d, Minutes %d%d, Seconds %d%d",
896 oct = tvb_get_guint8(tvb, offset);
898 sign = (oct & 0x08)?'-':'+';
899 oct = (oct >> 4) + (oct & 0x07) * 10;
901 proto_tree_add_text(tree,
903 "Timezone: GMT %c %d hours %d minutes",
904 sign, oct / 4, oct % 4 * 15);
909 dis_field_scts(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
912 proto_tree *subtree = NULL;
919 length = tvb_length_remaining(tvb, offset);
923 proto_tree_add_text(tree,
925 "TP-Service-Centre-Time-Stamp: Short Data (?)");
932 proto_tree_add_text(tree, tvb,
934 "TP-Service-Centre-Time-Stamp");
936 subtree = proto_item_add_subtree(item, ett_scts);
938 dis_field_scts_aux(tvb, subtree, *offset_p);
945 dis_field_vp(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, guint8 vp_form)
948 proto_tree *subtree = NULL;
951 guint8 oct, oct2, oct3;
957 if (vp_form == 0x00) return;
968 length = tvb_length_remaining(tvb, offset);
972 proto_tree_add_text(tree,
974 "TP-Validity-Period: Short Data (?)");
981 proto_tree_add_text(tree, tvb,
983 "TP-Validity-Period");
985 subtree = proto_item_add_subtree(item, ett_vp);
987 oct = tvb_get_guint8(tvb, offset);
989 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
990 proto_tree_add_text(subtree, tvb,
994 (oct & 0x80) ? "Extended" : "No extension");
998 proto_tree_add_text(subtree,
1000 "Extension not implemented, ignored");
1006 other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
1007 proto_tree_add_text(subtree, tvb,
1011 (oct & 0x40) ? "Single shot SM" : "Not single shot SM");
1013 other_decode_bitfield_value(bigbuf, oct, 0x38, 8);
1014 proto_tree_add_text(subtree, tvb,
1019 loc_form = oct & 0x7;
1024 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1025 proto_tree_add_text(subtree, tvb,
1027 "%s : No Validity Period specified",
1034 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1035 proto_tree_add_text(subtree, tvb,
1037 "%s : Validity Period Format: relative",
1041 /* go around again */
1046 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1047 proto_tree_add_text(subtree, tvb,
1049 "%s : Validity Period Format: relative",
1053 oct = tvb_get_guint8(tvb, offset);
1055 proto_tree_add_text(subtree, tvb,
1064 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1065 proto_tree_add_text(subtree, tvb,
1067 "%s : Validity Period Format: relative",
1071 oct = tvb_get_guint8(tvb, offset);
1072 oct2 = tvb_get_guint8(tvb, offset+1);
1073 oct3 = tvb_get_guint8(tvb, offset+2);
1075 proto_tree_add_text(subtree,
1077 "Hour %d%d, Minutes %d%d, Seconds %d%d",
1083 (oct3 & 0xf0) >> 4);
1089 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1090 proto_tree_add_text(subtree, tvb,
1092 "%s : Validity Period Format: Reserved",
1101 oct = tvb_get_guint8(tvb, offset);
1105 mins = (oct + 1) * 5;
1111 proto_tree_add_text(subtree, tvb,
1113 "TP-Validity-Period: %d hours %d minutes",
1119 proto_tree_add_text(subtree, tvb,
1121 "TP-Validity-Period: %d minutes",
1125 else if ((oct >= 144) &&
1128 mins = (oct - 143) * 30;
1129 hours = 12 + (mins / 60);
1132 proto_tree_add_text(subtree, tvb,
1134 "TP-Validity-Period: %d hours %d minutes",
1138 else if ((oct >= 168) &&
1141 proto_tree_add_text(subtree, tvb,
1143 "TP-Validity-Period: %d day(s)",
1146 else if (oct >= 197)
1148 proto_tree_add_text(subtree, tvb,
1150 "TP-Validity-Period: %d week(s)",
1158 length = tvb_length_remaining(tvb, offset);
1162 proto_tree_add_text(tree,
1163 tvb, offset, length,
1164 "TP-Validity-Period: Short Data (?)");
1166 *offset_p += length;
1171 proto_tree_add_text(tree, tvb,
1173 "TP-Validity-Period: absolute");
1175 subtree = proto_item_add_subtree(item, ett_vp);
1177 dis_field_scts_aux(tvb, subtree, *offset_p);
1197 dis_field_dt(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
1200 proto_tree *subtree = NULL;
1207 length = tvb_length_remaining(tvb, offset);
1211 proto_tree_add_text(tree,
1212 tvb, offset, length,
1213 "TP-Discharge-Time: Short Data (?)");
1215 *offset_p += length;
1220 proto_tree_add_text(tree, tvb,
1222 "TP-Discharge-Time");
1224 subtree = proto_item_add_subtree(item, ett_dt);
1226 dis_field_scts_aux(tvb, subtree, *offset_p);
1232 /* use dis_field_addr() */
1236 dis_field_st(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1238 static const gchar *sc_complete = "Short message transaction completed";
1239 static const gchar *sc_temporary = "Temporary error, SC still trying to transfer SM";
1240 static const gchar *sc_perm = "Permanent error, SC is not making any more transfer attempts";
1241 static const gchar *sc_tempfin = "Temporary error, SC is not making any more transfer attempts";
1243 proto_tree *subtree = NULL;
1245 const gchar *str = NULL;
1246 const gchar *str2 = NULL;
1250 proto_tree_add_text(tree, tvb,
1254 subtree = proto_item_add_subtree(item, ett_st);
1256 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1257 proto_tree_add_text(subtree, tvb,
1259 "%s : Definition of bits 0-6: %s",
1261 (oct & 0x80) ? "Reserved" : "as follows");
1267 case 0x00: str2 = sc_complete; str = "Short message received by the SME"; break;
1268 case 0x01: str2 = sc_complete; str = "Short message forwarded by the SC to the SME but the SC is unable to confirm delivery"; break;
1269 case 0x02: str2 = sc_complete; str = "Short message replaced by the SC Reserved values"; break;
1271 case 0x20: str2 = sc_temporary; str = "Congestion"; break;
1272 case 0x21: str2 = sc_temporary; str = "SME busy"; break;
1273 case 0x22: str2 = sc_temporary; str = "No response from SME"; break;
1274 case 0x23: str2 = sc_temporary; str = "Service rejected"; break;
1275 case 0x24: str2 = sc_temporary; str = "Quality of service not available"; break;
1276 case 0x25: str2 = sc_temporary; str = "Error in SME"; break;
1278 case 0x40: str2 = sc_perm; str = "Remote procedure error"; break;
1279 case 0x41: str2 = sc_perm; str = "Incompatible destination"; break;
1280 case 0x42: str2 = sc_perm; str = "Connection rejected by SME"; break;
1281 case 0x43: str2 = sc_perm; str = "Not obtainable"; break;
1282 case 0x44: str2 = sc_perm; str = "Quality of service not available"; break;
1283 case 0x45: str2 = sc_perm; str = "No interworking available"; break;
1284 case 0x46: str2 = sc_perm; str = "SM Validity Period Expired"; break;
1285 case 0x47: str2 = sc_perm; str = "SM Deleted by originating SME"; break;
1286 case 0x48: str2 = sc_perm; str = "SM Deleted by SC Administration"; break;
1287 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;
1289 case 0x60: str2 = sc_tempfin; str = "Congestion"; break;
1290 case 0x61: str2 = sc_tempfin; str = "SME busy"; break;
1291 case 0x62: str2 = sc_tempfin; str = "No response from SME"; break;
1292 case 0x63: str2 = sc_tempfin; str = "Service rejected"; break;
1293 case 0x64: str2 = sc_tempfin; str = "Quality of service not available"; break;
1294 case 0x65: str2 = sc_tempfin; str = "Error in SME"; break;
1297 if ((value >= 0x03) &&
1303 else if ((value >= 0x10) &&
1307 str = "Values specific to each SC";
1309 else if ((value >= 0x26) &&
1312 str2 = sc_temporary;
1315 else if ((value >= 0x30) &&
1318 str2 = sc_temporary;
1319 str = "Values specific to each SC";
1321 else if ((value >= 0x4a) &&
1327 else if ((value >= 0x50) &&
1331 str = "Values specific to each SC";
1333 else if ((value >= 0x66) &&
1339 else if ((value >= 0x70) &&
1343 str = "Values specific to each SC";
1348 other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
1349 proto_tree_add_text(subtree, tvb,
1359 #define DIS_FIELD_UDL(m_tree, m_offset) \
1361 proto_tree_add_text(m_tree, tvb, \
1363 "TP-User-Data-Length: (%d) %s", \
1365 oct ? "depends on Data-Coding-Scheme" : "no User-Data");\
1369 #define DIS_FIELD_RP(m_tree, m_bitmask, m_offset) \
1371 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1372 proto_tree_add_text(m_tree, tvb, \
1374 "%s : TP-Reply-Path: parameter is %sset in this SMS-SUBMIT/DELIVER", \
1376 (oct & m_bitmask) ? "" : "not "); \
1380 #define DIS_FIELD_MN(m_tree, m_offset) \
1382 proto_tree_add_text(m_tree, tvb, \
1384 "TP-Message-Number: %d", \
1389 #define DIS_FIELD_CT(m_tree, m_offset) \
1393 case 0: str = "Enquiry relating to previously submitted short message"; break; \
1394 case 1: str = "Cancel Status Report Request relating to previously submitted short message"; break; \
1395 case 2: str = "Delete previously submitted Short Message"; break; \
1396 case 3: str = "Enable Status Report Request relating to previously submitted short message"; break; \
1398 if ((oct >= 0x04) && \
1401 str = "Reserved unspecified"; \
1403 else if (oct >= 0xe0) \
1405 str = "Values specific for each SC"; \
1409 str = "undefined"; \
1413 proto_tree_add_text(m_tree, tvb, \
1415 "TP-Command-Type: (%d), %s", \
1421 #define DIS_FIELD_CDL(m_tree, m_offset) \
1423 proto_tree_add_text(m_tree, tvb, \
1425 "TP-Command-Data-Length: (%d)%s", \
1427 oct ? "" : " no Command-Data");\
1431 /* done in-line in the message functions */
1435 dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1438 proto_tree *subtree = NULL;
1439 const gchar *str = NULL;
1443 proto_tree_add_text(tree, tvb,
1445 "TP-Failure-Cause");
1447 subtree = proto_item_add_subtree(item, ett_fcs);
1451 case 0x80: str = "Telematic interworking not supported"; break;
1452 case 0x81: str = "Short message Type 0 not supported"; break;
1453 case 0x82: str = "Cannot replace short message"; break;
1454 case 0x8F: str = "Unspecified TP-PID error"; break;
1455 case 0x90: str = "Data coding scheme (alphabet) not supported"; break;
1456 case 0x91: str = "Message class not supported"; break;
1457 case 0x9F: str = "Unspecified TP-DCS error"; break;
1458 case 0xA0: str = "Command cannot be actioned"; break;
1459 case 0xA1: str = "Command unsupported"; break;
1460 case 0xAF: str = "Unspecified TP-Command error"; break;
1461 case 0xB0: str = "TPDU not supported"; break;
1462 case 0xC0: str = "SC busy"; break;
1463 case 0xC1: str = "No SC subscription"; break;
1464 case 0xC2: str = "SC system failure"; break;
1465 case 0xC3: str = "Invalid SME address"; break;
1466 case 0xC4: str = "Destination SME barred"; break;
1467 case 0xC5: str = "SM Rejected-Duplicate SM"; break;
1468 case 0xC6: str = "TP-VPF not supported"; break;
1469 case 0xC7: str = "TP-VP not supported"; break;
1470 case 0xD0: str = "(U)SIM SMS storage full"; break;
1471 case 0xD1: str = "No SMS storage capability in (U)SIM"; break;
1472 case 0xD2: str = "Error in MS"; break;
1473 case 0xD3: str = "Memory Capacity Exceeded"; break;
1474 case 0xD4: str = "(U)SIM Application Toolkit Busy"; break;
1475 case 0xD5: str = "(U)SIM data download error"; break;
1476 case 0xFF: str = "Unspecified error cause"; break;
1478 if ((oct >= 0x80) &&
1481 str = "TP-PID errors"; break;
1483 else if ((oct >= 0x90) &&
1486 str = "TP-DCS errors"; break;
1488 else if ((oct >= 0xA0) &&
1491 str = "TP-Command errors"; break;
1493 else if ((oct >= 0xE0) &&
1496 str = "Values specific to an application"; break;
1500 str = "Reserved"; break;
1504 proto_tree_add_text(subtree, tvb,
1510 #define DIS_FIELD_UDHI(m_tree, m_bitmask, m_offset, m_udhi) \
1512 SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, m_udhi); \
1513 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1514 proto_tree_add_text(m_tree, tvb, \
1516 "%s : TP-User-Data-Header-Indicator: %s short message", \
1519 "The beginning of the TP-UD field contains a Header in addition to the" : \
1520 "The TP-UD field contains only the"); \
1528 #define GN_BYTE_MASK ((1 << bits) - 1)
1531 gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length,
1532 const guint8 *input, unsigned char *output)
1534 unsigned char *out_num = output; /* Current pointer to the output buffer */
1535 const guint8 *in_num = input; /* Current pointer to the input buffer */
1536 unsigned char rest = 0x00;
1539 bits = offset ? offset : 7;
1541 while ((unsigned int)(in_num - input) < in_length)
1543 *out_num = ((*in_num & GN_BYTE_MASK) << (7 - bits)) | rest;
1544 rest = *in_num >> bits;
1546 /* If we don't start from 0th bit, we shouldn't go to the
1547 next char. Under *out_num we have now 0 and under Rest -
1548 _first_ part of the char. */
1549 if ((in_num != input) || (bits == 7)) out_num++;
1552 if ((unsigned int)(out_num - output) >= out_length) break;
1554 /* After reading 7 octets we have read 7 full characters but
1555 we have 7 bits as well. This is the next character */
1569 return (int)(out_num - output);
1572 #define GN_CHAR_ALPHABET_SIZE 128
1574 #define GN_CHAR_ESCAPE 0x1b
1576 static gunichar gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
1578 /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
1579 /* Fixed to use unicode */
1580 /* Characters in hex position 10, [12 to 1a] and 24 are not present on
1581 latin1 charset, so we cannot reproduce on the screen, however they are
1582 greek symbol not present even on my Nokia */
1584 '@', 0xa3, '$' , 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
1585 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
1586 0x394, '_', 0x3a6,0x393,0x39b,0x3a9,0x3a0,0x3a8,
1587 0x3a3,0x398,0x39e, 0xa0, 0xc6, 0xe6, 0xdf, 0xc9,
1588 ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
1589 '(', ')', '*', '+', ',', '-', '.', '/',
1590 '0', '1', '2', '3', '4', '5', '6', '7',
1591 '8', '9', ':', ';', '<', '=', '>', '?',
1592 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
1593 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
1594 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
1595 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
1596 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
1597 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
1598 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
1599 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
1603 char_is_escape(unsigned char value)
1605 return (value == GN_CHAR_ESCAPE);
1609 char_def_alphabet_ext_decode(unsigned char value)
1613 case 0x0a: return 0x0c; /* form feed */
1614 case 0x14: return '^';
1615 case 0x28: return '{';
1616 case 0x29: return '}';
1617 case 0x2f: return '\\';
1618 case 0x3c: return '[';
1619 case 0x3d: return '~';
1620 case 0x3e: return ']';
1621 case 0x40: return '|';
1622 case 0x65: return 0x20ac; /* euro */
1623 default: return '?'; /* invalid character */
1628 char_def_alphabet_decode(unsigned char value)
1630 if (value < GN_CHAR_ALPHABET_SIZE)
1632 return gsm_default_alphabet[value];
1641 gsm_sms_char_ascii_decode(unsigned char * dest, const unsigned char* src, int len)
1647 for (i = 0, j = 0; j < len; j++)
1649 if (char_is_escape(src[j])) {
1650 buf = char_def_alphabet_ext_decode(src[++j]);
1651 i += g_unichar_to_utf8(buf,&(dest[i]));
1654 buf = char_def_alphabet_decode(src[j]);
1655 i += g_unichar_to_utf8(buf,&(dest[i]));
1668 dis_iei_csm8(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1672 EXACT_DATA_CHECK(length, 3);
1673 oct = tvb_get_guint8(tvb, offset);
1675 proto_tree_add_uint (tree,
1676 hf_gsm_sms_ud_multiple_messages_msg_id,
1677 tvb, offset, 1, g_sm_id);
1680 oct = tvb_get_guint8(tvb, offset);
1682 proto_tree_add_uint (tree,
1683 hf_gsm_sms_ud_multiple_messages_msg_parts,
1684 tvb , offset , 1, g_frags);
1686 oct = tvb_get_guint8(tvb, offset);
1688 proto_tree_add_uint (tree,
1689 hf_gsm_sms_ud_multiple_messages_msg_part,
1690 tvb, offset, 1, g_frag);
1694 /* TODO 9.2.3.24.2 Special SMS Message Indication */
1698 dis_iei_apa_8bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1700 const gchar *str = NULL;
1704 EXACT_DATA_CHECK(length, 2);
1706 oct = tvb_get_guint8(tvb, offset);
1714 str = "Available for allocation by applications";
1717 proto_tree_add_text(tree,
1719 "Destination port: %d, %s",
1724 oct = tvb_get_guint8(tvb, offset);
1732 str = "Available for allocation by applications";
1735 proto_tree_add_text(tree,
1737 "Originator port: %d, %s",
1744 dis_iei_apa_16bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1746 const gchar *str = NULL;
1750 EXACT_DATA_CHECK(length, 4);
1752 value = tvb_get_ntohs(tvb, offset);
1756 str = "As allocated by IANA (http://www.IANA.com/)";
1758 else if (value < 17000)
1760 str = "Available for allocation by applications";
1767 proto_tree_add_text(tree,
1769 "Destination port: %d, %s",
1774 value = tvb_get_ntohs(tvb, offset);
1778 str = "As allocated by IANA (http://www.IANA.com/)";
1780 else if (value < 17000)
1782 str = "Available for allocation by applications";
1789 proto_tree_add_text(tree,
1791 "Originator port: %d, %s",
1800 dis_iei_scp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1804 EXACT_DATA_CHECK(length, 1);
1806 oct = tvb_get_guint8(tvb, offset);
1810 proto_tree_add_text(tree,
1812 "Status Report for short message transaction completed");
1816 proto_tree_add_text(tree,
1818 "No Status Report for short message transaction completed");
1823 proto_tree_add_text(tree,
1825 "Status Report for permanent error when SC is not making any more transfer attempts");
1829 proto_tree_add_text(tree,
1831 "No Status Report for permanent error when SC is not making any more transfer attempts");
1836 proto_tree_add_text(tree,
1838 "Status Report for temporary error when SC is not making any more transfer attempts");
1842 proto_tree_add_text(tree,
1844 "No Status Report for temporary error when SC is not making any more transfer attempts");
1850 proto_tree_add_text(tree,
1852 "Status Report for temporary error when SC is still trying to transfer SM");
1856 proto_tree_add_text(tree,
1858 "No Status Report for temporary error when SC is still trying to transfer SM");
1864 proto_tree_add_text(tree,
1866 "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");
1870 proto_tree_add_text(tree,
1878 proto_tree_add_text(tree,
1880 "Include original UDH into the Status Report");
1884 proto_tree_add_text(tree,
1886 "Do not include original UDH into the Status Report");
1893 dis_iei_udh_si(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1897 EXACT_DATA_CHECK(length, 1);
1899 oct = tvb_get_guint8(tvb, offset);
1904 proto_tree_add_text(tree,
1906 "The following part of the UDH is created by the original sender (valid in case of Status Report)");
1909 proto_tree_add_text(tree,
1911 "The following part of the UDH is created by the original receiver (valid in case of Status Report)");
1914 proto_tree_add_text(tree,
1916 "The following part of the UDH is created by the SMSC (can occur in any message or report)");
1919 proto_tree_add_text(tree,
1921 "The following part of the UDH is created by %d" , oct);
1927 dis_iei_csm16(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1932 EXACT_DATA_CHECK(length, 4);
1933 oct_ref = tvb_get_ntohs(tvb, offset);
1935 proto_tree_add_uint (tree,
1936 hf_gsm_sms_ud_multiple_messages_msg_id,
1937 tvb, offset, 2, g_sm_id);
1939 oct = tvb_get_guint8(tvb, offset);
1941 proto_tree_add_uint (tree,
1942 hf_gsm_sms_ud_multiple_messages_msg_parts,
1943 tvb , offset , 1, g_frags);
1946 oct = tvb_get_guint8(tvb, offset);
1948 proto_tree_add_uint (tree,
1949 hf_gsm_sms_ud_multiple_messages_msg_part,
1950 tvb, offset, 1, g_frag);
1953 /* 9.2.3.24.10.1.1 */
1955 dis_iei_tf(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1957 const gchar *str = NULL;
1960 proto_item *item_colour;
1961 proto_tree *subtree = NULL;
1962 proto_tree *subtree_colour = NULL;
1965 EXACT_DATA_CHECK(length, 4);
1966 oct = tvb_get_guint8(tvb, offset);
1968 proto_tree_add_text(tree,
1970 "Start position of the text formatting: %d",
1974 oct = tvb_get_guint8(tvb, offset);
1976 proto_tree_add_text(tree,
1978 "Text formatting length: %d",
1982 oct = tvb_get_guint8(tvb, offset);
1985 proto_tree_add_text(tree,
1989 subtree = proto_item_add_subtree(item, ett_udh_tfm);
2002 str = "Language dependent";
2006 proto_tree_add_text(subtree,
2008 "Alignment : %d %s",
2011 switch((oct >> 2) & 0x03)
2027 proto_tree_add_text(subtree,
2029 "Font Size : %d %s",
2030 (oct >> 2) & 0x03 , str);
2036 proto_tree_add_text(subtree,
2038 "Style bold : %d %s",
2045 proto_tree_add_text(subtree,
2047 "Style Italic : %d %s",
2054 proto_tree_add_text(subtree,
2056 "Style Underlined : %d %s",
2063 proto_tree_add_text(subtree,
2065 "Style Strikethrough : %d %s",
2069 oct = tvb_get_guint8(tvb, offset);
2071 proto_tree_add_text(tree,
2075 subtree_colour = proto_item_add_subtree(item_colour, ett_udh_tfc);
2084 str = "Dark Yellow";
2092 str = "Dark Magenta";
2100 str = "Bright Yellow";
2102 str = "Bright Green";
2104 str = "Bright Cyan";
2106 str = "Bright Blue";
2108 str = "Bright Magenta";
2112 proto_tree_add_text(subtree_colour,
2114 "Foreground Colour : %d %s",
2117 switch((oct >> 4) & 0x0f)
2125 str = "Dark Yellow";
2133 str = "Dark Magenta";
2141 str = "Bright Yellow";
2143 str = "Bright Green";
2145 str = "Bright Cyan";
2147 str = "Bright Blue";
2149 str = "Bright Magenta";
2153 proto_tree_add_text(subtree_colour,
2155 "Background Colour : %d %s",
2156 (oct >> 4) & 0x0f , str);
2161 /* 9.2.3.24.10.1.2 */
2163 dis_iei_ps(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2167 EXACT_DATA_CHECK(length, 2);
2168 oct = tvb_get_guint8(tvb, offset);
2170 proto_tree_add_text(tree,
2176 oct = tvb_get_guint8(tvb, offset);
2178 proto_tree_add_text(tree,
2184 /* 9.2.3.24.10.1.3 */
2186 dis_iei_uds(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2190 SHORT_DATA_CHECK(length, 2);
2191 oct = tvb_get_guint8(tvb, offset);
2193 proto_tree_add_text(tree,
2199 oct = tvb_get_guint8(tvb, offset);
2201 proto_tree_add_text(tree,
2202 tvb, offset, length - 1,
2203 "User Defined Sound ");
2207 /* 9.2.3.24.10.1.4 */
2209 dis_iei_pa(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2213 EXACT_DATA_CHECK(length, 2);
2214 oct = tvb_get_guint8(tvb, offset);
2216 proto_tree_add_text(tree,
2222 oct = tvb_get_guint8(tvb, offset);
2224 proto_tree_add_text(tree,
2226 "animation number: %d",
2231 /* 9.2.3.24.10.1.5 */
2233 dis_iei_la(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2237 SHORT_DATA_CHECK(length, 2);
2238 oct = tvb_get_guint8(tvb, offset);
2240 proto_tree_add_text(tree,
2246 oct = tvb_get_guint8(tvb, offset);
2248 proto_tree_add_text(tree,
2249 tvb, offset, length - 1,
2250 "Large Animation ");
2253 /* 9.2.3.24.10.1.6 */
2255 dis_iei_sa(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2259 SHORT_DATA_CHECK(length, 2);
2260 oct = tvb_get_guint8(tvb, offset);
2262 proto_tree_add_text(tree,
2268 oct = tvb_get_guint8(tvb, offset);
2270 proto_tree_add_text(tree,
2271 tvb, offset, length - 1,
2272 "Small Animation ");
2276 /* 9.2.3.24.10.1.7 */
2278 dis_iei_lp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2282 SHORT_DATA_CHECK(length, 2);
2283 oct = tvb_get_guint8(tvb, offset);
2285 proto_tree_add_text(tree,
2291 oct = tvb_get_guint8(tvb, offset);
2293 proto_tree_add_text(tree,
2294 tvb, offset, length - 1,
2298 /* 9.2.3.24.10.1.8 */
2300 dis_iei_sp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2304 SHORT_DATA_CHECK(length, 2);
2305 oct = tvb_get_guint8(tvb, offset);
2307 proto_tree_add_text(tree,
2313 oct = tvb_get_guint8(tvb, offset);
2315 proto_tree_add_text(tree,
2316 tvb, offset, length - 1,
2321 /* 9.2.3.24.10.1.9 */
2323 dis_iei_vp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2327 SHORT_DATA_CHECK(length, 4);
2328 oct = tvb_get_guint8(tvb, offset);
2330 proto_tree_add_text(tree,
2336 oct = tvb_get_guint8(tvb, offset);
2337 proto_tree_add_text(tree,
2339 "Horizontal dimension: %d",
2343 oct = tvb_get_guint8(tvb, offset);
2344 proto_tree_add_text(tree,
2346 "Vertical dimension: %d",
2351 oct = tvb_get_guint8(tvb, offset);
2352 proto_tree_add_text(tree,
2353 tvb, offset, length - 3,
2354 "Variable Picture ");
2357 /* 9.2.3.24.10.1.10 */
2359 dis_iei_upi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2363 EXACT_DATA_CHECK(length, 1);
2364 oct = tvb_get_guint8(tvb, offset);
2366 proto_tree_add_text(tree,
2368 "Number of corresponding objects: %d",
2378 dis_field_ud_iei(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2380 void (*iei_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length);
2383 proto_tree *subtree = NULL;
2384 const gchar *str = NULL;
2392 oct = tvb_get_guint8(tvb, offset);
2396 case 0x00: str = "Concatenated short messages, 8-bit reference number (SMS Control)"; iei_fcn = dis_iei_csm8; break;
2397 case 0x01: str = "Special SMS Message Indication (SMS Control)"; break;
2398 case 0x02: str = "Reserved N/A"; break;
2399 case 0x03: str = "Value not used to avoid misinterpretation as <LF> character N/A"; break;
2400 case 0x04: str = "Application port addressing scheme, 8 bit address (SMS Control)"; iei_fcn = dis_iei_apa_8bit; break;
2401 case 0x05: str = "Application port addressing scheme, 16 bit address (SMS Control)"; iei_fcn = dis_iei_apa_16bit; break;
2402 case 0x06: str = "SMSC Control Parameters (SMS Control)"; iei_fcn = dis_iei_scp; break;
2403 case 0x07: str = "UDH Source Indicator (SMS Control)"; iei_fcn = dis_iei_udh_si; break;
2404 case 0x08: str = "Concatenated short message, 16-bit reference number (SMS Control)"; iei_fcn = dis_iei_csm16; break;
2405 case 0x09: str = "Wireless Control Message Protocol (SMS Control)"; break;
2406 case 0x0A: str = "Text Formatting (EMS Control)"; iei_fcn = dis_iei_tf;
2407 case 0x0B: str = "Predefined Sound (EMS Content)"; iei_fcn = dis_iei_ps;break;
2408 case 0x0C: str = "User Defined Sound (iMelody max 128 bytes) (EMS Content)"; iei_fcn = dis_iei_uds;break;
2409 case 0x0D: str = "Predefined Animation (EMS Content)"; iei_fcn = dis_iei_pa;break;
2410 case 0x0E: str = "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)"; iei_fcn = dis_iei_la;break;
2411 case 0x0F: str = "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)"; iei_fcn = dis_iei_sa;break;
2412 case 0x10: str = "Large Picture (32*32 = 128 bytes) (EMS Content)"; iei_fcn = dis_iei_lp;break;
2413 case 0x11: str = "Small Picture (16*16 = 32 bytes) (EMS Content)"; iei_fcn = dis_iei_sp;break;
2414 case 0x12: str = "Variable Picture (EMS Content)"; iei_fcn = dis_iei_vp;break;
2415 case 0x13: str = "User prompt indicator (EMS Control)"; iei_fcn = dis_iei_upi;break;
2416 case 0x14: str = "Extended Object (EMS Content)"; break;
2417 case 0x15: str = "Reused Extended Object (EMS Control)"; break;
2418 case 0x16: str = "Compression Control (EMS Control)"; break;
2419 case 0x17: str = "Object Distribution Indicator (EMS Control)"; break;
2420 case 0x18: str = "Standard WVG object (EMS Content)"; break;
2421 case 0x19: str = "Character Size WVG object (EMS Content)"; break;
2422 case 0x1A: str = "Extended Object Data Request Command (EMS Control)"; break;
2423 case 0x20: str = "RFC 822 E-Mail Header (SMS Control)"; break;
2424 case 0x21: str = "Hyperlink format element (SMS Control)"; break;
2425 case 0x22: str = "Reply Address Element (SMS Control)"; break;
2427 if ((oct >= 0x1b) &&
2430 str = "Reserved for future EMS features (see subclause 3.10) N/A"; break;
2432 else if ((oct >= 0x23) &&
2435 str = "Reserved for future use N/A"; break;
2437 else if ((oct >= 0x70) &&
2440 str = "(U)SIM Toolkit Security Headers (SMS Control)"; break;
2442 else if ((oct >= 0x80) &&
2445 str = "SME to SME specific use (SMS Control)"; break;
2447 else if ((oct >= 0xa0) &&
2450 str = "Reserved for future use N/A"; break;
2452 else if ((oct >= 0xc0) &&
2455 str = "SC specific use (SMS Control)"; break;
2459 str = "Reserved for future use N/A"; break;
2463 iei_len = tvb_get_guint8(tvb, offset + 1);
2466 proto_tree_add_text(tree,
2467 tvb, offset, iei_len + 2,
2471 subtree = proto_item_add_subtree(item, ett_udh_ieis[oct]);
2473 proto_tree_add_text(subtree,
2475 "Information Element Identifier: %d",
2480 proto_tree_add_text(subtree,
2489 if (iei_fcn == NULL)
2491 proto_tree_add_text(subtree,
2492 tvb, offset, iei_len,
2497 iei_fcn(tvb, subtree, offset, iei_len);
2501 length -= 2 + iei_len;
2507 #define NUM_FILL_BITS_MASKS 6
2508 #define SMS_MAX_MESSAGE_SIZE 160
2509 char messagebuf[SMS_MAX_MESSAGE_SIZE+1];
2511 dis_field_ud(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 length, gboolean udhi, guint8 udl,
2512 gboolean seven_bit, gboolean eight_bit, gboolean ucs2, gboolean compressed)
2514 static guint8 fill_bits_mask[NUM_FILL_BITS_MASKS] =
2515 { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };
2517 proto_item *udh_item;
2518 proto_tree *subtree = NULL;
2519 proto_tree *udh_subtree = NULL;
2520 tvbuff_t *sm_tvb = NULL;
2521 fragment_data *fd_sm = NULL;
2524 guint32 out_len , total_sms_len , len_sms , length_ucs2 , i;
2526 proto_item *ucs2_item;
2527 gchar *utf8_text = NULL;
2528 gchar save_byte = 0 , save_byte2 = 0;
2530 GError *l_conv_error = NULL;
2532 gboolean reassembled = FALSE;
2533 guint32 reassembled_in = 0;
2534 gboolean is_fragmented = FALSE;
2535 gboolean save_fragmented = FALSE, try_gsm_sms_ud_reassemble = FALSE;
2536 guint32 num_labels , save_offset;
2540 proto_tree_add_text(tree, tvb,
2543 save_offset = offset;
2544 subtree = proto_item_add_subtree(item, ett_ud);
2546 oct = tvb_get_guint8(tvb, offset);
2551 /* step over header */
2554 proto_tree_add_text(subtree, tvb,
2556 "User-Data Header");
2558 udh_subtree = proto_item_add_subtree(udh_item, ett_udh);
2560 proto_tree_add_text(udh_subtree,
2562 "User Data Header Length (%u)",
2569 dis_field_ud_iei(tvb, udh_subtree, offset, oct);
2577 /* step over fill bits ? */
2579 fill_bits = 7 - (((oct + 1) * 8) % 7);
2580 if (fill_bits < NUM_FILL_BITS_MASKS)
2582 oct = tvb_get_guint8(tvb, offset);
2584 other_decode_bitfield_value(bigbuf, oct, fill_bits_mask[fill_bits], 8);
2585 proto_tree_add_text(udh_subtree,
2594 is_fragmented = TRUE;
2596 if ( is_fragmented )
2598 try_gsm_sms_ud_reassemble = TRUE;
2599 save_fragmented = g_pinfo->fragmented;
2600 g_pinfo->fragmented = TRUE;
2601 fd_sm = fragment_add_seq_check (tvb, offset, g_pinfo,
2602 g_sm_id, /* guint32 ID for fragments belonging together */
2603 g_sm_fragment_table, /* list of message fragments */
2604 g_sm_reassembled_table, /* list of reassembled messages */
2605 g_frag-1, /* guint32 fragment sequence number */
2606 length, /* guint32 fragment length */
2607 (g_frag != g_frags)); /* More fragments? */
2611 reassembled_in = fd_sm->reassembled_in;
2614 sm_tvb = process_reassembled_data(tvb, offset, g_pinfo,
2615 "Reassembled Short Message", fd_sm, &sm_frag_items,
2620 col_append_str (g_pinfo->cinfo, COL_INFO,
2621 " (Short Message Reassembled)");
2625 /* Not last packet of reassembled Short Message */
2626 if (check_col (g_pinfo->cinfo, COL_INFO))
2627 col_append_fstr (g_pinfo->cinfo, COL_INFO,
2628 " (Short Message fragment %u of %u)", g_frag, g_frags);
2630 } /* Else: not fragmented */
2631 if (! sm_tvb) /* One single Short Message, or not reassembled */
2632 sm_tvb = tvb_new_subset_remaining (tvb, offset);
2636 proto_tree_add_text(subtree, tvb,
2642 if ((reassembled && g_pinfo->fd->num == reassembled_in) || g_frag==0 || ((g_frag != 0 && msg_udh_frag)))
2646 if(msg_udh_frag || g_frag == 0 )
2649 gsm_sms_char_7bit_unpack(fill_bits, length , SMS_MAX_MESSAGE_SIZE,
2650 tvb_get_ptr(tvb , offset , length) , messagebuf);
2651 messagebuf[out_len] = '\0';
2652 gsm_sms_char_ascii_decode(bigbuf, messagebuf, out_len);
2653 proto_tree_add_text(subtree, tvb , offset , length , "%s", bigbuf);
2659 total_sms_len = sm_tvb->length;
2660 for(i = 0 ; i<g_frags; i++)
2662 /* maximum len msg in 7 bit with csm8 header*/
2663 if(total_sms_len > MAX_SMS_FRAG_LEN)
2665 total_sms_len -= MAX_SMS_FRAG_LEN;
2666 len_sms = MAX_SMS_FRAG_LEN;
2669 len_sms = total_sms_len;
2671 gsm_sms_char_7bit_unpack(fill_bits, len_sms , SMS_MAX_MESSAGE_SIZE,
2672 tvb_get_ptr(sm_tvb , i * MAX_SMS_FRAG_LEN , len_sms) , messagebuf);
2674 messagebuf[out_len] = '\0';
2675 gsm_sms_char_ascii_decode(bigbuf, messagebuf, out_len);
2676 proto_tree_add_text(subtree, sm_tvb , i * MAX_SMS_FRAG_LEN , len_sms , "%s", bigbuf);
2682 /*proto_tree_add_text(subtree, tvb , offset , length, "%s",
2683 tvb_format_text(tvb, offset, length)); */
2684 if (! dissector_try_port(gsm_sms_dissector_tbl, g_port_src, sm_tvb, g_pinfo, subtree))
2686 if (! dissector_try_port(gsm_sms_dissector_tbl, g_port_dst,sm_tvb, g_pinfo, subtree))
2689 { /* Only display if needed */
2690 proto_tree_add_text (subtree, sm_tvb, 0, -1,
2691 "Short Message body");
2698 if ((cd = g_iconv_open("UTF-8","UCS-2BE")) != (GIConv)-1)
2700 if(msg_udh_frag || g_frag == 0 )
2702 utf8_text = g_convert_with_iconv(sm_tvb->real_data, sm_tvb->reported_length , cd , NULL , NULL , &l_conv_error);
2704 ucs2_item = proto_tree_add_text(subtree, tvb, offset, length, "%s", utf8_text);
2706 ucs2_item = proto_tree_add_text(subtree, tvb, offset, length, "%s", "Failed on UCS2 contact wireshark developers");
2708 PROTO_ITEM_SET_GENERATED(ucs2_item);
2712 utf8_text = g_convert_with_iconv(sm_tvb->real_data, sm_tvb->reported_length , cd , NULL , NULL , &l_conv_error);
2715 len_sms = (int)strlen(utf8_text);
2716 num_labels = len_sms / MAX_SMS_FRAG_LEN;
2717 num_labels += len_sms % MAX_SMS_FRAG_LEN ? 1 : 0;
2718 for(i = 0; i < num_labels;i++)
2720 if(i * MAX_SMS_FRAG_LEN < len_sms)
2722 /* set '\0' to byte number 134 text_node MAX size*/
2723 save_byte = utf8_text[i * MAX_SMS_FRAG_LEN];
2724 save_byte2 = utf8_text[i * MAX_SMS_FRAG_LEN + 1];
2727 utf8_text[i * MAX_SMS_FRAG_LEN] = '\0';
2728 utf8_text[i * MAX_SMS_FRAG_LEN + 1] = '\0';
2731 length_ucs2 = MAX_SMS_FRAG_LEN;
2734 length_ucs2 = len_sms % MAX_SMS_FRAG_LEN;
2736 ucs2_item = proto_tree_add_text(subtree, sm_tvb , i * MAX_SMS_FRAG_LEN , length_ucs2 , "%s", &utf8_text[i * MAX_SMS_FRAG_LEN]);
2737 /* return the save byte to utf8 buffer*/
2738 if(i * MAX_SMS_FRAG_LEN < len_sms)
2740 utf8_text[i * MAX_SMS_FRAG_LEN] = save_byte;
2741 utf8_text[i * MAX_SMS_FRAG_LEN + 1] = save_byte2;
2745 ucs2_item = proto_tree_add_text(subtree, tvb, offset, length, "%s", "Failed on UCS2 contact wireshark developers");
2754 /* tvb_get_ephemeral_faked_unicode takes the lengt in number of guint16's */
2755 ustr = tvb_get_ephemeral_faked_unicode(tvb, offset, (length>>1), FALSE);
2756 proto_tree_add_text(subtree, tvb, offset, length, "%s", ustr);
2762 if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */
2763 g_pinfo->fragmented = save_fragmented;
2768 dis_field_pi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
2771 proto_tree *subtree = NULL;
2775 proto_tree_add_text(tree, tvb,
2777 "TP-Parameter-Indicator");
2779 subtree = proto_item_add_subtree(item, ett_pi);
2781 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
2782 proto_tree_add_text(subtree, tvb,
2786 (oct & 0x80) ? "Extended" : "No extension");
2788 other_decode_bitfield_value(bigbuf, oct, 0x78, 8);
2789 proto_tree_add_text(subtree, tvb,
2794 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
2795 proto_tree_add_text(subtree, tvb,
2797 "%s : TP-UDL %spresent",
2799 (oct & 0x04) ? "" : "not ");
2801 other_decode_bitfield_value(bigbuf, oct, 0x02, 8);
2802 proto_tree_add_text(subtree, tvb,
2804 "%s : TP-DCS %spresent",
2806 (oct & 0x02) ? "" : "not ");
2808 other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
2809 proto_tree_add_text(subtree, tvb,
2811 "%s : TP-PID %spresent",
2813 (oct & 0x01) ? "" : "not ");
2821 dis_msg_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2823 guint32 saved_offset;
2830 gboolean compressed;
2834 saved_offset = offset;
2835 length = tvb_length_remaining(tvb, offset);
2837 oct = tvb_get_guint8(tvb, offset);
2840 proto_tree_add_item(tree, hf_gsm_sms_tp_rp, tvb, offset, 1, FALSE);
2841 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
2842 proto_tree_add_item(tree, hf_gsm_sms_tp_sri, tvb, offset, 1, FALSE);
2843 proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, FALSE);
2844 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, FALSE);
2848 dis_field_addr(tvb, tree, &offset, "TP-Originating-Address");
2850 oct = tvb_get_guint8(tvb, offset);
2852 dis_field_pid(tvb, tree, offset, oct);
2855 oct = tvb_get_guint8(tvb, offset);
2857 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2860 dis_field_scts(tvb, tree, &offset);
2862 oct = tvb_get_guint8(tvb, offset);
2865 DIS_FIELD_UDL(tree, offset);
2871 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2872 seven_bit, eight_bit, ucs2, compressed);
2881 dis_msg_deliver_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2883 guint32 saved_offset;
2891 gboolean compressed;
2896 saved_offset = offset;
2897 length = tvb_length_remaining(tvb, offset);
2899 oct = tvb_get_guint8(tvb, offset);
2902 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
2903 proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, FALSE);
2904 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, FALSE);
2908 proto_tree_add_text(tree,
2909 tvb, offset, length,
2915 * there does not seem to be a way to determine that this
2916 * deliver report is from an RP-ERROR or RP-ACK other
2917 * than to look at the next octet
2919 * FCS values are 0x80 and higher
2920 * PI uses bit 7 as an extension indicator
2922 * will assume that if bit 7 is set then this octet
2923 * is an FCS otherwise PI
2926 oct = tvb_get_guint8(tvb, offset);
2930 dis_field_fcs(tvb, tree, offset, oct);
2934 pi = tvb_get_guint8(tvb, offset);
2936 dis_field_pi(tvb, tree, offset, pi);
2940 if (length <= (offset - saved_offset))
2942 proto_tree_add_text(tree,
2949 oct = tvb_get_guint8(tvb, offset);
2951 dis_field_pid(tvb, tree, offset, oct);
2956 if (length <= (offset - saved_offset))
2958 proto_tree_add_text(tree,
2965 oct = tvb_get_guint8(tvb, offset);
2967 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2972 if (length <= (offset - saved_offset))
2974 proto_tree_add_text(tree,
2981 oct = tvb_get_guint8(tvb, offset);
2984 DIS_FIELD_UDL(tree, offset);
2991 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2992 seven_bit, eight_bit, ucs2, compressed);
3001 dis_msg_submit(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3003 guint32 saved_offset;
3011 gboolean compressed;
3015 saved_offset = offset;
3016 length = tvb_length_remaining(tvb, offset);
3018 oct = tvb_get_guint8(tvb, offset);
3020 vp_form = ((oct & 0x18) >> 3);
3022 proto_tree_add_item(tree, hf_gsm_sms_tp_rp, tvb, offset, 1, FALSE);
3023 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3024 proto_tree_add_item(tree, hf_gsm_sms_tp_srr, tvb, offset, 1, FALSE);
3025 proto_tree_add_item(tree, hf_gsm_sms_tp_vpf, tvb, offset, 1, FALSE);
3026 proto_tree_add_item(tree, hf_gsm_sms_tp_rd, tvb, offset, 1, FALSE);
3027 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, FALSE);
3030 oct = tvb_get_guint8(tvb, offset);
3032 proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, FALSE);
3036 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
3038 oct = tvb_get_guint8(tvb, offset);
3040 dis_field_pid(tvb, tree, offset, oct);
3043 oct = tvb_get_guint8(tvb, offset);
3045 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3048 dis_field_vp(tvb, tree, &offset, vp_form);
3050 oct = tvb_get_guint8(tvb, offset);
3053 DIS_FIELD_UDL(tree, offset);
3059 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3060 seven_bit, eight_bit, ucs2, compressed);
3069 dis_msg_submit_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3071 guint32 saved_offset;
3079 gboolean compressed;
3084 saved_offset = offset;
3085 length = tvb_length_remaining(tvb, offset);
3087 oct = tvb_get_guint8(tvb, offset);
3090 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3091 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, FALSE);
3094 * there does not seem to be a way to determine that this
3095 * deliver report is from an RP-ERROR or RP-ACK other
3096 * than to look at the next octet
3098 * FCS values are 0x80 and higher
3099 * PI uses bit 7 as an extension indicator
3101 * will assume that if bit 7 is set then this octet
3102 * is an FCS otherwise PI
3105 oct = tvb_get_guint8(tvb, offset);
3109 dis_field_fcs(tvb, tree, offset, oct);
3113 pi = tvb_get_guint8(tvb, offset);
3115 dis_field_pi(tvb, tree, offset, pi);
3118 dis_field_scts(tvb, tree, &offset);
3121 if (length <= (offset - saved_offset)) {
3122 proto_tree_add_text(tree,
3128 oct = tvb_get_guint8(tvb, offset);
3130 dis_field_pid(tvb, tree, offset, oct);
3136 if (length <= (offset - saved_offset))
3138 proto_tree_add_text(tree,
3144 oct = tvb_get_guint8(tvb, offset);
3146 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3152 if (length <= (offset - saved_offset))
3154 proto_tree_add_text(tree,
3160 oct = tvb_get_guint8(tvb, offset);
3163 DIS_FIELD_UDL(tree, offset);
3169 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3170 seven_bit, eight_bit, ucs2, compressed);
3179 dis_msg_status_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3181 guint32 saved_offset;
3189 gboolean compressed;
3194 saved_offset = offset;
3195 length = tvb_length_remaining(tvb, offset);
3197 oct = tvb_get_guint8(tvb, offset);
3200 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3201 proto_tree_add_item(tree, hf_gsm_sms_tp_srq, tvb, offset, 1, FALSE);
3202 proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, FALSE);
3203 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, FALSE);
3206 oct = tvb_get_guint8(tvb, offset);
3208 proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, FALSE);
3212 dis_field_addr(tvb, tree, &offset, "TP-Recipient-Address");
3214 dis_field_scts(tvb, tree, &offset);
3216 dis_field_dt(tvb, tree, &offset);
3218 oct = tvb_get_guint8(tvb, offset);
3220 dis_field_st(tvb, tree, offset, oct);
3223 /* Parameter indicating the presence of any of
3224 * the optional parameters which follow
3225 * 4) Mandatory if any of the optional parameters following TP-PI is present,
3226 * otherwise optional.
3228 if (length <= (offset - saved_offset))
3232 pi = tvb_get_guint8(tvb, offset);
3234 dis_field_pi(tvb, tree, offset, pi);
3238 if (length <= (offset - saved_offset))
3240 proto_tree_add_text(tree,
3247 oct = tvb_get_guint8(tvb, offset);
3249 dis_field_pid(tvb, tree, offset, oct);
3254 if (length <= (offset - saved_offset))
3256 proto_tree_add_text(tree,
3263 oct = tvb_get_guint8(tvb, offset);
3265 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3270 if (length <= (offset - saved_offset))
3272 proto_tree_add_text(tree,
3279 oct = tvb_get_guint8(tvb, offset);
3282 DIS_FIELD_UDL(tree, offset);
3289 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3290 seven_bit, eight_bit, ucs2, compressed);
3299 dis_msg_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3301 guint32 saved_offset;
3305 const gchar *str = NULL;
3310 saved_offset = offset;
3311 length = tvb_length_remaining(tvb, offset);
3313 oct = tvb_get_guint8(tvb, offset);
3316 proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3317 proto_tree_add_item(tree, hf_gsm_sms_tp_srr, tvb, offset, 1, FALSE);
3318 proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, FALSE);
3321 oct = tvb_get_guint8(tvb, offset);
3323 proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, FALSE);
3326 oct = tvb_get_guint8(tvb, offset);
3328 dis_field_pid(tvb, tree, offset, oct);
3331 oct = tvb_get_guint8(tvb, offset);
3333 DIS_FIELD_CT(tree, offset);
3336 oct = tvb_get_guint8(tvb, offset);
3338 DIS_FIELD_MN(tree, offset);
3342 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
3344 oct = tvb_get_guint8(tvb, offset);
3347 DIS_FIELD_CDL(tree, offset);
3353 proto_tree_add_text(tree,
3359 #define NUM_MSGS (sizeof(msg_type_strings)/sizeof(value_string))
3360 static gint ett_msgs[NUM_MSGS];
3361 static void (*gsm_sms_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = {
3362 dis_msg_deliver, /* SMS-DELIVER */
3363 dis_msg_deliver_report, /* SMS-DELIVER REPORT */
3364 dis_msg_submit, /* SMS-SUBMIT */
3365 dis_msg_submit_report, /* SMS-SUBMIT REPORT */
3366 dis_msg_status_report, /* SMS-STATUS REPORT */
3367 dis_msg_command, /* SMS-COMMAND */
3368 NULL, /* Reserved */
3369 NULL, /* Reserved */
3373 /* GENERIC DISSECTOR FUNCTIONS */
3376 dissect_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3378 void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = NULL;
3379 proto_item *gsm_sms_item;
3380 proto_tree *gsm_sms_tree = NULL;
3385 const gchar *str = NULL;
3397 if (check_col(pinfo->cinfo, COL_PROTOCOL))
3399 col_set_str(pinfo->cinfo, COL_PROTOCOL, gsm_sms_proto_name_short);
3402 /* In the interest of speed, if "tree" is NULL, don't do any work not
3403 * necessary to generate protocol tree items.
3411 oct = tvb_get_guint8(tvb, offset);
3417 * convert the 2 bit value to one based on direction
3419 if (pinfo->p2p_dir == P2P_DIR_UNKNOWN)
3421 /* Return Result ... */
3422 if (msg_type == 0) /* SMS-DELIVER */
3424 msg_type |= 0x04; /* see the msg_type_strings */
3429 msg_type |= ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x04 : 0x00);
3432 str = match_strval_idx(msg_type, msg_type_strings, &idx);
3435 * create the GSM_SMS protocol tree
3438 proto_tree_add_protocol_format(tree, proto_gsm_sms, tvb, 0, -1,
3441 (str == NULL) ? "Unknown message identifier" : str);
3444 proto_item_add_subtree(gsm_sms_item, ett_gsm_sms);
3446 if ((str == NULL) ||
3447 (msg_type == 0x03) ||
3454 ett_msg_idx = ett_msgs[idx];
3455 msg_fcn = gsm_sms_msg_fcn[idx];
3458 if (msg_fcn == NULL)
3460 proto_tree_add_text(gsm_sms_tree,
3462 "Message dissector not implemented");
3466 (*msg_fcn)(tvb, gsm_sms_tree, offset);
3472 /* Register the protocol with Wireshark */
3474 proto_register_gsm_sms(void)
3478 module_t *gsm_sms_module; /* Preferences for GSM SMS UD */
3480 /* Setup list of header fields */
3481 static hf_register_info hf[] =
3483 { &hf_gsm_sms_coding_group_bits2,
3484 { "Coding Group Bits", "gsm_sms.coding_group_bits2",
3485 FT_UINT8, BASE_DEC, VALS(gsm_sms_coding_group_bits_vals), 0xc0,
3488 { &hf_gsm_sms_coding_group_bits4,
3489 { "Coding Group Bits", "gsm_sms.coding_group_bits4",
3490 FT_UINT8, BASE_DEC, VALS(gsm_sms_coding_group_bits_vals), 0xf0,
3495 * Short Message fragment reassembly
3497 { &hf_gsm_sms_ud_fragments,
3498 { "Short Message fragments", "gsm-sms-ud.fragments",
3499 FT_NONE, BASE_NONE, NULL, 0x00,
3500 "GSM Short Message fragments",
3504 { &hf_gsm_sms_ud_fragment,
3505 { "Short Message fragment", "gsm-sms-ud.fragment",
3506 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3507 "GSM Short Message fragment",
3511 { &hf_gsm_sms_ud_fragment_overlap,
3512 { "Short Message fragment overlap", "gsm-sms-ud.fragment.overlap",
3513 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3514 "GSM Short Message fragment overlaps with other fragment(s)",
3518 { &hf_gsm_sms_ud_fragment_overlap_conflicts,
3519 { "Short Message fragment overlapping with conflicting data",
3520 "gsm-sms-ud.fragment.overlap.conflicts",
3521 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3522 "GSM Short Message fragment overlaps with conflicting data",
3526 { &hf_gsm_sms_ud_fragment_multiple_tails,
3527 { "Short Message has multiple tail fragments",
3528 "gsm-sms-ud.fragment.multiple_tails",
3529 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3530 "GSM Short Message fragment has multiple tail fragments",
3534 { &hf_gsm_sms_ud_fragment_too_long_fragment,
3535 { "Short Message fragment too long",
3536 "gsm-sms-ud.fragment.too_long_fragment",
3537 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3538 "GSM Short Message fragment data goes beyond the packet end",
3542 { &hf_gsm_sms_ud_fragment_error,
3543 { "Short Message defragmentation error", "gsm-sms-ud.fragment.error",
3544 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3545 "GSM Short Message defragmentation error due to illegal fragments",
3549 { &hf_gsm_sms_ud_reassembled_in,
3551 "gsm-sms-ud.reassembled.in",
3552 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3553 "GSM Short Message has been reassembled in this packet.", HFILL
3556 { &hf_gsm_sms_ud_multiple_messages_msg_id,
3557 { "Message identifier", "gsm-sms.udh.mm.msg_id",
3558 FT_UINT16, BASE_DEC, NULL, 0x00,
3559 "Identification of the message",
3563 { &hf_gsm_sms_ud_multiple_messages_msg_parts,
3564 { "Message parts", "gsm-sms.udh.mm.msg_parts",
3565 FT_UINT8, BASE_DEC, NULL, 0x00,
3566 "Total number of message parts (fragments)",
3570 { &hf_gsm_sms_ud_multiple_messages_msg_part,
3571 { "Message part number", "gsm-sms.udh.mm.msg_part",
3572 FT_UINT8, BASE_DEC, NULL, 0x00,
3573 "Message part (fragment) sequence number",
3577 /* TPDU parameters */
3578 { &hf_gsm_sms_tp_mti_up,
3579 { "TP-MTI", "gsm_sms.tp-mti",
3580 FT_UINT8, BASE_DEC, VALS(msg_type_strings_ms_to_sc), 0x03,
3581 "TP-Message-Type-Indicator (in the direction MS to SC)", HFILL }
3583 { &hf_gsm_sms_tp_mti_down,
3584 { "TP-MTI", "gsm_sms.tp-mti",
3585 FT_UINT8, BASE_DEC, VALS(msg_type_strings_sc_to_ms), 0x03,
3586 "TP-Message-Type-Indicator (in the direction SC to MS)", HFILL }
3588 { &hf_gsm_sms_tp_oa,
3589 { "TP-OA Digits", "gsm_sms.tp-oa",
3590 FT_STRING, BASE_NONE, NULL, 0x00,
3591 "TP-Originating-Address Digits", HFILL }
3593 { &hf_gsm_sms_tp_da,
3594 { "TP-DA Digits", "gsm_sms.tp-da",
3595 FT_STRING, BASE_NONE, NULL, 0x00,
3596 "TP-Destination-Address Digits", HFILL }
3598 { &hf_gsm_sms_tp_ra,
3599 { "TP-RA Digits", "gsm_sms.tp-ra",
3600 FT_STRING, BASE_NONE, NULL, 0x00,
3601 "TP-Recipient-Address Digits", HFILL }
3603 { &hf_gsm_sms_tp_pid,
3604 { "TP-PID", "gsm_sms.tp-pid",
3605 FT_UINT8, BASE_DEC, NULL, 0x00,
3606 "TP-Protocol-Identifier", HFILL }
3608 { &hf_gsm_sms_tp_dcs,
3609 { "TP-DCS", "gsm_sms.tp-dcs",
3610 FT_UINT8, BASE_DEC, NULL, 0x00,
3611 "TP-Data-Coding-Scheme", HFILL }
3613 { &hf_gsm_sms_tp_mr,
3614 { "TP-MR", "gsm_sms.tp-mr",
3615 FT_UINT8, BASE_DEC, NULL, 0x00,
3616 "TP-Message-Reference", HFILL }
3618 { &hf_gsm_sms_tp_mms,
3619 { "TP-MMS", "gsm_sms.tp-mms",
3620 FT_BOOLEAN, 8, TFS(&mms_bool_strings), 0x04,
3621 "TP-More-Messages-to-Send", HFILL }
3623 { &hf_gsm_sms_tp_sri,
3624 { "TP-SRI", "gsm_sms.tp-sri",
3625 FT_BOOLEAN, 8, TFS(&sri_bool_strings), 0x20,
3626 "TP-Status-Report-Indication", HFILL }
3628 { &hf_gsm_sms_tp_srr,
3629 { "TP-SRR", "gsm_sms.tp-srr",
3630 FT_BOOLEAN, 8, TFS(&srr_bool_strings), 0x20,
3631 "TP-Status-Report-Request", HFILL }
3633 { &hf_gsm_sms_tp_udhi,
3634 { "TP-UDHI", "gsm_sms.tp-udhi",
3635 FT_BOOLEAN, 8, TFS(&udhi_bool_strings), 0x40,
3636 "TP-User-Data-Header-Indicator", HFILL }
3638 { &hf_gsm_sms_tp_rp,
3639 { "TP-RP", "gsm_sms.tp-rp",
3640 FT_BOOLEAN, 8, TFS(&rp_bool_strings), 0x80,
3641 "TP-Reply-Path", HFILL }
3643 { &hf_gsm_sms_tp_vpf,
3644 { "TP-VPF", "gsm_sms.tp-vpf",
3645 FT_UINT8, BASE_DEC, VALS(vp_type_strings), 0x18,
3646 "TP-Validity-Period-Format", HFILL }
3648 { &hf_gsm_sms_tp_rd,
3649 { "TP-RD", "gsm_sms.tp-rd",
3650 FT_BOOLEAN, 8, TFS(&rd_bool_strings), 0x04,
3651 "TP-Reject-Duplicates", HFILL }
3653 { &hf_gsm_sms_tp_srq,
3654 { "TP-SRQ", "gsm_sms.tp-srq",
3655 FT_BOOLEAN, 8, TFS(&srq_bool_strings), 0x20,
3656 "TP-Status-Report-Qualifier", HFILL }
3660 /* Setup protocol subtree array */
3661 #define NUM_INDIVIDUAL_PARMS 12
3662 gint *ett[NUM_INDIVIDUAL_PARMS+NUM_MSGS+NUM_UDH_IEIS+2];
3664 ett[0] = &ett_gsm_sms;
3677 last_offset = NUM_INDIVIDUAL_PARMS;
3679 for (i=0; i < NUM_MSGS; i++, last_offset++)
3682 ett[last_offset] = &ett_msgs[i];
3685 for (i=0; i < NUM_UDH_IEIS; i++, last_offset++)
3687 ett_udh_ieis[i] = -1;
3688 ett[last_offset] = &ett_udh_ieis[i];
3691 ett[last_offset++] = &ett_gsm_sms_ud_fragment;
3692 ett[last_offset] = &ett_gsm_sms_ud_fragments;
3694 /* Register the protocol name and description */
3697 proto_register_protocol(gsm_sms_proto_name, gsm_sms_proto_name_short, "gsm_sms");
3700 proto_register_field_array(proto_gsm_sms, hf, array_length(hf));
3702 proto_register_subtree_array(ett, array_length(ett));
3704 gsm_sms_dissector_tbl = register_dissector_table("gsm-sms.udh.port",
3705 "GSM SMS port IE in UDH", FT_UINT16, BASE_DEC);
3707 gsm_sms_module = prefs_register_protocol (proto_gsm_sms, NULL);
3708 prefs_register_bool_preference (gsm_sms_module,
3709 "try_dissect_message_fragment",
3710 "Always try subdissection of the fragment of a fragmented",
3711 "Always try subdissection of 7bit, UCS2 Short Message fragment."
3712 "If checked, every msg decode will shown in its fragment",
3715 /* register_dissector("gsm-sms", dissect_gsm_sms, proto_gsm_sms); */
3717 /* GSM SMS UD dissector initialization routines */
3718 register_init_routine (gsm_sms_defragment_init);
3723 proto_reg_handoff_gsm_sms(void)
3725 dissector_handle_t gsm_sms_handle;
3727 gsm_sms_handle = create_dissector_handle(dissect_gsm_sms, proto_gsm_sms);
3729 dissector_add("gsm_a.sms_tpdu", 0, gsm_sms_handle);
3730 dissector_add("gsm_map.sms_tpdu", 0, gsm_sms_handle);