From Didier Gautheron:
[obnox/wireshark/wip.git] / epan / dissectors / packet-gsm_sms.c
1 /* packet-gsm_sms.c
2  * Routines for GSM SMS TPDU (GSM 03.40) dissection
3  *
4  * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
5  * In association with Telos Technology Inc.
6  *
7  * TPDU User-Data unpack routines from GNOKII.
8  *
9  *   Reference [1]
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)
13  *
14  * Header field support for TPDU Parameters added by
15  * Abhik Sarkar.
16  *
17  * $Id$
18  *
19  * Wireshark - Network traffic analyzer
20  * By Gerald Combs <gerald@wireshark.org>
21  * Copyright 1998 Gerald Combs
22  *
23  * This program is free software; you can redistribute it and/or
24  * modify it under the terms of the GNU General Public License
25  * as published by the Free Software Foundation; either version 2
26  * of the License, or (at your option) any later version.
27  *
28  * This program is distributed in the hope that it will be useful,
29  * but WITHOUT ANY WARRANTY; without even the implied warranty of
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31  * GNU General Public License for more details.
32  *
33  * You should have received a copy of the GNU General Public License
34  * along with this program; if not, write to the Free Software
35  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36  */
37
38 #ifdef HAVE_CONFIG_H
39 # include "config.h"
40 #endif
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <gmodule.h>
45
46 #ifdef HAVE_SYS_TYPES_H
47 # include <sys/types.h>
48 #endif
49
50 #ifdef HAVE_NETINET_IN_H
51 # include <netinet/in.h>
52 #endif
53
54 #include <string.h>
55
56 #include <epan/packet.h>
57 #include <epan/prefs.h>
58 #include <epan/reassemble.h>
59 #include <glib.h>
60
61 #include "packet-gsm_sms.h"
62
63 #define MAX_SMS_FRAG_LEN                134
64
65 /* PROTOTYPES/FORWARDS */
66
67 #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
68     if ((edc_len) > (edc_max_len)) \
69     { \
70         proto_tree_add_text(tree, tvb, \
71             offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
72     }
73
74 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
75     if ((sdc_len) < (sdc_min_len)) \
76     { \
77         proto_tree_add_text(tree, tvb, \
78             offset, (sdc_len), "Short Data (?)"); \
79         return; \
80     }
81
82 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
83     if ((edc_len) != (edc_eq_len)) \
84     { \
85         proto_tree_add_text(tree, tvb, \
86             offset, (edc_len), "Unexpected Data Length"); \
87         return; \
88     }
89
90 #define SMS_SHIFTMASK(m_val, m_bitmask, m_sval); \
91     { \
92         int     _temp_val = m_val; \
93         int     _temp_bm = m_bitmask; \
94         while (_temp_bm && !(_temp_bm & 0x01)) \
95         { \
96             _temp_bm = _temp_bm >> 1; \
97             _temp_val = _temp_val >> 1; \
98         } \
99         m_sval = _temp_val; \
100     }
101
102
103 static const char *gsm_sms_proto_name = "GSM SMS TPDU (GSM 03.40)";
104 static const char *gsm_sms_proto_name_short = "GSM SMS";
105
106 /* Initialize the subtree pointers */
107 static gint ett_gsm_sms = -1;
108 static gint ett_pid = -1;
109 static gint ett_pi = -1;
110 static gint ett_fcs = -1;
111 static gint ett_vp = -1;
112 static gint ett_scts = -1;
113 static gint ett_dt = -1;
114 static gint ett_st = -1;
115 static gint ett_addr = -1;
116 static gint ett_dcs = -1;
117 static gint ett_ud = -1;
118 static gint ett_udh = -1;
119
120 static gint ett_udh_tfm = -1;
121 static gint ett_udh_tfc = -1;
122
123 /* Initialize the protocol and registered fields */
124 static int proto_gsm_sms = -1;
125
126 static gint hf_gsm_sms_coding_group_bits2 = -1;
127 static gint hf_gsm_sms_coding_group_bits4 = -1;
128 static gint  hf_gsm_sms_ud_multiple_messages_msg_id = -1;
129 static gint  hf_gsm_sms_ud_multiple_messages_msg_parts = -1;
130 static gint  hf_gsm_sms_ud_multiple_messages_msg_part = -1;
131
132 /* TPDU Parameters */
133 static gint hf_gsm_sms_tp_mti_up = -1;
134 static gint hf_gsm_sms_tp_mti_down = -1;
135 static gint hf_gsm_sms_tp_mms = -1;
136 static gint hf_gsm_sms_tp_vpf = -1;
137 static gint hf_gsm_sms_tp_sri = -1;
138 static gint hf_gsm_sms_tp_srr = -1;
139 static gint hf_gsm_sms_tp_mr = -1;
140 static gint hf_gsm_sms_tp_oa = -1;
141 static gint hf_gsm_sms_tp_da = -1;
142 static gint hf_gsm_sms_tp_pid = -1;
143 static gint hf_gsm_sms_tp_dcs = -1;
144 static gint hf_gsm_sms_tp_ra = -1;
145 static gint hf_gsm_sms_tp_rp = -1;
146 static gint hf_gsm_sms_tp_udhi = -1;
147 static gint hf_gsm_sms_tp_rd = -1;
148 static gint hf_gsm_sms_tp_srq = -1;
149 #if 0
150 static gint hf_gsm_sms_tp_scts = -1;
151 static gint hf_gsm_sms_tp_vp = -1;
152 static gint hf_gsm_sms_tp_dt = -1;
153 static gint hf_gsm_sms_tp_st = -1;
154 static gint hf_gsm_sms_tp_udl = -1;
155 static gint hf_gsm_sms_tp_mn = -1;
156 static gint hf_gsm_sms_tp_ct = -1;
157 static gint hf_gsm_sms_tp_cdl = -1;
158 static gint hf_gsm_sms_tp_cd = -1;
159 static gint hf_gsm_sms_tp_ud = -1;
160 #endif
161  
162 static gboolean msg_udh_frag = FALSE;
163 static char bigbuf[1024];
164 static packet_info *g_pinfo;
165 static proto_tree *g_tree;
166
167 /* 3GPP TS 23.038 version 7.0.0 Release 7
168  * The TP-Data-Coding-Scheme field, defined in 3GPP TS 23.040 [4],
169  * indicates the data coding scheme of the TP-UD field, and may indicate a message class.
170  * Any reserved codings shall be assumed to be the GSM 7 bit default alphabet
171  * (the same as codepoint 00000000) by a receiving entity.
172  * The octet is used according to a coding group which is indicated in bits 7..4.
173  */
174
175 /* Coding Group Bits */
176 static const value_string gsm_sms_coding_group_bits_vals[] = {
177         { 0,    "General Data Coding indication" }, /* 00xx */
178         { 1,    "General Data Coding indication" }, /* 00xx */
179         { 2,    "General Data Coding indication" }, /* 00xx */
180         { 3,    "General Data Coding indication" }, /* 00xx */
181         { 4,    "Message Marked for Automatic Deletion Group" }, /* 01xx */
182         { 5,    "Message Marked for Automatic Deletion Group" }, /* 01xx */
183         { 6,    "Message Marked for Automatic Deletion Group" }, /* 01xx */
184         { 7,    "Message Marked for Automatic Deletion Group" }, /* 01xx */
185         { 8,    "Reserved coding groups" },                     /* 1000..1011  */
186         { 9,    "Reserved coding groups" },                     /* 1000..1011  */
187         { 10,   "Reserved coding groups" },                     /* 1000..1011  */
188         { 11,   "Reserved coding groups" },                     /* 1000..1011  */
189         { 12,   "Message Waiting Indication Group: Discard Message" },/* 1100  */
190         { 13,   "Message Waiting Indication Group: Store Message" },  /* 1101  */
191         { 14,   "Message Waiting Indication Group: Store Message" },  /* 1110  */
192         { 15,   "Data coding/message class" },  /* 1111  */
193     { 0, NULL },
194 };
195
196 guint16 g_sm_id;
197 guint16 g_frags;
198 guint16 g_frag;
199
200 guint16 g_port_src;
201 guint16 g_port_dst;
202 static gboolean    g_is_wsp;
203
204 static dissector_table_t gsm_sms_dissector_tbl;
205 /* Short Message reassembly */
206 static GHashTable *g_sm_fragment_table = NULL;
207 static GHashTable *g_sm_reassembled_table = NULL;
208 static gint ett_gsm_sms_ud_fragment = -1;
209 static gint ett_gsm_sms_ud_fragments = -1;
210  /*
211  * Short Message fragment handling
212  */
213 static int hf_gsm_sms_ud_fragments = -1;
214 static int hf_gsm_sms_ud_fragment = -1;
215 static int hf_gsm_sms_ud_fragment_overlap = -1;
216 static int hf_gsm_sms_ud_fragment_overlap_conflicts = -1;
217 static int hf_gsm_sms_ud_fragment_multiple_tails = -1;
218 static int hf_gsm_sms_ud_fragment_too_long_fragment = -1;
219 static int hf_gsm_sms_ud_fragment_error = -1;
220 static int hf_gsm_sms_ud_reassembled_in = -1;
221
222 static const fragment_items sm_frag_items = {
223         /* Fragment subtrees */
224         &ett_gsm_sms_ud_fragment,
225         &ett_gsm_sms_ud_fragments,
226         /* Fragment fields */
227         &hf_gsm_sms_ud_fragments,
228         &hf_gsm_sms_ud_fragment,
229         &hf_gsm_sms_ud_fragment_overlap,
230         &hf_gsm_sms_ud_fragment_overlap_conflicts,
231         &hf_gsm_sms_ud_fragment_multiple_tails,
232         &hf_gsm_sms_ud_fragment_too_long_fragment,
233         &hf_gsm_sms_ud_fragment_error,
234         /* Reassembled in field */
235         &hf_gsm_sms_ud_reassembled_in,
236         /* Tag */
237         "Short Message fragments"
238 };
239
240
241 static void
242 gsm_sms_defragment_init (void)
243 {
244         fragment_table_init (&g_sm_fragment_table);
245         reassembled_table_init(&g_sm_reassembled_table);
246 }
247
248 /*
249  * this is the GSM 03.40 definition with the bit 2
250  * set to 1 for uplink messages
251  */
252 static const value_string msg_type_strings[] = {
253     { 0,        "SMS-DELIVER" },
254     { 4,        "SMS-DELIVER REPORT" },
255     { 5,        "SMS-SUBMIT" },
256     { 1,        "SMS-SUBMIT REPORT" },
257     { 2,        "SMS-STATUS REPORT" },
258     { 6,        "SMS-COMMAND" },
259     { 3,        "Reserved" },
260     { 7,        "Reserved" },
261     { 0, NULL },
262 };
263
264 static const value_string msg_type_strings_sc_to_ms[] = {
265     { 0,        "SMS-DELIVER" },
266     { 1,        "SMS-SUBMIT REPORT" },
267     { 2,        "SMS-STATUS REPORT" },
268     { 3,        "Reserved" },
269     { 0, NULL },
270 };
271
272 static const value_string msg_type_strings_ms_to_sc[] = {
273     { 0,        "SMS-DELIVER REPORT" },
274     { 1,        "SMS-SUBMIT" },
275     { 2,        "SMS-COMMAND" },
276     { 3,        "Reserved" },
277     { 0, NULL },
278 };
279
280 static const value_string vp_type_strings[] = {
281     { 0,        "TP VP field not present"},
282     { 1,        "TP VP field present - relative format"},
283     { 2,        "TP-VP field present - enhanced format"},
284     { 3,        "TP VP field present - absolute format"},
285     { 0, NULL },
286 };
287
288 static const true_false_string mms_bool_strings = {
289         "No more messages are waiting for the MS in this SC",
290         "More messages are waiting for the MS in this SC"
291 };
292
293 static const true_false_string sri_bool_strings = {
294         "A status report shall be returned to the SME",
295         "A status report shall not be returned to the SME"
296 };
297
298 static const true_false_string srr_bool_strings = {
299         "A status report is requested",
300         "A status report is not requested"
301 };
302
303 static const true_false_string udhi_bool_strings = {
304         "The beginning of the TP UD field contains a Header in addition to the short message",
305         "The TP UD field contains only the short message"
306 };
307
308 static const true_false_string rp_bool_strings = {
309         "TP Reply Path parameter is set in this SMS SUBMIT/DELIVER",
310         "TP Reply Path parameter is not set in this SMS SUBMIT/DELIVER"
311 };
312
313 static const true_false_string rd_bool_strings = {
314         "Instruct SC to reject duplicates",
315         "Instruct SC to accept duplicates"
316 };
317
318 static const true_false_string srq_bool_strings = {
319         "The SMS STATUS REPORT is the result of an SMS COMMAND e.g. an Enquiry.",
320         "SMS STATUS REPORT is the result of a SMS SUBMIT."
321 };
322
323 #define NUM_UDH_IEIS    256
324 static gint ett_udh_ieis[NUM_UDH_IEIS];
325
326 #define MAX_ADDR_SIZE 20
327 static void
328 dis_field_addr(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, const gchar *title)
329 {
330     static gchar        digit_table[] = {"0123456789*#abc\0"};
331     proto_item          *item;
332     proto_tree          *subtree = NULL;
333     const gchar         *str = NULL;
334     guint8              oct;
335     guint32             offset;
336     guint32             numdigocts;
337     guint32             length;
338     guint32             i, j;
339     char                addrbuf[MAX_ADDR_SIZE+1];
340
341     offset = *offset_p;
342
343     oct = tvb_get_guint8(tvb, offset);
344     numdigocts = (oct + 1) / 2;
345
346     length = tvb_length_remaining(tvb, offset);
347
348     if (length <= numdigocts)
349     {
350         proto_tree_add_text(tree,
351             tvb, offset, length,
352             "%s: Short Data (?)",
353             title);
354
355         *offset_p += length;
356         return;
357     }
358
359     item = proto_tree_add_text(tree, tvb,
360             offset, numdigocts + 2, "%s",
361             title);
362
363     subtree = proto_item_add_subtree(item, ett_addr);
364
365     proto_tree_add_text(subtree,
366         tvb, offset, 1,
367         "Length: %d address digits",
368         oct);
369
370     offset++;
371     oct = tvb_get_guint8(tvb, offset);
372
373     other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
374     proto_tree_add_text(subtree, tvb,
375         offset, 1,
376         "%s :  %s",
377         bigbuf,
378         (oct & 0x80) ? "No extension" : "Extended");
379
380     switch ((oct & 0x70) >> 4)
381     {
382     case 0x00: str = "Unknown"; break;
383     case 0x01: str = "International"; break;
384     case 0x02: str = "National"; break;
385     case 0x03: str = "Network specific"; break;
386     case 0x04: str = "Subscriber"; break;
387     case 0x05: str = "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)"; break;
388     case 0x06: str = "Abbreviated number"; break;
389     case 0x07: str = "Reserved for extension"; break;
390     default: str = "Unknown, reserved (?)"; break;
391     }
392
393     other_decode_bitfield_value(bigbuf, oct, 0x70, 8);
394     proto_tree_add_text(subtree,
395         tvb, offset, 1,
396         "%s :  Type of number: (%d) %s",
397         bigbuf,
398         (oct & 0x70) >> 4,
399         str);
400
401     switch (oct & 0x0f)
402     {
403     case 0x00: str = "Unknown"; break;
404     case 0x01: str = "ISDN/telephone (E.164/E.163)"; break;
405     case 0x03: str = "Data numbering plan (X.121)"; break;
406     case 0x04: str = "Telex numbering plan"; break;
407     case 0x05: str = "Service Centre Specific plan"; break;
408     case 0x06: str = "Service Centre Specific plan"; break;
409     case 0x08: str = "National numbering plan"; break;
410     case 0x09: str = "Private numbering plan"; break;
411     case 0x0a: str = "ERMES numbering plan (ETSI DE/PS 3 01-3)"; break;
412     case 0x0f: str = "Reserved for extension"; break;
413     default: str = "Unknown, reserved (?)"; break;
414     }
415
416     other_decode_bitfield_value(bigbuf, oct, 0x0f, 8);
417     proto_tree_add_text(subtree,
418         tvb, offset, 1,
419         "%s :  Numbering plan: (%d) %s",
420         bigbuf,
421         oct & 0x0f,
422         str);
423
424     offset++;
425
426     j = 0;
427     switch ((oct & 0x70) >> 4)
428     {
429     case 0x05: /* "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)" */
430         i = gsm_sms_char_7bit_unpack(0, numdigocts, MAX_ADDR_SIZE, tvb_get_ptr(tvb, offset, numdigocts), addrbuf);
431         addrbuf[i] = '\0';
432         gsm_sms_char_ascii_decode(bigbuf, addrbuf, i);
433         break;
434     default:
435         for (i = 0; i < numdigocts; i++)
436         {
437             oct = tvb_get_guint8(tvb, offset + i);
438
439             bigbuf[j++] = digit_table[oct & 0x0f];
440             bigbuf[j++] = digit_table[(oct & 0xf0) >> 4];
441         }
442         bigbuf[j++] = '\0';
443         break;
444     }
445
446     if (g_ascii_strncasecmp(title, "TP-O", 4) == 0) {
447         proto_tree_add_string(subtree, hf_gsm_sms_tp_oa, tvb,
448                 offset, numdigocts, bigbuf);
449     } else if (g_ascii_strncasecmp(title, "TP-D", 4) == 0) {
450         proto_tree_add_string(subtree, hf_gsm_sms_tp_da, tvb,
451                 offset, numdigocts, bigbuf);
452     } else if (g_ascii_strncasecmp(title, "TP-R", 4) == 0) {
453         proto_tree_add_string(subtree, hf_gsm_sms_tp_ra, tvb,
454                 offset, numdigocts, bigbuf);
455     } else {
456         proto_tree_add_text(subtree,
457         tvb, offset, numdigocts,
458         "Digits: %s",
459         bigbuf);
460     }
461
462     proto_item_append_text(item, " - (%s)", bigbuf);
463
464     *offset_p = offset + numdigocts;
465 }
466
467 /* 9.2.3.7 */
468 /* use dis_field_addr() */
469
470 /* 9.2.3.8 */
471 /* use dis_field_addr() */
472
473 /* 9.2.3.9 */
474 static void
475 dis_field_pid(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
476 {
477     proto_item  *item;
478     proto_tree  *subtree = NULL;
479     guint8      form;
480     guint8      telematic;
481     const gchar *str = NULL;
482
483
484     item =
485         proto_tree_add_item(tree, hf_gsm_sms_tp_pid, tvb,
486             offset, 1, FALSE);
487
488     subtree = proto_item_add_subtree(item, ett_pid);
489
490     form = (oct & 0xc0) >> 6;
491
492     switch (form)
493     {
494     case 0:
495         other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
496         proto_tree_add_text(subtree, tvb,
497             offset, 1,
498             "%s :  defines formatting for subsequent bits",
499             bigbuf);
500
501         other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
502         proto_tree_add_text(subtree, tvb,
503             offset, 1,
504             "%s :  %s",
505             bigbuf,
506             (oct & 0x20) ?
507             "telematic interworking" :
508             "no telematic interworking, but SME-to-SME protocol");
509
510         if (oct & 0x20)
511         {
512             telematic = oct & 0x1f;
513
514             switch (telematic)
515             {
516             case 0x00: str = "implicit - device type is specific to this SC, or can be concluded on the basis of the address"; break;
517             case 0x01: str = "telex (or teletex reduced to telex format)"; break;
518             case 0x02: str = "group 3 telefax"; break;
519             case 0x03: str = "group 4 telefax"; break;
520             case 0x04: str = "voice telephone (i.e. conversion to speech)"; break;
521             case 0x05: str = "ERMES (European Radio Messaging System)"; break;
522             case 0x06: str = "National Paging system (known to the SC)"; break;
523             case 0x07: str = "Videotex (T.100 [20] /T.101 [21])"; break;
524             case 0x08: str = "teletex, carrier unspecified"; break;
525             case 0x09: str = "teletex, in PSPDN"; break;
526             case 0x0a: str = "teletex, in CSPDN"; break;
527             case 0x0b: str = "teletex, in analog PSTN"; break;
528             case 0x0c: str = "teletex, in digital ISDN"; break;
529             case 0x0d: str = "UCI (Universal Computer Interface, ETSI DE/PS 3 01-3)"; break;
530             case 0x10: str = "a message handling facility (known to the SC)"; break;
531             case 0x11: str = "any public X.400-based message handling system"; break;
532             case 0x12: str = "Internet Electronic Mail"; break;
533             case 0x1f: str = "A GSM/UMTS mobile station"; break;
534             default:
535                 if ((telematic >= 0x18) &&
536                     (telematic <= 0x1e))
537                 {
538                     str = "values specific to each SC";
539                 }
540                 else
541                 {
542                     str = "reserved";
543                 }
544                 break;
545             }
546
547             other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
548             proto_tree_add_text(subtree, tvb,
549                 offset, 1,
550                 "%s :  device type: (%d) %s",
551                 bigbuf,
552                 telematic,
553                 str);
554         }
555         else
556         {
557             other_decode_bitfield_value(bigbuf, oct, 0x1f, 8);
558             proto_tree_add_text(subtree, tvb,
559                 offset, 1,
560                 "%s :  the SM-AL protocol being used between the SME and the MS (%d)",
561                 bigbuf,
562                 oct & 0x1f);
563         }
564         break;
565
566     case 1:
567         other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
568         proto_tree_add_text(subtree, tvb,
569             offset, 1,
570             "%s :  defines formatting for subsequent bits",
571             bigbuf);
572
573         switch (oct & 0x3f)
574         {
575         case 0x00: str = "Short Message Type 0"; break;
576         case 0x01: str = "Replace Short Message Type 1"; break;
577         case 0x02: str = "Replace Short Message Type 2"; break;
578         case 0x03: str = "Replace Short Message Type 3"; break;
579         case 0x04: str = "Replace Short Message Type 4"; break;
580         case 0x05: str = "Replace Short Message Type 5"; break;
581         case 0x06: str = "Replace Short Message Type 6"; break;
582         case 0x07: str = "Replace Short Message Type 7"; break;
583         case 0x1e: str = "Enhanced Message Service (Obsolete)"; break;
584         case 0x1f: str = "Return Call Message"; break;
585         case 0x3c: str = "ANSI-136 R-DATA"; break;
586         case 0x3d: str = "ME Data download"; break;
587         case 0x3e: str = "ME De-personalization Short Message"; break;
588         case 0x3f: str = "(U)SIM Data download"; break;
589         default:
590             str = "Reserved"; break;
591         }
592
593         other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
594         proto_tree_add_text(subtree, tvb,
595             offset, 1,
596             "%s :  (%d) %s",
597             bigbuf,
598             oct & 0x3f,
599             str);
600         break;
601
602     case 2:
603         other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
604         proto_tree_add_text(subtree, tvb,
605             offset, 1,
606             "%s :  Reserved",
607             bigbuf);
608
609         other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
610         proto_tree_add_text(subtree, tvb,
611             offset, 1,
612             "%s :  undefined",
613             bigbuf);
614         break;
615
616     case 3:
617         other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
618         proto_tree_add_text(subtree, tvb,
619             offset, 1,
620             "%s :  bits 0-5 for SC specific use",
621             bigbuf);
622
623         other_decode_bitfield_value(bigbuf, oct, 0x3f, 8);
624         proto_tree_add_text(subtree, tvb,
625             offset, 1,
626             "%s :  SC specific",
627             bigbuf);
628         break;
629     }
630 }
631
632 /* 9.2.3.10 */
633 static void
634 dis_field_dcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct,
635     gboolean *seven_bit, gboolean *eight_bit, gboolean *ucs2, gboolean *compressed)
636 {
637     proto_item  *item;
638     proto_tree  *subtree = NULL;
639     guint8      form;
640     const gchar *str = NULL;
641     gboolean    default_5_bits;
642     gboolean    default_3_bits;
643     gboolean    default_data;
644
645
646     *seven_bit = FALSE;
647     *eight_bit = FALSE;
648     *ucs2 = FALSE;
649     *compressed = FALSE;
650
651     item =
652         proto_tree_add_item(tree, hf_gsm_sms_tp_dcs, tvb,
653             offset, 1, FALSE);
654
655     subtree = proto_item_add_subtree(item, ett_dcs);
656         if(oct&0x80){
657                 proto_tree_add_item(subtree, hf_gsm_sms_coding_group_bits4, tvb, offset, 1, FALSE);
658         }else{
659                 proto_tree_add_item(subtree, hf_gsm_sms_coding_group_bits2, tvb, offset, 1, FALSE);
660         }
661
662     if (oct == 0x00)
663     {
664         proto_tree_add_text(subtree, tvb,
665             offset, 1,
666             "Special case, GSM 7 bit default alphabet");
667
668         *seven_bit = TRUE;
669         return;
670     }
671
672     default_5_bits = FALSE;
673     default_3_bits = FALSE;
674     default_data = FALSE;
675     form = (oct & 0xc0) >> 6;
676
677     switch (form)
678     {
679     case 0:
680         other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
681         proto_tree_add_text(subtree, tvb,
682             offset, 1,
683             "%s :  General Data Coding indication",
684             bigbuf);
685
686         default_5_bits = TRUE;
687         break;
688
689     case 1:
690         other_decode_bitfield_value(bigbuf, oct, 0xc0, 8);
691         proto_tree_add_text(subtree, tvb,
692             offset, 1,
693             "%s :  Message Marked for Automatic Deletion Group",
694             bigbuf);
695
696         default_5_bits = TRUE;
697         break;
698
699     case 2:
700         /* use top four bits */
701         other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
702         proto_tree_add_text(subtree, tvb,
703             offset, 1,
704             "%s :  Reserved coding groups",
705             bigbuf);
706         return;
707
708     case 3:
709         switch ((oct & 0x30) >> 4)
710         {
711         case 0x00: str = "Message Waiting Indication Group: Discard Message (GSM 7 bit default alphabet)";
712             default_3_bits = TRUE;
713             *seven_bit = TRUE;
714             break;
715         case 0x01: str = "Message Waiting Indication Group: Store Message (GSM 7 bit default alphabet)";
716             default_3_bits = TRUE;
717             *seven_bit = TRUE;
718             break;
719         case 0x02: str = "Message Waiting Indication Group: Store Message (uncompressed UCS2 alphabet)";
720             default_3_bits = TRUE;
721             break;
722         case 0x03: str = "Data coding/message class";
723             default_data = TRUE;
724             break;
725         }
726
727         /* use top four bits */
728         other_decode_bitfield_value(bigbuf, oct, 0xf0, 8);
729         proto_tree_add_text(subtree, tvb,
730             offset, 1,
731             "%s :  %s",
732             bigbuf,
733             str);
734         break;
735     }
736
737     if (default_5_bits)
738     {
739         other_decode_bitfield_value(bigbuf, oct, 0x20, 8);
740         proto_tree_add_text(subtree, tvb,
741             offset, 1,
742             "%s :  Text is %scompressed",
743             bigbuf,
744             (oct & 0x20) ?  "" : "not ");
745
746         *compressed = (oct & 0x20) >> 5;
747
748         other_decode_bitfield_value(bigbuf, oct, 0x10, 8);
749         proto_tree_add_text(subtree, tvb,
750             offset, 1,
751             "%s :  %s",
752             bigbuf,
753             (oct & 0x10) ?  "Message class is defined below" :
754                 "Reserved, no message class");
755
756         switch ((oct & 0x0c) >> 2)
757         {
758         case 0x00: str = "GSM 7 bit default alphabet";
759             *seven_bit = TRUE;
760             break;
761         case 0x01: str = "8 bit data";
762                 *eight_bit = TRUE;
763                 break;
764         case 0x02: str = "UCS2 (16 bit)";
765             *ucs2 = TRUE;
766             break;
767         case 0x03: str = "Reserved"; break;
768         }
769
770         other_decode_bitfield_value(bigbuf, oct, 0x0c, 8);
771         proto_tree_add_text(subtree, tvb,
772             offset, 1,
773             "%s :  Character set: %s",
774             bigbuf,
775             str);
776
777         switch (oct & 0x03)
778         {
779         case 0x00: str = "Class 0"; break;
780         case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
781         case 0x02: str = "Class 2 (U)SIM specific message"; break;
782         case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
783         }
784
785         other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
786         proto_tree_add_text(subtree, tvb,
787             offset, 1,
788             "%s :  Message Class: %s%s",
789             bigbuf,
790             str,
791             (oct & 0x10) ?  "" : " (reserved)");
792     }
793     else if (default_3_bits)
794     {
795         other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
796         proto_tree_add_text(subtree, tvb,
797             offset, 1,
798             "%s :  Indication Sense: %s",
799             bigbuf,
800             (oct & 0x08) ?  "Set Indication Active" : "Set Indication Inactive");
801
802         other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
803         proto_tree_add_text(subtree, tvb,
804             offset, 1,
805             "%s :  Reserved",
806             bigbuf);
807
808         switch (oct & 0x03)
809         {
810         case 0x00: str = "Voicemail Message Waiting"; break;
811         case 0x01: str = "Fax Message Waiting"; break;
812         case 0x02: str = "Electronic Mail Message Waiting"; break;
813         case 0x03: str = "Other Message Waiting"; break;
814         }
815
816         other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
817         proto_tree_add_text(subtree, tvb,
818             offset, 1,
819             "%s :  %s",
820             bigbuf,
821             str);
822     }
823     else if (default_data)
824     {
825         other_decode_bitfield_value(bigbuf, oct, 0x08, 8);
826         proto_tree_add_text(subtree, tvb,
827             offset, 1,
828             "%s :  Reserved",
829             bigbuf);
830
831         *seven_bit = !(*eight_bit = (oct & 0x04) ? TRUE : FALSE);
832
833         other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
834         proto_tree_add_text(subtree, tvb,
835             offset, 1,
836             "%s :  Message coding: %s",
837             bigbuf,
838             (*eight_bit) ? "8 bit data" : "GSM 7 bit default alphabet");
839
840         switch (oct & 0x03)
841         {
842         case 0x00: str = "Class 0"; break;
843         case 0x01: str = "Class 1 Default meaning: ME-specific"; break;
844         case 0x02: str = "Class 2 (U)SIM specific message"; break;
845         case 0x03: str = "Class 3 Default meaning: TE-specific"; break;
846         }
847
848         other_decode_bitfield_value(bigbuf, oct, 0x03, 8);
849         proto_tree_add_text(subtree, tvb,
850             offset, 1,
851             "%s :  Message Class: %s",
852             bigbuf,
853             str);
854     }
855 }
856
857 static void
858 dis_field_scts_aux(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
859 {
860     guint8      oct, oct2, oct3;
861     char sign;
862
863
864     oct = tvb_get_guint8(tvb, offset);
865     oct2 = tvb_get_guint8(tvb, offset+1);
866     oct3 = tvb_get_guint8(tvb, offset+2);
867
868     proto_tree_add_text(tree,
869         tvb, offset, 3,
870         "Year %d%d, Month %d%d, Day %d%d",
871         oct & 0x0f,
872         (oct & 0xf0) >> 4,
873         oct2 & 0x0f,
874         (oct2 & 0xf0) >> 4,
875         oct3 & 0x0f,
876         (oct3 & 0xf0) >> 4);
877
878     offset += 3;
879
880     oct = tvb_get_guint8(tvb, offset);
881     oct2 = tvb_get_guint8(tvb, offset+1);
882     oct3 = tvb_get_guint8(tvb, offset+2);
883
884     proto_tree_add_text(tree,
885         tvb, offset, 3,
886         "Hour %d%d, Minutes %d%d, Seconds %d%d",
887         oct & 0x0f,
888         (oct & 0xf0) >> 4,
889         oct2 & 0x0f,
890         (oct2 & 0xf0) >> 4,
891         oct3 & 0x0f,
892         (oct3 & 0xf0) >> 4);
893
894     offset += 3;
895
896     oct = tvb_get_guint8(tvb, offset);
897
898     sign = (oct & 0x08)?'-':'+';
899     oct = (oct >> 4) + (oct & 0x07) * 10;
900
901     proto_tree_add_text(tree,
902         tvb, offset, 1,
903         "Timezone: GMT %c %d hours %d minutes",
904         sign, oct / 4, oct % 4 * 15);
905 }
906
907 /* 9.2.3.11 */
908 static void
909 dis_field_scts(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
910 {
911     proto_item  *item;
912     proto_tree  *subtree = NULL;
913     guint32     offset;
914     guint32     length;
915
916
917     offset = *offset_p;
918
919     length = tvb_length_remaining(tvb, offset);
920
921     if (length < 7)
922     {
923         proto_tree_add_text(tree,
924             tvb, offset, length,
925             "TP-Service-Centre-Time-Stamp: Short Data (?)");
926
927         *offset_p += length;
928         return;
929     }
930
931     item =
932         proto_tree_add_text(tree, tvb,
933             offset, 7,
934             "TP-Service-Centre-Time-Stamp");
935
936     subtree = proto_item_add_subtree(item, ett_scts);
937
938     dis_field_scts_aux(tvb, subtree, *offset_p);
939
940     *offset_p += 7;
941 }
942
943 /* 9.2.3.12 */
944 static void
945 dis_field_vp(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p, guint8 vp_form)
946 {
947     proto_item  *item;
948     proto_tree  *subtree = NULL;
949     guint32     offset;
950     guint32     length;
951     guint8      oct, oct2, oct3;
952     guint8      loc_form;
953     guint32     mins, hours;
954     gboolean    done;
955
956
957     if (vp_form == 0x00) return;
958
959     offset = *offset_p;
960     subtree = tree;
961
962     done = FALSE;
963     do
964     {
965         switch (vp_form)
966         {
967         case 1:
968             length = tvb_length_remaining(tvb, offset);
969
970             if (length < 7)
971             {
972                 proto_tree_add_text(tree,
973                     tvb, offset, length,
974                     "TP-Validity-Period: Short Data (?)");
975
976                 *offset_p += length;
977                 return;
978             }
979
980             item =
981                 proto_tree_add_text(tree, tvb,
982                     offset, 7,
983                     "TP-Validity-Period");
984
985             subtree = proto_item_add_subtree(item, ett_vp);
986
987             oct = tvb_get_guint8(tvb, offset);
988
989             other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
990             proto_tree_add_text(subtree, tvb,
991                 offset, 1,
992                 "%s :  %s",
993                 bigbuf,
994                 (oct & 0x80) ? "Extended" : "No extension");
995
996             if (oct & 0x80)
997             {
998                 proto_tree_add_text(subtree,
999                     tvb, offset + 1, 6,
1000                     "Extension not implemented, ignored");
1001
1002                 *offset_p += 7;
1003                 return;
1004             }
1005
1006             other_decode_bitfield_value(bigbuf, oct, 0x40, 8);
1007             proto_tree_add_text(subtree, tvb,
1008                 offset, 1,
1009                 "%s :  %s",
1010                 bigbuf,
1011                 (oct & 0x40) ? "Single shot SM" : "Not single shot SM");
1012
1013             other_decode_bitfield_value(bigbuf, oct, 0x38, 8);
1014             proto_tree_add_text(subtree, tvb,
1015                 offset, 1,
1016                 "%s :  Reserved",
1017                 bigbuf);
1018
1019             loc_form = oct & 0x7;
1020
1021             switch (loc_form)
1022             {
1023             case 0x00:
1024                 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1025                 proto_tree_add_text(subtree, tvb,
1026                     offset, 1,
1027                     "%s :  No Validity Period specified",
1028                     bigbuf);
1029
1030                 done = TRUE;
1031                 break;
1032
1033             case 0x01:
1034                 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1035                 proto_tree_add_text(subtree, tvb,
1036                     offset, 1,
1037                     "%s :  Validity Period Format: relative",
1038                     bigbuf);
1039
1040                 offset++;
1041                 /* go around again */
1042                 vp_form = 2;
1043                 break;
1044
1045             case 0x02:
1046                 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1047                 proto_tree_add_text(subtree, tvb,
1048                     offset, 1,
1049                     "%s :  Validity Period Format: relative",
1050                     bigbuf);
1051
1052                 offset++;
1053                 oct = tvb_get_guint8(tvb, offset);
1054
1055                 proto_tree_add_text(subtree, tvb,
1056                     offset, 1,
1057                     "%d seconds",
1058                     oct);
1059
1060                 done = TRUE;
1061                 break;
1062
1063             case 0x03:
1064                 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1065                 proto_tree_add_text(subtree, tvb,
1066                     offset, 1,
1067                     "%s :  Validity Period Format: relative",
1068                     bigbuf);
1069
1070                 offset++;
1071                 oct = tvb_get_guint8(tvb, offset);
1072                 oct2 = tvb_get_guint8(tvb, offset+1);
1073                 oct3 = tvb_get_guint8(tvb, offset+2);
1074
1075                 proto_tree_add_text(subtree,
1076                     tvb, offset, 3,
1077                     "Hour %d%d, Minutes %d%d, Seconds %d%d",
1078                     oct & 0x0f,
1079                     (oct & 0xf0) >> 4,
1080                     oct2 & 0x0f,
1081                     (oct2 & 0xf0) >> 4,
1082                     oct3 & 0x0f,
1083                     (oct3 & 0xf0) >> 4);
1084
1085                 done = TRUE;
1086                 break;
1087
1088             default:
1089                 other_decode_bitfield_value(bigbuf, oct, 0x07, 8);
1090                 proto_tree_add_text(subtree, tvb,
1091                     offset, 1,
1092                     "%s :  Validity Period Format: Reserved",
1093                     bigbuf);
1094
1095                 done = TRUE;
1096                 break;
1097             }
1098             break;
1099
1100         case 2:
1101             oct = tvb_get_guint8(tvb, offset);
1102
1103             if (oct <= 143)
1104             {
1105                 mins = (oct + 1) * 5;
1106                 if (mins >= 60)
1107                 {
1108                     hours = mins / 60;
1109                     mins %= 60;
1110
1111                     proto_tree_add_text(subtree, tvb,
1112                         offset, 1,
1113                         "TP-Validity-Period: %d hours %d minutes",
1114                         hours,
1115                         mins);
1116                 }
1117                 else
1118                 {
1119                     proto_tree_add_text(subtree, tvb,
1120                         offset, 1,
1121                         "TP-Validity-Period: %d minutes",
1122                         mins);
1123                 }
1124             }
1125             else if ((oct >= 144) &&
1126                 (oct <= 167))
1127             {
1128                 mins = (oct - 143) * 30;
1129                 hours = 12 + (mins / 60);
1130                 mins %= 60;
1131
1132                 proto_tree_add_text(subtree, tvb,
1133                     offset, 1,
1134                     "TP-Validity-Period: %d hours %d minutes",
1135                     hours,
1136                     mins);
1137             }
1138             else if ((oct >= 168) &&
1139                 (oct <= 196))
1140             {
1141                 proto_tree_add_text(subtree, tvb,
1142                     offset, 1,
1143                     "TP-Validity-Period: %d day(s)",
1144                     oct - 166);
1145             }
1146             else if (oct >= 197)
1147             {
1148                 proto_tree_add_text(subtree, tvb,
1149                     offset, 1,
1150                     "TP-Validity-Period: %d week(s)",
1151                     oct - 192);
1152             }
1153
1154             done = TRUE;
1155             break;
1156
1157         case 3:
1158             length = tvb_length_remaining(tvb, offset);
1159
1160             if (length < 7)
1161             {
1162                 proto_tree_add_text(tree,
1163                     tvb, offset, length,
1164                     "TP-Validity-Period: Short Data (?)");
1165
1166                 *offset_p += length;
1167                 return;
1168             }
1169
1170             item =
1171                 proto_tree_add_text(tree, tvb,
1172                     offset, 7,
1173                     "TP-Validity-Period: absolute");
1174
1175             subtree = proto_item_add_subtree(item, ett_vp);
1176
1177             dis_field_scts_aux(tvb, subtree, *offset_p);
1178
1179             done = TRUE;
1180             break;
1181         }
1182     }
1183     while (!done);
1184
1185     if (vp_form == 2)
1186     {
1187         (*offset_p)++;
1188     }
1189     else
1190     {
1191         *offset_p += 7;
1192     }
1193 }
1194
1195 /* 9.2.3.13 */
1196 static void
1197 dis_field_dt(tvbuff_t *tvb, proto_tree *tree, guint32 *offset_p)
1198 {
1199     proto_item  *item;
1200     proto_tree  *subtree = NULL;
1201     guint32     offset;
1202     guint32     length;
1203
1204
1205     offset = *offset_p;
1206
1207     length = tvb_length_remaining(tvb, offset);
1208
1209     if (length < 7)
1210     {
1211         proto_tree_add_text(tree,
1212             tvb, offset, length,
1213             "TP-Discharge-Time: Short Data (?)");
1214
1215         *offset_p += length;
1216         return;
1217     }
1218
1219     item =
1220         proto_tree_add_text(tree, tvb,
1221             offset, 7,
1222             "TP-Discharge-Time");
1223
1224     subtree = proto_item_add_subtree(item, ett_dt);
1225
1226     dis_field_scts_aux(tvb, subtree, *offset_p);
1227
1228     *offset_p += 7;
1229 }
1230
1231 /* 9.2.3.14 */
1232 /* use dis_field_addr() */
1233
1234 /* 9.2.3.15 */
1235 static void
1236 dis_field_st(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1237 {
1238     static const gchar  *sc_complete = "Short message transaction completed";
1239     static const gchar  *sc_temporary = "Temporary error, SC still trying to transfer SM";
1240     static const gchar  *sc_perm = "Permanent error, SC is not making any more transfer attempts";
1241     static const gchar  *sc_tempfin = "Temporary error, SC is not making any more transfer attempts";
1242     proto_item          *item;
1243     proto_tree          *subtree = NULL;
1244     guint8              value;
1245     const gchar         *str = NULL;
1246     const gchar *str2 = NULL;
1247
1248
1249     item =
1250         proto_tree_add_text(tree, tvb,
1251             offset, 1,
1252             "TP-Status");
1253
1254     subtree = proto_item_add_subtree(item, ett_st);
1255
1256     other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
1257     proto_tree_add_text(subtree, tvb,
1258         offset, 1,
1259         "%s :  Definition of bits 0-6: %s",
1260         bigbuf,
1261         (oct & 0x80) ?  "Reserved" : "as follows");
1262
1263     value = oct & 0x7f;
1264
1265     switch (value)
1266     {
1267     case 0x00: str2 = sc_complete; str = "Short message received by the SME"; break;
1268     case 0x01: str2 = sc_complete; str = "Short message forwarded by the SC to the SME but the SC is unable to confirm delivery"; break;
1269     case 0x02: str2 = sc_complete; str = "Short message replaced by the SC Reserved values"; break;
1270
1271     case 0x20: str2 = sc_temporary; str = "Congestion"; break;
1272     case 0x21: str2 = sc_temporary; str = "SME busy"; break;
1273     case 0x22: str2 = sc_temporary; str = "No response from SME"; break;
1274     case 0x23: str2 = sc_temporary; str = "Service rejected"; break;
1275     case 0x24: str2 = sc_temporary; str = "Quality of service not available"; break;
1276     case 0x25: str2 = sc_temporary; str = "Error in SME"; break;
1277
1278     case 0x40: str2 = sc_perm; str = "Remote procedure error"; break;
1279     case 0x41: str2 = sc_perm; str = "Incompatible destination"; break;
1280     case 0x42: str2 = sc_perm; str = "Connection rejected by SME"; break;
1281     case 0x43: str2 = sc_perm; str = "Not obtainable"; break;
1282     case 0x44: str2 = sc_perm; str = "Quality of service not available"; break;
1283     case 0x45: str2 = sc_perm; str = "No interworking available"; break;
1284     case 0x46: str2 = sc_perm; str = "SM Validity Period Expired"; break;
1285     case 0x47: str2 = sc_perm; str = "SM Deleted by originating SME"; break;
1286     case 0x48: str2 = sc_perm; str = "SM Deleted by SC Administration"; break;
1287     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;
1288
1289     case 0x60: str2 = sc_tempfin; str = "Congestion"; break;
1290     case 0x61: str2 = sc_tempfin; str = "SME busy"; break;
1291     case 0x62: str2 = sc_tempfin; str = "No response from SME"; break;
1292     case 0x63: str2 = sc_tempfin; str = "Service rejected"; break;
1293     case 0x64: str2 = sc_tempfin; str = "Quality of service not available"; break;
1294     case 0x65: str2 = sc_tempfin; str = "Error in SME"; break;
1295
1296     default:
1297         if ((value >= 0x03) &&
1298             (value <= 0x0f))
1299         {
1300             str2 = sc_complete;
1301             str = "Reserved";
1302         }
1303         else if ((value >= 0x10) &&
1304             (value <= 0x1f))
1305         {
1306             str2 = sc_complete;
1307             str = "Values specific to each SC";
1308         }
1309         else if ((value >= 0x26) &&
1310             (value <= 0x2f))
1311         {
1312             str2 = sc_temporary;
1313             str = "Reserved";
1314         }
1315         else if ((value >= 0x30) &&
1316             (value <= 0x3f))
1317         {
1318             str2 = sc_temporary;
1319             str = "Values specific to each SC";
1320         }
1321         else if ((value >= 0x4a) &&
1322             (value <= 0x4f))
1323         {
1324             str2 = sc_perm;
1325             str = "Reserved";
1326         }
1327         else if ((value >= 0x50) &&
1328             (value <= 0x5f))
1329         {
1330             str2 = sc_perm;
1331             str = "Values specific to each SC";
1332         }
1333         else if ((value >= 0x66) &&
1334             (value <= 0x6f))
1335         {
1336             str2 = sc_tempfin;
1337             str = "Reserved";
1338         }
1339         else if ((value >= 0x70) &&
1340             (value <= 0x7f))
1341         {
1342             str2 = sc_tempfin;
1343             str = "Values specific to each SC";
1344         }
1345         break;
1346     }
1347
1348     other_decode_bitfield_value(bigbuf, oct, 0x7f, 8);
1349     proto_tree_add_text(subtree, tvb,
1350         offset, 1,
1351         "%s :  (%d) %s, %s",
1352         bigbuf,
1353         value,
1354         str2,
1355         str);
1356 }
1357
1358 /* 9.2.3.16 */
1359 #define DIS_FIELD_UDL(m_tree, m_offset) \
1360 { \
1361     proto_tree_add_text(m_tree, tvb, \
1362         m_offset, 1, \
1363         "TP-User-Data-Length: (%d) %s", \
1364         oct, \
1365         oct ? "depends on Data-Coding-Scheme" : "no User-Data");\
1366 }
1367
1368 /* 9.2.3.17 */
1369 #define DIS_FIELD_RP(m_tree, m_bitmask, m_offset) \
1370 { \
1371     other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1372     proto_tree_add_text(m_tree, tvb, \
1373         m_offset, 1, \
1374         "%s :  TP-Reply-Path: parameter is %sset in this SMS-SUBMIT/DELIVER", \
1375         bigbuf, \
1376         (oct & m_bitmask) ? "" : "not "); \
1377 }
1378
1379 /* 9.2.3.18 */
1380 #define DIS_FIELD_MN(m_tree, m_offset) \
1381 { \
1382     proto_tree_add_text(m_tree, tvb, \
1383         m_offset, 1, \
1384         "TP-Message-Number: %d", \
1385         oct); \
1386 }
1387
1388 /* 9.2.3.19 */
1389 #define DIS_FIELD_CT(m_tree, m_offset) \
1390 { \
1391     switch (oct) \
1392     { \
1393     case 0: str = "Enquiry relating to previously submitted short message"; break; \
1394     case 1: str = "Cancel Status Report Request relating to previously submitted short message"; break; \
1395     case 2: str = "Delete previously submitted Short Message"; break; \
1396     case 3: str = "Enable Status Report Request relating to previously submitted short message"; break; \
1397     default: \
1398         if ((oct >= 0x04) && \
1399             (oct <= 0x1f)) \
1400         { \
1401             str = "Reserved unspecified"; \
1402         } \
1403         else if (oct >= 0xe0) \
1404         { \
1405             str = "Values specific for each SC"; \
1406         } \
1407         else \
1408         { \
1409             str = "undefined"; \
1410         } \
1411         break; \
1412     } \
1413     proto_tree_add_text(m_tree, tvb, \
1414         m_offset, 1, \
1415         "TP-Command-Type: (%d), %s", \
1416         oct, \
1417         str); \
1418 }
1419
1420 /* 9.2.3.20 */
1421 #define DIS_FIELD_CDL(m_tree, m_offset) \
1422 { \
1423     proto_tree_add_text(m_tree, tvb, \
1424         m_offset, 1, \
1425         "TP-Command-Data-Length: (%d)%s", \
1426         oct, \
1427         oct ? "" : " no Command-Data");\
1428 }
1429
1430 /* 9.2.3.21 */
1431 /* done in-line in the message functions */
1432
1433 /* 9.2.3.22 */
1434 static void
1435 dis_field_fcs(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
1436 {
1437     proto_item  *item;
1438     proto_tree  *subtree = NULL;
1439     const gchar *str = NULL;
1440
1441
1442     item =
1443         proto_tree_add_text(tree, tvb,
1444             offset, 1,
1445             "TP-Failure-Cause");
1446
1447     subtree = proto_item_add_subtree(item, ett_fcs);
1448
1449     switch (oct)
1450     {
1451     case 0x80: str = "Telematic interworking not supported"; break;
1452     case 0x81: str = "Short message Type 0 not supported"; break;
1453     case 0x82: str = "Cannot replace short message"; break;
1454     case 0x8F: str = "Unspecified TP-PID error"; break;
1455     case 0x90: str = "Data coding scheme (alphabet) not supported"; break;
1456     case 0x91: str = "Message class not supported"; break;
1457     case 0x9F: str = "Unspecified TP-DCS error"; break;
1458     case 0xA0: str = "Command cannot be actioned"; break;
1459     case 0xA1: str = "Command unsupported"; break;
1460     case 0xAF: str = "Unspecified TP-Command error"; break;
1461     case 0xB0: str = "TPDU not supported"; break;
1462     case 0xC0: str = "SC busy"; break;
1463     case 0xC1: str = "No SC subscription"; break;
1464     case 0xC2: str = "SC system failure"; break;
1465     case 0xC3: str = "Invalid SME address"; break;
1466     case 0xC4: str = "Destination SME barred"; break;
1467     case 0xC5: str = "SM Rejected-Duplicate SM"; break;
1468     case 0xC6: str = "TP-VPF not supported"; break;
1469     case 0xC7: str = "TP-VP not supported"; break;
1470     case 0xD0: str = "(U)SIM SMS storage full"; break;
1471     case 0xD1: str = "No SMS storage capability in (U)SIM"; break;
1472     case 0xD2: str = "Error in MS"; break;
1473     case 0xD3: str = "Memory Capacity Exceeded"; break;
1474     case 0xD4: str = "(U)SIM Application Toolkit Busy"; break;
1475     case 0xD5: str = "(U)SIM data download error"; break;
1476     case 0xFF: str = "Unspecified error cause"; break;
1477     default:
1478         if ((oct >= 0x80) &&
1479             (oct <= 0x8F))
1480         {
1481             str = "TP-PID errors"; break;
1482         }
1483         else if ((oct >= 0x90) &&
1484             (oct <= 0x9F))
1485         {
1486             str = "TP-DCS errors"; break;
1487         }
1488         else if ((oct >= 0xA0) &&
1489             (oct <= 0xAF))
1490         {
1491             str = "TP-Command errors"; break;
1492         }
1493         else if ((oct >= 0xE0) &&
1494             (oct <= 0xFE))
1495         {
1496             str = "Values specific to an application"; break;
1497         }
1498         else
1499         {
1500             str = "Reserved"; break;
1501         }
1502     }
1503
1504     proto_tree_add_text(subtree, tvb,
1505         offset, 1, "%s",
1506         str);
1507 }
1508
1509 /* 9.2.3.23 */
1510 #define DIS_FIELD_UDHI(m_tree, m_bitmask, m_offset, m_udhi) \
1511 { \
1512     SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, m_udhi); \
1513     other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1514     proto_tree_add_text(m_tree, tvb, \
1515         m_offset, 1, \
1516         "%s :  TP-User-Data-Header-Indicator: %s short message", \
1517         bigbuf, \
1518         m_udhi ? \
1519         "The beginning of the TP-UD field contains a Header in addition to the" : \
1520         "The TP-UD field contains only the"); \
1521 }
1522
1523 /*
1524  * FROM GNOKII
1525  * gsm-encoding.c
1526  * gsm-sms.c
1527  */
1528 #define GN_BYTE_MASK ((1 << bits) - 1)
1529
1530 int
1531 gsm_sms_char_7bit_unpack(unsigned int offset, unsigned int in_length, unsigned int out_length,
1532                      const guint8 *input, unsigned char *output)
1533 {
1534     unsigned char *out_num = output; /* Current pointer to the output buffer */
1535     const guint8 *in_num = input;    /* Current pointer to the input buffer */
1536     unsigned char rest = 0x00;
1537     int bits;
1538
1539     bits = offset ? offset : 7;
1540
1541     while ((unsigned int)(in_num - input) < in_length)
1542     {
1543         *out_num = ((*in_num & GN_BYTE_MASK) << (7 - bits)) | rest;
1544         rest = *in_num >> bits;
1545
1546         /* If we don't start from 0th bit, we shouldn't go to the
1547            next char. Under *out_num we have now 0 and under Rest -
1548            _first_ part of the char. */
1549         if ((in_num != input) || (bits == 7)) out_num++;
1550         in_num++;
1551
1552         if ((unsigned int)(out_num - output) >= out_length) break;
1553
1554         /* After reading 7 octets we have read 7 full characters but
1555            we have 7 bits as well. This is the next character */
1556         if (bits == 1)
1557         {
1558             *out_num = rest;
1559             out_num++;
1560             bits = 7;
1561             rest = 0x00;
1562         }
1563         else
1564         {
1565             bits--;
1566         }
1567     }
1568
1569     return (int)(out_num - output);
1570 }
1571
1572 #define GN_CHAR_ALPHABET_SIZE 128
1573
1574 #define GN_CHAR_ESCAPE 0x1b
1575
1576 static gunichar gsm_default_alphabet[GN_CHAR_ALPHABET_SIZE] = {
1577
1578     /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
1579     /* Fixed to use unicode */
1580     /* Characters in hex position 10, [12 to 1a] and 24 are not present on
1581        latin1 charset, so we cannot reproduce on the screen, however they are
1582        greek symbol not present even on my Nokia */
1583
1584     '@',  0xa3, '$' , 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
1585     0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
1586    0x394, '_', 0x3a6,0x393,0x39b,0x3a9,0x3a0,0x3a8,
1587    0x3a3,0x398,0x39e, 0xa0, 0xc6, 0xe6, 0xdf, 0xc9,
1588     ' ',  '!',  '\"', '#',  0xa4,  '%',  '&',  '\'',
1589     '(',  ')',  '*',  '+',  ',',  '-',  '.',  '/',
1590     '0',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
1591     '8',  '9',  ':',  ';',  '<',  '=',  '>',  '?',
1592     0xa1, 'A',  'B',  'C',  'D',  'E',  'F',  'G',
1593     'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',
1594     'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',
1595     'X',  'Y',  'Z',  0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
1596     0xbf, 'a',  'b',  'c',  'd',  'e',  'f',  'g',
1597     'h',  'i',  'j',  'k',  'l',  'm',  'n',  'o',
1598     'p',  'q',  'r',  's',  't',  'u',  'v',  'w',
1599     'x',  'y',  'z',  0xe4, 0xf6, 0xf1, 0xfc, 0xe0
1600 };
1601
1602 static gboolean
1603 char_is_escape(unsigned char value)
1604 {
1605     return (value == GN_CHAR_ESCAPE);
1606 }
1607
1608 static gunichar
1609 char_def_alphabet_ext_decode(unsigned char value)
1610 {
1611     switch (value)
1612     {
1613     case 0x0a: return 0x0c; /* form feed */
1614     case 0x14: return '^';
1615     case 0x28: return '{';
1616     case 0x29: return '}';
1617     case 0x2f: return '\\';
1618     case 0x3c: return '[';
1619     case 0x3d: return '~';
1620     case 0x3e: return ']';
1621     case 0x40: return '|';
1622     case 0x65: return 0x20ac; /* euro */
1623     default: return '?'; /* invalid character */
1624     }
1625 }
1626
1627 static gunichar
1628 char_def_alphabet_decode(unsigned char value)
1629 {
1630     if (value < GN_CHAR_ALPHABET_SIZE)
1631     {
1632         return gsm_default_alphabet[value];
1633     }
1634     else
1635     {
1636         return '?';
1637     }
1638 }
1639
1640 void
1641 gsm_sms_char_ascii_decode(unsigned char * dest, const unsigned char* src, int len)
1642 {
1643     int i, j;
1644     gunichar buf;
1645
1646
1647     for (i = 0, j = 0; j < len;  j++)
1648     {
1649         if (char_is_escape(src[j])) {
1650             buf = char_def_alphabet_ext_decode(src[++j]);
1651             i += g_unichar_to_utf8(buf,&(dest[i]));
1652         }
1653         else {
1654             buf = char_def_alphabet_decode(src[j]);
1655             i += g_unichar_to_utf8(buf,&(dest[i]));
1656         }
1657     }
1658     dest[i]=0;
1659     return;
1660 }
1661
1662 /*
1663  * END FROM GNOKII
1664  */
1665
1666 /* 9.2.3.24.1 */
1667 static void
1668 dis_iei_csm8(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1669 {
1670     guint8      oct;
1671
1672     EXACT_DATA_CHECK(length, 3);
1673     oct = tvb_get_guint8(tvb, offset);
1674         g_sm_id = oct;  
1675         proto_tree_add_uint (tree,
1676                                                         hf_gsm_sms_ud_multiple_messages_msg_id,
1677                                                         tvb, offset, 1, g_sm_id);
1678         offset++;
1679
1680         oct = tvb_get_guint8(tvb, offset);
1681         g_frags = oct;
1682         proto_tree_add_uint (tree,
1683                                                         hf_gsm_sms_ud_multiple_messages_msg_parts,
1684                                                         tvb , offset , 1, g_frags);
1685         offset++;
1686         oct = tvb_get_guint8(tvb, offset);
1687         g_frag = oct;
1688         proto_tree_add_uint (tree,
1689                                                         hf_gsm_sms_ud_multiple_messages_msg_part,
1690                                                         tvb, offset, 1, g_frag);
1691
1692 }
1693
1694 /* TODO 9.2.3.24.2 Special SMS Message Indication */
1695
1696 /* 9.2.3.24.3 */
1697 static void
1698 dis_iei_apa_8bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1699 {
1700     const gchar *str = NULL;
1701     guint8      oct;
1702
1703
1704     EXACT_DATA_CHECK(length, 2);
1705
1706     oct = tvb_get_guint8(tvb, offset);
1707         g_port_dst = oct;
1708     if (oct < 240)
1709     {
1710         str = "Reserved";
1711     }
1712     else
1713     {
1714         str = "Available for allocation by applications";
1715     }
1716
1717     proto_tree_add_text(tree,
1718         tvb, offset, 1,
1719         "Destination port: %d, %s",
1720         oct,
1721         str);
1722
1723     offset++;
1724     oct = tvb_get_guint8(tvb, offset);
1725         g_port_src = oct;
1726     if (oct < 240)
1727     {
1728         str = "Reserved";
1729     }
1730     else
1731     {
1732         str = "Available for allocation by applications";
1733     }
1734
1735     proto_tree_add_text(tree,
1736         tvb, offset, 1,
1737         "Originator port: %d, %s",
1738         oct,
1739         str);
1740 }
1741
1742 /* 9.2.3.24.4 */
1743 static void
1744 dis_iei_apa_16bit(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1745 {
1746     const gchar *str = NULL;
1747     guint32     value;
1748
1749
1750     EXACT_DATA_CHECK(length, 4);
1751
1752     value = tvb_get_ntohs(tvb, offset);
1753         g_port_dst = value;
1754     if (value < 16000)
1755     {
1756         str = "As allocated by IANA (http://www.IANA.com/)";
1757     }
1758     else if (value < 17000)
1759     {
1760         str = "Available for allocation by applications";
1761     }
1762     else
1763     {
1764         str = "Reserved";
1765     }
1766
1767     proto_tree_add_text(tree,
1768         tvb, offset, 2,
1769         "Destination port: %d, %s",
1770         value,
1771         str);
1772
1773     offset += 2;
1774     value = tvb_get_ntohs(tvb, offset);
1775         g_port_src = value;
1776     if (value < 16000)
1777     {
1778         str = "As allocated by IANA (http://www.IANA.com/)";
1779     }
1780     else if (value < 17000)
1781     {
1782         str = "Available for allocation by applications";
1783     }
1784     else
1785     {
1786         str = "Reserved";
1787     }
1788
1789     proto_tree_add_text(tree,
1790         tvb, offset, 2,
1791         "Originator port: %d, %s",
1792         value,
1793         str);
1794
1795         g_is_wsp = 1;
1796 }
1797
1798 /* 9.2.3.24.5 */
1799 static void
1800 dis_iei_scp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1801 {
1802     guint8      oct;
1803
1804     EXACT_DATA_CHECK(length, 1);
1805
1806         oct = tvb_get_guint8(tvb, offset);
1807
1808         if (oct & 0x01)
1809         {
1810                 proto_tree_add_text(tree,
1811                 tvb, offset, 1,
1812                 "Status Report for short message transaction completed");
1813         }
1814         else
1815         {
1816                 proto_tree_add_text(tree,
1817                 tvb, offset, 1,
1818                 "No Status Report for short message transaction completed");
1819         }
1820
1821         if (oct & 0x02)
1822         {
1823                 proto_tree_add_text(tree,
1824                 tvb, offset, 1,
1825                 "Status Report for permanent error when SC is not making any more transfer attempts");
1826         }
1827         else
1828         {
1829                 proto_tree_add_text(tree,
1830                 tvb, offset, 1,
1831                 "No Status Report for permanent error when SC is not making any more transfer attempts");
1832         }
1833
1834         if (oct & 0x04)
1835         {
1836                 proto_tree_add_text(tree,
1837                 tvb, offset, 1,
1838                 "Status Report for temporary error when SC is not making any more transfer attempts");
1839         }
1840         else
1841         {
1842                 proto_tree_add_text(tree,
1843                 tvb, offset, 1,
1844                 "No Status Report for temporary error when SC is not making any more transfer attempts");
1845         }
1846
1847         if (oct & 0x08)
1848         {
1849
1850                 proto_tree_add_text(tree,
1851                 tvb, offset, 1,
1852                 "Status Report for temporary error when SC is still trying to transfer SM");
1853         }
1854         else
1855         {
1856                 proto_tree_add_text(tree,
1857                 tvb, offset, 1,
1858                 "No Status Report for temporary error when SC is still trying to transfer SM");
1859         }
1860
1861         if (oct & 0x40)
1862         {
1863
1864                 proto_tree_add_text(tree,
1865                 tvb, offset, 1,
1866                 "A Status Report generated by this Short Message, due to a permanent error or last temporary error, cancels the SRR of the rest of the Short Messages in a concatenated message");
1867         }
1868         else
1869         {
1870                 proto_tree_add_text(tree,
1871                 tvb, offset, 1,
1872                 "No activation");
1873         }
1874
1875         if (oct & 0x80)
1876         {
1877
1878                 proto_tree_add_text(tree,
1879                 tvb, offset, 1,
1880                 "Include original UDH into the Status Report");
1881         }
1882         else
1883         {
1884                 proto_tree_add_text(tree,
1885                 tvb, offset, 1,
1886                 "Do not include original UDH into the Status Report");
1887         }
1888
1889 }
1890
1891 /* 9.2.3.24.6 */
1892 static void
1893 dis_iei_udh_si(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1894 {
1895     guint8      oct;
1896
1897     EXACT_DATA_CHECK(length, 1);
1898
1899         oct = tvb_get_guint8(tvb, offset);
1900
1901         switch (oct)
1902         {
1903                 case 1:
1904                         proto_tree_add_text(tree,
1905                         tvb, offset, 1,
1906                         "The following part of the UDH is created by the original sender (valid in case of Status Report)");
1907                 break;
1908                 case 2:
1909                         proto_tree_add_text(tree,
1910                         tvb, offset, 1,
1911                         "The following part of the UDH is created by the original receiver (valid in case of Status Report)");
1912                 break;
1913                 case 3:
1914                         proto_tree_add_text(tree,
1915                         tvb, offset, 1,
1916                         "The following part of the UDH is created by the SMSC (can occur in any message or report)");
1917                 break;
1918                 default:
1919                         proto_tree_add_text(tree,
1920                         tvb, offset, 1,
1921                         "The following part of the UDH is created by %d" , oct);
1922                 break;
1923         }       
1924 }
1925 /* 9.2.3.24.8 */
1926 static void
1927 dis_iei_csm16(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1928 {
1929     guint8      oct;
1930         guint16 oct_ref;
1931
1932     EXACT_DATA_CHECK(length, 4);
1933     oct_ref = tvb_get_ntohs(tvb, offset);
1934         g_sm_id = oct_ref;
1935         proto_tree_add_uint (tree,
1936                                                         hf_gsm_sms_ud_multiple_messages_msg_id,
1937                                                         tvb, offset, 2, g_sm_id);
1938         offset+=2;
1939         oct = tvb_get_guint8(tvb, offset);
1940         g_frags = oct;
1941         proto_tree_add_uint (tree,
1942                                                         hf_gsm_sms_ud_multiple_messages_msg_parts,
1943                                                         tvb , offset , 1, g_frags);
1944
1945         offset++;
1946         oct = tvb_get_guint8(tvb, offset);
1947         g_frag = oct;
1948         proto_tree_add_uint (tree,
1949                                                         hf_gsm_sms_ud_multiple_messages_msg_part,
1950                                                         tvb, offset, 1, g_frag);
1951 }
1952
1953 /* 9.2.3.24.10.1.1 */
1954 static void
1955 dis_iei_tf(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
1956 {
1957         const gchar *str = NULL;
1958     guint8      oct;
1959         proto_item      *item;
1960         proto_item      *item_colour;
1961     proto_tree  *subtree = NULL; 
1962         proto_tree      *subtree_colour = NULL;
1963         
1964
1965     EXACT_DATA_CHECK(length, 4);
1966     oct = tvb_get_guint8(tvb, offset);
1967         
1968         proto_tree_add_text(tree,
1969         tvb, offset, 1,
1970         "Start position of the text formatting: %d",
1971         oct);
1972         offset++;
1973
1974         oct = tvb_get_guint8(tvb, offset);
1975         
1976         proto_tree_add_text(tree,
1977         tvb, offset, 1,
1978         "Text formatting length: %d",
1979         oct);
1980         offset++;
1981
1982         oct = tvb_get_guint8(tvb, offset);
1983         
1984         item =
1985             proto_tree_add_text(tree,
1986                 tvb, offset, 1,
1987                 "formatting mode");
1988
1989         subtree = proto_item_add_subtree(item, ett_udh_tfm);
1990         switch(oct & 0x03)
1991         {
1992                 case 0x00:
1993                         str = "Left";
1994                 break;
1995                 case 0x01:
1996                         str = "Center";
1997                 break;
1998                 case 0x02:
1999                         str = "Right";
2000                 break;
2001                 case 0x03:
2002                         str = "Language dependent";
2003                 break;
2004         }
2005
2006         proto_tree_add_text(subtree,
2007         tvb, offset, 1,
2008         "Alignment : %d %s",
2009          oct & 0x03 , str);
2010
2011         switch((oct >> 2) & 0x03)
2012         {
2013                 case 0x00:
2014                         str = "Normal";
2015                 break;
2016                 case 0x01:
2017                         str = "Large";
2018                 break;
2019                 case 0x02:
2020                         str = "Small";
2021                 break;
2022                 case 0x03:
2023                         str = "reserved";
2024                 break;
2025         }
2026
2027         proto_tree_add_text(subtree,
2028         tvb, offset, 1,
2029         "Font Size : %d %s",
2030          (oct >> 2) & 0x03 , str);
2031         
2032         if(oct & 0x10)
2033                 str = "on";
2034         else
2035                 str = "off";
2036         proto_tree_add_text(subtree,
2037         tvb, offset, 1,
2038         "Style bold : %d %s",
2039          oct & 0x10 , str);
2040         
2041         if(oct & 0x20)
2042                 str = "on";
2043         else
2044                 str = "off";
2045         proto_tree_add_text(subtree,
2046         tvb, offset, 1,
2047         "Style Italic : %d %s",
2048          oct & 0x20 , str);
2049
2050         if(oct & 0x40)
2051                 str = "on";
2052         else
2053                 str = "off";
2054         proto_tree_add_text(subtree,
2055         tvb, offset, 1,
2056         "Style Underlined : %d %s",
2057          oct & 0x40 , str);
2058
2059         if(oct & 0x80)
2060                 str = "on";
2061         else
2062                 str = "off";
2063         proto_tree_add_text(subtree,
2064         tvb, offset, 1,
2065         "Style Strikethrough : %d %s",
2066          oct & 0x80 , str);
2067
2068         offset++;
2069         oct = tvb_get_guint8(tvb, offset);
2070         item_colour =
2071             proto_tree_add_text(tree,
2072                 tvb, offset, 1,
2073                 "Text Colour");
2074
2075         subtree_colour = proto_item_add_subtree(item_colour, ett_udh_tfc);
2076         switch(oct & 0x0f)
2077         {
2078                 case 0x00:
2079                         str = "Dark Grey";
2080                 break;
2081                 case 0x01:
2082                         str = "Dark Red";
2083                 break;
2084                         str = "Dark Yellow";
2085                 break;
2086                         str = "Dark Green";
2087                 break;
2088                         str = "Dark Cyan";
2089                 break;
2090                         str = "Dark Blue";
2091                 break;
2092                         str = "Dark Magenta";
2093                 break;
2094                         str = "Grey";
2095                 break;
2096                         str = "White";
2097                 break;
2098                         str = "Bright Red";
2099                 break;
2100                         str = "Bright Yellow";
2101                 break;
2102                         str = "Bright Green";
2103                 break;
2104                         str = "Bright Cyan";
2105                 break;
2106                         str = "Bright Blue";
2107                 break;
2108                         str = "Bright Magenta";
2109                 break;
2110         }
2111
2112         proto_tree_add_text(subtree_colour,
2113         tvb, offset, 1,
2114         "Foreground Colour : %d %s",
2115          oct & 0x0f , str);
2116         
2117         switch((oct >> 4) & 0x0f)
2118         {
2119                 case 0x00:
2120                         str = "Dark Grey";
2121                 break;
2122                 case 0x01:
2123                         str = "Dark Red";
2124                 break;
2125                         str = "Dark Yellow";
2126                 break;
2127                         str = "Dark Green";
2128                 break;
2129                         str = "Dark Cyan";
2130                 break;
2131                         str = "Dark Blue";
2132                 break;
2133                         str = "Dark Magenta";
2134                 break;
2135                         str = "Grey";
2136                 break;
2137                         str = "White";
2138                 break;
2139                         str = "Bright Red";
2140                 break;
2141                         str = "Bright Yellow";
2142                 break;
2143                         str = "Bright Green";
2144                 break;
2145                         str = "Bright Cyan";
2146                 break;
2147                         str = "Bright Blue";
2148                 break;
2149                         str = "Bright Magenta";
2150                 break;
2151         }
2152
2153         proto_tree_add_text(subtree_colour,
2154         tvb, offset, 1,
2155         "Background Colour : %d %s",
2156          (oct >> 4) & 0x0f , str);
2157
2158 }
2159
2160
2161 /* 9.2.3.24.10.1.2 */
2162 static void
2163 dis_iei_ps(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2164 {
2165     guint8      oct;
2166
2167     EXACT_DATA_CHECK(length, 2);
2168     oct = tvb_get_guint8(tvb, offset);
2169         
2170         proto_tree_add_text(tree,
2171         tvb, offset, 1,
2172         "position: %d",
2173         oct);
2174         offset++;
2175
2176         oct = tvb_get_guint8(tvb, offset);
2177         
2178         proto_tree_add_text(tree,
2179         tvb, offset, 1,
2180         "sound number: %d",
2181         oct);
2182 }
2183
2184 /* 9.2.3.24.10.1.3 */
2185 static void
2186 dis_iei_uds(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2187 {
2188     guint8      oct;
2189
2190     SHORT_DATA_CHECK(length, 2);
2191     oct = tvb_get_guint8(tvb, offset);
2192         
2193         proto_tree_add_text(tree,
2194         tvb, offset, 1,
2195         "position: %d",
2196         oct);
2197         offset++;
2198
2199         oct = tvb_get_guint8(tvb, offset);
2200         
2201         proto_tree_add_text(tree,
2202         tvb, offset, length - 1,
2203         "User Defined Sound ");
2204 }
2205
2206
2207 /* 9.2.3.24.10.1.4 */
2208 static void
2209 dis_iei_pa(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2210 {
2211     guint8      oct;
2212
2213     EXACT_DATA_CHECK(length, 2);
2214     oct = tvb_get_guint8(tvb, offset);
2215         
2216         proto_tree_add_text(tree,
2217         tvb, offset, 1,
2218         "position: %d",
2219         oct);
2220         offset++;
2221
2222         oct = tvb_get_guint8(tvb, offset);
2223         
2224         proto_tree_add_text(tree,
2225         tvb, offset, 1,
2226         "animation number: %d",
2227         oct);
2228 }
2229
2230
2231 /* 9.2.3.24.10.1.5 */
2232 static void
2233 dis_iei_la(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2234 {
2235     guint8      oct;
2236
2237     SHORT_DATA_CHECK(length, 2);
2238     oct = tvb_get_guint8(tvb, offset);
2239         
2240         proto_tree_add_text(tree,
2241         tvb, offset, 1,
2242         "position: %d",
2243         oct);
2244         offset++;
2245
2246         oct = tvb_get_guint8(tvb, offset);
2247         
2248         proto_tree_add_text(tree,
2249         tvb, offset, length - 1,
2250         "Large Animation ");
2251 }
2252
2253 /* 9.2.3.24.10.1.6 */
2254 static void
2255 dis_iei_sa(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2256 {
2257     guint8      oct;
2258
2259     SHORT_DATA_CHECK(length, 2);
2260     oct = tvb_get_guint8(tvb, offset);
2261         
2262         proto_tree_add_text(tree,
2263         tvb, offset, 1,
2264         "position: %d",
2265         oct);
2266         offset++;
2267
2268         oct = tvb_get_guint8(tvb, offset);
2269         
2270         proto_tree_add_text(tree,
2271         tvb, offset, length - 1,
2272         "Small Animation ");
2273 }
2274
2275
2276 /* 9.2.3.24.10.1.7 */
2277 static void
2278 dis_iei_lp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2279 {
2280     guint8      oct;
2281
2282     SHORT_DATA_CHECK(length, 2);
2283     oct = tvb_get_guint8(tvb, offset);
2284         
2285         proto_tree_add_text(tree,
2286         tvb, offset, 1,
2287         "position: %d",
2288         oct);
2289         offset++;
2290
2291         oct = tvb_get_guint8(tvb, offset);
2292         
2293         proto_tree_add_text(tree,
2294         tvb, offset, length - 1,
2295         "Large Picture ");
2296 }
2297
2298 /* 9.2.3.24.10.1.8 */
2299 static void
2300 dis_iei_sp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2301 {
2302     guint8      oct;
2303
2304     SHORT_DATA_CHECK(length, 2);
2305     oct = tvb_get_guint8(tvb, offset);
2306         
2307         proto_tree_add_text(tree,
2308         tvb, offset, 1,
2309         "position: %d",
2310         oct);
2311         offset++;
2312
2313         oct = tvb_get_guint8(tvb, offset);
2314         
2315         proto_tree_add_text(tree,
2316         tvb, offset, length - 1,
2317         "Small Picture ");
2318 }
2319
2320
2321 /* 9.2.3.24.10.1.9 */
2322 static void
2323 dis_iei_vp(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2324 {
2325     guint8      oct;
2326
2327     SHORT_DATA_CHECK(length, 4);
2328     oct = tvb_get_guint8(tvb, offset);
2329         
2330         proto_tree_add_text(tree,
2331         tvb, offset, 1,
2332         "position: %d",
2333         oct);
2334         offset++;
2335
2336         oct = tvb_get_guint8(tvb, offset);
2337         proto_tree_add_text(tree,
2338         tvb, offset, 1,
2339         "Horizontal dimension: %d",
2340         oct);
2341         offset++;
2342
2343         oct = tvb_get_guint8(tvb, offset);
2344         proto_tree_add_text(tree,
2345         tvb, offset, 1,
2346         "Vertical dimension: %d",
2347         oct);
2348         offset++;
2349
2350
2351         oct = tvb_get_guint8(tvb, offset);
2352         proto_tree_add_text(tree,
2353         tvb, offset, length - 3,
2354         "Variable Picture ");
2355 }
2356
2357 /* 9.2.3.24.10.1.10 */
2358 static void
2359 dis_iei_upi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2360 {
2361     guint8      oct;
2362
2363     EXACT_DATA_CHECK(length, 1);
2364     oct = tvb_get_guint8(tvb, offset);
2365         
2366         proto_tree_add_text(tree,
2367         tvb, offset, 1,
2368         "Number of corresponding objects: %d",
2369         oct);
2370         offset++;
2371 }
2372
2373
2374 /* */
2375
2376
2377 static void
2378 dis_field_ud_iei(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length)
2379 {
2380     void (*iei_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 length);
2381     guint8      oct;
2382     proto_item  *item;
2383     proto_tree  *subtree = NULL;
2384     const gchar *str = NULL;
2385     guint8      iei_len;
2386
2387
2388     while (length >= 2)
2389     {
2390         iei_fcn = NULL;
2391
2392         oct = tvb_get_guint8(tvb, offset);
2393
2394         switch (oct)
2395         {
2396         case 0x00: str = "Concatenated short messages, 8-bit reference number (SMS Control)"; iei_fcn = dis_iei_csm8; break;
2397         case 0x01: str = "Special SMS Message Indication (SMS Control)"; break;
2398         case 0x02: str = "Reserved N/A"; break;
2399         case 0x03: str = "Value not used to avoid misinterpretation as <LF> character N/A"; break;
2400         case 0x04: str = "Application port addressing scheme, 8 bit address (SMS Control)"; iei_fcn = dis_iei_apa_8bit; break;
2401         case 0x05: str = "Application port addressing scheme, 16 bit address (SMS Control)"; iei_fcn = dis_iei_apa_16bit; break;
2402         case 0x06: str = "SMSC Control Parameters (SMS Control)"; iei_fcn = dis_iei_scp; break;
2403         case 0x07: str = "UDH Source Indicator (SMS Control)"; iei_fcn  = dis_iei_udh_si; break;
2404         case 0x08: str = "Concatenated short message, 16-bit reference number (SMS Control)"; iei_fcn = dis_iei_csm16; break;
2405         case 0x09: str = "Wireless Control Message Protocol (SMS Control)"; break;
2406         case 0x0A: str = "Text Formatting (EMS Control)"; iei_fcn = dis_iei_tf;
2407         case 0x0B: str = "Predefined Sound (EMS Content)"; iei_fcn = dis_iei_ps;break;
2408         case 0x0C: str = "User Defined Sound (iMelody max 128 bytes) (EMS Content)"; iei_fcn = dis_iei_uds;break;
2409         case 0x0D: str = "Predefined Animation (EMS Content)"; iei_fcn = dis_iei_pa;break;
2410         case 0x0E: str = "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)"; iei_fcn = dis_iei_la;break;
2411         case 0x0F: str = "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)"; iei_fcn = dis_iei_sa;break;
2412         case 0x10: str = "Large Picture (32*32 = 128 bytes) (EMS Content)"; iei_fcn = dis_iei_lp;break;
2413         case 0x11: str = "Small Picture (16*16 = 32 bytes) (EMS Content)"; iei_fcn = dis_iei_sp;break;
2414         case 0x12: str = "Variable Picture (EMS Content)"; iei_fcn = dis_iei_vp;break;
2415         case 0x13: str = "User prompt indicator (EMS Control)"; iei_fcn = dis_iei_upi;break;
2416         case 0x14: str = "Extended Object (EMS Content)"; break;
2417         case 0x15: str = "Reused Extended Object (EMS Control)"; break;
2418         case 0x16: str = "Compression Control (EMS Control)"; break;
2419         case 0x17: str = "Object Distribution Indicator (EMS Control)"; break;
2420         case 0x18: str = "Standard WVG object (EMS Content)"; break;
2421         case 0x19: str = "Character Size WVG object (EMS Content)"; break;
2422         case 0x1A: str = "Extended Object Data Request Command (EMS Control)"; break;
2423         case 0x20: str = "RFC 822 E-Mail Header (SMS Control)"; break;
2424         case 0x21: str = "Hyperlink format element (SMS Control)"; break;
2425         case 0x22: str = "Reply Address Element (SMS Control)"; break;
2426         default:
2427             if ((oct >= 0x1b) &&
2428                 (oct <= 0x1f))
2429             {
2430                 str = "Reserved for future EMS features (see subclause 3.10) N/A"; break;
2431             }
2432             else if ((oct >= 0x23) &&
2433                 (oct <= 0x6f))
2434             {
2435                 str = "Reserved for future use N/A"; break;
2436             }
2437             else if ((oct >= 0x70) &&
2438                 (oct <= 0x7f))
2439             {
2440                 str = "(U)SIM Toolkit Security Headers (SMS Control)"; break;
2441             }
2442             else if ((oct >= 0x80) &&
2443                 (oct <= 0x9f))
2444             {
2445                 str = "SME to SME specific use (SMS Control)"; break;
2446             }
2447             else if ((oct >= 0xa0) &&
2448                 (oct <= 0xbf))
2449             {
2450                 str = "Reserved for future use N/A"; break;
2451             }
2452             else if ((oct >= 0xc0) &&
2453                 (oct <= 0xdf))
2454             {
2455                 str = "SC specific use (SMS Control)"; break;
2456             }
2457             else
2458             {
2459                 str = "Reserved for future use N/A"; break;
2460             }
2461         }
2462
2463         iei_len = tvb_get_guint8(tvb, offset + 1);
2464
2465         item =
2466             proto_tree_add_text(tree,
2467                 tvb, offset, iei_len + 2,
2468                 "IE: %s",
2469                 str);
2470
2471         subtree = proto_item_add_subtree(item, ett_udh_ieis[oct]);
2472
2473         proto_tree_add_text(subtree,
2474             tvb, offset, 1,
2475             "Information Element Identifier: %d",
2476             oct);
2477
2478         offset++;
2479
2480         proto_tree_add_text(subtree,
2481             tvb, offset, 1,
2482             "Length: %d",
2483             iei_len);
2484
2485         offset++;
2486
2487         if (iei_len > 0)
2488         {
2489             if (iei_fcn == NULL)
2490             {
2491                 proto_tree_add_text(subtree,
2492                     tvb, offset, iei_len,
2493                     "IE Data");
2494             }
2495             else
2496             {
2497                 iei_fcn(tvb, subtree, offset, iei_len);
2498             }
2499         }
2500
2501         length -= 2 + iei_len;
2502         offset += iei_len;
2503     }
2504 }
2505
2506 /* 9.2.3.24 */
2507 #define NUM_FILL_BITS_MASKS 6
2508 #define SMS_MAX_MESSAGE_SIZE 160
2509 char    messagebuf[SMS_MAX_MESSAGE_SIZE+1];
2510 static void
2511 dis_field_ud(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint32 length, gboolean udhi, guint8 udl,
2512     gboolean seven_bit, gboolean eight_bit, gboolean ucs2, gboolean compressed)
2513 {
2514     static guint8       fill_bits_mask[NUM_FILL_BITS_MASKS] =
2515         { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc };
2516     proto_item  *item;
2517     proto_item  *udh_item;
2518     proto_tree  *subtree = NULL;
2519     proto_tree  *udh_subtree = NULL;
2520         tvbuff_t *sm_tvb = NULL;
2521         fragment_data *fd_sm = NULL;
2522     guint8      oct;
2523     guint       fill_bits;
2524     guint32     out_len , total_sms_len , len_sms , length_ucs2 , i;
2525     char        *ustr;
2526     proto_item *ucs2_item;
2527     gchar *utf8_text = NULL;
2528         gchar save_byte = 0 , save_byte2 = 0;
2529     GIConv cd;
2530     GError *l_conv_error = NULL;
2531
2532         gboolean    reassembled = FALSE;
2533         guint32     reassembled_in = 0;
2534         gboolean is_fragmented = FALSE;
2535         gboolean save_fragmented = FALSE, try_gsm_sms_ud_reassemble = FALSE;
2536         guint32 num_labels , save_offset;
2537     fill_bits = 0;
2538
2539     item =
2540         proto_tree_add_text(tree, tvb,
2541             offset, length,
2542             "TP-User-Data");
2543         save_offset = offset;
2544     subtree = proto_item_add_subtree(item, ett_ud);
2545
2546     oct = tvb_get_guint8(tvb, offset);
2547
2548     if (udhi)
2549     {
2550
2551                 /* step over header */
2552
2553                 udh_item =
2554                     proto_tree_add_text(subtree, tvb,
2555                         offset, oct + 1,
2556                         "User-Data Header");
2557
2558                 udh_subtree = proto_item_add_subtree(udh_item, ett_udh);
2559
2560                 proto_tree_add_text(udh_subtree,
2561                     tvb, offset, 1,
2562                     "User Data Header Length (%u)",
2563                     oct);
2564
2565                 offset++;
2566                 udl--;
2567                 length--;
2568
2569                 dis_field_ud_iei(tvb, udh_subtree, offset, oct);
2570
2571                 offset += oct;
2572                 udl -= oct;
2573                 length -= oct;
2574
2575                 if (seven_bit)
2576                         {
2577                     /* step over fill bits ? */
2578
2579                     fill_bits = 7 - (((oct + 1) * 8) % 7);
2580                     if (fill_bits < NUM_FILL_BITS_MASKS)
2581                             {
2582                                 oct = tvb_get_guint8(tvb, offset);
2583
2584                                 other_decode_bitfield_value(bigbuf, oct, fill_bits_mask[fill_bits], 8);
2585                                 proto_tree_add_text(udh_subtree,
2586                                         tvb, offset, 1,
2587                                         "%s :  Fill bits",
2588                                         bigbuf);
2589                         }
2590                 }
2591     }
2592
2593         if (g_frags > 1)
2594                 is_fragmented = TRUE;
2595
2596         if ( is_fragmented ) 
2597         {
2598                 try_gsm_sms_ud_reassemble = TRUE;
2599                 save_fragmented = g_pinfo->fragmented;
2600                 g_pinfo->fragmented = TRUE;
2601                 fd_sm = fragment_add_seq_check (tvb, offset, g_pinfo,
2602                                 g_sm_id, /* guint32 ID for fragments belonging together */
2603                                 g_sm_fragment_table, /* list of message fragments */
2604                                 g_sm_reassembled_table, /* list of reassembled messages */
2605                                 g_frag-1, /* guint32 fragment sequence number */
2606                                 length, /* guint32 fragment length */
2607                                 (g_frag != g_frags)); /* More fragments? */
2608                 if (fd_sm) 
2609                 {
2610                         reassembled = TRUE;
2611                         reassembled_in = fd_sm->reassembled_in;
2612                 }
2613                                 
2614                 sm_tvb = process_reassembled_data(tvb, offset, g_pinfo,
2615                         "Reassembled Short Message", fd_sm, &sm_frag_items,
2616                         NULL, tree);
2617                 if (reassembled) 
2618                 { 
2619                         /* Reassembled */
2620                         col_append_str (g_pinfo->cinfo, COL_INFO,
2621                                                 " (Short Message Reassembled)");
2622                 } 
2623                 else 
2624                 {
2625                         /* Not last packet of reassembled Short Message */
2626                         if (check_col (g_pinfo->cinfo, COL_INFO))
2627                                 col_append_fstr (g_pinfo->cinfo, COL_INFO,
2628                                                 " (Short Message fragment %u of %u)", g_frag, g_frags);
2629                 }
2630         } /* Else: not fragmented */
2631         if (! sm_tvb) /* One single Short Message, or not reassembled */
2632                 sm_tvb = tvb_new_subset_remaining (tvb, offset);
2633         
2634     if (compressed)
2635     {
2636                 proto_tree_add_text(subtree, tvb,
2637                     offset, length,
2638                     "Compressed data");
2639     }
2640     else
2641     {
2642                 if ((reassembled && g_pinfo->fd->num == reassembled_in) || g_frag==0 || ((g_frag != 0 && msg_udh_frag)))
2643                 {
2644                         if (seven_bit)
2645                         {
2646                                 if(msg_udh_frag || g_frag == 0 )
2647                                 {
2648                                         out_len =
2649                                         gsm_sms_char_7bit_unpack(fill_bits, length , SMS_MAX_MESSAGE_SIZE,
2650                                         tvb_get_ptr(tvb , offset , length) , messagebuf);
2651                                         messagebuf[out_len] = '\0';
2652                                         gsm_sms_char_ascii_decode(bigbuf, messagebuf, out_len);
2653                                         proto_tree_add_text(subtree, tvb , offset , length , "%s", bigbuf);
2654                                 }
2655                                 else
2656                                 {
2657                                         out_len = 0;
2658                                         
2659                                         total_sms_len = sm_tvb->length;
2660                                         for(i = 0 ; i<g_frags; i++)
2661                                         {
2662                                                 /* maximum len msg in 7 bit with csm8 header*/
2663                                                 if(total_sms_len > MAX_SMS_FRAG_LEN)
2664                                                 {
2665                                                         total_sms_len -= MAX_SMS_FRAG_LEN;
2666                                                         len_sms = MAX_SMS_FRAG_LEN;
2667                                                 }
2668                                                 else
2669                                                         len_sms = total_sms_len;        
2670                                                 out_len =
2671                                                 gsm_sms_char_7bit_unpack(fill_bits, len_sms , SMS_MAX_MESSAGE_SIZE,
2672                                                 tvb_get_ptr(sm_tvb , i * MAX_SMS_FRAG_LEN  , len_sms) , messagebuf);
2673                                                 
2674                                                 messagebuf[out_len] = '\0';
2675                                                 gsm_sms_char_ascii_decode(bigbuf, messagebuf, out_len);
2676                                                 proto_tree_add_text(subtree, sm_tvb , i * MAX_SMS_FRAG_LEN , len_sms , "%s", bigbuf);
2677                                         }
2678                                 }
2679                         }
2680                         else if (eight_bit)
2681                         {
2682                                 /*proto_tree_add_text(subtree, tvb , offset , length, "%s",
2683                                 tvb_format_text(tvb, offset, length));                          */
2684                                 if (! dissector_try_port(gsm_sms_dissector_tbl, g_port_src, sm_tvb, g_pinfo, subtree)) 
2685                                 {
2686                                         if (! dissector_try_port(gsm_sms_dissector_tbl, g_port_dst,sm_tvb, g_pinfo, subtree)) 
2687                                         {
2688                                                         if (subtree) 
2689                                                         { /* Only display if needed */
2690                                                                 proto_tree_add_text (subtree, sm_tvb, 0, -1,
2691                                                                                 "Short Message body");
2692                                                         }
2693                                         }
2694                                 }
2695                         }
2696                         else if (ucs2)
2697                         {
2698                                 if ((cd = g_iconv_open("UTF-8","UCS-2BE")) != (GIConv)-1)
2699                                 {
2700                                         if(msg_udh_frag || g_frag == 0 )
2701                                         {
2702                                                 utf8_text = g_convert_with_iconv(sm_tvb->real_data, sm_tvb->reported_length , cd , NULL , NULL , &l_conv_error);
2703                                                 if(!l_conv_error){
2704                                                         ucs2_item = proto_tree_add_text(subtree, tvb, offset, length, "%s", utf8_text);
2705                                                 }else{
2706                                                         ucs2_item = proto_tree_add_text(subtree, tvb, offset, length, "%s", "Failed on UCS2 contact wireshark developers");
2707                                                 }
2708                                                 PROTO_ITEM_SET_GENERATED(ucs2_item);
2709                                         }
2710                                         else
2711                                         {
2712                                                 utf8_text = g_convert_with_iconv(sm_tvb->real_data, sm_tvb->reported_length , cd , NULL , NULL , &l_conv_error);
2713                                                 if(!l_conv_error)
2714                                                 {
2715                                                         len_sms = (int)strlen(utf8_text);
2716                                                         num_labels = len_sms / MAX_SMS_FRAG_LEN;
2717                                                         num_labels += len_sms % MAX_SMS_FRAG_LEN ? 1 : 0;
2718                                                         for(i = 0; i < num_labels;i++)
2719                                                         {
2720                                                                 if(i * MAX_SMS_FRAG_LEN < len_sms)
2721                                                                 {
2722                                                                         /* set '\0' to byte number 134 text_node MAX size*/
2723                                                                         save_byte =  utf8_text[i * MAX_SMS_FRAG_LEN];
2724                                                                         save_byte2 =  utf8_text[i * MAX_SMS_FRAG_LEN + 1];
2725                                                                         if(i > 0)
2726                                                                         {
2727                                                                                 utf8_text[i * MAX_SMS_FRAG_LEN] = '\0';
2728                                                                                 utf8_text[i * MAX_SMS_FRAG_LEN + 1] = '\0';
2729                                                                         }
2730
2731                                                                         length_ucs2 = MAX_SMS_FRAG_LEN;
2732                                                                 }
2733                                                                 else
2734                                                                         length_ucs2 = len_sms % MAX_SMS_FRAG_LEN;
2735
2736                                                                 ucs2_item = proto_tree_add_text(subtree, sm_tvb , i * MAX_SMS_FRAG_LEN , length_ucs2 , "%s", &utf8_text[i * MAX_SMS_FRAG_LEN]);
2737                                                                 /* return the save byte to utf8 buffer*/
2738                                                                 if(i * MAX_SMS_FRAG_LEN < len_sms)
2739                                                                 {
2740                                                                         utf8_text[i * MAX_SMS_FRAG_LEN] = save_byte;
2741                                                                         utf8_text[i * MAX_SMS_FRAG_LEN + 1] = save_byte2;
2742                                                                 }
2743                                                         }
2744                                                 }else{
2745                                                         ucs2_item = proto_tree_add_text(subtree, tvb, offset, length, "%s", "Failed on UCS2 contact wireshark developers");
2746                                                 }
2747                                         }
2748
2749                                         g_free(utf8_text);
2750                                         g_iconv_close(cd);
2751                                 }
2752                                 else
2753                                 {
2754                                         /* tvb_get_ephemeral_faked_unicode takes the lengt in number of guint16's */
2755                                         ustr = tvb_get_ephemeral_faked_unicode(tvb, offset, (length>>1), FALSE);
2756                                         proto_tree_add_text(subtree, tvb, offset, length, "%s", ustr);
2757                                 }
2758                         }
2759                 }
2760     }
2761
2762         if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */
2763                 g_pinfo->fragmented = save_fragmented;
2764 }
2765
2766 /* 9.2.3.27 */
2767 static void
2768 dis_field_pi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
2769 {
2770     proto_item  *item;
2771     proto_tree  *subtree = NULL;
2772
2773
2774     item =
2775         proto_tree_add_text(tree, tvb,
2776             offset, 1,
2777             "TP-Parameter-Indicator");
2778
2779     subtree = proto_item_add_subtree(item, ett_pi);
2780
2781     other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
2782     proto_tree_add_text(subtree, tvb,
2783         offset, 1,
2784         "%s :  %s",
2785         bigbuf,
2786         (oct & 0x80) ? "Extended" : "No extension");
2787
2788     other_decode_bitfield_value(bigbuf, oct, 0x78, 8);
2789     proto_tree_add_text(subtree, tvb,
2790         offset, 1,
2791         "%s :  Reserved",
2792         bigbuf);
2793
2794     other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
2795     proto_tree_add_text(subtree, tvb,
2796         offset, 1,
2797         "%s :  TP-UDL %spresent",
2798         bigbuf,
2799         (oct & 0x04) ? "" : "not ");
2800
2801     other_decode_bitfield_value(bigbuf, oct, 0x02, 8);
2802     proto_tree_add_text(subtree, tvb,
2803         offset, 1,
2804         "%s :  TP-DCS %spresent",
2805         bigbuf,
2806         (oct & 0x02) ? "" : "not ");
2807
2808     other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
2809     proto_tree_add_text(subtree, tvb,
2810         offset, 1,
2811         "%s :  TP-PID %spresent",
2812         bigbuf,
2813         (oct & 0x01) ? "" : "not ");
2814 }
2815
2816 /*
2817  * Ref. GSM 03.40
2818  * Section 9.2.2
2819  */
2820 static void
2821 dis_msg_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2822 {
2823     guint32     saved_offset;
2824     guint32     length;
2825     guint8      oct;
2826     guint8      udl;
2827     gboolean    seven_bit;
2828     gboolean    eight_bit;
2829     gboolean    ucs2;
2830     gboolean    compressed;
2831     gboolean    udhi;
2832
2833     udl = 0;
2834     saved_offset = offset;
2835     length = tvb_length_remaining(tvb, offset);
2836
2837     oct = tvb_get_guint8(tvb, offset);
2838     udhi = oct & 0x40;
2839
2840     proto_tree_add_item(tree, hf_gsm_sms_tp_rp, tvb, offset, 1, FALSE);
2841     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
2842     proto_tree_add_item(tree, hf_gsm_sms_tp_sri, tvb, offset, 1, FALSE);
2843     proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, FALSE);
2844     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, FALSE);
2845
2846     offset++;
2847
2848     dis_field_addr(tvb, tree, &offset, "TP-Originating-Address");
2849
2850     oct = tvb_get_guint8(tvb, offset);
2851
2852     dis_field_pid(tvb, tree, offset, oct);
2853
2854     offset++;
2855     oct = tvb_get_guint8(tvb, offset);
2856
2857     dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2858
2859     offset++;
2860     dis_field_scts(tvb, tree, &offset);
2861
2862     oct = tvb_get_guint8(tvb, offset);
2863     udl = oct;
2864
2865     DIS_FIELD_UDL(tree, offset);
2866
2867     if (udl > 0)
2868     {
2869         offset++;
2870
2871         dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2872             seven_bit, eight_bit, ucs2, compressed);
2873     }
2874 }
2875
2876 /*
2877  * Ref. GSM 03.40
2878  * Section 9.2.2
2879  */
2880 static void
2881 dis_msg_deliver_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2882 {
2883     guint32     saved_offset;
2884     guint32     length;
2885     guint8      oct;
2886     guint8      pi;
2887     guint8      udl;
2888     gboolean    seven_bit;
2889     gboolean    eight_bit;
2890     gboolean    ucs2;
2891     gboolean    compressed;
2892     gboolean    udhi;
2893
2894
2895     udl = 0;
2896     saved_offset = offset;
2897     length = tvb_length_remaining(tvb, offset);
2898
2899     oct = tvb_get_guint8(tvb, offset);
2900     udhi = oct & 0x40;
2901
2902     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
2903     proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, FALSE);
2904     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, FALSE);
2905
2906     if (length < 2)
2907     {
2908         proto_tree_add_text(tree,
2909             tvb, offset, length,
2910             "Short Data (?)");
2911         return;
2912     }
2913
2914     /*
2915      * there does not seem to be a way to determine that this
2916      * deliver report is from an RP-ERROR or RP-ACK other
2917      * than to look at the next octet
2918      *
2919      * FCS values are 0x80 and higher
2920      * PI uses bit 7 as an extension indicator
2921      *
2922      * will assume that if bit 7 is set then this octet
2923      * is an FCS otherwise PI
2924      */
2925     offset++;
2926     oct = tvb_get_guint8(tvb, offset);
2927
2928     if (oct & 0x80)
2929     {
2930         dis_field_fcs(tvb, tree, offset, oct);
2931         offset++;
2932     }
2933
2934     pi = tvb_get_guint8(tvb, offset);
2935
2936     dis_field_pi(tvb, tree, offset, pi);
2937
2938     if (pi & 0x01)
2939     {
2940         if (length <= (offset - saved_offset))
2941         {
2942             proto_tree_add_text(tree,
2943                 tvb, offset, -1,
2944                 "Short Data (?)");
2945             return;
2946         }
2947
2948         offset++;
2949         oct = tvb_get_guint8(tvb, offset);
2950
2951         dis_field_pid(tvb, tree, offset, oct);
2952     }
2953
2954     if (pi & 0x02)
2955     {
2956         if (length <= (offset - saved_offset))
2957         {
2958             proto_tree_add_text(tree,
2959                 tvb, offset, -1,
2960                 "Short Data (?)");
2961             return;
2962         }
2963
2964         offset++;
2965         oct = tvb_get_guint8(tvb, offset);
2966
2967         dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2968     }
2969
2970     if (pi & 0x04)
2971     {
2972         if (length <= (offset - saved_offset))
2973         {
2974             proto_tree_add_text(tree,
2975                 tvb, offset, -1,
2976                 "Short Data (?)");
2977             return;
2978         }
2979
2980         offset++;
2981         oct = tvb_get_guint8(tvb, offset);
2982         udl = oct;
2983
2984         DIS_FIELD_UDL(tree, offset);
2985     }
2986
2987     if (udl > 0)
2988     {
2989         offset++;
2990
2991         dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2992             seven_bit, eight_bit, ucs2, compressed);
2993     }
2994 }
2995
2996 /*
2997  * Ref. GSM 03.40
2998  * Section 9.2.2
2999  */
3000 static void
3001 dis_msg_submit(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3002 {
3003     guint32     saved_offset;
3004     guint32     length;
3005     guint8      oct;
3006     guint8      vp_form;
3007     guint8      udl;
3008     gboolean    seven_bit;
3009     gboolean    eight_bit;
3010     gboolean    ucs2;
3011     gboolean    compressed;
3012     gboolean    udhi;
3013
3014
3015     saved_offset = offset;
3016     length = tvb_length_remaining(tvb, offset);
3017
3018     oct = tvb_get_guint8(tvb, offset);
3019     udhi = oct & 0x40;
3020     vp_form = ((oct & 0x18) >> 3);
3021
3022     proto_tree_add_item(tree, hf_gsm_sms_tp_rp, tvb, offset, 1, FALSE);
3023     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3024     proto_tree_add_item(tree, hf_gsm_sms_tp_srr, tvb, offset, 1, FALSE);
3025     proto_tree_add_item(tree, hf_gsm_sms_tp_vpf, tvb, offset, 1, FALSE);
3026     proto_tree_add_item(tree, hf_gsm_sms_tp_rd, tvb, offset, 1, FALSE);
3027     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, FALSE);
3028
3029     offset++;
3030     oct = tvb_get_guint8(tvb, offset);
3031
3032     proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, FALSE);
3033
3034     offset++;
3035
3036     dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
3037
3038     oct = tvb_get_guint8(tvb, offset);
3039
3040     dis_field_pid(tvb, tree, offset, oct);
3041
3042     offset++;
3043     oct = tvb_get_guint8(tvb, offset);
3044
3045     dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3046
3047     offset++;
3048     dis_field_vp(tvb, tree, &offset, vp_form);
3049
3050     oct = tvb_get_guint8(tvb, offset);
3051     udl = oct;
3052
3053     DIS_FIELD_UDL(tree, offset);
3054
3055     if (udl > 0)
3056     {
3057         offset++;
3058
3059         dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3060             seven_bit, eight_bit, ucs2, compressed);
3061     }
3062 }
3063
3064 /*
3065  * Ref. GSM 03.40
3066  * Section 9.2.2
3067  */
3068 static void
3069 dis_msg_submit_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3070 {
3071     guint32     saved_offset;
3072     guint32     length;
3073     guint8      oct;
3074     guint8      pi;
3075     guint8      udl;
3076     gboolean    seven_bit;
3077     gboolean    eight_bit;
3078     gboolean    ucs2;
3079     gboolean    compressed;
3080     gboolean    udhi;
3081
3082
3083     udl = 0;
3084     saved_offset = offset;
3085     length = tvb_length_remaining(tvb, offset);
3086
3087     oct = tvb_get_guint8(tvb, offset);
3088     udhi = oct & 0x40;
3089     
3090     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3091     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, FALSE);
3092
3093     /*
3094      * there does not seem to be a way to determine that this
3095      * deliver report is from an RP-ERROR or RP-ACK other
3096      * than to look at the next octet
3097      *
3098      * FCS values are 0x80 and higher
3099      * PI uses bit 7 as an extension indicator
3100      *
3101      * will assume that if bit 7 is set then this octet
3102      * is an FCS otherwise PI
3103      */
3104     offset++;
3105     oct = tvb_get_guint8(tvb, offset);
3106
3107     if (oct & 0x80)
3108     {
3109         dis_field_fcs(tvb, tree, offset, oct);
3110         offset++;
3111     }
3112
3113     pi = tvb_get_guint8(tvb, offset);
3114
3115     dis_field_pi(tvb, tree, offset, pi);
3116     offset++;
3117
3118     dis_field_scts(tvb, tree, &offset);
3119
3120     if (pi & 0x01) {
3121         if (length <= (offset - saved_offset)) {
3122             proto_tree_add_text(tree,
3123                 tvb, offset, -1,
3124                 "Short Data (?)");
3125             return;
3126         }
3127
3128         oct = tvb_get_guint8(tvb, offset);
3129
3130         dis_field_pid(tvb, tree, offset, oct);
3131         offset++;
3132     }
3133
3134     if (pi & 0x02)
3135     {
3136         if (length <= (offset - saved_offset))
3137         {
3138             proto_tree_add_text(tree,
3139                 tvb, offset, -1,
3140                 "Short Data (?)");
3141             return;
3142         }
3143
3144         oct = tvb_get_guint8(tvb, offset);
3145
3146         dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3147         offset++;
3148     }
3149
3150     if (pi & 0x04)
3151     {
3152         if (length <= (offset - saved_offset))
3153         {
3154             proto_tree_add_text(tree,
3155                 tvb, offset, -1,
3156                 "Short Data (?)");
3157             return;
3158         }
3159
3160         oct = tvb_get_guint8(tvb, offset);
3161         udl = oct;
3162
3163         DIS_FIELD_UDL(tree, offset);
3164         offset++;
3165     }
3166
3167     if (udl > 0)
3168     {
3169         dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3170             seven_bit, eight_bit, ucs2, compressed);
3171     }
3172 }
3173
3174 /*
3175  * Ref. GSM 03.40
3176  * Section 9.2.2
3177  */
3178 static void
3179 dis_msg_status_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3180 {
3181     guint32     saved_offset;
3182     guint32     length;
3183     guint8      oct;
3184     guint8      pi;
3185     guint8      udl;
3186     gboolean    seven_bit;
3187     gboolean    eight_bit;
3188     gboolean    ucs2;
3189     gboolean    compressed;
3190     gboolean    udhi; 
3191
3192
3193     udl = 0;
3194     saved_offset = offset;
3195     length = tvb_length_remaining(tvb, offset);
3196
3197     oct = tvb_get_guint8(tvb, offset);
3198     udhi = oct & 0x40;
3199
3200     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3201     proto_tree_add_item(tree, hf_gsm_sms_tp_srq, tvb, offset, 1, FALSE);
3202     proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, FALSE);
3203     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, FALSE);
3204
3205     offset++;
3206     oct = tvb_get_guint8(tvb, offset);
3207
3208     proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, FALSE);
3209
3210     offset++;
3211
3212     dis_field_addr(tvb, tree, &offset, "TP-Recipient-Address");
3213
3214     dis_field_scts(tvb, tree, &offset);
3215
3216     dis_field_dt(tvb, tree, &offset);
3217
3218     oct = tvb_get_guint8(tvb, offset);
3219
3220     dis_field_st(tvb, tree, offset, oct);
3221
3222     offset++;
3223         /* Parameter indicating the presence of any of
3224          * the optional parameters which follow
3225          * 4) Mandatory if any of the optional parameters following TP-PI is present,
3226          * otherwise optional.
3227          */
3228         if (length <= (offset - saved_offset))
3229         {
3230             return;
3231         }
3232     pi = tvb_get_guint8(tvb, offset);
3233
3234     dis_field_pi(tvb, tree, offset, pi);
3235
3236     if (pi & 0x01)
3237     {
3238         if (length <= (offset - saved_offset))
3239         {
3240             proto_tree_add_text(tree,
3241                 tvb, offset, -1,
3242                 "Short Data (?)");
3243             return;
3244         }
3245
3246         offset++;
3247         oct = tvb_get_guint8(tvb, offset);
3248
3249         dis_field_pid(tvb, tree, offset, oct);
3250     }
3251
3252     if (pi & 0x02)
3253     {
3254         if (length <= (offset - saved_offset))
3255         {
3256             proto_tree_add_text(tree,
3257                 tvb, offset, -1,
3258                 "Short Data (?)");
3259             return;
3260         }
3261
3262         offset++;
3263         oct = tvb_get_guint8(tvb, offset);
3264
3265         dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3266     }
3267
3268     if (pi & 0x04)
3269     {
3270         if (length <= (offset - saved_offset))
3271         {
3272             proto_tree_add_text(tree,
3273                 tvb, offset, -1,
3274                 "Short Data (?)");
3275             return;
3276         }
3277
3278         offset++;
3279         oct = tvb_get_guint8(tvb, offset);
3280         udl = oct;
3281
3282         DIS_FIELD_UDL(tree, offset);
3283     }
3284
3285     if (udl > 0)
3286     {
3287         offset++;
3288
3289         dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3290             seven_bit, eight_bit, ucs2, compressed);
3291     }
3292 }
3293
3294 /*
3295  * Ref. GSM 03.40
3296  * Section 9.2.2
3297  */
3298 static void
3299 dis_msg_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3300 {
3301     guint32     saved_offset;
3302     guint32     length;
3303     guint8      oct;
3304     guint8      cdl;
3305     const gchar *str = NULL;
3306     gboolean    udhi;
3307
3308
3309     cdl = 0;
3310     saved_offset = offset;
3311     length = tvb_length_remaining(tvb, offset);
3312
3313     oct = tvb_get_guint8(tvb, offset);
3314     udhi = oct & 0x40;
3315
3316     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3317     proto_tree_add_item(tree, hf_gsm_sms_tp_srr, tvb, offset, 1, FALSE);
3318     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, FALSE);
3319
3320     offset++;
3321     oct = tvb_get_guint8(tvb, offset);
3322
3323     proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, FALSE);
3324
3325     offset++;
3326     oct = tvb_get_guint8(tvb, offset);
3327
3328     dis_field_pid(tvb, tree, offset, oct);
3329
3330     offset++;
3331     oct = tvb_get_guint8(tvb, offset);
3332
3333     DIS_FIELD_CT(tree, offset);
3334
3335     offset++;
3336     oct = tvb_get_guint8(tvb, offset);
3337
3338     DIS_FIELD_MN(tree, offset);
3339
3340     offset++;
3341
3342     dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
3343
3344     oct = tvb_get_guint8(tvb, offset);
3345     cdl = oct;
3346
3347     DIS_FIELD_CDL(tree, offset);
3348
3349     if (cdl > 0)
3350     {
3351         offset++;
3352
3353         proto_tree_add_text(tree,
3354             tvb, offset, cdl,
3355             "TP-Command-Data");
3356     }
3357 }
3358
3359 #define NUM_MSGS (sizeof(msg_type_strings)/sizeof(value_string))
3360 static gint ett_msgs[NUM_MSGS];
3361 static void (*gsm_sms_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = {
3362     dis_msg_deliver,            /* SMS-DELIVER */
3363     dis_msg_deliver_report,     /* SMS-DELIVER REPORT */
3364     dis_msg_submit,                     /* SMS-SUBMIT */
3365     dis_msg_submit_report,      /* SMS-SUBMIT REPORT */
3366     dis_msg_status_report,      /* SMS-STATUS REPORT */
3367     dis_msg_command,            /* SMS-COMMAND */
3368     NULL,                                       /* Reserved */
3369     NULL,                                       /* Reserved */
3370     NULL,                                       /* NONE */
3371 };
3372
3373 /* GENERIC DISSECTOR FUNCTIONS */
3374
3375 static void
3376 dissect_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3377 {
3378     void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = NULL;
3379     proto_item  *gsm_sms_item;
3380     proto_tree  *gsm_sms_tree = NULL;
3381     guint32     offset;
3382     guint8      msg_type;
3383     guint8      oct;
3384     gint        idx;
3385     const gchar *str = NULL;
3386     gint        ett_msg_idx;
3387         
3388
3389     g_pinfo = pinfo;
3390         g_is_wsp = 0;
3391         g_sm_id = 0;
3392         g_frags = 0;
3393         g_frag = 0;     
3394         g_port_src = 0;
3395         g_port_dst = 0;
3396
3397     if (check_col(pinfo->cinfo, COL_PROTOCOL))
3398     {
3399         col_set_str(pinfo->cinfo, COL_PROTOCOL, gsm_sms_proto_name_short);
3400     }
3401
3402     /* In the interest of speed, if "tree" is NULL, don't do any work not
3403      * necessary to generate protocol tree items.
3404      */
3405     if (tree)
3406     {
3407         g_tree = tree;
3408
3409         offset = 0;
3410
3411         oct = tvb_get_guint8(tvb, offset);
3412
3413         oct &= 0x03;
3414         msg_type = oct;
3415
3416         /*
3417          * convert the 2 bit value to one based on direction
3418          */
3419         if (pinfo->p2p_dir == P2P_DIR_UNKNOWN)
3420         {
3421             /* Return Result ... */
3422             if (msg_type == 0) /* SMS-DELIVER */
3423             {
3424                 msg_type |= 0x04; /* see the msg_type_strings */
3425             }
3426         }
3427         else
3428         {
3429             msg_type |= ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x04 : 0x00);
3430         }
3431
3432         str = match_strval_idx(msg_type, msg_type_strings, &idx);
3433
3434         /*
3435          * create the GSM_SMS protocol tree
3436          */
3437         gsm_sms_item =
3438             proto_tree_add_protocol_format(tree, proto_gsm_sms, tvb, 0, -1,
3439                 "%s %s",
3440                 gsm_sms_proto_name,
3441                 (str == NULL) ? "Unknown message identifier" : str);
3442
3443         gsm_sms_tree =
3444             proto_item_add_subtree(gsm_sms_item, ett_gsm_sms);
3445
3446         if ((str == NULL) ||
3447             (msg_type == 0x03) ||
3448             (msg_type == 0x07))
3449         {
3450             return;
3451         }
3452         else
3453         {
3454             ett_msg_idx = ett_msgs[idx];
3455             msg_fcn = gsm_sms_msg_fcn[idx];
3456         }
3457
3458         if (msg_fcn == NULL)
3459         {
3460             proto_tree_add_text(gsm_sms_tree,
3461                 tvb, offset, -1,
3462                 "Message dissector not implemented");
3463         }
3464         else
3465         {
3466             (*msg_fcn)(tvb, gsm_sms_tree, offset);
3467         }
3468     }
3469 }
3470
3471
3472 /* Register the protocol with Wireshark */
3473 void
3474 proto_register_gsm_sms(void)
3475 {
3476     guint               i;
3477     guint               last_offset;
3478         module_t *gsm_sms_module; /* Preferences for GSM SMS UD */
3479
3480     /* Setup list of header fields */
3481     static hf_register_info hf[] =
3482     {
3483             { &hf_gsm_sms_coding_group_bits2,
3484               { "Coding Group Bits", "gsm_sms.coding_group_bits2",
3485                 FT_UINT8, BASE_DEC, VALS(gsm_sms_coding_group_bits_vals), 0xc0,
3486                 NULL, HFILL }
3487                 },
3488             { &hf_gsm_sms_coding_group_bits4,
3489               { "Coding Group Bits", "gsm_sms.coding_group_bits4",
3490                 FT_UINT8, BASE_DEC, VALS(gsm_sms_coding_group_bits_vals), 0xf0,
3491                 NULL, HFILL }
3492                 },
3493
3494                 /*
3495                  * Short Message fragment reassembly
3496                  */
3497                 {       &hf_gsm_sms_ud_fragments,
3498                         {       "Short Message fragments", "gsm-sms-ud.fragments",
3499                                 FT_NONE, BASE_NONE, NULL, 0x00,
3500                                 "GSM Short Message fragments",
3501                                 HFILL
3502                         }
3503                 },
3504                 {       &hf_gsm_sms_ud_fragment,
3505                         {       "Short Message fragment", "gsm-sms-ud.fragment",
3506                                 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3507                                 "GSM Short Message fragment",
3508                                 HFILL
3509                         }
3510                 },
3511                 {       &hf_gsm_sms_ud_fragment_overlap,
3512                         {       "Short Message fragment overlap", "gsm-sms-ud.fragment.overlap",
3513                                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3514                                 "GSM Short Message fragment overlaps with other fragment(s)",
3515                                 HFILL
3516                         }
3517                 },
3518                 {       &hf_gsm_sms_ud_fragment_overlap_conflicts,
3519                         {       "Short Message fragment overlapping with conflicting data",
3520                                 "gsm-sms-ud.fragment.overlap.conflicts",
3521                                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3522                                 "GSM Short Message fragment overlaps with conflicting data",
3523                                 HFILL
3524                         }
3525                 },
3526                 {       &hf_gsm_sms_ud_fragment_multiple_tails,
3527                         {       "Short Message has multiple tail fragments",
3528                                 "gsm-sms-ud.fragment.multiple_tails",
3529                                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3530                                 "GSM Short Message fragment has multiple tail fragments",
3531                                 HFILL
3532                         }
3533                 },
3534                 {       &hf_gsm_sms_ud_fragment_too_long_fragment,
3535                         {       "Short Message fragment too long",
3536                                 "gsm-sms-ud.fragment.too_long_fragment",
3537                                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3538                                 "GSM Short Message fragment data goes beyond the packet end",
3539                                 HFILL
3540                         }
3541                 },
3542                 {       &hf_gsm_sms_ud_fragment_error,
3543                         {       "Short Message defragmentation error", "gsm-sms-ud.fragment.error",
3544                                 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3545                                 "GSM Short Message defragmentation error due to illegal fragments",
3546                                 HFILL
3547                         }
3548                 },
3549                 {       &hf_gsm_sms_ud_reassembled_in,
3550                         {       "Reassembled in",
3551                                 "gsm-sms-ud.reassembled.in",
3552                                 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3553                                 "GSM Short Message has been reassembled in this packet.", HFILL
3554                         }
3555                 },
3556                 {   &hf_gsm_sms_ud_multiple_messages_msg_id,
3557             {   "Message identifier", "gsm-sms.udh.mm.msg_id",
3558                 FT_UINT16, BASE_DEC, NULL, 0x00,
3559                 "Identification of the message",
3560                 HFILL
3561             }
3562         },
3563         {   &hf_gsm_sms_ud_multiple_messages_msg_parts,
3564             {   "Message parts", "gsm-sms.udh.mm.msg_parts",
3565                 FT_UINT8, BASE_DEC, NULL, 0x00,
3566                 "Total number of message parts (fragments)",
3567                 HFILL
3568             }
3569         },
3570         {   &hf_gsm_sms_ud_multiple_messages_msg_part,
3571             {   "Message part number", "gsm-sms.udh.mm.msg_part",
3572                 FT_UINT8, BASE_DEC, NULL, 0x00,
3573                 "Message part (fragment) sequence number",
3574                 HFILL
3575             }
3576         },
3577         /* TPDU parameters */
3578         { &hf_gsm_sms_tp_mti_up,
3579               { "TP-MTI", "gsm_sms.tp-mti",
3580                 FT_UINT8, BASE_DEC, VALS(msg_type_strings_ms_to_sc), 0x03,
3581                 "TP-Message-Type-Indicator (in the direction MS to SC)", HFILL }
3582         },      
3583         { &hf_gsm_sms_tp_mti_down,
3584               { "TP-MTI", "gsm_sms.tp-mti",
3585                 FT_UINT8, BASE_DEC, VALS(msg_type_strings_sc_to_ms), 0x03,
3586                 "TP-Message-Type-Indicator (in the direction SC to MS)", HFILL }
3587         },      
3588         { &hf_gsm_sms_tp_oa,
3589               { "TP-OA Digits", "gsm_sms.tp-oa",
3590                 FT_STRING, BASE_NONE, NULL, 0x00,
3591                 "TP-Originating-Address Digits", HFILL }
3592         },
3593         { &hf_gsm_sms_tp_da,
3594               { "TP-DA Digits", "gsm_sms.tp-da",
3595                 FT_STRING, BASE_NONE, NULL, 0x00,
3596                 "TP-Destination-Address Digits", HFILL }
3597         },
3598         { &hf_gsm_sms_tp_ra,
3599               { "TP-RA Digits", "gsm_sms.tp-ra",
3600                 FT_STRING, BASE_NONE, NULL, 0x00,
3601                 "TP-Recipient-Address Digits", HFILL }
3602         },
3603         { &hf_gsm_sms_tp_pid,
3604               { "TP-PID", "gsm_sms.tp-pid",
3605                 FT_UINT8, BASE_DEC, NULL, 0x00,
3606                 "TP-Protocol-Identifier", HFILL }
3607         },
3608         { &hf_gsm_sms_tp_dcs,
3609               { "TP-DCS", "gsm_sms.tp-dcs",
3610                 FT_UINT8, BASE_DEC, NULL, 0x00,
3611                 "TP-Data-Coding-Scheme", HFILL }
3612         },
3613         { &hf_gsm_sms_tp_mr,
3614               { "TP-MR", "gsm_sms.tp-mr",
3615                 FT_UINT8, BASE_DEC, NULL, 0x00,
3616                 "TP-Message-Reference", HFILL }
3617         },
3618         { &hf_gsm_sms_tp_mms,
3619               { "TP-MMS", "gsm_sms.tp-mms",
3620                 FT_BOOLEAN, 8, TFS(&mms_bool_strings), 0x04,
3621                 "TP-More-Messages-to-Send", HFILL }
3622         },
3623         { &hf_gsm_sms_tp_sri,
3624               { "TP-SRI", "gsm_sms.tp-sri",
3625                 FT_BOOLEAN, 8, TFS(&sri_bool_strings), 0x20,
3626                 "TP-Status-Report-Indication", HFILL }
3627         },
3628         { &hf_gsm_sms_tp_srr,
3629               { "TP-SRR", "gsm_sms.tp-srr",
3630                 FT_BOOLEAN, 8, TFS(&srr_bool_strings), 0x20,
3631                 "TP-Status-Report-Request", HFILL }
3632         },
3633         { &hf_gsm_sms_tp_udhi,
3634               { "TP-UDHI", "gsm_sms.tp-udhi",
3635                 FT_BOOLEAN, 8, TFS(&udhi_bool_strings), 0x40,
3636                 "TP-User-Data-Header-Indicator", HFILL }
3637         },
3638         { &hf_gsm_sms_tp_rp,
3639               { "TP-RP", "gsm_sms.tp-rp",
3640                 FT_BOOLEAN, 8, TFS(&rp_bool_strings), 0x80,
3641                 "TP-Reply-Path", HFILL }
3642         },      
3643         { &hf_gsm_sms_tp_vpf,
3644               { "TP-VPF", "gsm_sms.tp-vpf",
3645                 FT_UINT8, BASE_DEC, VALS(vp_type_strings), 0x18,
3646                 "TP-Validity-Period-Format", HFILL }
3647         },      
3648         { &hf_gsm_sms_tp_rd,
3649               { "TP-RD", "gsm_sms.tp-rd",
3650                 FT_BOOLEAN, 8, TFS(&rd_bool_strings), 0x04,
3651                 "TP-Reject-Duplicates", HFILL }
3652         },      
3653         { &hf_gsm_sms_tp_srq,
3654               { "TP-SRQ", "gsm_sms.tp-srq",
3655                 FT_BOOLEAN, 8, TFS(&srq_bool_strings), 0x20,
3656                 "TP-Status-Report-Qualifier", HFILL }
3657         },      
3658     };
3659
3660     /* Setup protocol subtree array */
3661 #define NUM_INDIVIDUAL_PARMS    12
3662     gint *ett[NUM_INDIVIDUAL_PARMS+NUM_MSGS+NUM_UDH_IEIS+2];
3663
3664     ett[0] = &ett_gsm_sms;
3665     ett[1] = &ett_pid;
3666     ett[2] = &ett_pi;
3667     ett[3] = &ett_fcs;
3668     ett[4] = &ett_vp;
3669     ett[5] = &ett_scts;
3670     ett[6] = &ett_dt;
3671     ett[7] = &ett_st;
3672     ett[8] = &ett_addr;
3673     ett[9] = &ett_dcs;
3674     ett[10] = &ett_ud;
3675     ett[11] = &ett_udh;
3676
3677     last_offset = NUM_INDIVIDUAL_PARMS;
3678
3679     for (i=0; i < NUM_MSGS; i++, last_offset++)
3680     {
3681         ett_msgs[i] = -1;
3682         ett[last_offset] = &ett_msgs[i];
3683     }
3684
3685     for (i=0; i < NUM_UDH_IEIS; i++, last_offset++)
3686     {
3687         ett_udh_ieis[i] = -1;
3688         ett[last_offset] = &ett_udh_ieis[i];
3689     }
3690
3691     ett[last_offset++] = &ett_gsm_sms_ud_fragment;
3692     ett[last_offset] = &ett_gsm_sms_ud_fragments;
3693
3694     /* Register the protocol name and description */
3695
3696     proto_gsm_sms =
3697         proto_register_protocol(gsm_sms_proto_name, gsm_sms_proto_name_short, "gsm_sms");
3698
3699
3700     proto_register_field_array(proto_gsm_sms, hf, array_length(hf));
3701
3702     proto_register_subtree_array(ett, array_length(ett));
3703
3704     gsm_sms_dissector_tbl = register_dissector_table("gsm-sms.udh.port",
3705         "GSM SMS port IE in UDH", FT_UINT16, BASE_DEC);
3706
3707     gsm_sms_module = prefs_register_protocol (proto_gsm_sms, NULL);
3708     prefs_register_bool_preference (gsm_sms_module,
3709         "try_dissect_message_fragment",
3710         "Always try subdissection of the fragment of a fragmented",
3711         "Always try subdissection of 7bit, UCS2 Short Message fragment."
3712         "If checked, every msg decode will shown in its fragment",
3713         &msg_udh_frag);
3714
3715     /* register_dissector("gsm-sms", dissect_gsm_sms, proto_gsm_sms); */
3716
3717     /* GSM SMS UD dissector initialization routines */
3718     register_init_routine (gsm_sms_defragment_init);
3719 }
3720
3721
3722 void
3723 proto_reg_handoff_gsm_sms(void)
3724 {
3725     dissector_handle_t  gsm_sms_handle;
3726
3727     gsm_sms_handle = create_dissector_handle(dissect_gsm_sms, proto_gsm_sms);
3728
3729     dissector_add("gsm_a.sms_tpdu", 0, gsm_sms_handle);
3730     dissector_add("gsm_map.sms_tpdu", 0, gsm_sms_handle);
3731 }