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.12 2004/04/21 05:53:56 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"
56 #include "packet-gsm_sms.h"
59 /* PROTOTYPES/FORWARDS */
61 #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
62 if ((edc_len) > (edc_max_len)) \
64 proto_tree_add_text(tree, tvb, \
65 offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
68 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
69 if ((sdc_len) < (sdc_min_len)) \
71 proto_tree_add_text(tree, tvb, \
72 offset, (sdc_len), "Short Data (?)"); \
76 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
77 if ((edc_len) != (edc_eq_len)) \
79 proto_tree_add_text(tree, tvb, \
80 offset, (edc_len), "Unexpected Data Length"); \
84 #define SMS_SHIFTMASK(m_val, m_bitmask, m_sval); \
86 int _temp_val = m_val; \
87 int _temp_bm = m_bitmask; \
88 while (_temp_bm && !(_temp_bm & 0x01)) \
90 _temp_bm = _temp_bm >> 1; \
91 _temp_val = _temp_val >> 1; \
97 static char *gsm_sms_proto_name = "GSM SMS TPDU (GSM 03.40)";
98 static char *gsm_sms_proto_name_short = "GSM SMS";
100 /* Initialize the subtree pointers */
101 static gint ett_gsm_sms = -1;
102 static gint ett_pid = -1;
103 static gint ett_pi = -1;
104 static gint ett_fcs = -1;
105 static gint ett_vp = -1;
106 static gint ett_scts = -1;
107 static gint ett_dt = -1;
108 static gint ett_st = -1;
109 static gint ett_addr = -1;
110 static gint ett_dcs = -1;
111 static gint ett_ud = -1;
112 static gint ett_udh = -1;
114 /* Initialize the protocol and registered fields */
115 static int proto_gsm_sms = -1;
117 static char bigbuf[1024];
118 static dissector_handle_t data_handle;
119 static packet_info *g_pinfo;
120 static proto_tree *g_tree;
123 * this is the GSM 03.40 definition with the bit 2
124 * set to 1 for uplink messages
126 static const value_string msg_type_strings[] = {
127 { 0, "SMS-DELIVER" },
128 { 4, "SMS-DELIVER REPORT" },
130 { 1, "SMS-SUBMIT REPORT" },
131 { 2, "SMS-STATUS REPORT" },
132 { 6, "SMS-COMMAND" },
138 #define NUM_UDH_IEIS 256
139 static gint ett_udh_ieis[NUM_UDH_IEIS];
144 my_match_strval(guint32 val, const value_string *vs, gint *idx)
148 while (vs[i].strptr) {
149 if (vs[i].value == val)
152 return(vs[i].strptr);
163 #define DIS_FIELD_MTI(m_tree, m_bitmask, m_offset) \
165 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
166 proto_tree_add_text(m_tree, tvb, \
168 "%s : TP-Message-Type-Indicator", \
173 #define DIS_FIELD_MMS(m_tree, m_bitmask, m_offset) \
175 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
176 proto_tree_add_text(m_tree, tvb, \
178 "%s : TP-More-Messages-to-Send: %s messages are waiting for the MS in this SC", \
180 (oct & m_bitmask) ? "No more" : "More"); \
184 #define DIS_FIELD_VPF(m_tree, m_bitmask, m_offset, m_form) \
186 SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, *m_form); \
189 case 0: str = "TP-VP field not present"; break; \
190 case 1: str = "TP-VP field present - enhanced format"; break; \
191 case 2: str = "TP-VP field present - relative format"; break; \
192 case 3: str = "TP-VP field present - absolute format"; break; \
194 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
195 proto_tree_add_text(m_tree, tvb, \
197 "%s : TP-Validity-Period-Format: %s", \
203 #define DIS_FIELD_SRI(m_tree, m_bitmask, m_offset) \
205 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
206 proto_tree_add_text(m_tree, tvb, \
208 "%s : TP-Status-Report-Indication: A status report shall %sbe returned to the SME", \
210 (oct & m_bitmask) ? "" : "not "); \
214 #define DIS_FIELD_SRR(m_tree, m_bitmask, m_offset) \
216 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
217 proto_tree_add_text(m_tree, tvb, \
219 "%s : TP-Status-Report-Request: A status report is %srequested", \
221 (oct & m_bitmask) ? "" : "not "); \
225 #define DIS_FIELD_MR(m_tree, m_offset) \
227 proto_tree_add_text(m_tree, tvb, \
229 "TP-Message-Reference %d", \
234 dis_field_addr(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, gchar *title)
236 static gchar digit_table[] = {"0123456789*#abc\0"};
238 proto_tree *subtree = NULL;
249 oct = tvb_get_guint8(tvb, offset);
250 numdigocts = (oct + 1) / 2;
252 length = tvb_length_remaining(tvb, offset);
254 if (length <= numdigocts)
256 proto_tree_add_text(tree,
258 "%s: Short Data (?)",
266 proto_tree_add_text(tree, tvb,
267 offset, numdigocts + 2,
270 subtree = proto_item_add_subtree(item, ett_addr);
272 proto_tree_add_text(subtree,
274 "Length: %d address digits",
278 oct = tvb_get_guint8(tvb, offset);
280 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
281 proto_tree_add_text(subtree, tvb,
285 (oct & 0x80) ? "No extension" : "Extended");
287 switch ((oct & 0x70) >> 4)
289 case 0x00: str = "Unknown"; break;
290 case 0x01: str = "International"; break;
291 case 0x02: str = "National"; break;
292 case 0x07: str = "Reserved for extension"; break;
293 default: str = "Unknown, reserved (?)"; break;
296 other_decode_bitfield_value(bigbuf, oct, 0x70, 8);
297 proto_tree_add_text(subtree,
299 "%s : Type of number: (%d) %s",
306 case 0x00: str = "Unknown"; break;
307 case 0x01: str = "ISDN/telephone"; break;
308 case 0x0f: str = "Reserved for extension"; break;
309 default: str = "Unknown, reserved (?)"; break;
312 other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
313 proto_tree_add_text(subtree,
315 "%s : Numbering plan: (%d) %s",
323 for (i = 0; i < numdigocts; i++)
325 oct = tvb_get_guint8(tvb, offset + i);
327 bigbuf[j++] = digit_table[oct & 0x0f];
328 bigbuf[j++] = digit_table[(oct & 0xf0) >> 4];
333 proto_tree_add_text(subtree,
334 tvb, offset, numdigocts,
338 proto_item_append_text(item, " - (%s)", bigbuf);
340 *offset_p = offset + i;
344 /* use dis_field_addr() */
347 /* use dis_field_addr() */
351 dis_field_pid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
354 proto_tree *subtree = NULL;
361 proto_tree_add_text(tree, tvb,
363 "TP-Protocol-Identifier");
365 subtree = proto_item_add_subtree(item, ett_pid);
367 form = (oct & 0xc0) >> 6;
372 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
373 proto_tree_add_text(subtree, tvb,
375 "%s : defines formatting for subsequent bits",
378 other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
379 proto_tree_add_text(subtree, tvb,
384 "telematic interworking" :
385 "no telematic interworking, but SME-to-SME protocol");
389 telematic = oct & 0x1f;
393 case 0x00: str = "implicit - device type is specific to this SC, or can be concluded on the basis of the address"; break;
394 case 0x01: str = "telex (or teletex reduced to telex format)"; break;
395 case 0x02: str = "group 3 telefax"; break;
396 case 0x03: str = "group 4 telefax"; break;
397 case 0x04: str = "voice telephone (i.e. conversion to speech)"; break;
398 case 0x05: str = "ERMES (European Radio Messaging System)"; break;
399 case 0x06: str = "National Paging system (known to the SC)"; break;
400 case 0x07: str = "Videotex (T.100 [20] /T.101 [21])"; break;
401 case 0x08: str = "teletex, carrier unspecified"; break;
402 case 0x09: str = "teletex, in PSPDN"; break;
403 case 0x0a: str = "teletex, in CSPDN"; break;
404 case 0x0b: str = "teletex, in analog PSTN"; break;
405 case 0x0c: str = "teletex, in digital ISDN"; break;
406 case 0x0d: str = "UCI (Universal Computer Interface, ETSI DE/PS 3 01-3)"; break;
407 case 0x10: str = "a message handling facility (known to the SC)"; break;
408 case 0x11: str = "any public X.400-based message handling system"; break;
409 case 0x12: str = "Internet Electronic Mail"; break;
410 case 0x1f: str = "A GSM/UMTS mobile station"; break;
412 if ((telematic >= 0x18) &&
415 str = "values specific to each SC";
424 other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
425 proto_tree_add_text(subtree, tvb,
427 "%s : device type: (%d) %s",
434 other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
435 proto_tree_add_text(subtree, tvb,
437 "%s : the SM-AL protocol being used between the SME and the MS (%d)",
444 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
445 proto_tree_add_text(subtree, tvb,
447 "%s : defines formatting for subsequent bits",
452 case 0x00: str = "Short Message Type 0"; break;
453 case 0x01: str = "Replace Short Message Type 1"; break;
454 case 0x02: str = "Replace Short Message Type 2"; break;
455 case 0x03: str = "Replace Short Message Type 3"; break;
456 case 0x04: str = "Replace Short Message Type 4"; break;
457 case 0x05: str = "Replace Short Message Type 5"; break;
458 case 0x06: str = "Replace Short Message Type 6"; break;
459 case 0x07: str = "Replace Short Message Type 7"; break;
460 case 0x1e: str = "Enhanced Message Service (Obsolete)"; break;
461 case 0x1f: str = "Return Call Message"; break;
462 case 0x3c: str = "ANSI-136 R-DATA"; break;
463 case 0x3d: str = "ME Data download"; break;
464 case 0x3e: str = "ME De-personalization Short Message"; break;
465 case 0x3f: str = "(U)SIM Data download"; break;
467 str = "Reserved"; break;
470 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
471 proto_tree_add_text(subtree, tvb,
480 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
481 proto_tree_add_text(subtree, tvb,
486 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
487 proto_tree_add_text(subtree, tvb,
494 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
495 proto_tree_add_text(subtree, tvb,
497 "%s : bits 0-5 for SC specific use",
500 other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
501 proto_tree_add_text(subtree, tvb,
511 dis_field_dcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct,
512 gboolean *seven_bit, gboolean *eight_bit, gboolean *ucs2, gboolean *compressed)
515 proto_tree *subtree = NULL;
518 gboolean default_5_bits;
519 gboolean default_3_bits;
520 gboolean default_data;
529 proto_tree_add_text(tree, tvb,
531 "TP-Data-Coding-Scheme (%d)",
534 subtree = proto_item_add_subtree(item, ett_dcs);
538 proto_tree_add_text(subtree, tvb,
540 "Special case, GSM 7 bit default alphabet");
546 default_5_bits = FALSE;
547 default_3_bits = FALSE;
548 default_data = FALSE;
549 form = (oct & 0xc0) >> 6;
554 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
555 proto_tree_add_text(subtree, tvb,
557 "%s : General Data Coding indication",
560 default_5_bits = TRUE;
564 other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
565 proto_tree_add_text(subtree, tvb,
567 "%s : Message Marked for Automatic Deletion Group",
570 default_5_bits = TRUE;
574 /* use top four bits */
575 other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
576 proto_tree_add_text(subtree, tvb,
578 "%s : Reserved coding groups",
583 switch ((oct & 0x30) >> 4)
585 case 0x00: str = "Message Waiting Indication Group: Discard Message (GSM 7 bit default alphabet)";
586 default_3_bits = TRUE;
589 case 0x01: str = "Message Waiting Indication Group: Store Message (GSM 7 bit default alphabet)";
590 default_3_bits = TRUE;
593 case 0x02: str = "Message Waiting Indication Group: Store Message (uncompressed UCS2 alphabet)";
594 default_3_bits = TRUE;
596 case 0x03: str = "Data coding/message class";
601 /* use top four bits */
602 other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
603 proto_tree_add_text(subtree, tvb,
613 other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
614 proto_tree_add_text(subtree, tvb,
616 "%s : Text is %scompressed",
618 (oct & 0x20) ? "" : "not ");
620 *compressed = (oct & 0x20) >> 5;
622 other_decode_bitfield_value(bigbuf, oct, 0x10, 8);
623 proto_tree_add_text(subtree, tvb,
627 (oct & 0x10) ? "Message class is defined below" :
628 "Reserved, no message class");
630 switch ((oct & 0x0c) >> 2)
632 case 0x00: str = "GSM 7 bit default alphabet";
635 case 0x01: str = "8 bit data"; break;
636 case 0x02: str = "UCS2 (16 bit)";
639 case 0x03: str = "Reserved"; break;
642 other_decode_bitfield_value(bigbuf, oct, 0x0c, 8);
643 proto_tree_add_text(subtree, tvb,
645 "%s : Character set: %s",
651 case 0x00: str = "Class 0"; break;
652 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
653 case 0x02: str = "Class 2 (U)SIM specific message"; break;
654 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
657 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
658 proto_tree_add_text(subtree, tvb,
660 "%s : Message Class: %s%s",
663 (oct & 0x10) ? "" : " (reserved)");
665 else if (default_3_bits)
667 other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
668 proto_tree_add_text(subtree, tvb,
670 "%s : Indication Sense: %s",
672 (oct & 0x08) ? "Set Indication Active" : "Set Indication Inactive");
674 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
675 proto_tree_add_text(subtree, tvb,
682 case 0x00: str = "Voicemail Message Waiting"; break;
683 case 0x01: str = "Fax Message Waiting"; break;
684 case 0x02: str = "Electronic Mail Message Waiting"; break;
685 case 0x03: str = "Other Message Waiting"; break;
688 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
689 proto_tree_add_text(subtree, tvb,
695 else if (default_data)
697 other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
698 proto_tree_add_text(subtree, tvb,
703 *seven_bit = !(*eight_bit = (oct & 0x04) ? TRUE : FALSE);
705 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
706 proto_tree_add_text(subtree, tvb,
708 "%s : Message coding: %s",
710 (*eight_bit) ? "8 bit data" : "GSM 7 bit default alphabet");
714 case 0x00: str = "Class 0"; break;
715 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
716 case 0x02: str = "Class 2 (U)SIM specific message"; break;
717 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
720 other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
721 proto_tree_add_text(subtree, tvb,
723 "%s : Message Class: %s",
730 dis_field_scts_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
732 guint8 oct, oct2, oct3;
735 oct = tvb_get_guint8(tvb, offset);
736 oct2 = tvb_get_guint8(tvb, offset+1);
737 oct3 = tvb_get_guint8(tvb, offset+2);
739 proto_tree_add_text(tree,
741 "Year %d%d, Month %d%d, Day %d%d",
751 oct = tvb_get_guint8(tvb, offset);
752 oct2 = tvb_get_guint8(tvb, offset+1);
753 oct3 = tvb_get_guint8(tvb, offset+2);
755 proto_tree_add_text(tree,
757 "Hour %d%d, Minutes %d%d, Seconds %d%d",
767 oct = tvb_get_guint8(tvb, offset);
769 proto_tree_add_text(tree,
777 dis_field_scts(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
780 proto_tree *subtree = NULL;
787 length = tvb_length_remaining(tvb, offset);
791 proto_tree_add_text(tree,
793 "TP-Service-Centre-Time-Stamp: Short Data (?)");
800 proto_tree_add_text(tree, tvb,
802 "TP-Service-Centre-Time-Stamp");
804 subtree = proto_item_add_subtree(item, ett_scts);
806 dis_field_scts_aux(tvb, subtree, *offset_p);
813 dis_field_vp(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, guint8 vp_form)
816 proto_tree *subtree = NULL;
819 guint8 oct, oct2, oct3;
825 if (vp_form == 0x00) return;
836 length = tvb_length_remaining(tvb, offset);
840 proto_tree_add_text(tree,
842 "TP-Validity-Period: Short Data (?)");
849 proto_tree_add_text(tree, tvb,
851 "TP-Validity-Period");
853 subtree = proto_item_add_subtree(item, ett_vp);
855 oct = tvb_get_guint8(tvb, offset);
857 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
858 proto_tree_add_text(subtree, tvb,
862 (oct & 0x80) ? "Extended" : "No extension");
866 proto_tree_add_text(subtree,
868 "Extension not implemented, ignored");
874 other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
875 proto_tree_add_text(subtree, tvb,
879 (oct & 0x40) ? "Single shot SM" : "Not single shot SM");
881 other_decode_bitfield_value(bigbuf, oct, 0x38, 8);
882 proto_tree_add_text(subtree, tvb,
887 loc_form = oct & 0x7;
892 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
893 proto_tree_add_text(subtree, tvb,
895 "%s : No Validity Period specified",
902 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
903 proto_tree_add_text(subtree, tvb,
905 "%s : Validity Period Format: relative",
908 /* go around again */
913 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
914 proto_tree_add_text(subtree, tvb,
916 "%s : Validity Period Format: relative",
920 oct = tvb_get_guint8(tvb, offset);
922 proto_tree_add_text(subtree, tvb,
931 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
932 proto_tree_add_text(subtree, tvb,
934 "%s : Validity Period Format: relative",
938 oct = tvb_get_guint8(tvb, offset);
939 oct2 = tvb_get_guint8(tvb, offset+1);
940 oct3 = tvb_get_guint8(tvb, offset+2);
942 proto_tree_add_text(subtree,
944 "Hour %d%d, Minutes %d%d, Seconds %d%d",
956 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
957 proto_tree_add_text(subtree, tvb,
959 "%s : Validity Period Format: Reserved",
968 oct = tvb_get_guint8(tvb, offset);
972 mins = (oct + 1) * 5;
978 proto_tree_add_text(subtree, tvb,
980 "TP-Validity-Period: %d hours %d minutes",
986 proto_tree_add_text(subtree, tvb,
988 "TP-Validity-Period: %d minutes",
992 else if ((oct >= 144) &&
995 mins = (oct - 143) * 30;
996 hours = 12 + (mins / 60);
999 proto_tree_add_text(subtree, tvb,
1001 "TP-Validity-Period: %d hours %d minutes",
1005 else if ((oct >= 168) &&
1008 proto_tree_add_text(subtree, tvb,
1010 "TP-Validity-Period: %d day(s)",
1013 else if (oct >= 197)
1015 proto_tree_add_text(subtree, tvb,
1017 "TP-Validity-Period: %d week(s)",
1025 length = tvb_length_remaining(tvb, offset);
1029 proto_tree_add_text(tree,
1030 tvb, offset, length,
1031 "TP-Validity-Period: Short Data (?)");
1033 *offset_p += length;
1038 proto_tree_add_text(tree, tvb,
1040 "TP-Validity-Period: absolute");
1042 subtree = proto_item_add_subtree(item, ett_vp);
1044 dis_field_scts_aux(tvb, subtree, *offset_p);
1064 dis_field_dt(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
1067 proto_tree *subtree = NULL;
1074 length = tvb_length_remaining(tvb, offset);
1078 proto_tree_add_text(tree,
1079 tvb, offset, length,
1080 "TP-Discharge-Time: Short Data (?)");
1082 *offset_p += length;
1087 proto_tree_add_text(tree, tvb,
1089 "TP-Discharge-Time");
1091 subtree = proto_item_add_subtree(item, ett_dt);
1093 dis_field_scts_aux(tvb, subtree, *offset_p);
1099 /* use dis_field_addr() */
1103 dis_field_st(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1105 static gchar *sc_complete = "Short message transaction completed";
1106 static gchar *sc_temporary = "Temporary error, SC still trying to transfer SM";
1107 static gchar *sc_perm = "Permanent error, SC is not making any more transfer attempts";
1108 static gchar *sc_tempfin = "Temporary error, SC is not making any more transfer attempts";
1110 proto_tree *subtree = NULL;
1117 proto_tree_add_text(tree, tvb,
1121 subtree = proto_item_add_subtree(item, ett_st);
1123 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1124 proto_tree_add_text(subtree, tvb,
1126 "%s : Definition of bits 0-6: %s",
1128 (oct & 0x80) ? "Reserved" : "as follows");
1134 case 0x00: str2 = sc_complete; str = "Short message received by the SME"; break;
1135 case 0x01: str2 = sc_complete; str = "Short message forwarded by the SC to the SME but the SC is unable to confirm delivery"; break;
1136 case 0x02: str2 = sc_complete; str = "Short message replaced by the SC Reserved values"; break;
1138 case 0x20: str2 = sc_temporary; str = "Congestion"; break;
1139 case 0x21: str2 = sc_temporary; str = "SME busy"; break;
1140 case 0x22: str2 = sc_temporary; str = "No response from SME"; break;
1141 case 0x23: str2 = sc_temporary; str = "Service rejected"; break;
1142 case 0x24: str2 = sc_temporary; str = "Quality of service not available"; break;
1143 case 0x25: str2 = sc_temporary; str = "Error in SME"; break;
1145 case 0x40: str2 = sc_perm; str = "Remote procedure error"; break;
1146 case 0x41: str2 = sc_perm; str = "Incompatible destination"; break;
1147 case 0x42: str2 = sc_perm; str = "Connection rejected by SME"; break;
1148 case 0x43: str2 = sc_perm; str = "Not obtainable"; break;
1149 case 0x44: str2 = sc_perm; str = "Quality of service not available"; break;
1150 case 0x45: str2 = sc_perm; str = "No interworking available"; break;
1151 case 0x46: str2 = sc_perm; str = "SM Validity Period Expired"; break;
1152 case 0x47: str2 = sc_perm; str = "SM Deleted by originating SME"; break;
1153 case 0x48: str2 = sc_perm; str = "SM Deleted by SC Administration"; break;
1154 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;
1156 case 0x60: str2 = sc_tempfin; str = "Congestion"; break;
1157 case 0x61: str2 = sc_tempfin; str = "SME busy"; break;
1158 case 0x62: str2 = sc_tempfin; str = "No response from SME"; break;
1159 case 0x63: str2 = sc_tempfin; str = "Service rejected"; break;
1160 case 0x64: str2 = sc_tempfin; str = "Quality of service not available"; break;
1161 case 0x65: str2 = sc_tempfin; str = "Error in SME"; break;
1164 if ((value >= 0x03) &&
1170 else if ((value >= 0x10) &&
1174 str = "Values specific to each SC";
1176 else if ((value >= 0x26) &&
1179 str2 = sc_temporary;
1182 else if ((value >= 0x30) &&
1185 str2 = sc_temporary;
1186 str = "Values specific to each SC";
1188 else if ((value >= 0x4a) &&
1194 else if ((value >= 0x50) &&
1198 str = "Values specific to each SC";
1200 else if ((value >= 0x66) &&
1206 else if ((value >= 0x70) &&
1210 str = "Values specific to each SC";
1215 other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
1216 proto_tree_add_text(subtree, tvb,
1226 #define DIS_FIELD_UDL(m_tree, m_offset) \
1228 proto_tree_add_text(m_tree, tvb, \
1230 "TP-User-Data-Length: (%d) %s", \
1232 oct ? "depends on Data-Coding-Scheme" : "no User-Data");\
1236 #define DIS_FIELD_RP(m_tree, m_bitmask, m_offset) \
1238 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1239 proto_tree_add_text(m_tree, tvb, \
1241 "%s : TP-Reply-Path: parameter is %sset in this SMS-SUBMIT/DELIVER", \
1243 (oct & m_bitmask) ? "" : "not "); \
1247 #define DIS_FIELD_MN(m_tree, m_offset) \
1249 proto_tree_add_text(m_tree, tvb, \
1251 "TP-Message-Number: %d", \
1256 #define DIS_FIELD_CT(m_tree, m_offset) \
1260 case 0: str = "Enquiry relating to previously submitted short message"; break; \
1261 case 1: str = "Cancel Status Report Request relating to previously submitted short message"; break; \
1262 case 2: str = "Delete previously submitted Short Message"; break; \
1263 case 3: str = "Enable Status Report Request relating to previously submitted short message"; break; \
1265 if ((oct >= 0x04) && \
1268 str = "Reserved unspecified"; \
1270 else if (oct >= 0xe0) \
1272 str = "Values specific for each SC"; \
1276 str = "undefined"; \
1280 proto_tree_add_text(m_tree, tvb, \
1282 "TP-Command-Type: (%d), %s", \
1288 #define DIS_FIELD_CDL(m_tree, m_offset) \
1290 proto_tree_add_text(m_tree, tvb, \
1292 "TP-Command-Data-Length: (%d)%s", \
1294 oct ? "" : " no Command-Data");\
1298 /* done in-line in the message functions */
1302 dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1305 proto_tree *subtree = NULL;
1310 proto_tree_add_text(tree, tvb,
1312 "TP-Failure-Cause");
1314 subtree = proto_item_add_subtree(item, ett_fcs);
1318 case 0x80: str = "Telematic interworking not supported"; break;
1319 case 0x81: str = "Short message Type 0 not supported"; break;
1320 case 0x82: str = "Cannot replace short message"; break;
1321 case 0x8F: str = "Unspecified TP-PID error"; break;
1322 case 0x90: str = "Data coding scheme (alphabet) not supported"; break;
1323 case 0x91: str = "Message class not supported"; break;
1324 case 0x9F: str = "Unspecified TP-DCS error"; break;
1325 case 0xA0: str = "Command cannot be actioned"; break;
1326 case 0xA1: str = "Command unsupported"; break;
1327 case 0xAF: str = "Unspecified TP-Command error"; break;
1328 case 0xB0: str = "TPDU not supported"; break;
1329 case 0xC0: str = "SC busy"; break;
1330 case 0xC1: str = "No SC subscription"; break;
1331 case 0xC2: str = "SC system failure"; break;
1332 case 0xC3: str = "Invalid SME address"; break;
1333 case 0xC4: str = "Destination SME barred"; break;
1334 case 0xC5: str = "SM Rejected-Duplicate SM"; break;
1335 case 0xC6: str = "TP-VPF not supported"; break;
1336 case 0xC7: str = "TP-VP not supported"; break;
1337 case 0xD0: str = "(U)SIM SMS storage full"; break;
1338 case 0xD1: str = "No SMS storage capability in (U)SIM"; break;
1339 case 0xD2: str = "Error in MS"; break;
1340 case 0xD3: str = "Memory Capacity Exceeded"; break;
1341 case 0xD4: str = "(U)SIM Application Toolkit Busy"; break;
1342 case 0xD5: str = "(U)SIM data download error"; break;
1343 case 0xFF: str = "Unspecified error cause"; break;
1345 if ((oct >= 0x80) &&
1348 str = "TP-PID errors"; break;
1350 else if ((oct >= 0x90) &&
1353 str = "TP-DCS errors"; break;
1355 else if ((oct >= 0xA0) &&
1358 str = "TP-Command errors"; break;
1360 else if ((oct >= 0xE0) &&
1363 str = "Values specific to an application"; break;
1367 str = "Reserved"; break;
1371 proto_tree_add_text(subtree, tvb,
1377 #define DIS_FIELD_UDHI(m_tree, m_bitmask, m_offset, m_udhi) \
1379 SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, m_udhi); \
1380 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1381 proto_tree_add_text(m_tree, tvb, \
1383 "%s : TP-User-Data-Header-Indicator: %s short message", \
1386 "The beginning of the TP-UD field contains a Header in addition to the" : \
1387 "The TP-UD field contains only the"); \
1395 #define GN_BYTE_MASK ((1 << bits) - 1)
1398 gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length,
1399 const guint8 *input, unsigned char *output)
1401 unsigned char *out_num = output; /* Current pointer to the output buffer */
1402 const guint8 *in_num = input; /* Current pointer to the input buffer */
1403 unsigned char rest = 0x00;
1406 bits = offset ? offset : 7;
1408 while ((unsigned int)(in_num - input) < in_length)
1410 *out_num = ((*in_num & GN_BYTE_MASK) << (7 - bits)) | rest;
1411 rest = *in_num >> bits;
1413 /* If we don't start from 0th bit, we shouldn't go to the
1414 next char. Under *out_num we have now 0 and under Rest -
1415 _first_ part of the char. */
1416 if ((in_num != input) || (bits == 7)) out_num++;
1419 if ((unsigned int)(out_num - output) >= out_length) break;
1421 /* After reading 7 octets we have read 7 full characters but
1422 we have 7 bits as well. This is the next character */
1436 return out_num - output;
1439 #define GN_CHAR_ALPHABET_SIZE 128
1441 #define GN_CHAR_ESCAPE 0x1b
1443 static unsigned char gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
1445 /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
1446 /* Characters in hex position 10, [12 to 1a] and 24 are not present on
1447 latin1 charset, so we cannot reproduce on the screen, however they are
1448 greek symbol not present even on my Nokia */
1450 '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
1451 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
1452 '?', '_', '?', '?', '?', '?', '?', '?',
1453 '?', '?', '?', '?', 0xc6, 0xe6, 0xdf, 0xc9,
1454 ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
1455 '(', ')', '*', '+', ',', '-', '.', '/',
1456 '0', '1', '2', '3', '4', '5', '6', '7',
1457 '8', '9', ':', ';', '<', '=', '>', '?',
1458 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
1459 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
1460 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
1461 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
1462 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
1463 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
1464 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
1465 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
1469 char_is_escape(unsigned char value)
1471 return (value == GN_CHAR_ESCAPE);
1474 static unsigned char
1475 char_def_alphabet_ext_decode(unsigned char value)
1479 case 0x0a: return 0x0c; break; /* form feed */
1480 case 0x14: return '^'; break;
1481 case 0x28: return '{'; break;
1482 case 0x29: return '}'; break;
1483 case 0x2f: return '\\'; break;
1484 case 0x3c: return '['; break;
1485 case 0x3d: return '~'; break;
1486 case 0x3e: return ']'; break;
1487 case 0x40: return '|'; break;
1488 case 0x65: return 0xa4; break; /* euro */
1489 default: return '?'; break; /* invalid character */
1493 static unsigned char
1494 char_def_alphabet_decode(unsigned char value)
1496 if (value < GN_CHAR_ALPHABET_SIZE)
1498 return gsm_default_alphabet[value];
1507 gsm_sms_char_ascii_decode(unsigned char* dest, const unsigned char* src, int len)
1511 for (i = 0, j = 0; j < len; i++, j++)
1513 if (char_is_escape(src[j]))
1514 dest[i] = char_def_alphabet_ext_decode(src[++j]);
1516 dest[i] = char_def_alphabet_decode(src[j]);
1527 dis_iei_apa_8bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1533 EXACT_DATA_CHECK(length, 2);
1535 oct = tvb_get_guint8(tvb, offset);
1543 str = "Available for allocation by applications";
1546 proto_tree_add_text(tree,
1548 "Destination port: %d, %s",
1553 oct = tvb_get_guint8(tvb, offset);
1561 str = "Available for allocation by applications";
1564 proto_tree_add_text(tree,
1566 "Originator port: %d, %s",
1572 dis_iei_apa_16bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1578 EXACT_DATA_CHECK(length, 4);
1580 value = tvb_get_ntohs(tvb, offset);
1584 str = "As allocated by IANA (http://www.IANA.com/)";
1586 else if (value < 17000)
1588 str = "Available for allocation by applications";
1595 proto_tree_add_text(tree,
1597 "Destination port: %d, %s",
1602 value = tvb_get_ntohs(tvb, offset);
1606 str = "As allocated by IANA (http://www.IANA.com/)";
1608 else if (value < 17000)
1610 str = "Available for allocation by applications";
1617 proto_tree_add_text(tree,
1619 "Originator port: %d, %s",
1625 dis_field_ud_iei(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1627 void (*iei_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length);
1630 proto_tree *subtree = NULL;
1639 oct = tvb_get_guint8(tvb, offset);
1643 case 0x00: str = "Concatenated short messages, 8-bit reference number (SMS Control)"; break;
1644 case 0x01: str = "Special SMS Message Indication (SMS Control)"; break;
1645 case 0x02: str = "Reserved N/A"; break;
1646 case 0x03: str = "Value not used to avoid misinterpretation as <LF> character N/A"; break;
1647 case 0x04: str = "Application port addressing scheme, 8 bit address (SMS Control)"; iei_fcn = dis_iei_apa_8bit; break;
1648 case 0x05: str = "Application port addressing scheme, 16 bit address (SMS Control)"; iei_fcn = dis_iei_apa_16bit; break;
1649 case 0x06: str = "SMSC Control Parameters (SMS Control)"; break;
1650 case 0x07: str = "UDH Source Indicator (SMS Control)"; break;
1651 case 0x08: str = "Concatenated short message, 16-bit reference number (SMS Control)"; break;
1652 case 0x09: str = "Wireless Control Message Protocol (SMS Control)"; break;
1653 case 0x0A: str = "Text Formatting (EMS Control)"; break;
1654 case 0x0B: str = "Predefined Sound (EMS Content)"; break;
1655 case 0x0C: str = "User Defined Sound (iMelody max 128 bytes) (EMS Content)"; break;
1656 case 0x0D: str = "Predefined Animation (EMS Content)"; break;
1657 case 0x0E: str = "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)"; break;
1658 case 0x0F: str = "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)"; break;
1659 case 0x10: str = "Large Picture (32*32 = 128 bytes) (EMS Content)"; break;
1660 case 0x11: str = "Small Picture (16*16 = 32 bytes) (EMS Content)"; break;
1661 case 0x12: str = "Variable Picture (EMS Content)"; break;
1662 case 0x13: str = "User prompt indicator (EMS Control)"; break;
1663 case 0x14: str = "Extended Object (EMS Content)"; break;
1664 case 0x15: str = "Reused Extended Object (EMS Control)"; break;
1665 case 0x16: str = "Compression Control (EMS Control)"; break;
1666 case 0x17: str = "Object Distribution Indicator (EMS Control)"; break;
1667 case 0x18: str = "Standard WVG object (EMS Content)"; break;
1668 case 0x19: str = "Character Size WVG object (EMS Content)"; break;
1669 case 0x1A: str = "Extended Object Data Request Command (EMS Control)"; break;
1670 case 0x20: str = "RFC 822 E-Mail Header (SMS Control)"; break;
1671 case 0x21: str = "Hyperlink format element (SMS Control)"; break;
1672 case 0x22: str = "Reply Address Element (SMS Control)"; break;
1674 if ((oct >= 0x1b) &&
1677 str = "Reserved for future EMS features (see subclause 3.10) N/A"; break;
1679 else if ((oct >= 0x23) &&
1682 str = "Reserved for future use N/A"; break;
1684 else if ((oct >= 0x70) &&
1687 str = "(U)SIM Toolkit Security Headers (SMS Control)"; break;
1689 else if ((oct >= 0x80) &&
1692 str = "SME to SME specific use (SMS Control)"; break;
1694 else if ((oct >= 0xa0) &&
1697 str = "Reserved for future use N/A"; break;
1699 else if ((oct >= 0xc0) &&
1702 str = "SC specific use (SMS Control)"; break;
1706 str = "Reserved for future use N/A"; break;
1710 iei_len = tvb_get_guint8(tvb, offset + 1);
1713 proto_tree_add_text(tree,
1714 tvb, offset, iei_len + 2,
1718 subtree = proto_item_add_subtree(item, ett_udh_ieis[oct]);
1720 proto_tree_add_text(subtree,
1722 "Information Element Identifier: %d",
1727 proto_tree_add_text(subtree,
1736 if (iei_fcn == NULL)
1738 proto_tree_add_text(subtree,
1739 tvb, offset, iei_len,
1744 iei_fcn(tvb, subtree, offset, iei_len);
1748 length -= 2 + iei_len;
1755 dis_field_ud(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 length, gboolean udhi, guint8 udl,
1756 gboolean seven_bit, gboolean eight_bit, gboolean ucs2, gboolean compressed)
1758 static guint8 fill_bits_mask[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };
1760 proto_item *udh_item;
1761 proto_tree *subtree = NULL;
1762 proto_tree *udh_subtree = NULL;
1771 proto_tree_add_text(tree, tvb,
1775 subtree = proto_item_add_subtree(item, ett_ud);
1777 oct = tvb_get_guint8(tvb, offset);
1781 /* step over header */
1784 proto_tree_add_text(subtree, tvb,
1786 "User-Data Header");
1788 udh_subtree = proto_item_add_subtree(udh_item, ett_udh);
1790 proto_tree_add_text(udh_subtree,
1792 "User Data Header Length (%d)",
1799 dis_field_ud_iei(tvb, udh_subtree, offset, oct);
1807 /* step over fill bits ? */
1809 fill_bits = 7 - (((oct + 1) * 8) % 7);
1812 oct = tvb_get_guint8(tvb, offset);
1814 other_decode_bitfield_value(bigbuf, oct, fill_bits_mask[fill_bits], 8);
1815 proto_tree_add_text(udh_subtree,
1825 proto_tree_add_text(subtree, tvb,
1834 gsm_sms_char_7bit_unpack(fill_bits, length, sizeof(bigbuf),
1835 tvb_get_ptr(tvb, offset, length), bigbuf);
1836 bigbuf[out_len] = '\0';
1837 gsm_sms_char_ascii_decode(bigbuf, bigbuf, out_len);
1840 proto_tree_add_text(subtree, tvb, offset, length, "%s", bigbuf);
1844 proto_tree_add_text(subtree, tvb, offset, length, "%s",
1845 tvb_format_text(tvb, offset, length));
1849 ustr = tvb_fake_unicode(tvb, offset, length, FALSE);
1850 proto_tree_add_text(subtree, tvb, offset, length, "%s", ustr);
1857 #define DIS_FIELD_RD(m_tree, m_bitmask, m_offset) \
1859 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1860 proto_tree_add_text(m_tree, tvb, \
1862 "%s : TP-Reject-Duplicates: Instruct SC to %s duplicates", \
1864 (oct & m_bitmask) ? \
1870 #define DIS_FIELD_SRQ(m_tree, m_bitmask, m_offset) \
1872 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1873 proto_tree_add_text(m_tree, tvb, \
1875 "%s : TP-Status-Report-Qualifier: The SMS-STATUS-REPORT is the result of %s", \
1877 (oct & m_bitmask) ? \
1878 "an SMS-COMMAND e.g. an Enquiry" : \
1884 dis_field_pi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1887 proto_tree *subtree = NULL;
1891 proto_tree_add_text(tree, tvb,
1893 "TP-Parameter-Indicator");
1895 subtree = proto_item_add_subtree(item, ett_pi);
1897 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1898 proto_tree_add_text(subtree, tvb,
1902 (oct & 0x80) ? "Extended" : "No extension");
1904 other_decode_bitfield_value(bigbuf, oct, 0x78, 8);
1905 proto_tree_add_text(subtree, tvb,
1910 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
1911 proto_tree_add_text(subtree, tvb,
1913 "%s : TP-UDL %spresent",
1915 (oct & 0x04) ? "" : "not ");
1917 other_decode_bitfield_value(bigbuf, oct, 0x02, 8);
1918 proto_tree_add_text(subtree, tvb,
1920 "%s : TP-DCS %spresent",
1922 (oct & 0x02) ? "" : "not ");
1924 other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
1925 proto_tree_add_text(subtree, tvb,
1927 "%s : TP-PID %spresent",
1929 (oct & 0x01) ? "" : "not ");
1937 dis_msg_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
1939 guint32 saved_offset;
1946 gboolean compressed;
1950 saved_offset = offset;
1951 length = tvb_length_remaining(tvb, offset);
1953 oct = tvb_get_guint8(tvb, offset);
1955 DIS_FIELD_SRI(tree, 0x20, offset);
1957 DIS_FIELD_UDHI(tree, 0x10, offset, udhi);
1959 DIS_FIELD_RP(tree, 0x08, offset);
1961 DIS_FIELD_MMS(tree, 0x04, offset);
1963 DIS_FIELD_MTI(tree, 0x03, offset);
1967 dis_field_addr(tvb, tree, &offset, "TP-Originating-Address");
1969 oct = tvb_get_guint8(tvb, offset);
1971 dis_field_pid(tvb, tree, offset, oct);
1974 oct = tvb_get_guint8(tvb, offset);
1976 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
1979 dis_field_scts(tvb, tree, &offset);
1981 oct = tvb_get_guint8(tvb, offset);
1984 DIS_FIELD_UDL(tree, offset);
1990 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
1991 seven_bit, eight_bit, ucs2, compressed);
2000 dis_msg_deliver_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2002 guint32 saved_offset;
2010 gboolean compressed;
2015 saved_offset = offset;
2016 length = tvb_length_remaining(tvb, offset);
2018 oct = tvb_get_guint8(tvb, offset);
2020 DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
2022 DIS_FIELD_MTI(tree, 0x03, offset);
2026 proto_tree_add_text(tree,
2027 tvb, offset, length,
2033 * there does not seem to be a way to determine that this
2034 * deliver report is from an RP-ERROR or RP-ACK other
2035 * than to look at the next octet
2037 * FCS values are 0x80 and higher
2038 * PI uses bit 7 as an extension indicator
2040 * will assume that if bit 7 is set then this octet
2041 * is an FCS otherwise PI
2044 oct = tvb_get_guint8(tvb, offset);
2048 dis_field_fcs(tvb, tree, offset, oct);
2052 pi = tvb_get_guint8(tvb, offset);
2054 dis_field_pi(tvb, tree, offset, pi);
2058 if (length <= (offset - saved_offset))
2060 proto_tree_add_text(tree,
2067 oct = tvb_get_guint8(tvb, offset);
2069 dis_field_pid(tvb, tree, offset, oct);
2074 if (length <= (offset - saved_offset))
2076 proto_tree_add_text(tree,
2083 oct = tvb_get_guint8(tvb, offset);
2085 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2090 if (length <= (offset - saved_offset))
2092 proto_tree_add_text(tree,
2099 oct = tvb_get_guint8(tvb, offset);
2102 DIS_FIELD_UDL(tree, offset);
2109 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2110 seven_bit, eight_bit, ucs2, compressed);
2119 dis_msg_submit(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2121 guint32 saved_offset;
2130 gboolean compressed;
2134 saved_offset = offset;
2135 length = tvb_length_remaining(tvb, offset);
2137 oct = tvb_get_guint8(tvb, offset);
2139 DIS_FIELD_SRR(tree, 0x80, offset);
2141 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2143 DIS_FIELD_RP(tree, 0x20, offset);
2145 DIS_FIELD_VPF(tree, 0x18, offset, &vp_form);
2147 DIS_FIELD_RD(tree, 0x04, offset);
2149 DIS_FIELD_MTI(tree, 0x03, offset);
2152 oct = tvb_get_guint8(tvb, offset);
2154 DIS_FIELD_MR(tree, offset);
2158 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
2160 oct = tvb_get_guint8(tvb, offset);
2162 dis_field_pid(tvb, tree, offset, oct);
2165 oct = tvb_get_guint8(tvb, offset);
2167 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2170 dis_field_vp(tvb, tree, &offset, vp_form);
2172 oct = tvb_get_guint8(tvb, offset);
2175 DIS_FIELD_UDL(tree, offset);
2181 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2182 seven_bit, eight_bit, ucs2, compressed);
2191 dis_msg_submit_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2193 guint32 saved_offset;
2201 gboolean compressed;
2206 saved_offset = offset;
2207 length = tvb_length_remaining(tvb, offset);
2209 oct = tvb_get_guint8(tvb, offset);
2211 DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
2213 DIS_FIELD_MTI(tree, 0x03, offset);
2216 * there does not seem to be a way to determine that this
2217 * deliver report is from an RP-ERROR or RP-ACK other
2218 * than to look at the next octet
2220 * FCS values are 0x80 and higher
2221 * PI uses bit 7 as an extension indicator
2223 * will assume that if bit 7 is set then this octet
2224 * is an FCS otherwise PI
2227 oct = tvb_get_guint8(tvb, offset);
2231 dis_field_fcs(tvb, tree, offset, oct);
2235 pi = tvb_get_guint8(tvb, offset);
2237 dis_field_pi(tvb, tree, offset, pi);
2240 dis_field_scts(tvb, tree, &offset);
2244 if (length <= (offset - saved_offset))
2246 proto_tree_add_text(tree,
2253 oct = tvb_get_guint8(tvb, offset);
2255 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2260 if (length <= (offset - saved_offset))
2262 proto_tree_add_text(tree,
2269 oct = tvb_get_guint8(tvb, offset);
2272 DIS_FIELD_UDL(tree, offset);
2279 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2280 seven_bit, eight_bit, ucs2, compressed);
2289 dis_msg_status_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2291 guint32 saved_offset;
2299 gboolean compressed;
2304 saved_offset = offset;
2305 length = tvb_length_remaining(tvb, offset);
2307 oct = tvb_get_guint8(tvb, offset);
2309 DIS_FIELD_SRQ(tree, 0x10, offset);
2311 DIS_FIELD_MMS(tree, 0x08, offset);
2313 DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
2315 DIS_FIELD_MTI(tree, 0x03, offset);
2318 oct = tvb_get_guint8(tvb, offset);
2320 DIS_FIELD_MR(tree, offset);
2324 dis_field_addr(tvb, tree, &offset, "TP-Recipient-Address");
2326 dis_field_scts(tvb, tree, &offset);
2328 dis_field_dt(tvb, tree, &offset);
2330 oct = tvb_get_guint8(tvb, offset);
2332 dis_field_st(tvb, tree, offset, oct);
2335 pi = tvb_get_guint8(tvb, offset);
2337 dis_field_pi(tvb, tree, offset, pi);
2341 if (length <= (offset - saved_offset))
2343 proto_tree_add_text(tree,
2350 oct = tvb_get_guint8(tvb, offset);
2352 dis_field_pid(tvb, tree, offset, oct);
2357 if (length <= (offset - saved_offset))
2359 proto_tree_add_text(tree,
2366 oct = tvb_get_guint8(tvb, offset);
2368 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2373 if (length <= (offset - saved_offset))
2375 proto_tree_add_text(tree,
2382 oct = tvb_get_guint8(tvb, offset);
2385 DIS_FIELD_UDL(tree, offset);
2392 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2393 seven_bit, eight_bit, ucs2, compressed);
2402 dis_msg_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2404 guint32 saved_offset;
2413 saved_offset = offset;
2414 length = tvb_length_remaining(tvb, offset);
2416 oct = tvb_get_guint8(tvb, offset);
2418 DIS_FIELD_SRR(tree, 0x08, offset);
2420 DIS_FIELD_UDHI(tree, 0x04, offset, udhi);
2422 DIS_FIELD_MTI(tree, 0x03, offset);
2425 oct = tvb_get_guint8(tvb, offset);
2427 DIS_FIELD_MR(tree, offset);
2430 oct = tvb_get_guint8(tvb, offset);
2432 dis_field_pid(tvb, tree, offset, oct);
2435 oct = tvb_get_guint8(tvb, offset);
2437 DIS_FIELD_CT(tree, offset);
2440 oct = tvb_get_guint8(tvb, offset);
2442 DIS_FIELD_MN(tree, offset);
2446 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
2448 oct = tvb_get_guint8(tvb, offset);
2451 DIS_FIELD_CDL(tree, offset);
2457 proto_tree_add_text(tree,
2463 #define NUM_MSGS (sizeof(msg_type_strings)/sizeof(value_string))
2464 static gint ett_msgs[NUM_MSGS];
2465 static void (*gsm_sms_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = {
2466 dis_msg_deliver, /* SMS-DELIVER */
2467 dis_msg_deliver_report, /* SMS-DELIVER REPORT */
2468 dis_msg_submit, /* SMS-SUBMIT */
2469 dis_msg_submit_report, /* SMS-SUBMIT REPORT */
2470 dis_msg_status_report, /* SMS-STATUS REPORT */
2471 dis_msg_command, /* SMS-COMMAND */
2472 NULL, /* Reserved */
2473 NULL, /* Reserved */
2477 /* GENERIC DISSECTOR FUNCTIONS */
2480 dissect_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2482 void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = NULL;
2483 proto_item *gsm_sms_item;
2484 proto_tree *gsm_sms_tree = NULL;
2495 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2497 col_set_str(pinfo->cinfo, COL_PROTOCOL, gsm_sms_proto_name_short);
2500 /* In the interest of speed, if "tree" is NULL, don't do any work not
2501 * necessary to generate protocol tree items.
2509 oct = tvb_get_guint8(tvb, offset);
2515 * convert the 2 bit value to one based on direction
2517 msg_type |= ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x04 : 0x00);
2519 str = my_match_strval(msg_type, msg_type_strings, &idx);
2522 * create the GSM_SMS protocol tree
2525 proto_tree_add_protocol_format(tree, proto_gsm_sms, tvb, 0, -1,
2528 (str == NULL) ? "Unknown message identifier" : str);
2531 proto_item_add_subtree(gsm_sms_item, ett_gsm_sms);
2533 if ((str == NULL) ||
2534 (msg_type == 0x03) ||
2541 ett_msg_idx = ett_msgs[idx];
2542 msg_fcn = gsm_sms_msg_fcn[idx];
2545 if (msg_fcn == NULL)
2547 proto_tree_add_text(gsm_sms_tree,
2549 "Message dissector not implemented");
2553 (*msg_fcn)(tvb, gsm_sms_tree, offset);
2559 /* Register the protocol with Ethereal */
2561 proto_register_gsm_sms(void)
2567 /* Setup list of header fields */
2568 static hf_register_info hf[] =
2573 /* Setup protocol subtree array */
2574 #define NUM_INDIVIDUAL_PARMS 12
2575 static gint *ett[NUM_INDIVIDUAL_PARMS+NUM_MSGS+NUM_UDH_IEIS];
2577 ett[0] = &ett_gsm_sms;
2590 last_offset = NUM_INDIVIDUAL_PARMS;
2592 for (i=0; i < NUM_MSGS; i++, last_offset++)
2595 ett[last_offset] = &ett_msgs[i];
2598 for (i=0; i < NUM_UDH_IEIS; i++, last_offset++)
2600 ett_udh_ieis[i] = -1;
2601 ett[last_offset] = &ett_udh_ieis[i];
2604 /* Register the protocol name and description */
2607 proto_register_protocol(gsm_sms_proto_name, gsm_sms_proto_name_short, "gsm_sms");
2610 proto_register_field_array(proto_gsm_sms, hf, array_length(hf));
2613 proto_register_subtree_array(ett, array_length(ett));
2618 proto_reg_handoff_gsm_sms(void)
2620 dissector_handle_t gsm_sms_handle;
2622 gsm_sms_handle = create_dissector_handle(dissect_gsm_sms, proto_gsm_sms);
2624 dissector_add("gsm_a.sms_tpdu", 0, gsm_sms_handle);
2625 dissector_add("gsm_map.sms_tpdu", 0, gsm_sms_handle);
2627 data_handle = find_dissector("data");