2 * Routines for GSM SMS TPDU (GSM 03.40) dissection
4 * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
5 * In association with Telos Technology Inc.
7 * TPDU User-Data unpack routines from GNOKII.
10 * Universal Mobile Telecommunications System (UMTS);
11 * Technical realization of Short Message Service (SMS)
12 * (3GPP TS 23.040 version 5.4.0 Release 5)
16 * 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"
54 #include <epan/prefs.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;
736 oct = tvb_get_guint8(tvb, offset);
737 oct2 = tvb_get_guint8(tvb, offset+1);
738 oct3 = tvb_get_guint8(tvb, offset+2);
740 proto_tree_add_text(tree,
742 "Year %d%d, Month %d%d, Day %d%d",
752 oct = tvb_get_guint8(tvb, offset);
753 oct2 = tvb_get_guint8(tvb, offset+1);
754 oct3 = tvb_get_guint8(tvb, offset+2);
756 proto_tree_add_text(tree,
758 "Hour %d%d, Minutes %d%d, Seconds %d%d",
768 oct = tvb_get_guint8(tvb, offset);
770 sign = (oct & 0x08)?'-':'+';
771 oct = ((oct >> 4) + (oct & 0x07) * 10) * 15;
773 proto_tree_add_text(tree,
775 "Timezone: GMT %c %d hours %d minutes",
776 sign, oct / 60, oct % 60);
781 dis_field_scts(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
784 proto_tree *subtree = NULL;
791 length = tvb_length_remaining(tvb, offset);
795 proto_tree_add_text(tree,
797 "TP-Service-Centre-Time-Stamp: Short Data (?)");
804 proto_tree_add_text(tree, tvb,
806 "TP-Service-Centre-Time-Stamp");
808 subtree = proto_item_add_subtree(item, ett_scts);
810 dis_field_scts_aux(tvb, subtree, *offset_p);
817 dis_field_vp(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, guint8 vp_form)
820 proto_tree *subtree = NULL;
823 guint8 oct, oct2, oct3;
829 if (vp_form == 0x00) return;
840 length = tvb_length_remaining(tvb, offset);
844 proto_tree_add_text(tree,
846 "TP-Validity-Period: Short Data (?)");
853 proto_tree_add_text(tree, tvb,
855 "TP-Validity-Period");
857 subtree = proto_item_add_subtree(item, ett_vp);
859 oct = tvb_get_guint8(tvb, offset);
861 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
862 proto_tree_add_text(subtree, tvb,
866 (oct & 0x80) ? "Extended" : "No extension");
870 proto_tree_add_text(subtree,
872 "Extension not implemented, ignored");
878 other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
879 proto_tree_add_text(subtree, tvb,
883 (oct & 0x40) ? "Single shot SM" : "Not single shot SM");
885 other_decode_bitfield_value(bigbuf, oct, 0x38, 8);
886 proto_tree_add_text(subtree, tvb,
891 loc_form = oct & 0x7;
896 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
897 proto_tree_add_text(subtree, tvb,
899 "%s : No Validity Period specified",
906 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
907 proto_tree_add_text(subtree, tvb,
909 "%s : Validity Period Format: relative",
912 /* go around again */
917 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
918 proto_tree_add_text(subtree, tvb,
920 "%s : Validity Period Format: relative",
924 oct = tvb_get_guint8(tvb, offset);
926 proto_tree_add_text(subtree, tvb,
935 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
936 proto_tree_add_text(subtree, tvb,
938 "%s : Validity Period Format: relative",
942 oct = tvb_get_guint8(tvb, offset);
943 oct2 = tvb_get_guint8(tvb, offset+1);
944 oct3 = tvb_get_guint8(tvb, offset+2);
946 proto_tree_add_text(subtree,
948 "Hour %d%d, Minutes %d%d, Seconds %d%d",
960 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
961 proto_tree_add_text(subtree, tvb,
963 "%s : Validity Period Format: Reserved",
972 oct = tvb_get_guint8(tvb, offset);
976 mins = (oct + 1) * 5;
982 proto_tree_add_text(subtree, tvb,
984 "TP-Validity-Period: %d hours %d minutes",
990 proto_tree_add_text(subtree, tvb,
992 "TP-Validity-Period: %d minutes",
996 else if ((oct >= 144) &&
999 mins = (oct - 143) * 30;
1000 hours = 12 + (mins / 60);
1003 proto_tree_add_text(subtree, tvb,
1005 "TP-Validity-Period: %d hours %d minutes",
1009 else if ((oct >= 168) &&
1012 proto_tree_add_text(subtree, tvb,
1014 "TP-Validity-Period: %d day(s)",
1017 else if (oct >= 197)
1019 proto_tree_add_text(subtree, tvb,
1021 "TP-Validity-Period: %d week(s)",
1029 length = tvb_length_remaining(tvb, offset);
1033 proto_tree_add_text(tree,
1034 tvb, offset, length,
1035 "TP-Validity-Period: Short Data (?)");
1037 *offset_p += length;
1042 proto_tree_add_text(tree, tvb,
1044 "TP-Validity-Period: absolute");
1046 subtree = proto_item_add_subtree(item, ett_vp);
1048 dis_field_scts_aux(tvb, subtree, *offset_p);
1068 dis_field_dt(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
1071 proto_tree *subtree = NULL;
1078 length = tvb_length_remaining(tvb, offset);
1082 proto_tree_add_text(tree,
1083 tvb, offset, length,
1084 "TP-Discharge-Time: Short Data (?)");
1086 *offset_p += length;
1091 proto_tree_add_text(tree, tvb,
1093 "TP-Discharge-Time");
1095 subtree = proto_item_add_subtree(item, ett_dt);
1097 dis_field_scts_aux(tvb, subtree, *offset_p);
1103 /* use dis_field_addr() */
1107 dis_field_st(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1109 static gchar *sc_complete = "Short message transaction completed";
1110 static gchar *sc_temporary = "Temporary error, SC still trying to transfer SM";
1111 static gchar *sc_perm = "Permanent error, SC is not making any more transfer attempts";
1112 static gchar *sc_tempfin = "Temporary error, SC is not making any more transfer attempts";
1114 proto_tree *subtree = NULL;
1121 proto_tree_add_text(tree, tvb,
1125 subtree = proto_item_add_subtree(item, ett_st);
1127 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1128 proto_tree_add_text(subtree, tvb,
1130 "%s : Definition of bits 0-6: %s",
1132 (oct & 0x80) ? "Reserved" : "as follows");
1138 case 0x00: str2 = sc_complete; str = "Short message received by the SME"; break;
1139 case 0x01: str2 = sc_complete; str = "Short message forwarded by the SC to the SME but the SC is unable to confirm delivery"; break;
1140 case 0x02: str2 = sc_complete; str = "Short message replaced by the SC Reserved values"; break;
1142 case 0x20: str2 = sc_temporary; str = "Congestion"; break;
1143 case 0x21: str2 = sc_temporary; str = "SME busy"; break;
1144 case 0x22: str2 = sc_temporary; str = "No response from SME"; break;
1145 case 0x23: str2 = sc_temporary; str = "Service rejected"; break;
1146 case 0x24: str2 = sc_temporary; str = "Quality of service not available"; break;
1147 case 0x25: str2 = sc_temporary; str = "Error in SME"; break;
1149 case 0x40: str2 = sc_perm; str = "Remote procedure error"; break;
1150 case 0x41: str2 = sc_perm; str = "Incompatible destination"; break;
1151 case 0x42: str2 = sc_perm; str = "Connection rejected by SME"; break;
1152 case 0x43: str2 = sc_perm; str = "Not obtainable"; break;
1153 case 0x44: str2 = sc_perm; str = "Quality of service not available"; break;
1154 case 0x45: str2 = sc_perm; str = "No interworking available"; break;
1155 case 0x46: str2 = sc_perm; str = "SM Validity Period Expired"; break;
1156 case 0x47: str2 = sc_perm; str = "SM Deleted by originating SME"; break;
1157 case 0x48: str2 = sc_perm; str = "SM Deleted by SC Administration"; break;
1158 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;
1160 case 0x60: str2 = sc_tempfin; str = "Congestion"; break;
1161 case 0x61: str2 = sc_tempfin; str = "SME busy"; break;
1162 case 0x62: str2 = sc_tempfin; str = "No response from SME"; break;
1163 case 0x63: str2 = sc_tempfin; str = "Service rejected"; break;
1164 case 0x64: str2 = sc_tempfin; str = "Quality of service not available"; break;
1165 case 0x65: str2 = sc_tempfin; str = "Error in SME"; break;
1168 if ((value >= 0x03) &&
1174 else if ((value >= 0x10) &&
1178 str = "Values specific to each SC";
1180 else if ((value >= 0x26) &&
1183 str2 = sc_temporary;
1186 else if ((value >= 0x30) &&
1189 str2 = sc_temporary;
1190 str = "Values specific to each SC";
1192 else if ((value >= 0x4a) &&
1198 else if ((value >= 0x50) &&
1202 str = "Values specific to each SC";
1204 else if ((value >= 0x66) &&
1210 else if ((value >= 0x70) &&
1214 str = "Values specific to each SC";
1219 other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
1220 proto_tree_add_text(subtree, tvb,
1230 #define DIS_FIELD_UDL(m_tree, m_offset) \
1232 proto_tree_add_text(m_tree, tvb, \
1234 "TP-User-Data-Length: (%d) %s", \
1236 oct ? "depends on Data-Coding-Scheme" : "no User-Data");\
1240 #define DIS_FIELD_RP(m_tree, m_bitmask, m_offset) \
1242 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1243 proto_tree_add_text(m_tree, tvb, \
1245 "%s : TP-Reply-Path: parameter is %sset in this SMS-SUBMIT/DELIVER", \
1247 (oct & m_bitmask) ? "" : "not "); \
1251 #define DIS_FIELD_MN(m_tree, m_offset) \
1253 proto_tree_add_text(m_tree, tvb, \
1255 "TP-Message-Number: %d", \
1260 #define DIS_FIELD_CT(m_tree, m_offset) \
1264 case 0: str = "Enquiry relating to previously submitted short message"; break; \
1265 case 1: str = "Cancel Status Report Request relating to previously submitted short message"; break; \
1266 case 2: str = "Delete previously submitted Short Message"; break; \
1267 case 3: str = "Enable Status Report Request relating to previously submitted short message"; break; \
1269 if ((oct >= 0x04) && \
1272 str = "Reserved unspecified"; \
1274 else if (oct >= 0xe0) \
1276 str = "Values specific for each SC"; \
1280 str = "undefined"; \
1284 proto_tree_add_text(m_tree, tvb, \
1286 "TP-Command-Type: (%d), %s", \
1292 #define DIS_FIELD_CDL(m_tree, m_offset) \
1294 proto_tree_add_text(m_tree, tvb, \
1296 "TP-Command-Data-Length: (%d)%s", \
1298 oct ? "" : " no Command-Data");\
1302 /* done in-line in the message functions */
1306 dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1309 proto_tree *subtree = NULL;
1314 proto_tree_add_text(tree, tvb,
1316 "TP-Failure-Cause");
1318 subtree = proto_item_add_subtree(item, ett_fcs);
1322 case 0x80: str = "Telematic interworking not supported"; break;
1323 case 0x81: str = "Short message Type 0 not supported"; break;
1324 case 0x82: str = "Cannot replace short message"; break;
1325 case 0x8F: str = "Unspecified TP-PID error"; break;
1326 case 0x90: str = "Data coding scheme (alphabet) not supported"; break;
1327 case 0x91: str = "Message class not supported"; break;
1328 case 0x9F: str = "Unspecified TP-DCS error"; break;
1329 case 0xA0: str = "Command cannot be actioned"; break;
1330 case 0xA1: str = "Command unsupported"; break;
1331 case 0xAF: str = "Unspecified TP-Command error"; break;
1332 case 0xB0: str = "TPDU not supported"; break;
1333 case 0xC0: str = "SC busy"; break;
1334 case 0xC1: str = "No SC subscription"; break;
1335 case 0xC2: str = "SC system failure"; break;
1336 case 0xC3: str = "Invalid SME address"; break;
1337 case 0xC4: str = "Destination SME barred"; break;
1338 case 0xC5: str = "SM Rejected-Duplicate SM"; break;
1339 case 0xC6: str = "TP-VPF not supported"; break;
1340 case 0xC7: str = "TP-VP not supported"; break;
1341 case 0xD0: str = "(U)SIM SMS storage full"; break;
1342 case 0xD1: str = "No SMS storage capability in (U)SIM"; break;
1343 case 0xD2: str = "Error in MS"; break;
1344 case 0xD3: str = "Memory Capacity Exceeded"; break;
1345 case 0xD4: str = "(U)SIM Application Toolkit Busy"; break;
1346 case 0xD5: str = "(U)SIM data download error"; break;
1347 case 0xFF: str = "Unspecified error cause"; break;
1349 if ((oct >= 0x80) &&
1352 str = "TP-PID errors"; break;
1354 else if ((oct >= 0x90) &&
1357 str = "TP-DCS errors"; break;
1359 else if ((oct >= 0xA0) &&
1362 str = "TP-Command errors"; break;
1364 else if ((oct >= 0xE0) &&
1367 str = "Values specific to an application"; break;
1371 str = "Reserved"; break;
1375 proto_tree_add_text(subtree, tvb,
1381 #define DIS_FIELD_UDHI(m_tree, m_bitmask, m_offset, m_udhi) \
1383 SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, m_udhi); \
1384 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1385 proto_tree_add_text(m_tree, tvb, \
1387 "%s : TP-User-Data-Header-Indicator: %s short message", \
1390 "The beginning of the TP-UD field contains a Header in addition to the" : \
1391 "The TP-UD field contains only the"); \
1399 #define GN_BYTE_MASK ((1 << bits) - 1)
1402 gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length,
1403 const guint8 *input, unsigned char *output)
1405 unsigned char *out_num = output; /* Current pointer to the output buffer */
1406 const guint8 *in_num = input; /* Current pointer to the input buffer */
1407 unsigned char rest = 0x00;
1410 bits = offset ? offset : 7;
1412 while ((unsigned int)(in_num - input) < in_length)
1414 *out_num = ((*in_num & GN_BYTE_MASK) << (7 - bits)) | rest;
1415 rest = *in_num >> bits;
1417 /* If we don't start from 0th bit, we shouldn't go to the
1418 next char. Under *out_num we have now 0 and under Rest -
1419 _first_ part of the char. */
1420 if ((in_num != input) || (bits == 7)) out_num++;
1423 if ((unsigned int)(out_num - output) >= out_length) break;
1425 /* After reading 7 octets we have read 7 full characters but
1426 we have 7 bits as well. This is the next character */
1440 return out_num - output;
1443 #define GN_CHAR_ALPHABET_SIZE 128
1445 #define GN_CHAR_ESCAPE 0x1b
1447 static unsigned char gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
1449 /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
1450 /* Characters in hex position 10, [12 to 1a] and 24 are not present on
1451 latin1 charset, so we cannot reproduce on the screen, however they are
1452 greek symbol not present even on my Nokia */
1454 '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
1455 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
1456 '?', '_', '?', '?', '?', '?', '?', '?',
1457 '?', '?', '?', '?', 0xc6, 0xe6, 0xdf, 0xc9,
1458 ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
1459 '(', ')', '*', '+', ',', '-', '.', '/',
1460 '0', '1', '2', '3', '4', '5', '6', '7',
1461 '8', '9', ':', ';', '<', '=', '>', '?',
1462 0xa1, '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', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
1466 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
1467 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
1468 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
1469 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
1473 char_is_escape(unsigned char value)
1475 return (value == GN_CHAR_ESCAPE);
1478 static unsigned char
1479 char_def_alphabet_ext_decode(unsigned char value)
1483 case 0x0a: return 0x0c; break; /* form feed */
1484 case 0x14: return '^'; break;
1485 case 0x28: return '{'; break;
1486 case 0x29: return '}'; break;
1487 case 0x2f: return '\\'; break;
1488 case 0x3c: return '['; break;
1489 case 0x3d: return '~'; break;
1490 case 0x3e: return ']'; break;
1491 case 0x40: return '|'; break;
1492 case 0x65: return 0xa4; break; /* euro */
1493 default: return '?'; break; /* invalid character */
1497 static unsigned char
1498 char_def_alphabet_decode(unsigned char value)
1500 if (value < GN_CHAR_ALPHABET_SIZE)
1502 return gsm_default_alphabet[value];
1511 gsm_sms_char_ascii_decode(unsigned char* dest, const unsigned char* src, int len)
1515 for (i = 0, j = 0; j < len; i++, j++)
1517 if (char_is_escape(src[j]))
1518 dest[i] = char_def_alphabet_ext_decode(src[++j]);
1520 dest[i] = char_def_alphabet_decode(src[j]);
1531 dis_iei_apa_8bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1537 EXACT_DATA_CHECK(length, 2);
1539 oct = tvb_get_guint8(tvb, offset);
1547 str = "Available for allocation by applications";
1550 proto_tree_add_text(tree,
1552 "Destination port: %d, %s",
1557 oct = tvb_get_guint8(tvb, offset);
1565 str = "Available for allocation by applications";
1568 proto_tree_add_text(tree,
1570 "Originator port: %d, %s",
1576 dis_iei_apa_16bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1582 EXACT_DATA_CHECK(length, 4);
1584 value = tvb_get_ntohs(tvb, offset);
1588 str = "As allocated by IANA (http://www.IANA.com/)";
1590 else if (value < 17000)
1592 str = "Available for allocation by applications";
1599 proto_tree_add_text(tree,
1601 "Destination port: %d, %s",
1606 value = tvb_get_ntohs(tvb, offset);
1610 str = "As allocated by IANA (http://www.IANA.com/)";
1612 else if (value < 17000)
1614 str = "Available for allocation by applications";
1621 proto_tree_add_text(tree,
1623 "Originator port: %d, %s",
1629 dis_field_ud_iei(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1631 void (*iei_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length);
1634 proto_tree *subtree = NULL;
1643 oct = tvb_get_guint8(tvb, offset);
1647 case 0x00: str = "Concatenated short messages, 8-bit reference number (SMS Control)"; break;
1648 case 0x01: str = "Special SMS Message Indication (SMS Control)"; break;
1649 case 0x02: str = "Reserved N/A"; break;
1650 case 0x03: str = "Value not used to avoid misinterpretation as <LF> character N/A"; break;
1651 case 0x04: str = "Application port addressing scheme, 8 bit address (SMS Control)"; iei_fcn = dis_iei_apa_8bit; break;
1652 case 0x05: str = "Application port addressing scheme, 16 bit address (SMS Control)"; iei_fcn = dis_iei_apa_16bit; break;
1653 case 0x06: str = "SMSC Control Parameters (SMS Control)"; break;
1654 case 0x07: str = "UDH Source Indicator (SMS Control)"; break;
1655 case 0x08: str = "Concatenated short message, 16-bit reference number (SMS Control)"; break;
1656 case 0x09: str = "Wireless Control Message Protocol (SMS Control)"; break;
1657 case 0x0A: str = "Text Formatting (EMS Control)"; break;
1658 case 0x0B: str = "Predefined Sound (EMS Content)"; break;
1659 case 0x0C: str = "User Defined Sound (iMelody max 128 bytes) (EMS Content)"; break;
1660 case 0x0D: str = "Predefined Animation (EMS Content)"; break;
1661 case 0x0E: str = "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)"; break;
1662 case 0x0F: str = "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)"; break;
1663 case 0x10: str = "Large Picture (32*32 = 128 bytes) (EMS Content)"; break;
1664 case 0x11: str = "Small Picture (16*16 = 32 bytes) (EMS Content)"; break;
1665 case 0x12: str = "Variable Picture (EMS Content)"; break;
1666 case 0x13: str = "User prompt indicator (EMS Control)"; break;
1667 case 0x14: str = "Extended Object (EMS Content)"; break;
1668 case 0x15: str = "Reused Extended Object (EMS Control)"; break;
1669 case 0x16: str = "Compression Control (EMS Control)"; break;
1670 case 0x17: str = "Object Distribution Indicator (EMS Control)"; break;
1671 case 0x18: str = "Standard WVG object (EMS Content)"; break;
1672 case 0x19: str = "Character Size WVG object (EMS Content)"; break;
1673 case 0x1A: str = "Extended Object Data Request Command (EMS Control)"; break;
1674 case 0x20: str = "RFC 822 E-Mail Header (SMS Control)"; break;
1675 case 0x21: str = "Hyperlink format element (SMS Control)"; break;
1676 case 0x22: str = "Reply Address Element (SMS Control)"; break;
1678 if ((oct >= 0x1b) &&
1681 str = "Reserved for future EMS features (see subclause 3.10) N/A"; break;
1683 else if ((oct >= 0x23) &&
1686 str = "Reserved for future use N/A"; break;
1688 else if ((oct >= 0x70) &&
1691 str = "(U)SIM Toolkit Security Headers (SMS Control)"; break;
1693 else if ((oct >= 0x80) &&
1696 str = "SME to SME specific use (SMS Control)"; break;
1698 else if ((oct >= 0xa0) &&
1701 str = "Reserved for future use N/A"; break;
1703 else if ((oct >= 0xc0) &&
1706 str = "SC specific use (SMS Control)"; break;
1710 str = "Reserved for future use N/A"; break;
1714 iei_len = tvb_get_guint8(tvb, offset + 1);
1717 proto_tree_add_text(tree,
1718 tvb, offset, iei_len + 2,
1722 subtree = proto_item_add_subtree(item, ett_udh_ieis[oct]);
1724 proto_tree_add_text(subtree,
1726 "Information Element Identifier: %d",
1731 proto_tree_add_text(subtree,
1740 if (iei_fcn == NULL)
1742 proto_tree_add_text(subtree,
1743 tvb, offset, iei_len,
1748 iei_fcn(tvb, subtree, offset, iei_len);
1752 length -= 2 + iei_len;
1759 dis_field_ud(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 length, gboolean udhi, guint8 udl,
1760 gboolean seven_bit, gboolean eight_bit, gboolean ucs2, gboolean compressed)
1762 static guint8 fill_bits_mask[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };
1764 proto_item *udh_item;
1765 proto_tree *subtree = NULL;
1766 proto_tree *udh_subtree = NULL;
1775 proto_tree_add_text(tree, tvb,
1779 subtree = proto_item_add_subtree(item, ett_ud);
1781 oct = tvb_get_guint8(tvb, offset);
1785 /* step over header */
1788 proto_tree_add_text(subtree, tvb,
1790 "User-Data Header");
1792 udh_subtree = proto_item_add_subtree(udh_item, ett_udh);
1794 proto_tree_add_text(udh_subtree,
1796 "User Data Header Length (%d)",
1803 dis_field_ud_iei(tvb, udh_subtree, offset, oct);
1811 /* step over fill bits ? */
1813 fill_bits = 7 - (((oct + 1) * 8) % 7);
1816 oct = tvb_get_guint8(tvb, offset);
1818 other_decode_bitfield_value(bigbuf, oct, fill_bits_mask[fill_bits], 8);
1819 proto_tree_add_text(udh_subtree,
1829 proto_tree_add_text(subtree, tvb,
1838 gsm_sms_char_7bit_unpack(fill_bits, length, sizeof(bigbuf),
1839 tvb_get_ptr(tvb, offset, length), bigbuf);
1840 bigbuf[out_len] = '\0';
1841 gsm_sms_char_ascii_decode(bigbuf, bigbuf, out_len);
1844 proto_tree_add_text(subtree, tvb, offset, length, "%s", bigbuf);
1848 proto_tree_add_text(subtree, tvb, offset, length, "%s",
1849 tvb_format_text(tvb, offset, length));
1853 ustr = tvb_fake_unicode(tvb, offset, length, FALSE);
1854 proto_tree_add_text(subtree, tvb, offset, length, "%s", ustr);
1861 #define DIS_FIELD_RD(m_tree, m_bitmask, m_offset) \
1863 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1864 proto_tree_add_text(m_tree, tvb, \
1866 "%s : TP-Reject-Duplicates: Instruct SC to %s duplicates", \
1868 (oct & m_bitmask) ? \
1874 #define DIS_FIELD_SRQ(m_tree, m_bitmask, m_offset) \
1876 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1877 proto_tree_add_text(m_tree, tvb, \
1879 "%s : TP-Status-Report-Qualifier: The SMS-STATUS-REPORT is the result of %s", \
1881 (oct & m_bitmask) ? \
1882 "an SMS-COMMAND e.g. an Enquiry" : \
1888 dis_field_pi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1891 proto_tree *subtree = NULL;
1895 proto_tree_add_text(tree, tvb,
1897 "TP-Parameter-Indicator");
1899 subtree = proto_item_add_subtree(item, ett_pi);
1901 other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1902 proto_tree_add_text(subtree, tvb,
1906 (oct & 0x80) ? "Extended" : "No extension");
1908 other_decode_bitfield_value(bigbuf, oct, 0x78, 8);
1909 proto_tree_add_text(subtree, tvb,
1914 other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
1915 proto_tree_add_text(subtree, tvb,
1917 "%s : TP-UDL %spresent",
1919 (oct & 0x04) ? "" : "not ");
1921 other_decode_bitfield_value(bigbuf, oct, 0x02, 8);
1922 proto_tree_add_text(subtree, tvb,
1924 "%s : TP-DCS %spresent",
1926 (oct & 0x02) ? "" : "not ");
1928 other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
1929 proto_tree_add_text(subtree, tvb,
1931 "%s : TP-PID %spresent",
1933 (oct & 0x01) ? "" : "not ");
1941 dis_msg_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
1943 guint32 saved_offset;
1950 gboolean compressed;
1954 saved_offset = offset;
1955 length = tvb_length_remaining(tvb, offset);
1957 oct = tvb_get_guint8(tvb, offset);
1959 DIS_FIELD_RP(tree, 0x80, offset);
1961 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
1963 DIS_FIELD_SRI(tree, 0x20, offset);
1965 DIS_FIELD_MMS(tree, 0x04, offset);
1967 DIS_FIELD_MTI(tree, 0x03, offset);
1971 dis_field_addr(tvb, tree, &offset, "TP-Originating-Address");
1973 oct = tvb_get_guint8(tvb, offset);
1975 dis_field_pid(tvb, tree, offset, oct);
1978 oct = tvb_get_guint8(tvb, offset);
1980 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
1983 dis_field_scts(tvb, tree, &offset);
1985 oct = tvb_get_guint8(tvb, offset);
1988 DIS_FIELD_UDL(tree, offset);
1994 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
1995 seven_bit, eight_bit, ucs2, compressed);
2004 dis_msg_deliver_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2006 guint32 saved_offset;
2014 gboolean compressed;
2019 saved_offset = offset;
2020 length = tvb_length_remaining(tvb, offset);
2022 oct = tvb_get_guint8(tvb, offset);
2024 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2026 DIS_FIELD_MTI(tree, 0x03, offset);
2030 proto_tree_add_text(tree,
2031 tvb, offset, length,
2037 * there does not seem to be a way to determine that this
2038 * deliver report is from an RP-ERROR or RP-ACK other
2039 * than to look at the next octet
2041 * FCS values are 0x80 and higher
2042 * PI uses bit 7 as an extension indicator
2044 * will assume that if bit 7 is set then this octet
2045 * is an FCS otherwise PI
2048 oct = tvb_get_guint8(tvb, offset);
2052 dis_field_fcs(tvb, tree, offset, oct);
2056 pi = tvb_get_guint8(tvb, offset);
2058 dis_field_pi(tvb, tree, offset, pi);
2062 if (length <= (offset - saved_offset))
2064 proto_tree_add_text(tree,
2071 oct = tvb_get_guint8(tvb, offset);
2073 dis_field_pid(tvb, tree, offset, oct);
2078 if (length <= (offset - saved_offset))
2080 proto_tree_add_text(tree,
2087 oct = tvb_get_guint8(tvb, offset);
2089 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2094 if (length <= (offset - saved_offset))
2096 proto_tree_add_text(tree,
2103 oct = tvb_get_guint8(tvb, offset);
2106 DIS_FIELD_UDL(tree, offset);
2113 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2114 seven_bit, eight_bit, ucs2, compressed);
2123 dis_msg_submit(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2125 guint32 saved_offset;
2134 gboolean compressed;
2138 saved_offset = offset;
2139 length = tvb_length_remaining(tvb, offset);
2141 oct = tvb_get_guint8(tvb, offset);
2143 DIS_FIELD_RP(tree, 0x80, offset);
2145 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2147 DIS_FIELD_SRR(tree, 0x20, offset);
2149 DIS_FIELD_VPF(tree, 0x18, offset, &vp_form);
2151 DIS_FIELD_RD(tree, 0x04, offset);
2153 DIS_FIELD_MTI(tree, 0x03, offset);
2156 oct = tvb_get_guint8(tvb, offset);
2158 DIS_FIELD_MR(tree, offset);
2162 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
2164 oct = tvb_get_guint8(tvb, offset);
2166 dis_field_pid(tvb, tree, offset, oct);
2169 oct = tvb_get_guint8(tvb, offset);
2171 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2174 dis_field_vp(tvb, tree, &offset, vp_form);
2176 oct = tvb_get_guint8(tvb, offset);
2179 DIS_FIELD_UDL(tree, offset);
2185 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2186 seven_bit, eight_bit, ucs2, compressed);
2195 dis_msg_submit_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2197 guint32 saved_offset;
2205 gboolean compressed;
2210 saved_offset = offset;
2211 length = tvb_length_remaining(tvb, offset);
2213 oct = tvb_get_guint8(tvb, offset);
2215 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2217 DIS_FIELD_MTI(tree, 0x03, offset);
2220 * there does not seem to be a way to determine that this
2221 * deliver report is from an RP-ERROR or RP-ACK other
2222 * than to look at the next octet
2224 * FCS values are 0x80 and higher
2225 * PI uses bit 7 as an extension indicator
2227 * will assume that if bit 7 is set then this octet
2228 * is an FCS otherwise PI
2231 oct = tvb_get_guint8(tvb, offset);
2235 dis_field_fcs(tvb, tree, offset, oct);
2239 pi = tvb_get_guint8(tvb, offset);
2241 dis_field_pi(tvb, tree, offset, pi);
2244 dis_field_scts(tvb, tree, &offset);
2248 if (length <= (offset - saved_offset))
2250 proto_tree_add_text(tree,
2257 oct = tvb_get_guint8(tvb, offset);
2259 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2264 if (length <= (offset - saved_offset))
2266 proto_tree_add_text(tree,
2273 oct = tvb_get_guint8(tvb, offset);
2276 DIS_FIELD_UDL(tree, offset);
2283 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2284 seven_bit, eight_bit, ucs2, compressed);
2293 dis_msg_status_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2295 guint32 saved_offset;
2303 gboolean compressed;
2308 saved_offset = offset;
2309 length = tvb_length_remaining(tvb, offset);
2311 oct = tvb_get_guint8(tvb, offset);
2313 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2315 DIS_FIELD_SRQ(tree, 0x20, offset);
2317 DIS_FIELD_MMS(tree, 0x04, offset);
2319 DIS_FIELD_MTI(tree, 0x03, offset);
2322 oct = tvb_get_guint8(tvb, offset);
2324 DIS_FIELD_MR(tree, offset);
2328 dis_field_addr(tvb, tree, &offset, "TP-Recipient-Address");
2330 dis_field_scts(tvb, tree, &offset);
2332 dis_field_dt(tvb, tree, &offset);
2334 oct = tvb_get_guint8(tvb, offset);
2336 dis_field_st(tvb, tree, offset, oct);
2339 pi = tvb_get_guint8(tvb, offset);
2341 dis_field_pi(tvb, tree, offset, pi);
2345 if (length <= (offset - saved_offset))
2347 proto_tree_add_text(tree,
2354 oct = tvb_get_guint8(tvb, offset);
2356 dis_field_pid(tvb, tree, offset, oct);
2361 if (length <= (offset - saved_offset))
2363 proto_tree_add_text(tree,
2370 oct = tvb_get_guint8(tvb, offset);
2372 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2377 if (length <= (offset - saved_offset))
2379 proto_tree_add_text(tree,
2386 oct = tvb_get_guint8(tvb, offset);
2389 DIS_FIELD_UDL(tree, offset);
2396 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2397 seven_bit, eight_bit, ucs2, compressed);
2406 dis_msg_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2408 guint32 saved_offset;
2417 saved_offset = offset;
2418 length = tvb_length_remaining(tvb, offset);
2420 oct = tvb_get_guint8(tvb, offset);
2422 DIS_FIELD_UDHI(tree, 0x40, offset, udhi);
2424 DIS_FIELD_SRR(tree, 0x20, offset);
2426 DIS_FIELD_MTI(tree, 0x03, offset);
2429 oct = tvb_get_guint8(tvb, offset);
2431 DIS_FIELD_MR(tree, offset);
2434 oct = tvb_get_guint8(tvb, offset);
2436 dis_field_pid(tvb, tree, offset, oct);
2439 oct = tvb_get_guint8(tvb, offset);
2441 DIS_FIELD_CT(tree, offset);
2444 oct = tvb_get_guint8(tvb, offset);
2446 DIS_FIELD_MN(tree, offset);
2450 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
2452 oct = tvb_get_guint8(tvb, offset);
2455 DIS_FIELD_CDL(tree, offset);
2461 proto_tree_add_text(tree,
2467 #define NUM_MSGS (sizeof(msg_type_strings)/sizeof(value_string))
2468 static gint ett_msgs[NUM_MSGS];
2469 static void (*gsm_sms_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = {
2470 dis_msg_deliver, /* SMS-DELIVER */
2471 dis_msg_deliver_report, /* SMS-DELIVER REPORT */
2472 dis_msg_submit, /* SMS-SUBMIT */
2473 dis_msg_submit_report, /* SMS-SUBMIT REPORT */
2474 dis_msg_status_report, /* SMS-STATUS REPORT */
2475 dis_msg_command, /* SMS-COMMAND */
2476 NULL, /* Reserved */
2477 NULL, /* Reserved */
2481 /* GENERIC DISSECTOR FUNCTIONS */
2484 dissect_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2486 void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = NULL;
2487 proto_item *gsm_sms_item;
2488 proto_tree *gsm_sms_tree = NULL;
2499 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2501 col_set_str(pinfo->cinfo, COL_PROTOCOL, gsm_sms_proto_name_short);
2504 /* In the interest of speed, if "tree" is NULL, don't do any work not
2505 * necessary to generate protocol tree items.
2513 oct = tvb_get_guint8(tvb, offset);
2519 * convert the 2 bit value to one based on direction
2521 if (pinfo->p2p_dir == P2P_DIR_UNKNOWN)
2523 /* Return Result ... */
2524 if (msg_type == 0) /* SMS-DELIVER */
2526 msg_type |= 0x04; /* see the msg_type_strings */
2531 msg_type |= ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x04 : 0x00);
2534 str = my_match_strval(msg_type, msg_type_strings, &idx);
2537 * create the GSM_SMS protocol tree
2540 proto_tree_add_protocol_format(tree, proto_gsm_sms, tvb, 0, -1,
2543 (str == NULL) ? "Unknown message identifier" : str);
2546 proto_item_add_subtree(gsm_sms_item, ett_gsm_sms);
2548 if ((str == NULL) ||
2549 (msg_type == 0x03) ||
2556 ett_msg_idx = ett_msgs[idx];
2557 msg_fcn = gsm_sms_msg_fcn[idx];
2560 if (msg_fcn == NULL)
2562 proto_tree_add_text(gsm_sms_tree,
2564 "Message dissector not implemented");
2568 (*msg_fcn)(tvb, gsm_sms_tree, offset);
2574 /* Register the protocol with Ethereal */
2576 proto_register_gsm_sms(void)
2582 /* Setup list of header fields */
2583 static hf_register_info hf[] =
2588 /* Setup protocol subtree array */
2589 #define NUM_INDIVIDUAL_PARMS 12
2590 static gint *ett[NUM_INDIVIDUAL_PARMS+NUM_MSGS+NUM_UDH_IEIS];
2592 ett[0] = &ett_gsm_sms;
2605 last_offset = NUM_INDIVIDUAL_PARMS;
2607 for (i=0; i < NUM_MSGS; i++, last_offset++)
2610 ett[last_offset] = &ett_msgs[i];
2613 for (i=0; i < NUM_UDH_IEIS; i++, last_offset++)
2615 ett_udh_ieis[i] = -1;
2616 ett[last_offset] = &ett_udh_ieis[i];
2619 /* Register the protocol name and description */
2622 proto_register_protocol(gsm_sms_proto_name, gsm_sms_proto_name_short, "gsm_sms");
2625 proto_register_field_array(proto_gsm_sms, hf, array_length(hf));
2628 proto_register_subtree_array(ett, array_length(ett));
2633 proto_reg_handoff_gsm_sms(void)
2635 dissector_handle_t gsm_sms_handle;
2637 gsm_sms_handle = create_dissector_handle(dissect_gsm_sms, proto_gsm_sms);
2639 dissector_add("gsm_a.sms_tpdu", 0, gsm_sms_handle);
2640 dissector_add("gsm_map.sms_tpdu", 0, gsm_sms_handle);
2642 data_handle = find_dissector("data");