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.3 2003/10/30 11:54:21 guy Exp $
16 * Ethereal - Network traffic analyzer
17 * By Gerald Combs <gerald@ethereal.com>
18 * Copyright 1998 Gerald Combs
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43 #ifdef HAVE_SYS_TYPES_H
44 # include <sys/types.h>
47 #ifdef HAVE_NETINET_IN_H
48 # include <netinet/in.h>
53 #include "epan/packet.h"
57 /* PROTOTYPES/FORWARDS */
59 #define RP_DATA_MS_TO_N 0x00
60 #define RP_DATA_N_TO_MS 0x01
61 #define RP_ACK_MS_TO_N 0x02
62 #define RP_ACK_N_TO_MS 0x03
63 #define RP_ERROR_MS_TO_N 0x04
64 #define RP_ERROR_N_TO_MS 0x05
66 #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
67 if ((edc_len) > (edc_max_len)) \
69 proto_tree_add_text(tree, tvb, \
70 offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
73 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
74 if ((sdc_len) < (sdc_min_len)) \
76 proto_tree_add_text(tree, tvb, \
77 offset, (sdc_len), "Short Data (?)"); \
81 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
82 if ((edc_len) != (edc_eq_len)) \
84 proto_tree_add_text(tree, tvb, \
85 offset, (edc_len), "Unexpected Data Length"); \
89 static char *gsm_sms_proto_name = "GSM SMS TPDU (GSM 03.40)";
90 static char *gsm_sms_proto_name_short = "GSM SMS";
92 /* Initialize the subtree pointers */
93 static gint ett_gsm_sms = -1;
94 static gint ett_pid = -1;
95 static gint ett_pi = -1;
96 static gint ett_fcs = -1;
97 static gint ett_vp = -1;
98 static gint ett_scts = -1;
99 static gint ett_dt = -1;
100 static gint ett_st = -1;
101 static gint ett_addr = -1;
102 static gint ett_dcs = -1;
103 static gint ett_ud = -1;
104 static gint ett_udh = -1;
106 /* Initialize the protocol and registered fields */
107 static int proto_gsm_sms = -1;
109 static char bigbuf[1024];
110 static dissector_handle_t data_handle;
111 static packet_info *g_pinfo;
112 static proto_tree *g_tree;
113 static gint g_rp_type;
116 * this is the GSM 03.40 definition with the bit 2
117 * set to 1 for uplink messages
119 static const value_string msg_type_strings[] = {
120 { 0, "SMS-DELIVER" },
121 { 4, "SMS-DELIVER REPORT" },
123 { 1, "SMS-SUBMIT REPORT" },
124 { 2, "SMS-STATUS REPORT" },
125 { 6, "SMS-COMMAND" },
131 #define NUM_UDH_IEIS 256
132 static gint ett_udh_ieis[NUM_UDH_IEIS];
136 /* Generate, into "buf", a string showing the bits of a bitfield.
137 * Return a pointer to the character after that string.
140 my_decode_bitfield_value(char *buf, guint32 val, guint32 mask, int width)
148 bit = 1 << (width - 1);
154 /* This bit is part of the field. Show its value. */
162 /* This bit is not part of the field. */
168 if (i >= width) break;
169 if (i % 4 == 0) *p++ = ' ';
178 my_match_strval(guint32 val, const value_string *vs, gint *idx)
182 while (vs[i].strptr) {
183 if (vs[i].value == val)
186 return(vs[i].strptr);
197 #define DIS_FIELD_MTI(m_tree, m_offset) \
199 my_decode_bitfield_value(bigbuf, oct, 0x03, 8); \
200 proto_tree_add_text(m_tree, tvb, \
202 "%s : TP-Message-Type-Indicator", \
207 #define DIS_FIELD_MMS(m_tree, m_offset) \
209 my_decode_bitfield_value(bigbuf, oct, 0x04, 8); \
210 proto_tree_add_text(m_tree, tvb, \
212 "%s : TP-More-Messages-to-Send: %s messages are waiting for the MS in this SC", \
214 (oct & 0x04) ? "No more" : "More"); \
218 #define DIS_FIELD_VPF(m_tree, m_offset, m_form) \
220 *m_form = (oct & 0x18) >> 3; \
223 case 0: str = "TP-VP field not present"; break; \
224 case 1: str = "TP-VP field present - enhanced format"; break; \
225 case 2: str = "TP-VP field present - relative format"; break; \
226 case 3: str = "TP-VP field present - absolute format"; break; \
228 my_decode_bitfield_value(bigbuf, oct, 0x18, 8); \
229 proto_tree_add_text(m_tree, tvb, \
231 "%s : TP-Validity-Period-Format: %s", \
237 #define DIS_FIELD_SRI(m_tree, m_offset) \
239 my_decode_bitfield_value(bigbuf, oct, 0x20, 8); \
240 proto_tree_add_text(m_tree, tvb, \
242 "%s : TP-Status-Report-Indication: A status report shall %sbe returned to the SME", \
244 (oct & 0x20) ? "" : "not "); \
248 #define DIS_FIELD_SRR(m_tree, m_offset) \
250 my_decode_bitfield_value(bigbuf, oct, 0x20, 8); \
251 proto_tree_add_text(m_tree, tvb, \
253 "%s : TP-Status-Report-Request: A status report is %srequested", \
255 (oct & 0x20) ? "" : "not "); \
259 #define DIS_FIELD_MR(m_tree, m_offset) \
261 proto_tree_add_text(m_tree, tvb, \
263 "TP-Message-Reference %d", \
268 dis_field_addr(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, gchar *title)
270 static gchar digit_table[] = {"0123456789*#abc\0"};
272 proto_tree *subtree = NULL;
283 oct = tvb_get_guint8(tvb, offset);
284 numdigocts = (oct + 1) / 2;
286 length = tvb_length_remaining(tvb, offset);
288 if (length <= numdigocts)
290 proto_tree_add_text(tree,
292 "%s: Short Data (?)",
300 proto_tree_add_text(tree, tvb,
301 offset, numdigocts + 2,
304 subtree = proto_item_add_subtree(item, ett_addr);
306 proto_tree_add_text(subtree,
308 "Length: %d address digits",
312 oct = tvb_get_guint8(tvb, offset);
314 my_decode_bitfield_value(bigbuf, oct, 0x80, 8);
315 proto_tree_add_text(subtree, tvb,
319 (oct & 0x80) ? "No extension" : "Extended");
321 switch ((oct & 0x70) >> 4)
323 case 0x00: str = "Unknown"; break;
324 case 0x01: str = "International"; break;
325 case 0x02: str = "National"; break;
326 case 0x07: str = "Reserved for extension"; break;
327 default: str = "Unknown, reserved (?)"; break;
330 my_decode_bitfield_value(bigbuf, oct, 0x70, 8);
331 proto_tree_add_text(subtree,
333 "%s : Type of number: (%d) %s",
340 case 0x00: str = "Unknown"; break;
341 case 0x01: str = "ISDN/telephone"; break;
342 case 0x0f: str = "Reserved for extension"; break;
343 default: str = "Unknown, reserved (?)"; break;
346 my_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
347 proto_tree_add_text(subtree,
349 "%s : Numbering plan: (%d) %s",
357 for (i = 0; i < numdigocts; i++)
359 oct = tvb_get_guint8(tvb, offset + i);
361 bigbuf[j++] = digit_table[oct & 0x0f];
362 bigbuf[j++] = digit_table[(oct & 0xf0) >> 4];
367 proto_tree_add_text(subtree,
368 tvb, offset, numdigocts,
372 proto_item_append_text(item, " - (%s)", bigbuf);
374 *offset_p = offset + i;
378 /* use dis_field_addr() */
381 /* use dis_field_addr() */
385 dis_field_pid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
388 proto_tree *subtree = NULL;
395 proto_tree_add_text(tree, tvb,
397 "TP-Protocol-Identifier");
399 subtree = proto_item_add_subtree(item, ett_pid);
401 form = (oct & 0xc0) >> 6;
406 my_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
407 proto_tree_add_text(subtree, tvb,
409 "%s : defines formatting for subsequent bits",
412 my_decode_bitfield_value(bigbuf, oct, 0x20, 8);
413 proto_tree_add_text(subtree, tvb,
418 "telematic interworking" :
419 "no telematic interworking, but SME-to-SME protocol");
423 telematic = oct & 0x1f;
427 case 0x00: str = "implicit - device type is specific to this SC, or can be concluded on the basis of the address"; break;
428 case 0x01: str = "telex (or teletex reduced to telex format)"; break;
429 case 0x02: str = "group 3 telefax"; break;
430 case 0x03: str = "group 4 telefax"; break;
431 case 0x04: str = "voice telephone (i.e. conversion to speech)"; break;
432 case 0x05: str = "ERMES (European Radio Messaging System)"; break;
433 case 0x06: str = "National Paging system (known to the SC)"; break;
434 case 0x07: str = "Videotex (T.100 [20] /T.101 [21])"; break;
435 case 0x08: str = "teletex, carrier unspecified"; break;
436 case 0x09: str = "teletex, in PSPDN"; break;
437 case 0x0a: str = "teletex, in CSPDN"; break;
438 case 0x0b: str = "teletex, in analog PSTN"; break;
439 case 0x0c: str = "teletex, in digital ISDN"; break;
440 case 0x0d: str = "UCI (Universal Computer Interface, ETSI DE/PS 3 01-3)"; break;
441 case 0x10: str = "a message handling facility (known to the SC)"; break;
442 case 0x11: str = "any public X.400-based message handling system"; break;
443 case 0x12: str = "Internet Electronic Mail"; break;
444 case 0x1f: str = "A GSM/UMTS mobile station"; break;
446 if ((telematic >= 0x18) &&
449 str = "values specific to each SC";
458 my_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
459 proto_tree_add_text(subtree, tvb,
461 "%s : device type: (%d) %s",
468 my_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
469 proto_tree_add_text(subtree, tvb,
471 "%s : the SM-AL protocol being used between the SME and the MS (%d)",
478 my_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
479 proto_tree_add_text(subtree, tvb,
481 "%s : defines formatting for subsequent bits",
486 case 0x00: str = "Short Message Type 0"; break;
487 case 0x01: str = "Replace Short Message Type 1"; break;
488 case 0x02: str = "Replace Short Message Type 2"; break;
489 case 0x03: str = "Replace Short Message Type 3"; break;
490 case 0x04: str = "Replace Short Message Type 4"; break;
491 case 0x05: str = "Replace Short Message Type 5"; break;
492 case 0x06: str = "Replace Short Message Type 6"; break;
493 case 0x07: str = "Replace Short Message Type 7"; break;
494 case 0x1e: str = "Enhanced Message Service (Obsolete)"; break;
495 case 0x1f: str = "Return Call Message"; break;
496 case 0x3c: str = "ANSI-136 R-DATA"; break;
497 case 0x3d: str = "ME Data download"; break;
498 case 0x3e: str = "ME De-personalization Short Message"; break;
499 case 0x3f: str = "(U)SIM Data download"; break;
501 str = "Reserved"; break;
504 my_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
505 proto_tree_add_text(subtree, tvb,
514 my_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
515 proto_tree_add_text(subtree, tvb,
520 my_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
521 proto_tree_add_text(subtree, tvb,
528 my_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
529 proto_tree_add_text(subtree, tvb,
531 "%s : bits 0-5 for SC specific use",
534 my_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
535 proto_tree_add_text(subtree, tvb,
545 dis_field_dcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct,
546 gboolean *seven_bit, gboolean *eight_bit, gboolean *ucs2, gboolean *compressed)
549 proto_tree *subtree = NULL;
552 gboolean default_5_bits;
553 gboolean default_3_bits;
554 gboolean default_data;
563 proto_tree_add_text(tree, tvb,
565 "TP-Data-Coding-Scheme (%d)",
568 subtree = proto_item_add_subtree(item, ett_dcs);
572 proto_tree_add_text(subtree, tvb,
574 "Special case, GSM 7 bit default alphabet");
580 default_5_bits = FALSE;
581 default_3_bits = FALSE;
582 default_data = FALSE;
583 form = (oct & 0xc0) >> 6;
588 my_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
589 proto_tree_add_text(subtree, tvb,
591 "%s : General Data Coding indication",
594 default_5_bits = TRUE;
598 my_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
599 proto_tree_add_text(subtree, tvb,
601 "%s : Message Marked for Automatic Deletion Group",
604 default_5_bits = TRUE;
608 /* use top four bits */
609 my_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
610 proto_tree_add_text(subtree, tvb,
612 "%s : Reserved coding groups",
617 switch ((oct & 0x30) >> 4)
619 case 0x00: str = "Message Waiting Indication Group: Discard Message (GSM 7 bit default alphabet)";
620 default_3_bits = TRUE;
623 case 0x01: str = "Message Waiting Indication Group: Store Message (GSM 7 bit default alphabet)";
624 default_3_bits = TRUE;
627 case 0x02: str = "Message Waiting Indication Group: Store Message (uncompressed UCS2 alphabet)";
628 default_3_bits = TRUE;
630 case 0x03: str = "Data coding/message class";
635 /* use top four bits */
636 my_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
637 proto_tree_add_text(subtree, tvb,
647 my_decode_bitfield_value(bigbuf, oct, 0x20, 8);
648 proto_tree_add_text(subtree, tvb,
650 "%s : Text is %scompressed",
652 (oct & 0x20) ? "" : "not ");
654 *compressed = (oct & 0x20) >> 5;
656 my_decode_bitfield_value(bigbuf, oct, 0x10, 8);
657 proto_tree_add_text(subtree, tvb,
661 (oct & 0x10) ? "Message class is defined below" :
662 "Reserved, no message class");
664 switch ((oct & 0x0c) >> 2)
666 case 0x00: str = "GSM 7 bit default alphabet";
669 case 0x01: str = "8 bit data"; break;
670 case 0x02: str = "UCS2 (16 bit)";
673 case 0x03: str = "Reserved"; break;
676 my_decode_bitfield_value(bigbuf, oct, 0x0c, 8);
677 proto_tree_add_text(subtree, tvb,
679 "%s : Character set: %s",
685 case 0x00: str = "Class 0"; break;
686 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
687 case 0x02: str = "Class 2 (U)SIM specific message"; break;
688 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
691 my_decode_bitfield_value(bigbuf, oct, 0x03, 8);
692 proto_tree_add_text(subtree, tvb,
694 "%s : Message Class: %s%s",
697 (oct & 0x10) ? "" : " (reserved)");
699 else if (default_3_bits)
701 my_decode_bitfield_value(bigbuf, oct, 0x08, 8);
702 proto_tree_add_text(subtree, tvb,
704 "%s : Indication Sense: %s",
706 (oct & 0x08) ? "Set Indication Active" : "Set Indication Inactive");
708 my_decode_bitfield_value(bigbuf, oct, 0x04, 8);
709 proto_tree_add_text(subtree, tvb,
716 case 0x00: str = "Voicemail Message Waiting"; break;
717 case 0x01: str = "Fax Message Waiting"; break;
718 case 0x02: str = "Electronic Mail Message Waiting"; break;
719 case 0x03: str = "Other Message Waiting"; break;
722 my_decode_bitfield_value(bigbuf, oct, 0x03, 8);
723 proto_tree_add_text(subtree, tvb,
729 else if (default_data)
731 my_decode_bitfield_value(bigbuf, oct, 0x08, 8);
732 proto_tree_add_text(subtree, tvb,
737 *seven_bit = !(*eight_bit = (oct & 0x04) ? TRUE : FALSE);
739 my_decode_bitfield_value(bigbuf, oct, 0x04, 8);
740 proto_tree_add_text(subtree, tvb,
742 "%s : Message coding: %s",
744 (*eight_bit) ? "8 bit data" : "GSM 7 bit default alphabet");
748 case 0x00: str = "Class 0"; break;
749 case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
750 case 0x02: str = "Class 2 (U)SIM specific message"; break;
751 case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
754 my_decode_bitfield_value(bigbuf, oct, 0x03, 8);
755 proto_tree_add_text(subtree, tvb,
757 "%s : Message Class: %s",
764 dis_field_scts_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
766 guint8 oct, oct2, oct3;
769 oct = tvb_get_guint8(tvb, offset);
770 oct2 = tvb_get_guint8(tvb, offset+1);
771 oct3 = tvb_get_guint8(tvb, offset+2);
773 proto_tree_add_text(tree,
775 "Year %d%d, Month %d%d, Day %d%d",
785 oct = tvb_get_guint8(tvb, offset);
786 oct2 = tvb_get_guint8(tvb, offset+1);
787 oct3 = tvb_get_guint8(tvb, offset+2);
789 proto_tree_add_text(tree,
791 "Hour %d%d, Minutes %d%d, Seconds %d%d",
801 oct = tvb_get_guint8(tvb, offset);
803 proto_tree_add_text(tree,
811 dis_field_scts(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
814 proto_tree *subtree = NULL;
821 length = tvb_length_remaining(tvb, offset);
825 proto_tree_add_text(tree,
827 "TP-Service-Centre-Time-Stamp: Short Data (?)");
834 proto_tree_add_text(tree, tvb,
836 "TP-Service-Centre-Time-Stamp");
838 subtree = proto_item_add_subtree(item, ett_scts);
840 dis_field_scts_aux(tvb, subtree, *offset_p);
847 dis_field_vp(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, guint8 vp_form)
850 proto_tree *subtree = NULL;
853 guint8 oct, oct2, oct3;
859 if (vp_form == 0x00) return;
870 length = tvb_length_remaining(tvb, offset);
874 proto_tree_add_text(tree,
876 "TP-Validity-Period: Short Data (?)");
883 proto_tree_add_text(tree, tvb,
885 "TP-Validity-Period");
887 subtree = proto_item_add_subtree(item, ett_vp);
889 oct = tvb_get_guint8(tvb, offset);
891 my_decode_bitfield_value(bigbuf, oct, 0x80, 8);
892 proto_tree_add_text(subtree, tvb,
896 (oct & 0x80) ? "Extended" : "No extension");
900 proto_tree_add_text(subtree,
902 "Extension not implemented, ignored");
908 my_decode_bitfield_value(bigbuf, oct, 0x40, 8);
909 proto_tree_add_text(subtree, tvb,
913 (oct & 0x40) ? "Single shot SM" : "Not single shot SM");
915 my_decode_bitfield_value(bigbuf, oct, 0x38, 8);
916 proto_tree_add_text(subtree, tvb,
921 loc_form = oct & 0x7;
926 my_decode_bitfield_value(bigbuf, oct, 0x07, 8);
927 proto_tree_add_text(subtree, tvb,
929 "%s : No Validity Period specified",
936 my_decode_bitfield_value(bigbuf, oct, 0x07, 8);
937 proto_tree_add_text(subtree, tvb,
939 "%s : Validity Period Format: relative",
942 /* go around again */
947 my_decode_bitfield_value(bigbuf, oct, 0x07, 8);
948 proto_tree_add_text(subtree, tvb,
950 "%s : Validity Period Format: relative",
954 oct = tvb_get_guint8(tvb, offset);
956 proto_tree_add_text(subtree, tvb,
965 my_decode_bitfield_value(bigbuf, oct, 0x07, 8);
966 proto_tree_add_text(subtree, tvb,
968 "%s : Validity Period Format: relative",
972 oct = tvb_get_guint8(tvb, offset);
973 oct2 = tvb_get_guint8(tvb, offset+1);
974 oct3 = tvb_get_guint8(tvb, offset+2);
976 proto_tree_add_text(subtree,
978 "Hour %d%d, Minutes %d%d, Seconds %d%d",
990 my_decode_bitfield_value(bigbuf, oct, 0x07, 8);
991 proto_tree_add_text(subtree, tvb,
993 "%s : Validity Period Format: Reserved",
1002 oct = tvb_get_guint8(tvb, offset);
1006 mins = (oct + 1) * 5;
1012 proto_tree_add_text(subtree, tvb,
1014 "TP-Validity-Period: %d hours %d minutes",
1020 proto_tree_add_text(subtree, tvb,
1022 "TP-Validity-Period: %d minutes",
1026 else if ((oct >= 144) &&
1029 mins = (oct - 143) * 30;
1030 hours = 12 + (mins / 60);
1033 proto_tree_add_text(subtree, tvb,
1035 "TP-Validity-Period: %d hours %d minutes",
1039 else if ((oct >= 168) &&
1042 proto_tree_add_text(subtree, tvb,
1044 "TP-Validity-Period: %d day(s)",
1047 else if (oct >= 197)
1049 proto_tree_add_text(subtree, tvb,
1051 "TP-Validity-Period: %d week(s)",
1059 length = tvb_length_remaining(tvb, offset);
1063 proto_tree_add_text(tree,
1064 tvb, offset, length,
1065 "TP-Validity-Period: Short Data (?)");
1067 *offset_p += length;
1072 proto_tree_add_text(tree, tvb,
1074 "TP-Validity-Period: absolute");
1076 subtree = proto_item_add_subtree(item, ett_vp);
1078 dis_field_scts_aux(tvb, subtree, *offset_p);
1098 dis_field_dt(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
1101 proto_tree *subtree = NULL;
1108 length = tvb_length_remaining(tvb, offset);
1112 proto_tree_add_text(tree,
1113 tvb, offset, length,
1114 "TP-Discharge-Time: Short Data (?)");
1116 *offset_p += length;
1121 proto_tree_add_text(tree, tvb,
1123 "TP-Discharge-Time");
1125 subtree = proto_item_add_subtree(item, ett_dt);
1127 dis_field_scts_aux(tvb, subtree, *offset_p);
1133 /* use dis_field_addr() */
1137 dis_field_st(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1139 static gchar *sc_complete = "Short message transaction completed";
1140 static gchar *sc_temporary = "Temporary error, SC still trying to transfer SM";
1141 static gchar *sc_perm = "Permanent error, SC is not making any more transfer attempts";
1142 static gchar *sc_tempfin = "Temporary error, SC is not making any more transfer attempts";
1144 proto_tree *subtree = NULL;
1151 proto_tree_add_text(tree, tvb,
1155 subtree = proto_item_add_subtree(item, ett_st);
1157 my_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1158 proto_tree_add_text(subtree, tvb,
1160 "%s : Definition of bits 0-6: %s",
1162 (oct & 0x80) ? "Reserved" : "as follows");
1168 case 0x00: str2 = sc_complete; str = "Short message received by the SME"; break;
1169 case 0x01: str2 = sc_complete; str = "Short message forwarded by the SC to the SME but the SC is unable to confirm delivery"; break;
1170 case 0x02: str2 = sc_complete; str = "Short message replaced by the SC Reserved values"; break;
1172 case 0x20: str2 = sc_temporary; str = "Congestion"; break;
1173 case 0x21: str2 = sc_temporary; str = "SME busy"; break;
1174 case 0x22: str2 = sc_temporary; str = "No response from SME"; break;
1175 case 0x23: str2 = sc_temporary; str = "Service rejected"; break;
1176 case 0x24: str2 = sc_temporary; str = "Quality of service not available"; break;
1177 case 0x25: str2 = sc_temporary; str = "Error in SME"; break;
1179 case 0x40: str2 = sc_perm; str = "Remote procedure error"; break;
1180 case 0x41: str2 = sc_perm; str = "Incompatible destination"; break;
1181 case 0x42: str2 = sc_perm; str = "Connection rejected by SME"; break;
1182 case 0x43: str2 = sc_perm; str = "Not obtainable"; break;
1183 case 0x44: str2 = sc_perm; str = "Quality of service not available"; break;
1184 case 0x45: str2 = sc_perm; str = "No interworking available"; break;
1185 case 0x46: str2 = sc_perm; str = "SM Validity Period Expired"; break;
1186 case 0x47: str2 = sc_perm; str = "SM Deleted by originating SME"; break;
1187 case 0x48: str2 = sc_perm; str = "SM Deleted by SC Administration"; break;
1188 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;
1190 case 0x60: str2 = sc_tempfin; str = "Congestion"; break;
1191 case 0x61: str2 = sc_tempfin; str = "SME busy"; break;
1192 case 0x62: str2 = sc_tempfin; str = "No response from SME"; break;
1193 case 0x63: str2 = sc_tempfin; str = "Service rejected"; break;
1194 case 0x64: str2 = sc_tempfin; str = "Quality of service not available"; break;
1195 case 0x65: str2 = sc_tempfin; str = "Error in SME"; break;
1198 if ((value >= 0x03) &&
1204 else if ((value >= 0x10) &&
1208 str = "Values specific to each SC";
1210 else if ((value >= 0x26) &&
1213 str2 = sc_temporary;
1216 else if ((value >= 0x30) &&
1219 str2 = sc_temporary;
1220 str = "Values specific to each SC";
1222 else if ((value >= 0x4a) &&
1228 else if ((value >= 0x50) &&
1232 str = "Values specific to each SC";
1234 else if ((value >= 0x66) &&
1240 else if ((value >= 0x70) &&
1244 str = "Values specific to each SC";
1249 my_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
1250 proto_tree_add_text(subtree, tvb,
1260 #define DIS_FIELD_UDL(m_tree, m_offset) \
1262 proto_tree_add_text(m_tree, tvb, \
1264 "TP-User-Data-Length: (%d) %s", \
1266 oct ? "depends on Data-Coding-Scheme" : "no User-Data");\
1270 #define DIS_FIELD_RP(m_tree, m_offset) \
1272 my_decode_bitfield_value(bigbuf, oct, 0x80, 8); \
1273 proto_tree_add_text(m_tree, tvb, \
1275 "%s : TP-Reply-Path: parameter is %sset in this SMS-SUBMIT/DELIVER", \
1277 (oct & 0x80) ? "" : "not "); \
1281 #define DIS_FIELD_MN(m_tree, m_offset) \
1283 proto_tree_add_text(m_tree, tvb, \
1285 "TP-Message-Number: %d", \
1290 #define DIS_FIELD_CT(m_tree, m_offset) \
1294 case 0: str = "Enquiry relating to previously submitted short message"; break; \
1295 case 1: str = "Cancel Status Report Request relating to previously submitted short message"; break; \
1296 case 2: str = "Delete previously submitted Short Message"; break; \
1297 case 3: str = "Enable Status Report Request relating to previously submitted short message"; break; \
1299 if ((oct >= 0x04) && \
1302 str = "Reserved unspecified"; \
1304 else if (oct >= 0xe0) \
1306 str = "Values specific for each SC"; \
1310 str = "undefined"; \
1314 proto_tree_add_text(m_tree, tvb, \
1316 "TP-Command-Type: (%d), %s", \
1322 #define DIS_FIELD_CDL(m_tree, m_offset) \
1324 proto_tree_add_text(m_tree, tvb, \
1326 "TP-Command-Data-Length: (%d)%s", \
1328 oct ? "" : " no Command-Data");\
1332 /* done in-line in the message functions */
1336 dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1339 proto_tree *subtree = NULL;
1344 proto_tree_add_text(tree, tvb,
1346 "TP-Failure-Cause");
1348 subtree = proto_item_add_subtree(item, ett_fcs);
1352 case 0x80: str = "Telematic interworking not supported"; break;
1353 case 0x81: str = "Short message Type 0 not supported"; break;
1354 case 0x82: str = "Cannot replace short message"; break;
1355 case 0x8F: str = "Unspecified TP-PID error"; break;
1356 case 0x90: str = "Data coding scheme (alphabet) not supported"; break;
1357 case 0x91: str = "Message class not supported"; break;
1358 case 0x9F: str = "Unspecified TP-DCS error"; break;
1359 case 0xA0: str = "Command cannot be actioned"; break;
1360 case 0xA1: str = "Command unsupported"; break;
1361 case 0xAF: str = "Unspecified TP-Command error"; break;
1362 case 0xB0: str = "TPDU not supported"; break;
1363 case 0xC0: str = "SC busy"; break;
1364 case 0xC1: str = "No SC subscription"; break;
1365 case 0xC2: str = "SC system failure"; break;
1366 case 0xC3: str = "Invalid SME address"; break;
1367 case 0xC4: str = "Destination SME barred"; break;
1368 case 0xC5: str = "SM Rejected-Duplicate SM"; break;
1369 case 0xC6: str = "TP-VPF not supported"; break;
1370 case 0xC7: str = "TP-VP not supported"; break;
1371 case 0xD0: str = "(U)SIM SMS storage full"; break;
1372 case 0xD1: str = "No SMS storage capability in (U)SIM"; break;
1373 case 0xD2: str = "Error in MS"; break;
1374 case 0xD3: str = "Memory Capacity Exceeded"; break;
1375 case 0xD4: str = "(U)SIM Application Toolkit Busy"; break;
1376 case 0xD5: str = "(U)SIM data download error"; break;
1377 case 0xFF: str = "Unspecified error cause"; break;
1379 if ((oct >= 0x80) &&
1382 str = "TP-PID errors"; break;
1384 else if ((oct >= 0x90) &&
1387 str = "TP-DCS errors"; break;
1389 else if ((oct >= 0xA0) &&
1392 str = "TP-Command errors"; break;
1394 else if ((oct >= 0xE0) &&
1397 str = "Values specific to an application"; break;
1401 str = "Reserved"; break;
1405 proto_tree_add_text(subtree, tvb,
1411 #define DIS_FIELD_UDHI(m_tree, m_offset, m_udhi) \
1413 m_udhi = (oct & 0x40) >> 6; \
1414 my_decode_bitfield_value(bigbuf, oct, 0x40, 8); \
1415 proto_tree_add_text(m_tree, tvb, \
1417 "%s : TP-User-Data-Header-Indicator: %s short message", \
1420 "The beginning of the TP-UD field contains a Header in addition to the" : \
1421 "The TP-UD field contains only the"); \
1429 #define GN_BYTE_MASK ((1 << bits) - 1)
1432 char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length,
1433 unsigned char *input, unsigned char *output)
1435 unsigned char *out_num = output; /* Current pointer to the output buffer */
1436 unsigned char *in_num = input; /* Current pointer to the input buffer */
1437 unsigned char rest = 0x00;
1440 bits = offset ? offset : 7;
1442 while ((unsigned int)(in_num - input) < in_length)
1444 *out_num = ((*in_num & GN_BYTE_MASK) << (7 - bits)) | rest;
1445 rest = *in_num >> bits;
1447 /* If we don't start from 0th bit, we shouldn't go to the
1448 next char. Under *out_num we have now 0 and under Rest -
1449 _first_ part of the char. */
1450 if ((in_num != input) || (bits == 7)) out_num++;
1453 if ((unsigned int)(out_num - output) >= out_length) break;
1455 /* After reading 7 octets we have read 7 full characters but
1456 we have 7 bits as well. This is the next character */
1470 return out_num - output;
1473 #define GN_CHAR_ALPHABET_SIZE 128
1475 #define GN_CHAR_ESCAPE 0x1b
1477 static unsigned char gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
1479 /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
1480 /* Characters in hex position 10, [12 to 1a] and 24 are not present on
1481 latin1 charset, so we cannot reproduce on the screen, however they are
1482 greek symbol not present even on my Nokia */
1484 '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
1485 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
1486 '?', '_', '?', '?', '?', '?', '?', '?',
1487 '?', '?', '?', '?', 0xc6, 0xe6, 0xdf, 0xc9,
1488 ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
1489 '(', ')', '*', '+', ',', '-', '.', '/',
1490 '0', '1', '2', '3', '4', '5', '6', '7',
1491 '8', '9', ':', ';', '<', '=', '>', '?',
1492 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
1493 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
1494 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
1495 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
1496 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
1497 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
1498 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
1499 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
1503 char_is_escape(unsigned char value)
1505 return (value == GN_CHAR_ESCAPE);
1508 static unsigned char
1509 char_def_alphabet_ext_decode(unsigned char value)
1513 case 0x0a: return 0x0c; break; /* form feed */
1514 case 0x14: return '^'; break;
1515 case 0x28: return '{'; break;
1516 case 0x29: return '}'; break;
1517 case 0x2f: return '\\'; break;
1518 case 0x3c: return '['; break;
1519 case 0x3d: return '~'; break;
1520 case 0x3e: return ']'; break;
1521 case 0x40: return '|'; break;
1522 case 0x65: return 0xa4; break; /* euro */
1523 default: return '?'; break; /* invalid character */
1527 unsigned char char_def_alphabet_decode(unsigned char value)
1529 if (value < GN_CHAR_ALPHABET_SIZE)
1531 return gsm_default_alphabet[value];
1540 char_ascii_decode(unsigned char* dest, const unsigned char* src, int len)
1544 for (i = 0, j = 0; j < len; i++, j++)
1546 if (char_is_escape(src[j]))
1547 dest[i] = char_def_alphabet_ext_decode(src[++j]);
1549 dest[i] = char_def_alphabet_decode(src[j]);
1556 char_uni_alphabet_decode(wchar_t value, unsigned char *dest)
1560 switch (length = wctomb(dest, value))
1571 char_unicode_decode(unsigned char* dest, const unsigned char* src, int len)
1573 int i, length = 0, pos = 0;
1575 for (i = 0; i < len / 2; i++)
1577 length = char_uni_alphabet_decode((src[i * 2] << 8) | src[(i * 2) + 1], dest);
1589 dis_iei_apa_8bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1595 EXACT_DATA_CHECK(length, 2);
1597 oct = tvb_get_guint8(tvb, offset);
1605 str = "Available for allocation by applications";
1608 proto_tree_add_text(tree,
1610 "Destination port: %d, %s",
1615 oct = tvb_get_guint8(tvb, offset);
1623 str = "Available for allocation by applications";
1626 proto_tree_add_text(tree,
1628 "Originator port: %d, %s",
1634 dis_iei_apa_16bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1640 EXACT_DATA_CHECK(length, 4);
1642 value = tvb_get_ntohs(tvb, offset);
1646 str = "As allocated by IANA (http://www.IANA.com/)";
1648 else if (value < 17000)
1650 str = "Available for allocation by applications";
1657 proto_tree_add_text(tree,
1659 "Destination port: %d, %s",
1664 value = tvb_get_ntohs(tvb, offset);
1668 str = "As allocated by IANA (http://www.IANA.com/)";
1670 else if (value < 17000)
1672 str = "Available for allocation by applications";
1679 proto_tree_add_text(tree,
1681 "Originator port: %d, %s",
1687 dis_field_ud_iei(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1689 void (*iei_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length) = NULL;
1692 proto_tree *subtree = NULL;
1699 oct = tvb_get_guint8(tvb, offset);
1703 case 0x00: str = "Concatenated short messages, 8-bit reference number (SMS Control)"; break;
1704 case 0x01: str = "Special SMS Message Indication (SMS Control)"; break;
1705 case 0x02: str = "Reserved N/A"; break;
1706 case 0x03: str = "Value not used to avoid misinterpretation as <LF> character N/A"; break;
1707 case 0x04: str = "Application port addressing scheme, 8 bit address (SMS Control)"; iei_fcn = dis_iei_apa_8bit; break;
1708 case 0x05: str = "Application port addressing scheme, 16 bit address (SMS Control)"; iei_fcn = dis_iei_apa_16bit; break;
1709 case 0x06: str = "SMSC Control Parameters (SMS Control)"; break;
1710 case 0x07: str = "UDH Source Indicator (SMS Control)"; break;
1711 case 0x08: str = "Concatenated short message, 16-bit reference number (SMS Control)"; break;
1712 case 0x09: str = "Wireless Control Message Protocol (SMS Control)"; break;
1713 case 0x0A: str = "Text Formatting (EMS Control)"; break;
1714 case 0x0B: str = "Predefined Sound (EMS Content)"; break;
1715 case 0x0C: str = "User Defined Sound (iMelody max 128 bytes) (EMS Content)"; break;
1716 case 0x0D: str = "Predefined Animation (EMS Content)"; break;
1717 case 0x0E: str = "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)"; break;
1718 case 0x0F: str = "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)"; break;
1719 case 0x10: str = "Large Picture (32*32 = 128 bytes) (EMS Content)"; break;
1720 case 0x11: str = "Small Picture (16*16 = 32 bytes) (EMS Content)"; break;
1721 case 0x12: str = "Variable Picture (EMS Content)"; break;
1722 case 0x13: str = "User prompt indicator (EMS Control)"; break;
1723 case 0x14: str = "Extended Object (EMS Content)"; break;
1724 case 0x15: str = "Reused Extended Object (EMS Control)"; break;
1725 case 0x16: str = "Compression Control (EMS Control)"; break;
1726 case 0x17: str = "Object Distribution Indicator (EMS Control)"; break;
1727 case 0x18: str = "Standard WVG object (EMS Content)"; break;
1728 case 0x19: str = "Character Size WVG object (EMS Content)"; break;
1729 case 0x1A: str = "Extended Object Data Request Command (EMS Control)"; break;
1730 case 0x20: str = "RFC 822 E-Mail Header (SMS Control)"; break;
1731 case 0x21: str = "Hyperlink format element (SMS Control)"; break;
1732 case 0x22: str = "Reply Address Element (SMS Control)"; break;
1734 if ((oct >= 0x1b) &&
1737 str = "Reserved for future EMS features (see subclause 3.10) N/A"; break;
1739 else if ((oct >= 0x23) &&
1742 str = "Reserved for future use N/A"; break;
1744 else if ((oct >= 0x70) &&
1747 str = "(U)SIM Toolkit Security Headers (SMS Control)"; break;
1749 else if ((oct >= 0x80) &&
1752 str = "SME to SME specific use (SMS Control)"; break;
1754 else if ((oct >= 0xa0) &&
1757 str = "Reserved for future use N/A"; break;
1759 else if ((oct >= 0xc0) &&
1762 str = "SC specific use (SMS Control)"; break;
1766 str = "Reserved for future use N/A"; break;
1770 iei_len = tvb_get_guint8(tvb, offset + 1);
1773 proto_tree_add_text(tree,
1774 tvb, offset, iei_len + 2,
1778 subtree = proto_item_add_subtree(item, ett_udh_ieis[oct]);
1780 proto_tree_add_text(subtree,
1782 "Information Element Identifier: %d",
1787 proto_tree_add_text(subtree,
1796 if (iei_fcn == NULL)
1798 proto_tree_add_text(subtree,
1799 tvb, offset, iei_len,
1804 iei_fcn(tvb, subtree, offset, iei_len);
1808 length -= 2 + iei_len;
1814 dis_field_ud(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 length, gboolean udhi, guint8 udl,
1815 gboolean seven_bit, gboolean eight_bit, gboolean ucs2, gboolean compressed)
1817 static guint8 fill_bits_mask[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };
1819 proto_item *udh_item;
1820 proto_tree *subtree = NULL;
1821 proto_tree *udh_subtree = NULL;
1830 proto_tree_add_text(tree, tvb,
1834 subtree = proto_item_add_subtree(item, ett_ud);
1836 oct = tvb_get_guint8(tvb, offset);
1840 /* step over header */
1843 proto_tree_add_text(subtree, tvb,
1845 "User-Data Header");
1847 udh_subtree = proto_item_add_subtree(udh_item, ett_udh);
1849 proto_tree_add_text(udh_subtree,
1851 "User Data Header Length (%d)",
1858 dis_field_ud_iei(tvb, udh_subtree, offset, oct);
1866 /* step over fill bits ? */
1868 fill_bits = 7 - (((oct + 1) * 8) % 7);
1871 oct = tvb_get_guint8(tvb, offset);
1873 my_decode_bitfield_value(bigbuf, oct, fill_bits_mask[fill_bits], 8);
1874 proto_tree_add_text(udh_subtree,
1884 proto_tree_add_text(subtree, tvb,
1893 char_7bit_unpack(fill_bits, length, sizeof(bigbuf),
1894 (guchar*) (tvb_get_ptr(tvb, offset, length)), bigbuf);
1895 bigbuf[out_len] = '\0';
1896 char_ascii_decode(bigbuf, bigbuf, out_len);
1898 proto_tree_add_text(subtree, tvb,
1905 (guchar*) (tvb_get_ptr(tvb, offset, length)), length);
1906 bigbuf[length] = '\0';
1908 proto_tree_add_text(subtree, tvb,
1914 char_unicode_decode(bigbuf,
1915 (guchar*) (tvb_get_ptr(tvb, offset, length)), length);
1917 proto_tree_add_text(subtree, tvb,
1925 #define DIS_FIELD_RD(m_tree, m_offset) \
1927 my_decode_bitfield_value(bigbuf, oct, 0x04, 8); \
1928 proto_tree_add_text(m_tree, tvb, \
1930 "%s : TP-Reject-Duplicates: Instruct SC to %s duplicates", \
1938 #define DIS_FIELD_SRQ(m_tree, m_offset) \
1940 my_decode_bitfield_value(bigbuf, oct, 0x20, 8); \
1941 proto_tree_add_text(m_tree, tvb, \
1943 "%s : TP-Status-Report-Qualifier: The SMS-STATUS-REPORT is the result of %s", \
1946 "an SMS-COMMAND e.g. an Enquiry" : \
1952 dis_field_pi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1955 proto_tree *subtree = NULL;
1959 proto_tree_add_text(tree, tvb,
1961 "TP-Parameter-Indicator");
1963 subtree = proto_item_add_subtree(item, ett_pi);
1965 my_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1966 proto_tree_add_text(subtree, tvb,
1970 (oct & 0x80) ? "Extended" : "No extension");
1972 my_decode_bitfield_value(bigbuf, oct, 0x78, 8);
1973 proto_tree_add_text(subtree, tvb,
1978 my_decode_bitfield_value(bigbuf, oct, 0x04, 8);
1979 proto_tree_add_text(subtree, tvb,
1981 "%s : TP-UDL %spresent",
1983 (oct & 0x04) ? "" : "not ");
1985 my_decode_bitfield_value(bigbuf, oct, 0x02, 8);
1986 proto_tree_add_text(subtree, tvb,
1988 "%s : TP-DCS %spresent",
1990 (oct & 0x02) ? "" : "not ");
1992 my_decode_bitfield_value(bigbuf, oct, 0x01, 8);
1993 proto_tree_add_text(subtree, tvb,
1995 "%s : TP-PID %spresent",
1997 (oct & 0x01) ? "" : "not ");
2005 dis_msg_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2007 guint32 saved_offset;
2014 gboolean compressed;
2018 saved_offset = offset;
2019 length = tvb_length_remaining(tvb, offset);
2021 oct = tvb_get_guint8(tvb, offset);
2023 DIS_FIELD_RP(tree, offset);
2025 DIS_FIELD_UDHI(tree, offset, udhi);
2027 DIS_FIELD_SRI(tree, offset);
2029 DIS_FIELD_MMS(tree, offset);
2031 DIS_FIELD_MTI(tree, offset);
2035 dis_field_addr(tvb, tree, &offset, "TP-Originating-Address");
2037 oct = tvb_get_guint8(tvb, offset);
2039 dis_field_pid(tvb, tree, offset, oct);
2042 oct = tvb_get_guint8(tvb, offset);
2044 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2047 dis_field_scts(tvb, tree, &offset);
2049 oct = tvb_get_guint8(tvb, offset);
2052 DIS_FIELD_UDL(tree, offset);
2058 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2059 seven_bit, eight_bit, ucs2, compressed);
2068 dis_msg_deliver_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2070 guint32 saved_offset;
2078 gboolean compressed;
2083 saved_offset = offset;
2084 length = tvb_length_remaining(tvb, offset);
2086 oct = tvb_get_guint8(tvb, offset);
2088 DIS_FIELD_UDHI(tree, offset, udhi);
2090 DIS_FIELD_MTI(tree, offset);
2094 proto_tree_add_text(tree,
2095 tvb, offset, length,
2102 case RP_ERROR_MS_TO_N:
2105 case RP_ERROR_N_TO_MS:
2107 oct = tvb_get_guint8(tvb, offset);
2109 dis_field_fcs(tvb, tree, offset, oct);
2113 proto_tree_add_text(tree,
2114 tvb, saved_offset, length,
2122 pi = tvb_get_guint8(tvb, offset);
2124 dis_field_pi(tvb, tree, offset, pi);
2128 if (length <= (offset - saved_offset))
2130 proto_tree_add_text(tree,
2137 oct = tvb_get_guint8(tvb, offset);
2139 dis_field_pid(tvb, tree, offset, oct);
2144 if (length <= (offset - saved_offset))
2146 proto_tree_add_text(tree,
2153 oct = tvb_get_guint8(tvb, offset);
2155 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2160 if (length <= (offset - saved_offset))
2162 proto_tree_add_text(tree,
2169 oct = tvb_get_guint8(tvb, offset);
2172 DIS_FIELD_UDL(tree, offset);
2179 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2180 seven_bit, eight_bit, ucs2, compressed);
2189 dis_msg_submit(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2191 guint32 saved_offset;
2200 gboolean compressed;
2204 saved_offset = offset;
2205 length = tvb_length_remaining(tvb, offset);
2207 oct = tvb_get_guint8(tvb, offset);
2209 DIS_FIELD_RP(tree, offset);
2211 DIS_FIELD_UDHI(tree, offset, udhi);
2213 DIS_FIELD_SRR(tree, offset);
2215 DIS_FIELD_VPF(tree, offset, &vp_form);
2217 DIS_FIELD_RD(tree, offset);
2219 DIS_FIELD_MTI(tree, offset);
2222 oct = tvb_get_guint8(tvb, offset);
2224 DIS_FIELD_MR(tree, offset);
2228 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
2230 oct = tvb_get_guint8(tvb, offset);
2232 dis_field_pid(tvb, tree, offset, oct);
2235 oct = tvb_get_guint8(tvb, offset);
2237 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2240 dis_field_vp(tvb, tree, &offset, vp_form);
2242 oct = tvb_get_guint8(tvb, offset);
2245 DIS_FIELD_UDL(tree, offset);
2251 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2252 seven_bit, eight_bit, ucs2, compressed);
2261 dis_msg_submit_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2263 guint32 saved_offset;
2271 gboolean compressed;
2276 saved_offset = offset;
2277 length = tvb_length_remaining(tvb, offset);
2279 oct = tvb_get_guint8(tvb, offset);
2281 DIS_FIELD_UDHI(tree, offset, udhi);
2283 DIS_FIELD_MTI(tree, offset);
2287 case RP_ERROR_MS_TO_N:
2290 case RP_ERROR_N_TO_MS:
2292 oct = tvb_get_guint8(tvb, offset);
2294 dis_field_fcs(tvb, tree, offset, oct);
2299 pi = tvb_get_guint8(tvb, offset);
2301 dis_field_pi(tvb, tree, offset, pi);
2304 dis_field_scts(tvb, tree, &offset);
2308 if (length <= (offset - saved_offset))
2310 proto_tree_add_text(tree,
2317 oct = tvb_get_guint8(tvb, offset);
2319 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2324 if (length <= (offset - saved_offset))
2326 proto_tree_add_text(tree,
2333 oct = tvb_get_guint8(tvb, offset);
2336 DIS_FIELD_UDL(tree, offset);
2343 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2344 seven_bit, eight_bit, ucs2, compressed);
2353 dis_msg_status_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2355 guint32 saved_offset;
2363 gboolean compressed;
2368 saved_offset = offset;
2369 length = tvb_length_remaining(tvb, offset);
2371 oct = tvb_get_guint8(tvb, offset);
2373 DIS_FIELD_SRQ(tree, offset);
2375 DIS_FIELD_MMS(tree, offset);
2377 DIS_FIELD_UDHI(tree, offset, udhi);
2379 DIS_FIELD_MTI(tree, offset);
2382 oct = tvb_get_guint8(tvb, offset);
2384 DIS_FIELD_MR(tree, offset);
2388 dis_field_addr(tvb, tree, &offset, "TP-Recipient-Address");
2390 dis_field_scts(tvb, tree, &offset);
2392 dis_field_dt(tvb, tree, &offset);
2394 oct = tvb_get_guint8(tvb, offset);
2396 dis_field_st(tvb, tree, offset, oct);
2399 pi = tvb_get_guint8(tvb, offset);
2401 dis_field_pi(tvb, tree, offset, pi);
2405 if (length <= (offset - saved_offset))
2407 proto_tree_add_text(tree,
2414 oct = tvb_get_guint8(tvb, offset);
2416 dis_field_pid(tvb, tree, offset, oct);
2421 if (length <= (offset - saved_offset))
2423 proto_tree_add_text(tree,
2430 oct = tvb_get_guint8(tvb, offset);
2432 dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2437 if (length <= (offset - saved_offset))
2439 proto_tree_add_text(tree,
2446 oct = tvb_get_guint8(tvb, offset);
2449 DIS_FIELD_UDL(tree, offset);
2456 dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2457 seven_bit, eight_bit, ucs2, compressed);
2466 dis_msg_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2468 guint32 saved_offset;
2477 saved_offset = offset;
2478 length = tvb_length_remaining(tvb, offset);
2480 oct = tvb_get_guint8(tvb, offset);
2482 DIS_FIELD_SRR(tree, offset);
2484 DIS_FIELD_UDHI(tree, offset, udhi);
2486 DIS_FIELD_MTI(tree, offset);
2489 oct = tvb_get_guint8(tvb, offset);
2491 DIS_FIELD_MR(tree, offset);
2494 oct = tvb_get_guint8(tvb, offset);
2496 dis_field_pid(tvb, tree, offset, oct);
2499 oct = tvb_get_guint8(tvb, offset);
2501 DIS_FIELD_CT(tree, offset);
2504 oct = tvb_get_guint8(tvb, offset);
2506 DIS_FIELD_MN(tree, offset);
2510 dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
2512 oct = tvb_get_guint8(tvb, offset);
2515 DIS_FIELD_CDL(tree, offset);
2521 proto_tree_add_text(tree,
2527 #define NUM_MSGS (sizeof(msg_type_strings)/sizeof(value_string))
2528 static gint ett_msgs[NUM_MSGS];
2529 static void (*gsm_sms_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = {
2530 dis_msg_deliver, /* SMS-DELIVER */
2531 dis_msg_deliver_report, /* SMS-DELIVER REPORT */
2532 dis_msg_submit, /* SMS-SUBMIT */
2533 dis_msg_submit_report, /* SMS-SUBMIT REPORT */
2534 dis_msg_status_report, /* SMS-STATUS REPORT */
2535 dis_msg_command, /* SMS-COMMAND */
2536 NULL, /* Reserved */
2537 NULL, /* Reserved */
2541 /* GENERIC DISSECTOR FUNCTIONS */
2544 dissect_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2546 void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = NULL;
2547 proto_item *gsm_sms_item;
2548 proto_tree *gsm_sms_tree = NULL;
2557 if (!proto_is_protocol_enabled(proto_gsm_sms))
2559 call_dissector(data_handle,tvb, pinfo, tree);
2565 if (check_col(pinfo->cinfo, COL_PROTOCOL))
2567 col_set_str(pinfo->cinfo, COL_PROTOCOL, gsm_sms_proto_name_short);
2570 /* In the interest of speed, if "tree" is NULL, don't do any work not
2571 * necessary to generate protocol tree items.
2576 g_rp_type = pinfo->match_port;
2580 oct = tvb_get_guint8(tvb, offset);
2586 * convert the 2 bit value to one based on direction
2588 msg_type |= ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x04 : 0x00);
2590 str = my_match_strval(msg_type, msg_type_strings, &idx);
2593 * create the GSM_SMS protocol tree
2596 proto_tree_add_protocol_format(tree, proto_gsm_sms, tvb, 0, -1,
2599 (str == NULL) ? "Unknown message identifier" : str);
2602 proto_item_add_subtree(gsm_sms_item, ett_gsm_sms);
2604 if ((str == NULL) ||
2605 (msg_type == 0x03) ||
2612 ett_msg_idx = ett_msgs[idx];
2613 msg_fcn = gsm_sms_msg_fcn[idx];
2616 if (msg_fcn == NULL)
2618 proto_tree_add_text(gsm_sms_tree,
2620 "Message dissector not implemented");
2624 (*msg_fcn)(tvb, gsm_sms_tree, offset);
2630 /* Register the protocol with Ethereal */
2632 proto_register_gsm_sms(void)
2638 /* Setup list of header fields */
2639 static hf_register_info hf[] =
2644 /* Setup protocol subtree array */
2645 #define NUM_INDIVIDUAL_PARMS 12
2646 static gint *ett[NUM_INDIVIDUAL_PARMS+NUM_MSGS+NUM_UDH_IEIS];
2648 memset((void *) ett, -1, sizeof(ett));
2650 ett[0] = &ett_gsm_sms;
2663 last_offset = NUM_INDIVIDUAL_PARMS;
2665 for (i=0; i < NUM_MSGS; i++, last_offset++)
2667 ett[last_offset] = &ett_msgs[i];
2670 for (i=0; i < NUM_UDH_IEIS; i++, last_offset++)
2672 ett[last_offset] = &ett_udh_ieis[i];
2675 /* Register the protocol name and description */
2678 proto_register_protocol(gsm_sms_proto_name, gsm_sms_proto_name_short, "gsm_sms");
2681 proto_register_field_array(proto_gsm_sms, hf, array_length(hf));
2684 proto_register_subtree_array(ett, array_length(ett));
2689 proto_reg_handoff_gsm_sms(void)
2691 dissector_handle_t gsm_sms_handle;
2693 gsm_sms_handle = create_dissector_handle(dissect_gsm_sms, proto_gsm_sms);
2695 dissector_add("gsm_a.sms_tpdu", RP_DATA_MS_TO_N, gsm_sms_handle);
2696 dissector_add("gsm_a.sms_tpdu", RP_DATA_N_TO_MS, gsm_sms_handle);
2697 dissector_add("gsm_a.sms_tpdu", RP_ACK_MS_TO_N, gsm_sms_handle);
2698 dissector_add("gsm_a.sms_tpdu", RP_ACK_N_TO_MS, gsm_sms_handle);
2699 dissector_add("gsm_a.sms_tpdu", RP_ERROR_MS_TO_N, gsm_sms_handle);
2700 dissector_add("gsm_a.sms_tpdu", RP_ERROR_N_TO_MS, gsm_sms_handle);
2702 data_handle = find_dissector("data");