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)
16 * Wireshark - Network traffic analyzer
17 * By Gerald Combs <gerald@wireshark.org>
18 * Copyright 1998 Gerald Combs
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43 #ifdef HAVE_SYS_TYPES_H
44 # include <sys/types.h>
47 #ifdef HAVE_NETINET_IN_H
48 # include <netinet/in.h>
53 #include "epan/packet.h"
54 #include <epan/prefs.h>
56 #if GLIB_MAJOR_VERSION >= 2
60 #include "packet-gsm_sms.h"
63 /* PROTOTYPES/FORWARDS */
65 #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
66 if ((edc_len) > (edc_max_len)) \
68 proto_tree_add_text(tree, tvb, \
69 offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
72 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
73 if ((sdc_len) < (sdc_min_len)) \
75 proto_tree_add_text(tree, tvb, \
76 offset, (sdc_len), "Short Data (?)"); \
80 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
81 if ((edc_len) != (edc_eq_len)) \
83 proto_tree_add_text(tree, tvb, \
84 offset, (edc_len), "Unexpected Data Length"); \
88 #define SMS_SHIFTMASK(m_val, m_bitmask, m_sval); \
90 int _temp_val = m_val; \
91 int _temp_bm = m_bitmask; \
92 while (_temp_bm && !(_temp_bm & 0x01)) \
94 _temp_bm = _temp_bm >> 1; \
95 _temp_val = _temp_val >> 1; \
101 static const char *gsm_sms_proto_name = "GSM SMS TPDU (GSM 03.40)";
102 static const char *gsm_sms_proto_name_short = "GSM SMS";
104 /* Initialize the subtree pointers */
105 static gint ett_gsm_sms = -1;
106 static gint ett_pid = -1;
107 static gint ett_pi = -1;
108 static gint ett_fcs = -1;
109 static gint ett_vp = -1;
110 static gint ett_scts = -1;
111 static gint ett_dt = -1;
112 static gint ett_st = -1;
113 static gint ett_addr = -1;
114 static gint ett_dcs = -1;
115 static gint ett_ud = -1;
116 static gint ett_udh = -1;
118 /* Initialize the protocol and registered fields */
119 static int proto_gsm_sms = -1;
121 static char bigbuf[1024];
122 static dissector_handle_t data_handle;
123 static packet_info *g_pinfo;
124 static proto_tree *g_tree;
127 * this is the GSM 03.40 definition with the bit 2
128 * set to 1 for uplink messages
130 static const value_string msg_type_strings[] = {
131 { 0, "SMS-DELIVER" },
132 { 4, "SMS-DELIVER REPORT" },
134 { 1, "SMS-SUBMIT REPORT" },
135 { 2, "SMS-STATUS REPORT" },
136 { 6, "SMS-COMMAND" },
142 #define NUM_UDH_IEIS 256
143 static gint ett_udh_ieis[NUM_UDH_IEIS];
148 #define DIS_FIELD_MTI(m_tree, m_bitmask, m_offset) \
150 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
151 proto_tree_add_text(m_tree, tvb, \
153 "%s : TP-Message-Type-Indicator", \
158 #define DIS_FIELD_MMS(m_tree, m_bitmask, m_offset) \
160 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
161 proto_tree_add_text(m_tree, tvb, \
163 "%s : TP-More-Messages-to-Send: %s messages are waiting for the MS in this SC", \
165 (oct & m_bitmask) ? "No more" : "More"); \
169 #define DIS_FIELD_VPF(m_tree, m_bitmask, m_offset, m_form) \
171 SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, *m_form); \
174 case 0: str = "TP-VP field not present"; break; \
175 case 1: str = "TP-VP field present - enhanced format"; break; \
176 case 2: str = "TP-VP field present - relative format"; break; \
177 case 3: str = "TP-VP field present - absolute format"; break; \
179 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
180 proto_tree_add_text(m_tree, tvb, \
182 "%s : TP-Validity-Period-Format: %s", \
188 #define DIS_FIELD_SRI(m_tree, m_bitmask, m_offset) \
190 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
191 proto_tree_add_text(m_tree, tvb, \
193 "%s : TP-Status-Report-Indication: A status report shall %sbe returned to the SME", \
195 (oct & m_bitmask) ? "" : "not "); \
199 #define DIS_FIELD_SRR(m_tree, m_bitmask, m_offset) \
201 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
202 proto_tree_add_text(m_tree, tvb, \
204 "%s : TP-Status-Report-Request: A status report is %srequested", \
206 (oct & m_bitmask) ? "" : "not "); \
210 #define DIS_FIELD_MR(m_tree, m_offset) \
212 proto_tree_add_text(m_tree, tvb, \
214 "TP-Message-Reference %d", \
219 dis_field_addr(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, const gchar *title)
221 static gchar digit_table[] = {"0123456789*#abc\0"};
223 proto_tree *subtree = NULL;
224 const gchar *str = NULL;
234 oct = tvb_get_guint8(tvb, offset);
235 numdigocts = (oct + 1) / 2;
237 length = tvb_length_remaining(tvb, offset);
239 if (length <= numdigocts)
241 proto_tree_add_text(tree,
243 "%s: Short Data (?)",
251 proto_tree_add_text(tree, tvb,
252 offset, numdigocts + 2,
255 subtree = proto_item_add_subtree(item, ett_addr);
257 proto_tree_add_text(subtree,
259 "Length: %d address digits",
263 oct = tvb_get_guint8(tvb, offset);
265 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
266 proto_tree_add_text(subtree, tvb,
270 (oct & 0x80) ? "No extension" : "Extended");
272 switch ((oct & 0x70) >> 4)
274 case 0x00: str = "Unknown"; break;
275 case 0x01: str = "International"; break;
276 case 0x02: str = "National"; break;
277 case 0x03: str = "Network specific"; break;
278 case 0x04: str = "Subscriber"; break;
279 case 0x05: str = "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)"; break;
280 case 0x06: str = "Abbreviated number"; break;
281 case 0x07: str = "Reserved for extension"; break;
282 default: str = "Unknown, reserved (?)"; break;
285 other_decode_bitfield_value(bigbuf, oct, 0x70, 8);
286 proto_tree_add_text(subtree,
288 "%s : Type of number: (%d) %s",
295 case 0x00: str = "Unknown"; break;
296 case 0x01: str = "ISDN/telephone (E.164/E.163)"; break;
297 case 0x03: str = "Data numbering plan (X.121)"; break;
298 case 0x04: str = "Telex numbering plan"; break;
299 case 0x05: str = "Service Centre Specific plan"; break;
300 case 0x06: str = "Service Centre Specific plan"; break;
301 case 0x08: str = "National numbering plan"; break;
302 case 0x09: str = "Private numbering plan"; break;
303 case 0x0a: str = "ERMES numbering plan (ETSI DE/PS 3 01-3)"; break;
304 case 0x0f: str = "Reserved for extension"; break;
305 default: str = "Unknown, reserved (?)"; break;
308 other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
309 proto_tree_add_text(subtree,
311 "%s : Numbering plan: (%d) %s",
319 switch ((oct & 0x70) >> 4)
321 case 0x05: /* "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)" */
322 i = gsm_sms_char_7bit_unpack(0, numdigocts, sizeof(addrbuf), tvb_get_ptr(tvb, offset, numdigocts), addrbuf);
324 gsm_sms_char_ascii_decode(bigbuf, addrbuf, i);
327 for (i = 0; i < numdigocts; i++)
329 oct = tvb_get_guint8(tvb, offset + i);
331 bigbuf[j++] = digit_table[oct & 0x0f];
332 bigbuf[j++] = digit_table[(oct & 0xf0) >> 4];
338 proto_tree_add_text(subtree,
339 tvb, offset, numdigocts,
343 proto_item_append_text(item, " - (%s)", bigbuf);
345 *offset_p = offset + numdigocts;
349 /* use dis_field_addr() */
352 /* use dis_field_addr() */
356 dis_field_pid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
359 proto_tree *subtree = NULL;
362 const gchar *str = NULL;
366 proto_tree_add_text(tree, tvb,
368 "TP-Protocol-Identifier");
370 subtree = proto_item_add_subtree(item, ett_pid);
372 form = (oct & 0xc0) >> 6;
377 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
378 proto_tree_add_text(subtree, tvb,
380 "%s : defines formatting for subsequent bits",
383 other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
384 proto_tree_add_text(subtree, tvb,
389 "telematic interworking" :
390 "no telematic interworking, but SME-to-SME protocol");
394 telematic = oct & 0x1f;
398 case 0x00: str = "implicit - device type is specific to this SC, or can be concluded on the basis of the address"; break;
399 case 0x01: str = "telex (or teletex reduced to telex format)"; break;
400 case 0x02: str = "group 3 telefax"; break;
401 case 0x03: str = "group 4 telefax"; break;
402 case 0x04: str = "voice telephone (i.e. conversion to speech)"; break;
403 case 0x05: str = "ERMES (European Radio Messaging System)"; break;
404 case 0x06: str = "National Paging system (known to the SC)"; break;
405 case 0x07: str = "Videotex (T.100 [20] /T.101 [21])"; break;
406 case 0x08: str = "teletex, carrier unspecified"; break;
407 case 0x09: str = "teletex, in PSPDN"; break;
408 case 0x0a: str = "teletex, in CSPDN"; break;
409 case 0x0b: str = "teletex, in analog PSTN"; break;
410 case 0x0c: str = "teletex, in digital ISDN"; break;
411 case 0x0d: str = "UCI (Universal Computer Interface, ETSI DE/PS 3 01-3)"; break;
412 case 0x10: str = "a message handling facility (known to the SC)"; break;
413 case 0x11: str = "any public X.400-based message handling system"; break;
414 case 0x12: str = "Internet Electronic Mail"; break;
415 case 0x1f: str = "A GSM/UMTS mobile station"; break;
417 if ((telematic >= 0x18) &&
420 str = "values specific to each SC";
429 other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
430 proto_tree_add_text(subtree, tvb,
432 "%s : device type: (%d) %s",
439 other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
440 proto_tree_add_text(subtree, tvb,
442 "%s : the SM-AL protocol being used between the SME and the MS (%d)",
449 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
450 proto_tree_add_text(subtree, tvb,
452 "%s : defines formatting for subsequent bits",
457 case 0x00: str = "Short Message Type 0"; break;
458 case 0x01: str = "Replace Short Message Type 1"; break;
459 case 0x02: str = "Replace Short Message Type 2"; break;
460 case 0x03: str = "Replace Short Message Type 3"; break;
461 case 0x04: str = "Replace Short Message Type 4"; break;
462 case 0x05: str = "Replace Short Message Type 5"; break;
463 case 0x06: str = "Replace Short Message Type 6"; break;
464 case 0x07: str = "Replace Short Message Type 7"; break;
465 case 0x1e: str = "Enhanced Message Service (Obsolete)"; break;
466 case 0x1f: str = "Return Call Message"; break;
467 case 0x3c: str = "ANSI-136 R-DATA"; break;
468 case 0x3d: str = "ME Data download"; break;
469 case 0x3e: str = "ME De-personalization Short Message"; break;
470 case 0x3f: str = "(U)SIM Data download"; break;
472 str = "Reserved"; break;
475 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
476 proto_tree_add_text(subtree, tvb,
485 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
486 proto_tree_add_text(subtree, tvb,
491 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
492 proto_tree_add_text(subtree, tvb,
499 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
500 proto_tree_add_text(subtree, tvb,
502 "%s : bits 0-5 for SC specific use",
505 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
506 proto_tree_add_text(subtree, tvb,
516 dis_field_dcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct,
517 gboolean *seven_bit, gboolean *eight_bit, gboolean *ucs2, gboolean *compressed)
520 proto_tree *subtree = NULL;
522 const gchar *str = NULL;
523 gboolean default_5_bits;
524 gboolean default_3_bits;
525 gboolean default_data;
534 proto_tree_add_text(tree, tvb,
536 "TP-Data-Coding-Scheme (%d)",
539 subtree = proto_item_add_subtree(item, ett_dcs);
543 proto_tree_add_text(subtree, tvb,
545 "Special case, GSM 7 bit default alphabet");
551 default_5_bits = FALSE;
552 default_3_bits = FALSE;
553 default_data = FALSE;
554 form = (oct & 0xc0) >> 6;
559 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
560 proto_tree_add_text(subtree, tvb,
562 "%s : General Data Coding indication",
565 default_5_bits = TRUE;
569 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
570 proto_tree_add_text(subtree, tvb,
572 "%s : Message Marked for Automatic Deletion Group",
575 default_5_bits = TRUE;
579 /* use top four bits */
580 other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
581 proto_tree_add_text(subtree, tvb,
583 "%s : Reserved coding groups",
588 switch ((oct & 0x30) >> 4)
590 case 0x00: str = "Message Waiting Indication Group: Discard Message (GSM 7 bit default alphabet)";
591 default_3_bits = TRUE;
594 case 0x01: str = "Message Waiting Indication Group: Store Message (GSM 7 bit default alphabet)";
595 default_3_bits = TRUE;
598 case 0x02: str = "Message Waiting Indication Group: Store Message (uncompressed UCS2 alphabet)";
599 default_3_bits = TRUE;
601 case 0x03: str = "Data coding/message class";
606 /* use top four bits */
607 other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
608 proto_tree_add_text(subtree, tvb,
618 other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
619 proto_tree_add_text(subtree, tvb,
621 "%s : Text is %scompressed",
623 (oct & 0x20) ? "" : "not ");
625 *compressed = (oct & 0x20) >> 5;
627 other_decode_bitfield_value(bigbuf, oct, 0x10, 8);
628 proto_tree_add_text(subtree, tvb,
632 (oct & 0x10) ? "Message class is defined below" :
633 "Reserved, no message class");
635 switch ((oct & 0x0c) >> 2)
637 case 0x00: str = "GSM 7 bit default alphabet";
640 case 0x01: str = "8 bit data"; break;
641 case 0x02: str = "UCS2 (16 bit)";
644 case 0x03: str = "Reserved"; break;
647 other_decode_bitfield_value(bigbuf, oct, 0x0c, 8);
648 proto_tree_add_text(subtree, tvb,
650 "%s : Character set: %s",
656 case 0x00: str = "Class 0"; break;
657 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
658 case 0x02: str = "Class 2 (U)SIM specific message"; break;
659 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
662 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
663 proto_tree_add_text(subtree, tvb,
665 "%s : Message Class: %s%s",
668 (oct & 0x10) ? "" : " (reserved)");
670 else if (default_3_bits)
672 other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
673 proto_tree_add_text(subtree, tvb,
675 "%s : Indication Sense: %s",
677 (oct & 0x08) ? "Set Indication Active" : "Set Indication Inactive");
679 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
680 proto_tree_add_text(subtree, tvb,
687 case 0x00: str = "Voicemail Message Waiting"; break;
688 case 0x01: str = "Fax Message Waiting"; break;
689 case 0x02: str = "Electronic Mail Message Waiting"; break;
690 case 0x03: str = "Other Message Waiting"; break;
693 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
694 proto_tree_add_text(subtree, tvb,
700 else if (default_data)
702 other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
703 proto_tree_add_text(subtree, tvb,
708 *seven_bit = !(*eight_bit = (oct & 0x04) ? TRUE : FALSE);
710 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
711 proto_tree_add_text(subtree, tvb,
713 "%s : Message coding: %s",
715 (*eight_bit) ? "8 bit data" : "GSM 7 bit default alphabet");
719 case 0x00: str = "Class 0"; break;
720 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
721 case 0x02: str = "Class 2 (U)SIM specific message"; break;
722 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
725 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
726 proto_tree_add_text(subtree, tvb,
728 "%s : Message Class: %s",
735 dis_field_scts_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
737 guint8 oct, oct2, oct3;
741 oct = tvb_get_guint8(tvb, offset);
742 oct2 = tvb_get_guint8(tvb, offset+1);
743 oct3 = tvb_get_guint8(tvb, offset+2);
745 proto_tree_add_text(tree,
747 "Year %d%d, Month %d%d, Day %d%d",
757 oct = tvb_get_guint8(tvb, offset);
758 oct2 = tvb_get_guint8(tvb, offset+1);
759 oct3 = tvb_get_guint8(tvb, offset+2);
761 proto_tree_add_text(tree,
763 "Hour %d%d, Minutes %d%d, Seconds %d%d",
773 oct = tvb_get_guint8(tvb, offset);
775 sign = (oct & 0x08)?'-':'+';
776 oct = (oct >> 4) + (oct & 0x07) * 10;
778 proto_tree_add_text(tree,
780 "Timezone: GMT %c %d hours %d minutes",
781 sign, oct / 4, oct % 4 * 15);
786 dis_field_scts(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
789 proto_tree *subtree = NULL;
796 length = tvb_length_remaining(tvb, offset);
800 proto_tree_add_text(tree,
802 "TP-Service-Centre-Time-Stamp: Short Data (?)");
809 proto_tree_add_text(tree, tvb,
811 "TP-Service-Centre-Time-Stamp");
813 subtree = proto_item_add_subtree(item, ett_scts);
815 dis_field_scts_aux(tvb, subtree, *offset_p);
822 dis_field_vp(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, guint8 vp_form)
825 proto_tree *subtree = NULL;
828 guint8 oct, oct2, oct3;
834 if (vp_form == 0x00) return;
845 length = tvb_length_remaining(tvb, offset);
849 proto_tree_add_text(tree,
851 "TP-Validity-Period: Short Data (?)");
858 proto_tree_add_text(tree, tvb,
860 "TP-Validity-Period");
862 subtree = proto_item_add_subtree(item, ett_vp);
864 oct = tvb_get_guint8(tvb, offset);
866 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
867 proto_tree_add_text(subtree, tvb,
871 (oct & 0x80) ? "Extended" : "No extension");
875 proto_tree_add_text(subtree,
877 "Extension not implemented, ignored");
883 other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
884 proto_tree_add_text(subtree, tvb,
888 (oct & 0x40) ? "Single shot SM" : "Not single shot SM");
890 other_decode_bitfield_value(bigbuf, oct, 0x38, 8);
891 proto_tree_add_text(subtree, tvb,
896 loc_form = oct & 0x7;
901 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
902 proto_tree_add_text(subtree, tvb,
904 "%s : No Validity Period specified",
911 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
912 proto_tree_add_text(subtree, tvb,
914 "%s : Validity Period Format: relative",
918 /* go around again */
923 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
924 proto_tree_add_text(subtree, tvb,
926 "%s : Validity Period Format: relative",
930 oct = tvb_get_guint8(tvb, offset);
932 proto_tree_add_text(subtree, tvb,
941 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
942 proto_tree_add_text(subtree, tvb,
944 "%s : Validity Period Format: relative",
948 oct = tvb_get_guint8(tvb, offset);
949 oct2 = tvb_get_guint8(tvb, offset+1);
950 oct3 = tvb_get_guint8(tvb, offset+2);
952 proto_tree_add_text(subtree,
954 "Hour %d%d, Minutes %d%d, Seconds %d%d",
966 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
967 proto_tree_add_text(subtree, tvb,
969 "%s : Validity Period Format: Reserved",
978 oct = tvb_get_guint8(tvb, offset);
982 mins = (oct + 1) * 5;
988 proto_tree_add_text(subtree, tvb,
990 "TP-Validity-Period: %d hours %d minutes",
996 proto_tree_add_text(subtree, tvb,
998 "TP-Validity-Period: %d minutes",
1002 else if ((oct >= 144) &&
1005 mins = (oct - 143) * 30;
1006 hours = 12 + (mins / 60);
1009 proto_tree_add_text(subtree, tvb,
1011 "TP-Validity-Period: %d hours %d minutes",
1015 else if ((oct >= 168) &&
1018 proto_tree_add_text(subtree, tvb,
1020 "TP-Validity-Period: %d day(s)",
1023 else if (oct >= 197)
1025 proto_tree_add_text(subtree, tvb,
1027 "TP-Validity-Period: %d week(s)",
1035 length = tvb_length_remaining(tvb, offset);
1039 proto_tree_add_text(tree,
1040 tvb, offset, length,
1041 "TP-Validity-Period: Short Data (?)");
1043 *offset_p += length;
1048 proto_tree_add_text(tree, tvb,
1050 "TP-Validity-Period: absolute");
1052 subtree = proto_item_add_subtree(item, ett_vp);
1054 dis_field_scts_aux(tvb, subtree, *offset_p);
1074 dis_field_dt(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
1077 proto_tree *subtree = NULL;
1084 length = tvb_length_remaining(tvb, offset);
1088 proto_tree_add_text(tree,
1089 tvb, offset, length,
1090 "TP-Discharge-Time: Short Data (?)");
1092 *offset_p += length;
1097 proto_tree_add_text(tree, tvb,
1099 "TP-Discharge-Time");
1101 subtree = proto_item_add_subtree(item, ett_dt);
1103 dis_field_scts_aux(tvb, subtree, *offset_p);
1109 /* use dis_field_addr() */
1113 dis_field_st(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1115 static const gchar *sc_complete = "Short message transaction completed";
1116 static const gchar *sc_temporary = "Temporary error, SC still trying to transfer SM";
1117 static const gchar *sc_perm = "Permanent error, SC is not making any more transfer attempts";
1118 static const gchar *sc_tempfin = "Temporary error, SC is not making any more transfer attempts";
1120 proto_tree *subtree = NULL;
1122 const gchar *str = NULL;
1123 const gchar *str2 = NULL;
1127 proto_tree_add_text(tree, tvb,
1131 subtree = proto_item_add_subtree(item, ett_st);
1133 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1134 proto_tree_add_text(subtree, tvb,
1136 "%s : Definition of bits 0-6: %s",
1138 (oct & 0x80) ? "Reserved" : "as follows");
1144 case 0x00: str2 = sc_complete; str = "Short message received by the SME"; break;
1145 case 0x01: str2 = sc_complete; str = "Short message forwarded by the SC to the SME but the SC is unable to confirm delivery"; break;
1146 case 0x02: str2 = sc_complete; str = "Short message replaced by the SC Reserved values"; break;
1148 case 0x20: str2 = sc_temporary; str = "Congestion"; break;
1149 case 0x21: str2 = sc_temporary; str = "SME busy"; break;
1150 case 0x22: str2 = sc_temporary; str = "No response from SME"; break;
1151 case 0x23: str2 = sc_temporary; str = "Service rejected"; break;
1152 case 0x24: str2 = sc_temporary; str = "Quality of service not available"; break;
1153 case 0x25: str2 = sc_temporary; str = "Error in SME"; break;
1155 case 0x40: str2 = sc_perm; str = "Remote procedure error"; break;
1156 case 0x41: str2 = sc_perm; str = "Incompatible destination"; break;
1157 case 0x42: str2 = sc_perm; str = "Connection rejected by SME"; break;
1158 case 0x43: str2 = sc_perm; str = "Not obtainable"; break;
1159 case 0x44: str2 = sc_perm; str = "Quality of service not available"; break;
1160 case 0x45: str2 = sc_perm; str = "No interworking available"; break;
1161 case 0x46: str2 = sc_perm; str = "SM Validity Period Expired"; break;
1162 case 0x47: str2 = sc_perm; str = "SM Deleted by originating SME"; break;
1163 case 0x48: str2 = sc_perm; str = "SM Deleted by SC Administration"; break;
1164 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;
1166 case 0x60: str2 = sc_tempfin; str = "Congestion"; break;
1167 case 0x61: str2 = sc_tempfin; str = "SME busy"; break;
1168 case 0x62: str2 = sc_tempfin; str = "No response from SME"; break;
1169 case 0x63: str2 = sc_tempfin; str = "Service rejected"; break;
1170 case 0x64: str2 = sc_tempfin; str = "Quality of service not available"; break;
1171 case 0x65: str2 = sc_tempfin; str = "Error in SME"; break;
1174 if ((value >= 0x03) &&
1180 else if ((value >= 0x10) &&
1184 str = "Values specific to each SC";
1186 else if ((value >= 0x26) &&
1189 str2 = sc_temporary;
1192 else if ((value >= 0x30) &&
1195 str2 = sc_temporary;
1196 str = "Values specific to each SC";
1198 else if ((value >= 0x4a) &&
1204 else if ((value >= 0x50) &&
1208 str = "Values specific to each SC";
1210 else if ((value >= 0x66) &&
1216 else if ((value >= 0x70) &&
1220 str = "Values specific to each SC";
1225 other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
1226 proto_tree_add_text(subtree, tvb,
1236 #define DIS_FIELD_UDL(m_tree, m_offset) \
1238 proto_tree_add_text(m_tree, tvb, \
1240 "TP-User-Data-Length: (%d) %s", \
1242 oct ? "depends on Data-Coding-Scheme" : "no User-Data");\
1246 #define DIS_FIELD_RP(m_tree, m_bitmask, m_offset) \
1248 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1249 proto_tree_add_text(m_tree, tvb, \
1251 "%s : TP-Reply-Path: parameter is %sset in this SMS-SUBMIT/DELIVER", \
1253 (oct & m_bitmask) ? "" : "not "); \
1257 #define DIS_FIELD_MN(m_tree, m_offset) \
1259 proto_tree_add_text(m_tree, tvb, \
1261 "TP-Message-Number: %d", \
1266 #define DIS_FIELD_CT(m_tree, m_offset) \
1270 case 0: str = "Enquiry relating to previously submitted short message"; break; \
1271 case 1: str = "Cancel Status Report Request relating to previously submitted short message"; break; \
1272 case 2: str = "Delete previously submitted Short Message"; break; \
1273 case 3: str = "Enable Status Report Request relating to previously submitted short message"; break; \
1275 if ((oct >= 0x04) && \
1278 str = "Reserved unspecified"; \
1280 else if (oct >= 0xe0) \
1282 str = "Values specific for each SC"; \
1286 str = "undefined"; \
1290 proto_tree_add_text(m_tree, tvb, \
1292 "TP-Command-Type: (%d), %s", \
1298 #define DIS_FIELD_CDL(m_tree, m_offset) \
1300 proto_tree_add_text(m_tree, tvb, \
1302 "TP-Command-Data-Length: (%d)%s", \
1304 oct ? "" : " no Command-Data");\
1308 /* done in-line in the message functions */
1312 dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1315 proto_tree *subtree = NULL;
1316 const gchar *str = NULL;
1320 proto_tree_add_text(tree, tvb,
1322 "TP-Failure-Cause");
1324 subtree = proto_item_add_subtree(item, ett_fcs);
1328 case 0x80: str = "Telematic interworking not supported"; break;
1329 case 0x81: str = "Short message Type 0 not supported"; break;
1330 case 0x82: str = "Cannot replace short message"; break;
1331 case 0x8F: str = "Unspecified TP-PID error"; break;
1332 case 0x90: str = "Data coding scheme (alphabet) not supported"; break;
1333 case 0x91: str = "Message class not supported"; break;
1334 case 0x9F: str = "Unspecified TP-DCS error"; break;
1335 case 0xA0: str = "Command cannot be actioned"; break;
1336 case 0xA1: str = "Command unsupported"; break;
1337 case 0xAF: str = "Unspecified TP-Command error"; break;
1338 case 0xB0: str = "TPDU not supported"; break;
1339 case 0xC0: str = "SC busy"; break;
1340 case 0xC1: str = "No SC subscription"; break;
1341 case 0xC2: str = "SC system failure"; break;
1342 case 0xC3: str = "Invalid SME address"; break;
1343 case 0xC4: str = "Destination SME barred"; break;
1344 case 0xC5: str = "SM Rejected-Duplicate SM"; break;
1345 case 0xC6: str = "TP-VPF not supported"; break;
1346 case 0xC7: str = "TP-VP not supported"; break;
1347 case 0xD0: str = "(U)SIM SMS storage full"; break;
1348 case 0xD1: str = "No SMS storage capability in (U)SIM"; break;
1349 case 0xD2: str = "Error in MS"; break;
1350 case 0xD3: str = "Memory Capacity Exceeded"; break;
1351 case 0xD4: str = "(U)SIM Application Toolkit Busy"; break;
1352 case 0xD5: str = "(U)SIM data download error"; break;
1353 case 0xFF: str = "Unspecified error cause"; break;
1355 if ((oct >= 0x80) &&
1358 str = "TP-PID errors"; break;
1360 else if ((oct >= 0x90) &&
1363 str = "TP-DCS errors"; break;
1365 else if ((oct >= 0xA0) &&
1368 str = "TP-Command errors"; break;
1370 else if ((oct >= 0xE0) &&
1373 str = "Values specific to an application"; break;
1377 str = "Reserved"; break;
1381 proto_tree_add_text(subtree, tvb,
1387 #define DIS_FIELD_UDHI(m_tree, m_bitmask, m_offset, m_udhi) \
1389 SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, m_udhi); \
1390 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1391 proto_tree_add_text(m_tree, tvb, \
1393 "%s : TP-User-Data-Header-Indicator: %s short message", \
1396 "The beginning of the TP-UD field contains a Header in addition to the" : \
1397 "The TP-UD field contains only the"); \
1405 #define GN_BYTE_MASK ((1 << bits) - 1)
1408 gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length,
1409 const guint8 *input, unsigned char *output)
1411 unsigned char *out_num = output; /* Current pointer to the output buffer */
1412 const guint8 *in_num = input; /* Current pointer to the input buffer */
1413 unsigned char rest = 0x00;
1416 bits = offset ? offset : 7;
1418 while ((unsigned int)(in_num - input) < in_length)
1420 *out_num = ((*in_num & GN_BYTE_MASK) << (7 - bits)) | rest;
1421 rest = *in_num >> bits;
1423 /* If we don't start from 0th bit, we shouldn't go to the
1424 next char. Under *out_num we have now 0 and under Rest -
1425 _first_ part of the char. */
1426 if ((in_num != input) || (bits == 7)) out_num++;
1429 if ((unsigned int)(out_num - output) >= out_length) break;
1431 /* After reading 7 octets we have read 7 full characters but
1432 we have 7 bits as well. This is the next character */
1446 return out_num - output;
1449 #define GN_CHAR_ALPHABET_SIZE 128
1451 #define GN_CHAR_ESCAPE 0x1b
1452 #if GLIB_MAJOR_VERSION < 2
1453 typedef unsigned int gunichar;
1455 int g_unichar_to_utf8(gunichar c, char * outbuf) {
1456 *outbuf = (unsigned char) c;
1462 static gunichar gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
1464 /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
1465 /* Fixed to use unicode */
1466 /* Characters in hex position 10, [12 to 1a] and 24 are not present on
1467 latin1 charset, so we cannot reproduce on the screen, however they are
1468 greek symbol not present even on my Nokia */
1470 '@', 0xa3, '$' , 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
1471 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
1472 0x394, '_', 0x3a6,0x393,0x39b,0x3a9,0x3a0,0x3a8,
1473 0x3a3,0x398,0x39e, 0xa0, 0xc6, 0xe6, 0xdf, 0xc9,
1474 ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
1475 '(', ')', '*', '+', ',', '-', '.', '/',
1476 '0', '1', '2', '3', '4', '5', '6', '7',
1477 '8', '9', ':', ';', '<', '=', '>', '?',
1478 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
1479 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
1480 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
1481 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
1482 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
1483 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
1484 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
1485 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
1489 char_is_escape(unsigned char value)
1491 return (value == GN_CHAR_ESCAPE);
1495 char_def_alphabet_ext_decode(unsigned char value)
1499 case 0x0a: return 0x0c; break; /* form feed */
1500 case 0x14: return '^'; break;
1501 case 0x28: return '{'; break;
1502 case 0x29: return '}'; break;
1503 case 0x2f: return '\\'; break;
1504 case 0x3c: return '['; break;
1505 case 0x3d: return '~'; break;
1506 case 0x3e: return ']'; break;
1507 case 0x40: return '|'; break;
1508 case 0x65: return 0x20ac; break; /* euro */
1509 default: return '?'; break; /* invalid character */
1514 char_def_alphabet_decode(unsigned char value)
1516 if (value < GN_CHAR_ALPHABET_SIZE)
1518 return gsm_default_alphabet[value];
1527 gsm_sms_char_ascii_decode(unsigned char * dest, const unsigned char* src, int len)
1533 for (i = 0, j = 0; j < len; j++)
1535 if (char_is_escape(src[j])) {
1536 buf = char_def_alphabet_ext_decode(src[++j]);
1537 i += g_unichar_to_utf8(buf,&(dest[i]));
1540 buf = char_def_alphabet_decode(src[j]);
1541 i += g_unichar_to_utf8(buf,&(dest[i]));
1553 dis_iei_apa_8bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1555 const gchar *str = NULL;
1559 EXACT_DATA_CHECK(length, 2);
1561 oct = tvb_get_guint8(tvb, offset);
1569 str = "Available for allocation by applications";
1572 proto_tree_add_text(tree,
1574 "Destination port: %d, %s",
1579 oct = tvb_get_guint8(tvb, offset);
1587 str = "Available for allocation by applications";
1590 proto_tree_add_text(tree,
1592 "Originator port: %d, %s",
1598 dis_iei_apa_16bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1600 const gchar *str = NULL;
1604 EXACT_DATA_CHECK(length, 4);
1606 value = tvb_get_ntohs(tvb, offset);
1610 str = "As allocated by IANA (http://www.IANA.com/)";
1612 else if (value < 17000)
1614 str = "Available for allocation by applications";
1621 proto_tree_add_text(tree,
1623 "Destination port: %d, %s",
1628 value = tvb_get_ntohs(tvb, offset);
1632 str = "As allocated by IANA (http://www.IANA.com/)";
1634 else if (value < 17000)
1636 str = "Available for allocation by applications";
1643 proto_tree_add_text(tree,
1645 "Originator port: %d, %s",
1651 dis_field_ud_iei(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1653 void (*iei_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length);
1656 proto_tree *subtree = NULL;
1657 const gchar *str = NULL;
1665 oct = tvb_get_guint8(tvb, offset);
1669 case 0x00: str = "Concatenated short messages, 8-bit reference number (SMS Control)"; break;
1670 case 0x01: str = "Special SMS Message Indication (SMS Control)"; break;
1671 case 0x02: str = "Reserved N/A"; break;
1672 case 0x03: str = "Value not used to avoid misinterpretation as <LF> character N/A"; break;
1673 case 0x04: str = "Application port addressing scheme, 8 bit address (SMS Control)"; iei_fcn = dis_iei_apa_8bit; break;
1674 case 0x05: str = "Application port addressing scheme, 16 bit address (SMS Control)"; iei_fcn = dis_iei_apa_16bit; break;
1675 case 0x06: str = "SMSC Control Parameters (SMS Control)"; break;
1676 case 0x07: str = "UDH Source Indicator (SMS Control)"; break;
1677 case 0x08: str = "Concatenated short message, 16-bit reference number (SMS Control)"; break;
1678 case 0x09: str = "Wireless Control Message Protocol (SMS Control)"; break;
1679 case 0x0A: str = "Text Formatting (EMS Control)"; break;
1680 case 0x0B: str = "Predefined Sound (EMS Content)"; break;
1681 case 0x0C: str = "User Defined Sound (iMelody max 128 bytes) (EMS Content)"; break;
1682 case 0x0D: str = "Predefined Animation (EMS Content)"; break;
1683 case 0x0E: str = "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)"; break;
1684 case 0x0F: str = "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)"; break;
1685 case 0x10: str = "Large Picture (32*32 = 128 bytes) (EMS Content)"; break;
1686 case 0x11: str = "Small Picture (16*16 = 32 bytes) (EMS Content)"; break;
1687 case 0x12: str = "Variable Picture (EMS Content)"; break;
1688 case 0x13: str = "User prompt indicator (EMS Control)"; break;
1689 case 0x14: str = "Extended Object (EMS Content)"; break;
1690 case 0x15: str = "Reused Extended Object (EMS Control)"; break;
1691 case 0x16: str = "Compression Control (EMS Control)"; break;
1692 case 0x17: str = "Object Distribution Indicator (EMS Control)"; break;
1693 case 0x18: str = "Standard WVG object (EMS Content)"; break;
1694 case 0x19: str = "Character Size WVG object (EMS Content)"; break;
1695 case 0x1A: str = "Extended Object Data Request Command (EMS Control)"; break;
1696 case 0x20: str = "RFC 822 E-Mail Header (SMS Control)"; break;
1697 case 0x21: str = "Hyperlink format element (SMS Control)"; break;
1698 case 0x22: str = "Reply Address Element (SMS Control)"; break;
1700 if ((oct >= 0x1b) &&
1703 str = "Reserved for future EMS features (see subclause 3.10) N/A"; break;
1705 else if ((oct >= 0x23) &&
1708 str = "Reserved for future use N/A"; break;
1710 else if ((oct >= 0x70) &&
1713 str = "(U)SIM Toolkit Security Headers (SMS Control)"; break;
1715 else if ((oct >= 0x80) &&
1718 str = "SME to SME specific use (SMS Control)"; break;
1720 else if ((oct >= 0xa0) &&
1723 str = "Reserved for future use N/A"; break;
1725 else if ((oct >= 0xc0) &&
1728 str = "SC specific use (SMS Control)"; break;
1732 str = "Reserved for future use N/A"; break;
1736 iei_len = tvb_get_guint8(tvb, offset + 1);
1739 proto_tree_add_text(tree,
1740 tvb, offset, iei_len + 2,
1744 subtree = proto_item_add_subtree(item, ett_udh_ieis[oct]);
1746 proto_tree_add_text(subtree,
1748 "Information Element Identifier: %d",
1753 proto_tree_add_text(subtree,
1762 if (iei_fcn == NULL)
1764 proto_tree_add_text(subtree,
1765 tvb, offset, iei_len,
1770 iei_fcn(tvb, subtree, offset, iei_len);
1774 length -= 2 + iei_len;
1780 #define NUM_FILL_BITS_MASKS 6
1782 dis_field_ud(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 length, gboolean udhi, guint8 udl,
1783 gboolean seven_bit, gboolean eight_bit, gboolean ucs2, gboolean compressed)
1785 static guint8 fill_bits_mask[NUM_FILL_BITS_MASKS] =
1786 { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };
1788 proto_item *udh_item;
1789 proto_tree *subtree = NULL;
1790 proto_tree *udh_subtree = NULL;
1795 char messagebuf[160];
1800 proto_tree_add_text(tree, tvb,
1804 subtree = proto_item_add_subtree(item, ett_ud);
1806 oct = tvb_get_guint8(tvb, offset);
1811 /* step over header */
1814 proto_tree_add_text(subtree, tvb,
1816 "User-Data Header");
1818 udh_subtree = proto_item_add_subtree(udh_item, ett_udh);
1820 proto_tree_add_text(udh_subtree,
1822 "User Data Header Length (%u)",
1829 dis_field_ud_iei(tvb, udh_subtree, offset, oct);
1837 /* step over fill bits ? */
1839 fill_bits = 7 - (((oct + 1) * 8) % 7);
1840 if (fill_bits < NUM_FILL_BITS_MASKS)
1842 oct = tvb_get_guint8(tvb, offset);
1844 other_decode_bitfield_value(bigbuf, oct, fill_bits_mask[fill_bits], 8);
1845 proto_tree_add_text(udh_subtree,
1855 proto_tree_add_text(subtree, tvb,
1864 gsm_sms_char_7bit_unpack(fill_bits, length, sizeof(messagebuf),
1865 tvb_get_ptr(tvb, offset, length), messagebuf);
1866 messagebuf[out_len] = '\0';
1867 gsm_sms_char_ascii_decode(bigbuf, messagebuf, out_len);
1869 proto_tree_add_text(subtree, tvb, offset, length, "%s", bigbuf);
1873 proto_tree_add_text(subtree, tvb, offset, length, "%s",
1874 tvb_format_text(tvb, offset, length));
1878 /* tvb_get_ephemeral_faked_unicode takes the lengt in number of guint16's */
1879 ustr = tvb_get_ephemeral_faked_unicode(tvb, offset, (length>>1), FALSE);
1880 proto_tree_add_text(subtree, tvb, offset, length, "%s", ustr);
1886 #define DIS_FIELD_RD(m_tree, m_bitmask, m_offset) \
1888 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1889 proto_tree_add_text(m_tree, tvb, \
1891 "%s : TP-Reject-Duplicates: Instruct SC to %s duplicates", \
1893 (oct & m_bitmask) ? \
1899 #define DIS_FIELD_SRQ(m_tree, m_bitmask, m_offset) \
1901 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1902 proto_tree_add_text(m_tree, tvb, \
1904 "%s : TP-Status-Report-Qualifier: The SMS-STATUS-REPORT is the result of %s", \
1906 (oct & m_bitmask) ? \
1907 "an SMS-COMMAND e.g. an Enquiry" : \
1913 dis_field_pi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1916 proto_tree *subtree = NULL;
1920 proto_tree_add_text(tree, tvb,
1922 "TP-Parameter-Indicator");
1924 subtree = proto_item_add_subtree(item, ett_pi);
1926 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1927 proto_tree_add_text(subtree, tvb,
1931 (oct & 0x80) ? "Extended" : "No extension");
1933 other_decode_bitfield_value(bigbuf, oct, 0x78, 8);
1934 proto_tree_add_text(subtree, tvb,
1939 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
1940 proto_tree_add_text(subtree, tvb,
1942 "%s : TP-UDL %spresent",
1944 (oct & 0x04) ? "" : "not ");
1946 other_decode_bitfield_value(bigbuf, oct, 0x02, 8);
1947 proto_tree_add_text(subtree, tvb,
1949 "%s : TP-DCS %spresent",
1951 (oct & 0x02) ? "" : "not ");
1953 other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
1954 proto_tree_add_text(subtree, tvb,
1956 "%s : TP-PID %spresent",
1958 (oct & 0x01) ? "" : "not ");
1966 dis_msg_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
1968 guint32 saved_offset;
1975 gboolean compressed;
1979 saved_offset = offset;
1980 length = tvb_length_remaining(tvb, offset);
1982 oct = tvb_get_guint8(tvb, offset);
1984 DIS_FIELD_RP(tree, 0x80, offset);
1986 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
1988 DIS_FIELD_SRI(tree, 0x20, offset);
1990 DIS_FIELD_MMS(tree, 0x04, offset);
1992 DIS_FIELD_MTI(tree, 0x03, offset);
1996 dis_field_addr(tvb, tree, &offset, "TP-Originating-Address");
1998 oct = tvb_get_guint8(tvb, offset);
2000 dis_field_pid(tvb, tree, offset, oct);
2003 oct = tvb_get_guint8(tvb, offset);
2005 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2008 dis_field_scts(tvb, tree, &offset);
2010 oct = tvb_get_guint8(tvb, offset);
2013 DIS_FIELD_UDL(tree, offset);
2019 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2020 seven_bit, eight_bit, ucs2, compressed);
2029 dis_msg_deliver_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2031 guint32 saved_offset;
2039 gboolean compressed;
2044 saved_offset = offset;
2045 length = tvb_length_remaining(tvb, offset);
2047 oct = tvb_get_guint8(tvb, offset);
2049 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2051 DIS_FIELD_MMS(tree, 0x04, offset); /* Bit 2 */
2052 DIS_FIELD_MTI(tree, 0x03, offset); /* Bit 0 and 1 */
2056 proto_tree_add_text(tree,
2057 tvb, offset, length,
2063 * there does not seem to be a way to determine that this
2064 * deliver report is from an RP-ERROR or RP-ACK other
2065 * than to look at the next octet
2067 * FCS values are 0x80 and higher
2068 * PI uses bit 7 as an extension indicator
2070 * will assume that if bit 7 is set then this octet
2071 * is an FCS otherwise PI
2074 oct = tvb_get_guint8(tvb, offset);
2078 dis_field_fcs(tvb, tree, offset, oct);
2082 pi = tvb_get_guint8(tvb, offset);
2084 dis_field_pi(tvb, tree, offset, pi);
2088 if (length <= (offset - saved_offset))
2090 proto_tree_add_text(tree,
2097 oct = tvb_get_guint8(tvb, offset);
2099 dis_field_pid(tvb, tree, offset, oct);
2104 if (length <= (offset - saved_offset))
2106 proto_tree_add_text(tree,
2113 oct = tvb_get_guint8(tvb, offset);
2115 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2120 if (length <= (offset - saved_offset))
2122 proto_tree_add_text(tree,
2129 oct = tvb_get_guint8(tvb, offset);
2132 DIS_FIELD_UDL(tree, offset);
2139 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2140 seven_bit, eight_bit, ucs2, compressed);
2149 dis_msg_submit(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2151 guint32 saved_offset;
2156 const gchar *str = NULL;
2160 gboolean compressed;
2164 saved_offset = offset;
2165 length = tvb_length_remaining(tvb, offset);
2167 oct = tvb_get_guint8(tvb, offset);
2169 DIS_FIELD_RP(tree, 0x80, offset);
2171 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2173 DIS_FIELD_SRR(tree, 0x20, offset);
2175 DIS_FIELD_VPF(tree, 0x18, offset, &vp_form);
2177 DIS_FIELD_RD(tree, 0x04, offset);
2179 DIS_FIELD_MTI(tree, 0x03, offset);
2182 oct = tvb_get_guint8(tvb, offset);
2184 DIS_FIELD_MR(tree, offset);
2188 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
2190 oct = tvb_get_guint8(tvb, offset);
2192 dis_field_pid(tvb, tree, offset, oct);
2195 oct = tvb_get_guint8(tvb, offset);
2197 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2200 dis_field_vp(tvb, tree, &offset, vp_form);
2202 oct = tvb_get_guint8(tvb, offset);
2205 DIS_FIELD_UDL(tree, offset);
2211 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2212 seven_bit, eight_bit, ucs2, compressed);
2221 dis_msg_submit_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2223 guint32 saved_offset;
2231 gboolean compressed;
2236 saved_offset = offset;
2237 length = tvb_length_remaining(tvb, offset);
2239 oct = tvb_get_guint8(tvb, offset);
2241 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2243 DIS_FIELD_MTI(tree, 0x03, offset);
2246 * there does not seem to be a way to determine that this
2247 * deliver report is from an RP-ERROR or RP-ACK other
2248 * than to look at the next octet
2250 * FCS values are 0x80 and higher
2251 * PI uses bit 7 as an extension indicator
2253 * will assume that if bit 7 is set then this octet
2254 * is an FCS otherwise PI
2257 oct = tvb_get_guint8(tvb, offset);
2261 dis_field_fcs(tvb, tree, offset, oct);
2265 pi = tvb_get_guint8(tvb, offset);
2267 dis_field_pi(tvb, tree, offset, pi);
2270 dis_field_scts(tvb, tree, &offset);
2273 if (length <= (offset - saved_offset)) {
2274 proto_tree_add_text(tree,
2280 oct = tvb_get_guint8(tvb, offset);
2282 dis_field_pid(tvb, tree, offset, oct);
2288 if (length <= (offset - saved_offset))
2290 proto_tree_add_text(tree,
2296 oct = tvb_get_guint8(tvb, offset);
2298 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2304 if (length <= (offset - saved_offset))
2306 proto_tree_add_text(tree,
2312 oct = tvb_get_guint8(tvb, offset);
2315 DIS_FIELD_UDL(tree, offset);
2321 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2322 seven_bit, eight_bit, ucs2, compressed);
2331 dis_msg_status_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2333 guint32 saved_offset;
2341 gboolean compressed;
2346 saved_offset = offset;
2347 length = tvb_length_remaining(tvb, offset);
2349 oct = tvb_get_guint8(tvb, offset);
2351 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2353 DIS_FIELD_SRQ(tree, 0x20, offset);
2355 DIS_FIELD_MMS(tree, 0x04, offset);
2357 DIS_FIELD_MTI(tree, 0x03, offset);
2360 oct = tvb_get_guint8(tvb, offset);
2362 DIS_FIELD_MR(tree, offset);
2366 dis_field_addr(tvb, tree, &offset, "TP-Recipient-Address");
2368 dis_field_scts(tvb, tree, &offset);
2370 dis_field_dt(tvb, tree, &offset);
2372 oct = tvb_get_guint8(tvb, offset);
2374 dis_field_st(tvb, tree, offset, oct);
2377 /* Parameter indicating the presence of any of
2378 * the optional parameters which follow
2379 * 4) Mandatory if any of the optional parameters following TP-PI is present,
2380 * otherwise optional.
2382 if (length <= (offset - saved_offset))
2386 pi = tvb_get_guint8(tvb, offset);
2388 dis_field_pi(tvb, tree, offset, pi);
2392 if (length <= (offset - saved_offset))
2394 proto_tree_add_text(tree,
2401 oct = tvb_get_guint8(tvb, offset);
2403 dis_field_pid(tvb, tree, offset, oct);
2408 if (length <= (offset - saved_offset))
2410 proto_tree_add_text(tree,
2417 oct = tvb_get_guint8(tvb, offset);
2419 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2424 if (length <= (offset - saved_offset))
2426 proto_tree_add_text(tree,
2433 oct = tvb_get_guint8(tvb, offset);
2436 DIS_FIELD_UDL(tree, offset);
2443 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2444 seven_bit, eight_bit, ucs2, compressed);
2453 dis_msg_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2455 guint32 saved_offset;
2459 const gchar *str = NULL;
2464 saved_offset = offset;
2465 length = tvb_length_remaining(tvb, offset);
2467 oct = tvb_get_guint8(tvb, offset);
2469 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2471 DIS_FIELD_SRR(tree, 0x20, offset);
2473 DIS_FIELD_MTI(tree, 0x03, offset);
2476 oct = tvb_get_guint8(tvb, offset);
2478 DIS_FIELD_MR(tree, offset);
2481 oct = tvb_get_guint8(tvb, offset);
2483 dis_field_pid(tvb, tree, offset, oct);
2486 oct = tvb_get_guint8(tvb, offset);
2488 DIS_FIELD_CT(tree, offset);
2491 oct = tvb_get_guint8(tvb, offset);
2493 DIS_FIELD_MN(tree, offset);
2497 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
2499 oct = tvb_get_guint8(tvb, offset);
2502 DIS_FIELD_CDL(tree, offset);
2508 proto_tree_add_text(tree,
2514 #define NUM_MSGS (sizeof(msg_type_strings)/sizeof(value_string))
2515 static gint ett_msgs[NUM_MSGS];
2516 static void (*gsm_sms_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = {
2517 dis_msg_deliver, /* SMS-DELIVER */
2518 dis_msg_deliver_report, /* SMS-DELIVER REPORT */
2519 dis_msg_submit, /* SMS-SUBMIT */
2520 dis_msg_submit_report, /* SMS-SUBMIT REPORT */
2521 dis_msg_status_report, /* SMS-STATUS REPORT */
2522 dis_msg_command, /* SMS-COMMAND */
2523 NULL, /* Reserved */
2524 NULL, /* Reserved */
2528 /* GENERIC DISSECTOR FUNCTIONS */
2531 dissect_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2533 void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = NULL;
2534 proto_item *gsm_sms_item;
2535 proto_tree *gsm_sms_tree = NULL;
2540 const gchar *str = NULL;
2546 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2548 col_set_str(pinfo->cinfo, COL_PROTOCOL, gsm_sms_proto_name_short);
2551 /* In the interest of speed, if "tree" is NULL, don't do any work not
2552 * necessary to generate protocol tree items.
2560 oct = tvb_get_guint8(tvb, offset);
2566 * convert the 2 bit value to one based on direction
2568 if (pinfo->p2p_dir == P2P_DIR_UNKNOWN)
2570 /* Return Result ... */
2571 if (msg_type == 0) /* SMS-DELIVER */
2573 msg_type |= 0x04; /* see the msg_type_strings */
2578 msg_type |= ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x04 : 0x00);
2581 str = match_strval_idx(msg_type, msg_type_strings, &idx);
2584 * create the GSM_SMS protocol tree
2587 proto_tree_add_protocol_format(tree, proto_gsm_sms, tvb, 0, -1,
2590 (str == NULL) ? "Unknown message identifier" : str);
2593 proto_item_add_subtree(gsm_sms_item, ett_gsm_sms);
2595 if ((str == NULL) ||
2596 (msg_type == 0x03) ||
2603 ett_msg_idx = ett_msgs[idx];
2604 msg_fcn = gsm_sms_msg_fcn[idx];
2607 if (msg_fcn == NULL)
2609 proto_tree_add_text(gsm_sms_tree,
2611 "Message dissector not implemented");
2615 (*msg_fcn)(tvb, gsm_sms_tree, offset);
2621 /* Register the protocol with Wireshark */
2623 proto_register_gsm_sms(void)
2629 /* Setup list of header fields */
2630 static hf_register_info hf[] =
2635 /* Setup protocol subtree array */
2636 #define NUM_INDIVIDUAL_PARMS 12
2637 static gint *ett[NUM_INDIVIDUAL_PARMS+NUM_MSGS+NUM_UDH_IEIS];
2639 ett[0] = &ett_gsm_sms;
2652 last_offset = NUM_INDIVIDUAL_PARMS;
2654 for (i=0; i < NUM_MSGS; i++, last_offset++)
2657 ett[last_offset] = &ett_msgs[i];
2660 for (i=0; i < NUM_UDH_IEIS; i++, last_offset++)
2662 ett_udh_ieis[i] = -1;
2663 ett[last_offset] = &ett_udh_ieis[i];
2666 /* Register the protocol name and description */
2669 proto_register_protocol(gsm_sms_proto_name, gsm_sms_proto_name_short, "gsm_sms");
2672 proto_register_field_array(proto_gsm_sms, hf, array_length(hf));
2675 proto_register_subtree_array(ett, array_length(ett));
2680 proto_reg_handoff_gsm_sms(void)
2682 dissector_handle_t gsm_sms_handle;
2684 gsm_sms_handle = create_dissector_handle(dissect_gsm_sms, proto_gsm_sms);
2686 dissector_add("gsm_a.sms_tpdu", 0, gsm_sms_handle);
2687 dissector_add("gsm_map.sms_tpdu", 0, gsm_sms_handle);
2689 data_handle = find_dissector("data");