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 * $Id: packet-gsm_sms.c,v 1.10 2004/03/05 10:06:19 guy Exp $
16 * Ethereal - Network traffic analyzer
17 * By Gerald Combs <gerald@ethereal.com>
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"
57 /* PROTOTYPES/FORWARDS */
59 #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
60 if ((edc_len) > (edc_max_len)) \
62 proto_tree_add_text(tree, tvb, \
63 offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
66 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
67 if ((sdc_len) < (sdc_min_len)) \
69 proto_tree_add_text(tree, tvb, \
70 offset, (sdc_len), "Short Data (?)"); \
74 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
75 if ((edc_len) != (edc_eq_len)) \
77 proto_tree_add_text(tree, tvb, \
78 offset, (edc_len), "Unexpected Data Length"); \
82 #define SMS_SHIFTMASK(m_val, m_bitmask, m_sval); \
84 int _temp_val = m_val; \
85 int _temp_bm = m_bitmask; \
86 while (_temp_bm && !(_temp_bm & 0x01)) \
88 _temp_bm = _temp_bm >> 1; \
89 _temp_val = _temp_val >> 1; \
95 static char *gsm_sms_proto_name = "GSM SMS TPDU (GSM 03.40)";
96 static char *gsm_sms_proto_name_short = "GSM SMS";
98 /* Initialize the subtree pointers */
99 static gint ett_gsm_sms = -1;
100 static gint ett_pid = -1;
101 static gint ett_pi = -1;
102 static gint ett_fcs = -1;
103 static gint ett_vp = -1;
104 static gint ett_scts = -1;
105 static gint ett_dt = -1;
106 static gint ett_st = -1;
107 static gint ett_addr = -1;
108 static gint ett_dcs = -1;
109 static gint ett_ud = -1;
110 static gint ett_udh = -1;
112 /* Initialize the protocol and registered fields */
113 static int proto_gsm_sms = -1;
115 static char bigbuf[1024];
116 static dissector_handle_t data_handle;
117 static packet_info *g_pinfo;
118 static proto_tree *g_tree;
121 * this is the GSM 03.40 definition with the bit 2
122 * set to 1 for uplink messages
124 static const value_string msg_type_strings[] = {
125 { 0, "SMS-DELIVER" },
126 { 4, "SMS-DELIVER REPORT" },
128 { 1, "SMS-SUBMIT REPORT" },
129 { 2, "SMS-STATUS REPORT" },
130 { 6, "SMS-COMMAND" },
136 #define NUM_UDH_IEIS 256
137 static gint ett_udh_ieis[NUM_UDH_IEIS];
142 my_match_strval(guint32 val, const value_string *vs, gint *idx)
146 while (vs[i].strptr) {
147 if (vs[i].value == val)
150 return(vs[i].strptr);
161 #define DIS_FIELD_MTI(m_tree, m_bitmask, m_offset) \
163 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
164 proto_tree_add_text(m_tree, tvb, \
166 "%s : TP-Message-Type-Indicator", \
171 #define DIS_FIELD_MMS(m_tree, m_bitmask, m_offset) \
173 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
174 proto_tree_add_text(m_tree, tvb, \
176 "%s : TP-More-Messages-to-Send: %s messages are waiting for the MS in this SC", \
178 (oct & m_bitmask) ? "No more" : "More"); \
182 #define DIS_FIELD_VPF(m_tree, m_bitmask, m_offset, m_form) \
184 SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, *m_form); \
187 case 0: str = "TP-VP field not present"; break; \
188 case 1: str = "TP-VP field present - enhanced format"; break; \
189 case 2: str = "TP-VP field present - relative format"; break; \
190 case 3: str = "TP-VP field present - absolute format"; break; \
192 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
193 proto_tree_add_text(m_tree, tvb, \
195 "%s : TP-Validity-Period-Format: %s", \
201 #define DIS_FIELD_SRI(m_tree, m_bitmask, m_offset) \
203 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
204 proto_tree_add_text(m_tree, tvb, \
206 "%s : TP-Status-Report-Indication: A status report shall %sbe returned to the SME", \
208 (oct & m_bitmask) ? "" : "not "); \
212 #define DIS_FIELD_SRR(m_tree, m_bitmask, m_offset) \
214 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
215 proto_tree_add_text(m_tree, tvb, \
217 "%s : TP-Status-Report-Request: A status report is %srequested", \
219 (oct & m_bitmask) ? "" : "not "); \
223 #define DIS_FIELD_MR(m_tree, m_offset) \
225 proto_tree_add_text(m_tree, tvb, \
227 "TP-Message-Reference %d", \
232 dis_field_addr(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, gchar *title)
234 static gchar digit_table[] = {"0123456789*#abc\0"};
236 proto_tree *subtree = NULL;
247 oct = tvb_get_guint8(tvb, offset);
248 numdigocts = (oct + 1) / 2;
250 length = tvb_length_remaining(tvb, offset);
252 if (length <= numdigocts)
254 proto_tree_add_text(tree,
256 "%s: Short Data (?)",
264 proto_tree_add_text(tree, tvb,
265 offset, numdigocts + 2,
268 subtree = proto_item_add_subtree(item, ett_addr);
270 proto_tree_add_text(subtree,
272 "Length: %d address digits",
276 oct = tvb_get_guint8(tvb, offset);
278 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
279 proto_tree_add_text(subtree, tvb,
283 (oct & 0x80) ? "No extension" : "Extended");
285 switch ((oct & 0x70) >> 4)
287 case 0x00: str = "Unknown"; break;
288 case 0x01: str = "International"; break;
289 case 0x02: str = "National"; break;
290 case 0x07: str = "Reserved for extension"; break;
291 default: str = "Unknown, reserved (?)"; break;
294 other_decode_bitfield_value(bigbuf, oct, 0x70, 8);
295 proto_tree_add_text(subtree,
297 "%s : Type of number: (%d) %s",
304 case 0x00: str = "Unknown"; break;
305 case 0x01: str = "ISDN/telephone"; break;
306 case 0x0f: str = "Reserved for extension"; break;
307 default: str = "Unknown, reserved (?)"; break;
310 other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
311 proto_tree_add_text(subtree,
313 "%s : Numbering plan: (%d) %s",
321 for (i = 0; i < numdigocts; i++)
323 oct = tvb_get_guint8(tvb, offset + i);
325 bigbuf[j++] = digit_table[oct & 0x0f];
326 bigbuf[j++] = digit_table[(oct & 0xf0) >> 4];
331 proto_tree_add_text(subtree,
332 tvb, offset, numdigocts,
336 proto_item_append_text(item, " - (%s)", bigbuf);
338 *offset_p = offset + i;
342 /* use dis_field_addr() */
345 /* use dis_field_addr() */
349 dis_field_pid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
352 proto_tree *subtree = NULL;
359 proto_tree_add_text(tree, tvb,
361 "TP-Protocol-Identifier");
363 subtree = proto_item_add_subtree(item, ett_pid);
365 form = (oct & 0xc0) >> 6;
370 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
371 proto_tree_add_text(subtree, tvb,
373 "%s : defines formatting for subsequent bits",
376 other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
377 proto_tree_add_text(subtree, tvb,
382 "telematic interworking" :
383 "no telematic interworking, but SME-to-SME protocol");
387 telematic = oct & 0x1f;
391 case 0x00: str = "implicit - device type is specific to this SC, or can be concluded on the basis of the address"; break;
392 case 0x01: str = "telex (or teletex reduced to telex format)"; break;
393 case 0x02: str = "group 3 telefax"; break;
394 case 0x03: str = "group 4 telefax"; break;
395 case 0x04: str = "voice telephone (i.e. conversion to speech)"; break;
396 case 0x05: str = "ERMES (European Radio Messaging System)"; break;
397 case 0x06: str = "National Paging system (known to the SC)"; break;
398 case 0x07: str = "Videotex (T.100 [20] /T.101 [21])"; break;
399 case 0x08: str = "teletex, carrier unspecified"; break;
400 case 0x09: str = "teletex, in PSPDN"; break;
401 case 0x0a: str = "teletex, in CSPDN"; break;
402 case 0x0b: str = "teletex, in analog PSTN"; break;
403 case 0x0c: str = "teletex, in digital ISDN"; break;
404 case 0x0d: str = "UCI (Universal Computer Interface, ETSI DE/PS 3 01-3)"; break;
405 case 0x10: str = "a message handling facility (known to the SC)"; break;
406 case 0x11: str = "any public X.400-based message handling system"; break;
407 case 0x12: str = "Internet Electronic Mail"; break;
408 case 0x1f: str = "A GSM/UMTS mobile station"; break;
410 if ((telematic >= 0x18) &&
413 str = "values specific to each SC";
422 other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
423 proto_tree_add_text(subtree, tvb,
425 "%s : device type: (%d) %s",
432 other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
433 proto_tree_add_text(subtree, tvb,
435 "%s : the SM-AL protocol being used between the SME and the MS (%d)",
442 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
443 proto_tree_add_text(subtree, tvb,
445 "%s : defines formatting for subsequent bits",
450 case 0x00: str = "Short Message Type 0"; break;
451 case 0x01: str = "Replace Short Message Type 1"; break;
452 case 0x02: str = "Replace Short Message Type 2"; break;
453 case 0x03: str = "Replace Short Message Type 3"; break;
454 case 0x04: str = "Replace Short Message Type 4"; break;
455 case 0x05: str = "Replace Short Message Type 5"; break;
456 case 0x06: str = "Replace Short Message Type 6"; break;
457 case 0x07: str = "Replace Short Message Type 7"; break;
458 case 0x1e: str = "Enhanced Message Service (Obsolete)"; break;
459 case 0x1f: str = "Return Call Message"; break;
460 case 0x3c: str = "ANSI-136 R-DATA"; break;
461 case 0x3d: str = "ME Data download"; break;
462 case 0x3e: str = "ME De-personalization Short Message"; break;
463 case 0x3f: str = "(U)SIM Data download"; break;
465 str = "Reserved"; break;
468 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
469 proto_tree_add_text(subtree, tvb,
478 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
479 proto_tree_add_text(subtree, tvb,
484 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
485 proto_tree_add_text(subtree, tvb,
492 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
493 proto_tree_add_text(subtree, tvb,
495 "%s : bits 0-5 for SC specific use",
498 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
499 proto_tree_add_text(subtree, tvb,
509 dis_field_dcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct,
510 gboolean *seven_bit, gboolean *eight_bit, gboolean *ucs2, gboolean *compressed)
513 proto_tree *subtree = NULL;
516 gboolean default_5_bits;
517 gboolean default_3_bits;
518 gboolean default_data;
527 proto_tree_add_text(tree, tvb,
529 "TP-Data-Coding-Scheme (%d)",
532 subtree = proto_item_add_subtree(item, ett_dcs);
536 proto_tree_add_text(subtree, tvb,
538 "Special case, GSM 7 bit default alphabet");
544 default_5_bits = FALSE;
545 default_3_bits = FALSE;
546 default_data = FALSE;
547 form = (oct & 0xc0) >> 6;
552 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
553 proto_tree_add_text(subtree, tvb,
555 "%s : General Data Coding indication",
558 default_5_bits = TRUE;
562 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
563 proto_tree_add_text(subtree, tvb,
565 "%s : Message Marked for Automatic Deletion Group",
568 default_5_bits = TRUE;
572 /* use top four bits */
573 other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
574 proto_tree_add_text(subtree, tvb,
576 "%s : Reserved coding groups",
581 switch ((oct & 0x30) >> 4)
583 case 0x00: str = "Message Waiting Indication Group: Discard Message (GSM 7 bit default alphabet)";
584 default_3_bits = TRUE;
587 case 0x01: str = "Message Waiting Indication Group: Store Message (GSM 7 bit default alphabet)";
588 default_3_bits = TRUE;
591 case 0x02: str = "Message Waiting Indication Group: Store Message (uncompressed UCS2 alphabet)";
592 default_3_bits = TRUE;
594 case 0x03: str = "Data coding/message class";
599 /* use top four bits */
600 other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
601 proto_tree_add_text(subtree, tvb,
611 other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
612 proto_tree_add_text(subtree, tvb,
614 "%s : Text is %scompressed",
616 (oct & 0x20) ? "" : "not ");
618 *compressed = (oct & 0x20) >> 5;
620 other_decode_bitfield_value(bigbuf, oct, 0x10, 8);
621 proto_tree_add_text(subtree, tvb,
625 (oct & 0x10) ? "Message class is defined below" :
626 "Reserved, no message class");
628 switch ((oct & 0x0c) >> 2)
630 case 0x00: str = "GSM 7 bit default alphabet";
633 case 0x01: str = "8 bit data"; break;
634 case 0x02: str = "UCS2 (16 bit)";
637 case 0x03: str = "Reserved"; break;
640 other_decode_bitfield_value(bigbuf, oct, 0x0c, 8);
641 proto_tree_add_text(subtree, tvb,
643 "%s : Character set: %s",
649 case 0x00: str = "Class 0"; break;
650 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
651 case 0x02: str = "Class 2 (U)SIM specific message"; break;
652 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
655 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
656 proto_tree_add_text(subtree, tvb,
658 "%s : Message Class: %s%s",
661 (oct & 0x10) ? "" : " (reserved)");
663 else if (default_3_bits)
665 other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
666 proto_tree_add_text(subtree, tvb,
668 "%s : Indication Sense: %s",
670 (oct & 0x08) ? "Set Indication Active" : "Set Indication Inactive");
672 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
673 proto_tree_add_text(subtree, tvb,
680 case 0x00: str = "Voicemail Message Waiting"; break;
681 case 0x01: str = "Fax Message Waiting"; break;
682 case 0x02: str = "Electronic Mail Message Waiting"; break;
683 case 0x03: str = "Other Message Waiting"; break;
686 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
687 proto_tree_add_text(subtree, tvb,
693 else if (default_data)
695 other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
696 proto_tree_add_text(subtree, tvb,
701 *seven_bit = !(*eight_bit = (oct & 0x04) ? TRUE : FALSE);
703 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
704 proto_tree_add_text(subtree, tvb,
706 "%s : Message coding: %s",
708 (*eight_bit) ? "8 bit data" : "GSM 7 bit default alphabet");
712 case 0x00: str = "Class 0"; break;
713 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
714 case 0x02: str = "Class 2 (U)SIM specific message"; break;
715 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
718 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
719 proto_tree_add_text(subtree, tvb,
721 "%s : Message Class: %s",
728 dis_field_scts_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
730 guint8 oct, oct2, oct3;
733 oct = tvb_get_guint8(tvb, offset);
734 oct2 = tvb_get_guint8(tvb, offset+1);
735 oct3 = tvb_get_guint8(tvb, offset+2);
737 proto_tree_add_text(tree,
739 "Year %d%d, Month %d%d, Day %d%d",
749 oct = tvb_get_guint8(tvb, offset);
750 oct2 = tvb_get_guint8(tvb, offset+1);
751 oct3 = tvb_get_guint8(tvb, offset+2);
753 proto_tree_add_text(tree,
755 "Hour %d%d, Minutes %d%d, Seconds %d%d",
765 oct = tvb_get_guint8(tvb, offset);
767 proto_tree_add_text(tree,
775 dis_field_scts(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
778 proto_tree *subtree = NULL;
785 length = tvb_length_remaining(tvb, offset);
789 proto_tree_add_text(tree,
791 "TP-Service-Centre-Time-Stamp: Short Data (?)");
798 proto_tree_add_text(tree, tvb,
800 "TP-Service-Centre-Time-Stamp");
802 subtree = proto_item_add_subtree(item, ett_scts);
804 dis_field_scts_aux(tvb, subtree, *offset_p);
811 dis_field_vp(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, guint8 vp_form)
814 proto_tree *subtree = NULL;
817 guint8 oct, oct2, oct3;
823 if (vp_form == 0x00) return;
834 length = tvb_length_remaining(tvb, offset);
838 proto_tree_add_text(tree,
840 "TP-Validity-Period: Short Data (?)");
847 proto_tree_add_text(tree, tvb,
849 "TP-Validity-Period");
851 subtree = proto_item_add_subtree(item, ett_vp);
853 oct = tvb_get_guint8(tvb, offset);
855 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
856 proto_tree_add_text(subtree, tvb,
860 (oct & 0x80) ? "Extended" : "No extension");
864 proto_tree_add_text(subtree,
866 "Extension not implemented, ignored");
872 other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
873 proto_tree_add_text(subtree, tvb,
877 (oct & 0x40) ? "Single shot SM" : "Not single shot SM");
879 other_decode_bitfield_value(bigbuf, oct, 0x38, 8);
880 proto_tree_add_text(subtree, tvb,
885 loc_form = oct & 0x7;
890 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
891 proto_tree_add_text(subtree, tvb,
893 "%s : No Validity Period specified",
900 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
901 proto_tree_add_text(subtree, tvb,
903 "%s : Validity Period Format: relative",
906 /* go around again */
911 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
912 proto_tree_add_text(subtree, tvb,
914 "%s : Validity Period Format: relative",
918 oct = tvb_get_guint8(tvb, offset);
920 proto_tree_add_text(subtree, tvb,
929 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
930 proto_tree_add_text(subtree, tvb,
932 "%s : Validity Period Format: relative",
936 oct = tvb_get_guint8(tvb, offset);
937 oct2 = tvb_get_guint8(tvb, offset+1);
938 oct3 = tvb_get_guint8(tvb, offset+2);
940 proto_tree_add_text(subtree,
942 "Hour %d%d, Minutes %d%d, Seconds %d%d",
954 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
955 proto_tree_add_text(subtree, tvb,
957 "%s : Validity Period Format: Reserved",
966 oct = tvb_get_guint8(tvb, offset);
970 mins = (oct + 1) * 5;
976 proto_tree_add_text(subtree, tvb,
978 "TP-Validity-Period: %d hours %d minutes",
984 proto_tree_add_text(subtree, tvb,
986 "TP-Validity-Period: %d minutes",
990 else if ((oct >= 144) &&
993 mins = (oct - 143) * 30;
994 hours = 12 + (mins / 60);
997 proto_tree_add_text(subtree, tvb,
999 "TP-Validity-Period: %d hours %d minutes",
1003 else if ((oct >= 168) &&
1006 proto_tree_add_text(subtree, tvb,
1008 "TP-Validity-Period: %d day(s)",
1011 else if (oct >= 197)
1013 proto_tree_add_text(subtree, tvb,
1015 "TP-Validity-Period: %d week(s)",
1023 length = tvb_length_remaining(tvb, offset);
1027 proto_tree_add_text(tree,
1028 tvb, offset, length,
1029 "TP-Validity-Period: Short Data (?)");
1031 *offset_p += length;
1036 proto_tree_add_text(tree, tvb,
1038 "TP-Validity-Period: absolute");
1040 subtree = proto_item_add_subtree(item, ett_vp);
1042 dis_field_scts_aux(tvb, subtree, *offset_p);
1062 dis_field_dt(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
1065 proto_tree *subtree = NULL;
1072 length = tvb_length_remaining(tvb, offset);
1076 proto_tree_add_text(tree,
1077 tvb, offset, length,
1078 "TP-Discharge-Time: Short Data (?)");
1080 *offset_p += length;
1085 proto_tree_add_text(tree, tvb,
1087 "TP-Discharge-Time");
1089 subtree = proto_item_add_subtree(item, ett_dt);
1091 dis_field_scts_aux(tvb, subtree, *offset_p);
1097 /* use dis_field_addr() */
1101 dis_field_st(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1103 static gchar *sc_complete = "Short message transaction completed";
1104 static gchar *sc_temporary = "Temporary error, SC still trying to transfer SM";
1105 static gchar *sc_perm = "Permanent error, SC is not making any more transfer attempts";
1106 static gchar *sc_tempfin = "Temporary error, SC is not making any more transfer attempts";
1108 proto_tree *subtree = NULL;
1115 proto_tree_add_text(tree, tvb,
1119 subtree = proto_item_add_subtree(item, ett_st);
1121 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1122 proto_tree_add_text(subtree, tvb,
1124 "%s : Definition of bits 0-6: %s",
1126 (oct & 0x80) ? "Reserved" : "as follows");
1132 case 0x00: str2 = sc_complete; str = "Short message received by the SME"; break;
1133 case 0x01: str2 = sc_complete; str = "Short message forwarded by the SC to the SME but the SC is unable to confirm delivery"; break;
1134 case 0x02: str2 = sc_complete; str = "Short message replaced by the SC Reserved values"; break;
1136 case 0x20: str2 = sc_temporary; str = "Congestion"; break;
1137 case 0x21: str2 = sc_temporary; str = "SME busy"; break;
1138 case 0x22: str2 = sc_temporary; str = "No response from SME"; break;
1139 case 0x23: str2 = sc_temporary; str = "Service rejected"; break;
1140 case 0x24: str2 = sc_temporary; str = "Quality of service not available"; break;
1141 case 0x25: str2 = sc_temporary; str = "Error in SME"; break;
1143 case 0x40: str2 = sc_perm; str = "Remote procedure error"; break;
1144 case 0x41: str2 = sc_perm; str = "Incompatible destination"; break;
1145 case 0x42: str2 = sc_perm; str = "Connection rejected by SME"; break;
1146 case 0x43: str2 = sc_perm; str = "Not obtainable"; break;
1147 case 0x44: str2 = sc_perm; str = "Quality of service not available"; break;
1148 case 0x45: str2 = sc_perm; str = "No interworking available"; break;
1149 case 0x46: str2 = sc_perm; str = "SM Validity Period Expired"; break;
1150 case 0x47: str2 = sc_perm; str = "SM Deleted by originating SME"; break;
1151 case 0x48: str2 = sc_perm; str = "SM Deleted by SC Administration"; break;
1152 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;
1154 case 0x60: str2 = sc_tempfin; str = "Congestion"; break;
1155 case 0x61: str2 = sc_tempfin; str = "SME busy"; break;
1156 case 0x62: str2 = sc_tempfin; str = "No response from SME"; break;
1157 case 0x63: str2 = sc_tempfin; str = "Service rejected"; break;
1158 case 0x64: str2 = sc_tempfin; str = "Quality of service not available"; break;
1159 case 0x65: str2 = sc_tempfin; str = "Error in SME"; break;
1162 if ((value >= 0x03) &&
1168 else if ((value >= 0x10) &&
1172 str = "Values specific to each SC";
1174 else if ((value >= 0x26) &&
1177 str2 = sc_temporary;
1180 else if ((value >= 0x30) &&
1183 str2 = sc_temporary;
1184 str = "Values specific to each SC";
1186 else if ((value >= 0x4a) &&
1192 else if ((value >= 0x50) &&
1196 str = "Values specific to each SC";
1198 else if ((value >= 0x66) &&
1204 else if ((value >= 0x70) &&
1208 str = "Values specific to each SC";
1213 other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
1214 proto_tree_add_text(subtree, tvb,
1224 #define DIS_FIELD_UDL(m_tree, m_offset) \
1226 proto_tree_add_text(m_tree, tvb, \
1228 "TP-User-Data-Length: (%d) %s", \
1230 oct ? "depends on Data-Coding-Scheme" : "no User-Data");\
1234 #define DIS_FIELD_RP(m_tree, m_bitmask, m_offset) \
1236 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1237 proto_tree_add_text(m_tree, tvb, \
1239 "%s : TP-Reply-Path: parameter is %sset in this SMS-SUBMIT/DELIVER", \
1241 (oct & m_bitmask) ? "" : "not "); \
1245 #define DIS_FIELD_MN(m_tree, m_offset) \
1247 proto_tree_add_text(m_tree, tvb, \
1249 "TP-Message-Number: %d", \
1254 #define DIS_FIELD_CT(m_tree, m_offset) \
1258 case 0: str = "Enquiry relating to previously submitted short message"; break; \
1259 case 1: str = "Cancel Status Report Request relating to previously submitted short message"; break; \
1260 case 2: str = "Delete previously submitted Short Message"; break; \
1261 case 3: str = "Enable Status Report Request relating to previously submitted short message"; break; \
1263 if ((oct >= 0x04) && \
1266 str = "Reserved unspecified"; \
1268 else if (oct >= 0xe0) \
1270 str = "Values specific for each SC"; \
1274 str = "undefined"; \
1278 proto_tree_add_text(m_tree, tvb, \
1280 "TP-Command-Type: (%d), %s", \
1286 #define DIS_FIELD_CDL(m_tree, m_offset) \
1288 proto_tree_add_text(m_tree, tvb, \
1290 "TP-Command-Data-Length: (%d)%s", \
1292 oct ? "" : " no Command-Data");\
1296 /* done in-line in the message functions */
1300 dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1303 proto_tree *subtree = NULL;
1308 proto_tree_add_text(tree, tvb,
1310 "TP-Failure-Cause");
1312 subtree = proto_item_add_subtree(item, ett_fcs);
1316 case 0x80: str = "Telematic interworking not supported"; break;
1317 case 0x81: str = "Short message Type 0 not supported"; break;
1318 case 0x82: str = "Cannot replace short message"; break;
1319 case 0x8F: str = "Unspecified TP-PID error"; break;
1320 case 0x90: str = "Data coding scheme (alphabet) not supported"; break;
1321 case 0x91: str = "Message class not supported"; break;
1322 case 0x9F: str = "Unspecified TP-DCS error"; break;
1323 case 0xA0: str = "Command cannot be actioned"; break;
1324 case 0xA1: str = "Command unsupported"; break;
1325 case 0xAF: str = "Unspecified TP-Command error"; break;
1326 case 0xB0: str = "TPDU not supported"; break;
1327 case 0xC0: str = "SC busy"; break;
1328 case 0xC1: str = "No SC subscription"; break;
1329 case 0xC2: str = "SC system failure"; break;
1330 case 0xC3: str = "Invalid SME address"; break;
1331 case 0xC4: str = "Destination SME barred"; break;
1332 case 0xC5: str = "SM Rejected-Duplicate SM"; break;
1333 case 0xC6: str = "TP-VPF not supported"; break;
1334 case 0xC7: str = "TP-VP not supported"; break;
1335 case 0xD0: str = "(U)SIM SMS storage full"; break;
1336 case 0xD1: str = "No SMS storage capability in (U)SIM"; break;
1337 case 0xD2: str = "Error in MS"; break;
1338 case 0xD3: str = "Memory Capacity Exceeded"; break;
1339 case 0xD4: str = "(U)SIM Application Toolkit Busy"; break;
1340 case 0xD5: str = "(U)SIM data download error"; break;
1341 case 0xFF: str = "Unspecified error cause"; break;
1343 if ((oct >= 0x80) &&
1346 str = "TP-PID errors"; break;
1348 else if ((oct >= 0x90) &&
1351 str = "TP-DCS errors"; break;
1353 else if ((oct >= 0xA0) &&
1356 str = "TP-Command errors"; break;
1358 else if ((oct >= 0xE0) &&
1361 str = "Values specific to an application"; break;
1365 str = "Reserved"; break;
1369 proto_tree_add_text(subtree, tvb,
1375 #define DIS_FIELD_UDHI(m_tree, m_bitmask, m_offset, m_udhi) \
1377 SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, m_udhi); \
1378 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1379 proto_tree_add_text(m_tree, tvb, \
1381 "%s : TP-User-Data-Header-Indicator: %s short message", \
1384 "The beginning of the TP-UD field contains a Header in addition to the" : \
1385 "The TP-UD field contains only the"); \
1393 #define GN_BYTE_MASK ((1 << bits) - 1)
1396 char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length,
1397 const guint8 *input, unsigned char *output)
1399 unsigned char *out_num = output; /* Current pointer to the output buffer */
1400 const guint8 *in_num = input; /* Current pointer to the input buffer */
1401 unsigned char rest = 0x00;
1404 bits = offset ? offset : 7;
1406 while ((unsigned int)(in_num - input) < in_length)
1408 *out_num = ((*in_num & GN_BYTE_MASK) << (7 - bits)) | rest;
1409 rest = *in_num >> bits;
1411 /* If we don't start from 0th bit, we shouldn't go to the
1412 next char. Under *out_num we have now 0 and under Rest -
1413 _first_ part of the char. */
1414 if ((in_num != input) || (bits == 7)) out_num++;
1417 if ((unsigned int)(out_num - output) >= out_length) break;
1419 /* After reading 7 octets we have read 7 full characters but
1420 we have 7 bits as well. This is the next character */
1434 return out_num - output;
1437 #define GN_CHAR_ALPHABET_SIZE 128
1439 #define GN_CHAR_ESCAPE 0x1b
1441 static unsigned char gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
1443 /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
1444 /* Characters in hex position 10, [12 to 1a] and 24 are not present on
1445 latin1 charset, so we cannot reproduce on the screen, however they are
1446 greek symbol not present even on my Nokia */
1448 '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
1449 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
1450 '?', '_', '?', '?', '?', '?', '?', '?',
1451 '?', '?', '?', '?', 0xc6, 0xe6, 0xdf, 0xc9,
1452 ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
1453 '(', ')', '*', '+', ',', '-', '.', '/',
1454 '0', '1', '2', '3', '4', '5', '6', '7',
1455 '8', '9', ':', ';', '<', '=', '>', '?',
1456 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
1457 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
1458 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
1459 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
1460 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
1461 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
1462 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
1463 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
1467 char_is_escape(unsigned char value)
1469 return (value == GN_CHAR_ESCAPE);
1472 static unsigned char
1473 char_def_alphabet_ext_decode(unsigned char value)
1477 case 0x0a: return 0x0c; break; /* form feed */
1478 case 0x14: return '^'; break;
1479 case 0x28: return '{'; break;
1480 case 0x29: return '}'; break;
1481 case 0x2f: return '\\'; break;
1482 case 0x3c: return '['; break;
1483 case 0x3d: return '~'; break;
1484 case 0x3e: return ']'; break;
1485 case 0x40: return '|'; break;
1486 case 0x65: return 0xa4; break; /* euro */
1487 default: return '?'; break; /* invalid character */
1491 unsigned char char_def_alphabet_decode(unsigned char value)
1493 if (value < GN_CHAR_ALPHABET_SIZE)
1495 return gsm_default_alphabet[value];
1504 char_ascii_decode(unsigned char* dest, const unsigned char* src, int len)
1508 for (i = 0, j = 0; j < len; i++, j++)
1510 if (char_is_escape(src[j]))
1511 dest[i] = char_def_alphabet_ext_decode(src[++j]);
1513 dest[i] = char_def_alphabet_decode(src[j]);
1524 dis_iei_apa_8bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1530 EXACT_DATA_CHECK(length, 2);
1532 oct = tvb_get_guint8(tvb, offset);
1540 str = "Available for allocation by applications";
1543 proto_tree_add_text(tree,
1545 "Destination port: %d, %s",
1550 oct = tvb_get_guint8(tvb, offset);
1558 str = "Available for allocation by applications";
1561 proto_tree_add_text(tree,
1563 "Originator port: %d, %s",
1569 dis_iei_apa_16bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1575 EXACT_DATA_CHECK(length, 4);
1577 value = tvb_get_ntohs(tvb, offset);
1581 str = "As allocated by IANA (http://www.IANA.com/)";
1583 else if (value < 17000)
1585 str = "Available for allocation by applications";
1592 proto_tree_add_text(tree,
1594 "Destination port: %d, %s",
1599 value = tvb_get_ntohs(tvb, offset);
1603 str = "As allocated by IANA (http://www.IANA.com/)";
1605 else if (value < 17000)
1607 str = "Available for allocation by applications";
1614 proto_tree_add_text(tree,
1616 "Originator port: %d, %s",
1622 dis_field_ud_iei(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1624 void (*iei_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length);
1627 proto_tree *subtree = NULL;
1636 oct = tvb_get_guint8(tvb, offset);
1640 case 0x00: str = "Concatenated short messages, 8-bit reference number (SMS Control)"; break;
1641 case 0x01: str = "Special SMS Message Indication (SMS Control)"; break;
1642 case 0x02: str = "Reserved N/A"; break;
1643 case 0x03: str = "Value not used to avoid misinterpretation as <LF> character N/A"; break;
1644 case 0x04: str = "Application port addressing scheme, 8 bit address (SMS Control)"; iei_fcn = dis_iei_apa_8bit; break;
1645 case 0x05: str = "Application port addressing scheme, 16 bit address (SMS Control)"; iei_fcn = dis_iei_apa_16bit; break;
1646 case 0x06: str = "SMSC Control Parameters (SMS Control)"; break;
1647 case 0x07: str = "UDH Source Indicator (SMS Control)"; break;
1648 case 0x08: str = "Concatenated short message, 16-bit reference number (SMS Control)"; break;
1649 case 0x09: str = "Wireless Control Message Protocol (SMS Control)"; break;
1650 case 0x0A: str = "Text Formatting (EMS Control)"; break;
1651 case 0x0B: str = "Predefined Sound (EMS Content)"; break;
1652 case 0x0C: str = "User Defined Sound (iMelody max 128 bytes) (EMS Content)"; break;
1653 case 0x0D: str = "Predefined Animation (EMS Content)"; break;
1654 case 0x0E: str = "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)"; break;
1655 case 0x0F: str = "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)"; break;
1656 case 0x10: str = "Large Picture (32*32 = 128 bytes) (EMS Content)"; break;
1657 case 0x11: str = "Small Picture (16*16 = 32 bytes) (EMS Content)"; break;
1658 case 0x12: str = "Variable Picture (EMS Content)"; break;
1659 case 0x13: str = "User prompt indicator (EMS Control)"; break;
1660 case 0x14: str = "Extended Object (EMS Content)"; break;
1661 case 0x15: str = "Reused Extended Object (EMS Control)"; break;
1662 case 0x16: str = "Compression Control (EMS Control)"; break;
1663 case 0x17: str = "Object Distribution Indicator (EMS Control)"; break;
1664 case 0x18: str = "Standard WVG object (EMS Content)"; break;
1665 case 0x19: str = "Character Size WVG object (EMS Content)"; break;
1666 case 0x1A: str = "Extended Object Data Request Command (EMS Control)"; break;
1667 case 0x20: str = "RFC 822 E-Mail Header (SMS Control)"; break;
1668 case 0x21: str = "Hyperlink format element (SMS Control)"; break;
1669 case 0x22: str = "Reply Address Element (SMS Control)"; break;
1671 if ((oct >= 0x1b) &&
1674 str = "Reserved for future EMS features (see subclause 3.10) N/A"; break;
1676 else if ((oct >= 0x23) &&
1679 str = "Reserved for future use N/A"; break;
1681 else if ((oct >= 0x70) &&
1684 str = "(U)SIM Toolkit Security Headers (SMS Control)"; break;
1686 else if ((oct >= 0x80) &&
1689 str = "SME to SME specific use (SMS Control)"; break;
1691 else if ((oct >= 0xa0) &&
1694 str = "Reserved for future use N/A"; break;
1696 else if ((oct >= 0xc0) &&
1699 str = "SC specific use (SMS Control)"; break;
1703 str = "Reserved for future use N/A"; break;
1707 iei_len = tvb_get_guint8(tvb, offset + 1);
1710 proto_tree_add_text(tree,
1711 tvb, offset, iei_len + 2,
1715 subtree = proto_item_add_subtree(item, ett_udh_ieis[oct]);
1717 proto_tree_add_text(subtree,
1719 "Information Element Identifier: %d",
1724 proto_tree_add_text(subtree,
1733 if (iei_fcn == NULL)
1735 proto_tree_add_text(subtree,
1736 tvb, offset, iei_len,
1741 iei_fcn(tvb, subtree, offset, iei_len);
1745 length -= 2 + iei_len;
1752 dis_field_ud(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 length, gboolean udhi, guint8 udl,
1753 gboolean seven_bit, gboolean eight_bit, gboolean ucs2, gboolean compressed)
1755 static guint8 fill_bits_mask[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };
1757 proto_item *udh_item;
1758 proto_tree *subtree = NULL;
1759 proto_tree *udh_subtree = NULL;
1768 proto_tree_add_text(tree, tvb,
1772 subtree = proto_item_add_subtree(item, ett_ud);
1774 oct = tvb_get_guint8(tvb, offset);
1778 /* step over header */
1781 proto_tree_add_text(subtree, tvb,
1783 "User-Data Header");
1785 udh_subtree = proto_item_add_subtree(udh_item, ett_udh);
1787 proto_tree_add_text(udh_subtree,
1789 "User Data Header Length (%d)",
1796 dis_field_ud_iei(tvb, udh_subtree, offset, oct);
1804 /* step over fill bits ? */
1806 fill_bits = 7 - (((oct + 1) * 8) % 7);
1809 oct = tvb_get_guint8(tvb, offset);
1811 other_decode_bitfield_value(bigbuf, oct, fill_bits_mask[fill_bits], 8);
1812 proto_tree_add_text(udh_subtree,
1822 proto_tree_add_text(subtree, tvb,
1831 char_7bit_unpack(fill_bits, length, sizeof(bigbuf),
1832 tvb_get_ptr(tvb, offset, length), bigbuf);
1833 bigbuf[out_len] = '\0';
1834 char_ascii_decode(bigbuf, bigbuf, out_len);
1837 proto_tree_add_text(subtree, tvb, offset, length, "%s", bigbuf);
1841 proto_tree_add_text(subtree, tvb, offset, length, "%s",
1842 tvb_format_text(tvb, offset, length));
1846 ustr = tvb_fake_unicode(tvb, offset, length, FALSE);
1847 proto_tree_add_text(subtree, tvb, offset, length, "%s", ustr);
1854 #define DIS_FIELD_RD(m_tree, m_bitmask, m_offset) \
1856 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1857 proto_tree_add_text(m_tree, tvb, \
1859 "%s : TP-Reject-Duplicates: Instruct SC to %s duplicates", \
1861 (oct & m_bitmask) ? \
1867 #define DIS_FIELD_SRQ(m_tree, m_bitmask, m_offset) \
1869 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1870 proto_tree_add_text(m_tree, tvb, \
1872 "%s : TP-Status-Report-Qualifier: The SMS-STATUS-REPORT is the result of %s", \
1874 (oct & m_bitmask) ? \
1875 "an SMS-COMMAND e.g. an Enquiry" : \
1881 dis_field_pi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1884 proto_tree *subtree = NULL;
1888 proto_tree_add_text(tree, tvb,
1890 "TP-Parameter-Indicator");
1892 subtree = proto_item_add_subtree(item, ett_pi);
1894 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1895 proto_tree_add_text(subtree, tvb,
1899 (oct & 0x80) ? "Extended" : "No extension");
1901 other_decode_bitfield_value(bigbuf, oct, 0x78, 8);
1902 proto_tree_add_text(subtree, tvb,
1907 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
1908 proto_tree_add_text(subtree, tvb,
1910 "%s : TP-UDL %spresent",
1912 (oct & 0x04) ? "" : "not ");
1914 other_decode_bitfield_value(bigbuf, oct, 0x02, 8);
1915 proto_tree_add_text(subtree, tvb,
1917 "%s : TP-DCS %spresent",
1919 (oct & 0x02) ? "" : "not ");
1921 other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
1922 proto_tree_add_text(subtree, tvb,
1924 "%s : TP-PID %spresent",
1926 (oct & 0x01) ? "" : "not ");
1934 dis_msg_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
1936 guint32 saved_offset;
1943 gboolean compressed;
1947 saved_offset = offset;
1948 length = tvb_length_remaining(tvb, offset);
1950 oct = tvb_get_guint8(tvb, offset);
1952 DIS_FIELD_SRI(tree, 0x20, offset);
1954 DIS_FIELD_UDHI(tree, 0x10, offset, udhi);
1956 DIS_FIELD_RP(tree, 0x08, offset);
1958 DIS_FIELD_MMS(tree, 0x04, offset);
1960 DIS_FIELD_MTI(tree, 0x03, offset);
1964 dis_field_addr(tvb, tree, &offset, "TP-Originating-Address");
1966 oct = tvb_get_guint8(tvb, offset);
1968 dis_field_pid(tvb, tree, offset, oct);
1971 oct = tvb_get_guint8(tvb, offset);
1973 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
1976 dis_field_scts(tvb, tree, &offset);
1978 oct = tvb_get_guint8(tvb, offset);
1981 DIS_FIELD_UDL(tree, offset);
1987 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
1988 seven_bit, eight_bit, ucs2, compressed);
1997 dis_msg_deliver_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
1999 guint32 saved_offset;
2007 gboolean compressed;
2012 saved_offset = offset;
2013 length = tvb_length_remaining(tvb, offset);
2015 oct = tvb_get_guint8(tvb, offset);
2017 DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
2019 DIS_FIELD_MTI(tree, 0x03, offset);
2023 proto_tree_add_text(tree,
2024 tvb, offset, length,
2030 * there does not seem to be a way to determine that this
2031 * deliver report is from an RP-ERROR or RP-ACK other
2032 * than to look at the next octet
2034 * FCS values are 0x80 and higher
2035 * PI uses bit 7 as an extension indicator
2037 * will assume that if bit 7 is set then this octet
2038 * is an FCS otherwise PI
2041 oct = tvb_get_guint8(tvb, offset);
2045 dis_field_fcs(tvb, tree, offset, oct);
2049 pi = tvb_get_guint8(tvb, offset);
2051 dis_field_pi(tvb, tree, offset, pi);
2055 if (length <= (offset - saved_offset))
2057 proto_tree_add_text(tree,
2064 oct = tvb_get_guint8(tvb, offset);
2066 dis_field_pid(tvb, tree, offset, oct);
2071 if (length <= (offset - saved_offset))
2073 proto_tree_add_text(tree,
2080 oct = tvb_get_guint8(tvb, offset);
2082 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2087 if (length <= (offset - saved_offset))
2089 proto_tree_add_text(tree,
2096 oct = tvb_get_guint8(tvb, offset);
2099 DIS_FIELD_UDL(tree, offset);
2106 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2107 seven_bit, eight_bit, ucs2, compressed);
2116 dis_msg_submit(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2118 guint32 saved_offset;
2127 gboolean compressed;
2131 saved_offset = offset;
2132 length = tvb_length_remaining(tvb, offset);
2134 oct = tvb_get_guint8(tvb, offset);
2136 DIS_FIELD_SRR(tree, 0x80, offset);
2138 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2140 DIS_FIELD_RP(tree, 0x20, offset);
2142 DIS_FIELD_VPF(tree, 0x18, offset, &vp_form);
2144 DIS_FIELD_RD(tree, 0x04, offset);
2146 DIS_FIELD_MTI(tree, 0x03, offset);
2149 oct = tvb_get_guint8(tvb, offset);
2151 DIS_FIELD_MR(tree, offset);
2155 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
2157 oct = tvb_get_guint8(tvb, offset);
2159 dis_field_pid(tvb, tree, offset, oct);
2162 oct = tvb_get_guint8(tvb, offset);
2164 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2167 dis_field_vp(tvb, tree, &offset, vp_form);
2169 oct = tvb_get_guint8(tvb, offset);
2172 DIS_FIELD_UDL(tree, offset);
2178 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2179 seven_bit, eight_bit, ucs2, compressed);
2188 dis_msg_submit_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2190 guint32 saved_offset;
2198 gboolean compressed;
2203 saved_offset = offset;
2204 length = tvb_length_remaining(tvb, offset);
2206 oct = tvb_get_guint8(tvb, offset);
2208 DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
2210 DIS_FIELD_MTI(tree, 0x03, offset);
2213 * there does not seem to be a way to determine that this
2214 * deliver report is from an RP-ERROR or RP-ACK other
2215 * than to look at the next octet
2217 * FCS values are 0x80 and higher
2218 * PI uses bit 7 as an extension indicator
2220 * will assume that if bit 7 is set then this octet
2221 * is an FCS otherwise PI
2224 oct = tvb_get_guint8(tvb, offset);
2228 dis_field_fcs(tvb, tree, offset, oct);
2232 pi = tvb_get_guint8(tvb, offset);
2234 dis_field_pi(tvb, tree, offset, pi);
2237 dis_field_scts(tvb, tree, &offset);
2241 if (length <= (offset - saved_offset))
2243 proto_tree_add_text(tree,
2250 oct = tvb_get_guint8(tvb, offset);
2252 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2257 if (length <= (offset - saved_offset))
2259 proto_tree_add_text(tree,
2266 oct = tvb_get_guint8(tvb, offset);
2269 DIS_FIELD_UDL(tree, offset);
2276 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2277 seven_bit, eight_bit, ucs2, compressed);
2286 dis_msg_status_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2288 guint32 saved_offset;
2296 gboolean compressed;
2301 saved_offset = offset;
2302 length = tvb_length_remaining(tvb, offset);
2304 oct = tvb_get_guint8(tvb, offset);
2306 DIS_FIELD_SRQ(tree, 0x10, offset);
2308 DIS_FIELD_MMS(tree, 0x08, offset);
2310 DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
2312 DIS_FIELD_MTI(tree, 0x03, offset);
2315 oct = tvb_get_guint8(tvb, offset);
2317 DIS_FIELD_MR(tree, offset);
2321 dis_field_addr(tvb, tree, &offset, "TP-Recipient-Address");
2323 dis_field_scts(tvb, tree, &offset);
2325 dis_field_dt(tvb, tree, &offset);
2327 oct = tvb_get_guint8(tvb, offset);
2329 dis_field_st(tvb, tree, offset, oct);
2332 pi = tvb_get_guint8(tvb, offset);
2334 dis_field_pi(tvb, tree, offset, pi);
2338 if (length <= (offset - saved_offset))
2340 proto_tree_add_text(tree,
2347 oct = tvb_get_guint8(tvb, offset);
2349 dis_field_pid(tvb, tree, offset, oct);
2354 if (length <= (offset - saved_offset))
2356 proto_tree_add_text(tree,
2363 oct = tvb_get_guint8(tvb, offset);
2365 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2370 if (length <= (offset - saved_offset))
2372 proto_tree_add_text(tree,
2379 oct = tvb_get_guint8(tvb, offset);
2382 DIS_FIELD_UDL(tree, offset);
2389 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2390 seven_bit, eight_bit, ucs2, compressed);
2399 dis_msg_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2401 guint32 saved_offset;
2410 saved_offset = offset;
2411 length = tvb_length_remaining(tvb, offset);
2413 oct = tvb_get_guint8(tvb, offset);
2415 DIS_FIELD_SRR(tree, 0x08, offset);
2417 DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
2419 DIS_FIELD_MTI(tree, 0x03, offset);
2422 oct = tvb_get_guint8(tvb, offset);
2424 DIS_FIELD_MR(tree, offset);
2427 oct = tvb_get_guint8(tvb, offset);
2429 dis_field_pid(tvb, tree, offset, oct);
2432 oct = tvb_get_guint8(tvb, offset);
2434 DIS_FIELD_CT(tree, offset);
2437 oct = tvb_get_guint8(tvb, offset);
2439 DIS_FIELD_MN(tree, offset);
2443 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
2445 oct = tvb_get_guint8(tvb, offset);
2448 DIS_FIELD_CDL(tree, offset);
2454 proto_tree_add_text(tree,
2460 #define NUM_MSGS (sizeof(msg_type_strings)/sizeof(value_string))
2461 static gint ett_msgs[NUM_MSGS];
2462 static void (*gsm_sms_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = {
2463 dis_msg_deliver, /* SMS-DELIVER */
2464 dis_msg_deliver_report, /* SMS-DELIVER REPORT */
2465 dis_msg_submit, /* SMS-SUBMIT */
2466 dis_msg_submit_report, /* SMS-SUBMIT REPORT */
2467 dis_msg_status_report, /* SMS-STATUS REPORT */
2468 dis_msg_command, /* SMS-COMMAND */
2469 NULL, /* Reserved */
2470 NULL, /* Reserved */
2474 /* GENERIC DISSECTOR FUNCTIONS */
2477 dissect_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2479 void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = NULL;
2480 proto_item *gsm_sms_item;
2481 proto_tree *gsm_sms_tree = NULL;
2492 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2494 col_set_str(pinfo->cinfo, COL_PROTOCOL, gsm_sms_proto_name_short);
2497 /* In the interest of speed, if "tree" is NULL, don't do any work not
2498 * necessary to generate protocol tree items.
2506 oct = tvb_get_guint8(tvb, offset);
2512 * convert the 2 bit value to one based on direction
2514 msg_type |= ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x04 : 0x00);
2516 str = my_match_strval(msg_type, msg_type_strings, &idx);
2519 * create the GSM_SMS protocol tree
2522 proto_tree_add_protocol_format(tree, proto_gsm_sms, tvb, 0, -1,
2525 (str == NULL) ? "Unknown message identifier" : str);
2528 proto_item_add_subtree(gsm_sms_item, ett_gsm_sms);
2530 if ((str == NULL) ||
2531 (msg_type == 0x03) ||
2538 ett_msg_idx = ett_msgs[idx];
2539 msg_fcn = gsm_sms_msg_fcn[idx];
2542 if (msg_fcn == NULL)
2544 proto_tree_add_text(gsm_sms_tree,
2546 "Message dissector not implemented");
2550 (*msg_fcn)(tvb, gsm_sms_tree, offset);
2556 /* Register the protocol with Ethereal */
2558 proto_register_gsm_sms(void)
2564 /* Setup list of header fields */
2565 static hf_register_info hf[] =
2570 /* Setup protocol subtree array */
2571 #define NUM_INDIVIDUAL_PARMS 12
2572 static gint *ett[NUM_INDIVIDUAL_PARMS+NUM_MSGS+NUM_UDH_IEIS];
2574 memset((void *) ett, -1, sizeof(ett));
2576 ett[0] = &ett_gsm_sms;
2589 last_offset = NUM_INDIVIDUAL_PARMS;
2591 for (i=0; i < NUM_MSGS; i++, last_offset++)
2593 ett[last_offset] = &ett_msgs[i];
2596 for (i=0; i < NUM_UDH_IEIS; i++, last_offset++)
2598 ett[last_offset] = &ett_udh_ieis[i];
2601 /* Register the protocol name and description */
2604 proto_register_protocol(gsm_sms_proto_name, gsm_sms_proto_name_short, "gsm_sms");
2607 proto_register_field_array(proto_gsm_sms, hf, array_length(hf));
2610 proto_register_subtree_array(ett, array_length(ett));
2615 proto_reg_handoff_gsm_sms(void)
2617 dissector_handle_t gsm_sms_handle;
2619 gsm_sms_handle = create_dissector_handle(dissect_gsm_sms, proto_gsm_sms);
2621 dissector_add("gsm_a.sms_tpdu", 0, gsm_sms_handle);
2622 dissector_add("gsm_map.sms_tpdu", 0, gsm_sms_handle);
2624 data_handle = find_dissector("data");