9950eb1bf1c0d9c16a053f4f82e32b474ba338d1
[metze/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                         if (check_col (g_pinfo->cinfo, COL_INFO))
2621                                 col_append_str (g_pinfo->cinfo, COL_INFO,
2622                                                 " (Short Message Reassembled)");
2623                 } 
2624                 else 
2625                 {
2626                         /* Not last packet of reassembled Short Message */
2627                         if (check_col (g_pinfo->cinfo, COL_INFO))
2628                                 col_append_fstr (g_pinfo->cinfo, COL_INFO,
2629                                                 " (Short Message fragment %u of %u)", g_frag, g_frags);
2630                 }
2631         } /* Else: not fragmented */
2632         if (! sm_tvb) /* One single Short Message, or not reassembled */
2633                 sm_tvb = tvb_new_subset_remaining (tvb, offset);
2634         
2635     if (compressed)
2636     {
2637                 proto_tree_add_text(subtree, tvb,
2638                     offset, length,
2639                     "Compressed data");
2640     }
2641     else
2642     {
2643                 if ((reassembled && g_pinfo->fd->num == reassembled_in) || g_frag==0 || ((g_frag != 0 && msg_udh_frag)))
2644                 {
2645                         if (seven_bit)
2646                         {
2647                                 if(msg_udh_frag || g_frag == 0 )
2648                                 {
2649                                         out_len =
2650                                         gsm_sms_char_7bit_unpack(fill_bits, length , SMS_MAX_MESSAGE_SIZE,
2651                                         tvb_get_ptr(tvb , offset , length) , messagebuf);
2652                                         messagebuf[out_len] = '\0';
2653                                         gsm_sms_char_ascii_decode(bigbuf, messagebuf, out_len);
2654                                         proto_tree_add_text(subtree, tvb , offset , length , "%s", bigbuf);
2655                                 }
2656                                 else
2657                                 {
2658                                         out_len = 0;
2659                                         
2660                                         total_sms_len = sm_tvb->length;
2661                                         for(i = 0 ; i<g_frags; i++)
2662                                         {
2663                                                 /* maximum len msg in 7 bit with csm8 header*/
2664                                                 if(total_sms_len > MAX_SMS_FRAG_LEN)
2665                                                 {
2666                                                         total_sms_len -= MAX_SMS_FRAG_LEN;
2667                                                         len_sms = MAX_SMS_FRAG_LEN;
2668                                                 }
2669                                                 else
2670                                                         len_sms = total_sms_len;        
2671                                                 out_len =
2672                                                 gsm_sms_char_7bit_unpack(fill_bits, len_sms , SMS_MAX_MESSAGE_SIZE,
2673                                                 tvb_get_ptr(sm_tvb , i * MAX_SMS_FRAG_LEN  , len_sms) , messagebuf);
2674                                                 
2675                                                 messagebuf[out_len] = '\0';
2676                                                 gsm_sms_char_ascii_decode(bigbuf, messagebuf, out_len);
2677                                                 proto_tree_add_text(subtree, sm_tvb , i * MAX_SMS_FRAG_LEN , len_sms , "%s", bigbuf);
2678                                         }
2679                                 }
2680                         }
2681                         else if (eight_bit)
2682                         {
2683                                 /*proto_tree_add_text(subtree, tvb , offset , length, "%s",
2684                                 tvb_format_text(tvb, offset, length));                          */
2685                                 if (! dissector_try_port(gsm_sms_dissector_tbl, g_port_src, sm_tvb, g_pinfo, subtree)) 
2686                                 {
2687                                         if (! dissector_try_port(gsm_sms_dissector_tbl, g_port_dst,sm_tvb, g_pinfo, subtree)) 
2688                                         {
2689                                                         if (subtree) 
2690                                                         { /* Only display if needed */
2691                                                                 proto_tree_add_text (subtree, sm_tvb, 0, -1,
2692                                                                                 "Short Message body");
2693                                                         }
2694                                         }
2695                                 }
2696                         }
2697                         else if (ucs2)
2698                         {
2699                                 if ((cd = g_iconv_open("UTF-8","UCS-2BE")) != (GIConv)-1)
2700                                 {
2701                                         if(msg_udh_frag || g_frag == 0 )
2702                                         {
2703                                                 utf8_text = g_convert_with_iconv(sm_tvb->real_data, sm_tvb->reported_length , cd , NULL , NULL , &l_conv_error);
2704                                                 if(!l_conv_error){
2705                                                         ucs2_item = proto_tree_add_text(subtree, tvb, offset, length, "%s", utf8_text);
2706                                                 }else{
2707                                                         ucs2_item = proto_tree_add_text(subtree, tvb, offset, length, "%s", "Failed on UCS2 contact wireshark developers");
2708                                                 }
2709                                                 PROTO_ITEM_SET_GENERATED(ucs2_item);
2710                                         }
2711                                         else
2712                                         {
2713                                                 utf8_text = g_convert_with_iconv(sm_tvb->real_data, sm_tvb->reported_length , cd , NULL , NULL , &l_conv_error);
2714                                                 if(!l_conv_error)
2715                                                 {
2716                                                         len_sms = (int)strlen(utf8_text);
2717                                                         num_labels = len_sms / MAX_SMS_FRAG_LEN;
2718                                                         num_labels += len_sms % MAX_SMS_FRAG_LEN ? 1 : 0;
2719                                                         for(i = 0; i < num_labels;i++)
2720                                                         {
2721                                                                 if(i * MAX_SMS_FRAG_LEN < len_sms)
2722                                                                 {
2723                                                                         /* set '\0' to byte number 134 text_node MAX size*/
2724                                                                         save_byte =  utf8_text[i * MAX_SMS_FRAG_LEN];
2725                                                                         save_byte2 =  utf8_text[i * MAX_SMS_FRAG_LEN + 1];
2726                                                                         if(i > 0)
2727                                                                         {
2728                                                                                 utf8_text[i * MAX_SMS_FRAG_LEN] = '\0';
2729                                                                                 utf8_text[i * MAX_SMS_FRAG_LEN + 1] = '\0';
2730                                                                         }
2731
2732                                                                         length_ucs2 = MAX_SMS_FRAG_LEN;
2733                                                                 }
2734                                                                 else
2735                                                                         length_ucs2 = len_sms % MAX_SMS_FRAG_LEN;
2736
2737                                                                 ucs2_item = proto_tree_add_text(subtree, sm_tvb , i * MAX_SMS_FRAG_LEN , length_ucs2 , "%s", &utf8_text[i * MAX_SMS_FRAG_LEN]);
2738                                                                 /* return the save byte to utf8 buffer*/
2739                                                                 if(i * MAX_SMS_FRAG_LEN < len_sms)
2740                                                                 {
2741                                                                         utf8_text[i * MAX_SMS_FRAG_LEN] = save_byte;
2742                                                                         utf8_text[i * MAX_SMS_FRAG_LEN + 1] = save_byte2;
2743                                                                 }
2744                                                         }
2745                                                 }else{
2746                                                         ucs2_item = proto_tree_add_text(subtree, tvb, offset, length, "%s", "Failed on UCS2 contact wireshark developers");
2747                                                 }
2748                                         }
2749
2750                                         g_free(utf8_text);
2751                                         g_iconv_close(cd);
2752                                 }
2753                                 else
2754                                 {
2755                                         /* tvb_get_ephemeral_faked_unicode takes the lengt in number of guint16's */
2756                                         ustr = tvb_get_ephemeral_faked_unicode(tvb, offset, (length>>1), FALSE);
2757                                         proto_tree_add_text(subtree, tvb, offset, length, "%s", ustr);
2758                                 }
2759                         }
2760                 }
2761     }
2762
2763         if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */
2764                 g_pinfo->fragmented = save_fragmented;
2765 }
2766
2767 /* 9.2.3.27 */
2768 static void
2769 dis_field_pi(tvbuff_t *tvb, proto_tree *tree, guint32 offset, guint8 oct)
2770 {
2771     proto_item  *item;
2772     proto_tree  *subtree = NULL;
2773
2774
2775     item =
2776         proto_tree_add_text(tree, tvb,
2777             offset, 1,
2778             "TP-Parameter-Indicator");
2779
2780     subtree = proto_item_add_subtree(item, ett_pi);
2781
2782     other_decode_bitfield_value(bigbuf, oct, 0x80, 8);
2783     proto_tree_add_text(subtree, tvb,
2784         offset, 1,
2785         "%s :  %s",
2786         bigbuf,
2787         (oct & 0x80) ? "Extended" : "No extension");
2788
2789     other_decode_bitfield_value(bigbuf, oct, 0x78, 8);
2790     proto_tree_add_text(subtree, tvb,
2791         offset, 1,
2792         "%s :  Reserved",
2793         bigbuf);
2794
2795     other_decode_bitfield_value(bigbuf, oct, 0x04, 8);
2796     proto_tree_add_text(subtree, tvb,
2797         offset, 1,
2798         "%s :  TP-UDL %spresent",
2799         bigbuf,
2800         (oct & 0x04) ? "" : "not ");
2801
2802     other_decode_bitfield_value(bigbuf, oct, 0x02, 8);
2803     proto_tree_add_text(subtree, tvb,
2804         offset, 1,
2805         "%s :  TP-DCS %spresent",
2806         bigbuf,
2807         (oct & 0x02) ? "" : "not ");
2808
2809     other_decode_bitfield_value(bigbuf, oct, 0x01, 8);
2810     proto_tree_add_text(subtree, tvb,
2811         offset, 1,
2812         "%s :  TP-PID %spresent",
2813         bigbuf,
2814         (oct & 0x01) ? "" : "not ");
2815 }
2816
2817 /*
2818  * Ref. GSM 03.40
2819  * Section 9.2.2
2820  */
2821 static void
2822 dis_msg_deliver(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2823 {
2824     guint32     saved_offset;
2825     guint32     length;
2826     guint8      oct;
2827     guint8      udl;
2828     gboolean    seven_bit;
2829     gboolean    eight_bit;
2830     gboolean    ucs2;
2831     gboolean    compressed;
2832     gboolean    udhi;
2833
2834     udl = 0;
2835     saved_offset = offset;
2836     length = tvb_length_remaining(tvb, offset);
2837
2838     oct = tvb_get_guint8(tvb, offset);
2839     udhi = oct & 0x40;
2840
2841     proto_tree_add_item(tree, hf_gsm_sms_tp_rp, tvb, offset, 1, FALSE);
2842     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
2843     proto_tree_add_item(tree, hf_gsm_sms_tp_sri, tvb, offset, 1, FALSE);
2844     proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, FALSE);
2845     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, FALSE);
2846
2847     offset++;
2848
2849     dis_field_addr(tvb, tree, &offset, "TP-Originating-Address");
2850
2851     oct = tvb_get_guint8(tvb, offset);
2852
2853     dis_field_pid(tvb, tree, offset, oct);
2854
2855     offset++;
2856     oct = tvb_get_guint8(tvb, offset);
2857
2858     dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2859
2860     offset++;
2861     dis_field_scts(tvb, tree, &offset);
2862
2863     oct = tvb_get_guint8(tvb, offset);
2864     udl = oct;
2865
2866     DIS_FIELD_UDL(tree, offset);
2867
2868     if (udl > 0)
2869     {
2870         offset++;
2871
2872         dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2873             seven_bit, eight_bit, ucs2, compressed);
2874     }
2875 }
2876
2877 /*
2878  * Ref. GSM 03.40
2879  * Section 9.2.2
2880  */
2881 static void
2882 dis_msg_deliver_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
2883 {
2884     guint32     saved_offset;
2885     guint32     length;
2886     guint8      oct;
2887     guint8      pi;
2888     guint8      udl;
2889     gboolean    seven_bit;
2890     gboolean    eight_bit;
2891     gboolean    ucs2;
2892     gboolean    compressed;
2893     gboolean    udhi;
2894
2895
2896     udl = 0;
2897     saved_offset = offset;
2898     length = tvb_length_remaining(tvb, offset);
2899
2900     oct = tvb_get_guint8(tvb, offset);
2901     udhi = oct & 0x40;
2902
2903     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
2904     proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, FALSE);
2905     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, FALSE);
2906
2907     if (length < 2)
2908     {
2909         proto_tree_add_text(tree,
2910             tvb, offset, length,
2911             "Short Data (?)");
2912         return;
2913     }
2914
2915     /*
2916      * there does not seem to be a way to determine that this
2917      * deliver report is from an RP-ERROR or RP-ACK other
2918      * than to look at the next octet
2919      *
2920      * FCS values are 0x80 and higher
2921      * PI uses bit 7 as an extension indicator
2922      *
2923      * will assume that if bit 7 is set then this octet
2924      * is an FCS otherwise PI
2925      */
2926     offset++;
2927     oct = tvb_get_guint8(tvb, offset);
2928
2929     if (oct & 0x80)
2930     {
2931         dis_field_fcs(tvb, tree, offset, oct);
2932         offset++;
2933     }
2934
2935     pi = tvb_get_guint8(tvb, offset);
2936
2937     dis_field_pi(tvb, tree, offset, pi);
2938
2939     if (pi & 0x01)
2940     {
2941         if (length <= (offset - saved_offset))
2942         {
2943             proto_tree_add_text(tree,
2944                 tvb, offset, -1,
2945                 "Short Data (?)");
2946             return;
2947         }
2948
2949         offset++;
2950         oct = tvb_get_guint8(tvb, offset);
2951
2952         dis_field_pid(tvb, tree, offset, oct);
2953     }
2954
2955     if (pi & 0x02)
2956     {
2957         if (length <= (offset - saved_offset))
2958         {
2959             proto_tree_add_text(tree,
2960                 tvb, offset, -1,
2961                 "Short Data (?)");
2962             return;
2963         }
2964
2965         offset++;
2966         oct = tvb_get_guint8(tvb, offset);
2967
2968         dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
2969     }
2970
2971     if (pi & 0x04)
2972     {
2973         if (length <= (offset - saved_offset))
2974         {
2975             proto_tree_add_text(tree,
2976                 tvb, offset, -1,
2977                 "Short Data (?)");
2978             return;
2979         }
2980
2981         offset++;
2982         oct = tvb_get_guint8(tvb, offset);
2983         udl = oct;
2984
2985         DIS_FIELD_UDL(tree, offset);
2986     }
2987
2988     if (udl > 0)
2989     {
2990         offset++;
2991
2992         dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
2993             seven_bit, eight_bit, ucs2, compressed);
2994     }
2995 }
2996
2997 /*
2998  * Ref. GSM 03.40
2999  * Section 9.2.2
3000  */
3001 static void
3002 dis_msg_submit(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3003 {
3004     guint32     saved_offset;
3005     guint32     length;
3006     guint8      oct;
3007     guint8      vp_form;
3008     guint8      udl;
3009     gboolean    seven_bit;
3010     gboolean    eight_bit;
3011     gboolean    ucs2;
3012     gboolean    compressed;
3013     gboolean    udhi;
3014
3015
3016     saved_offset = offset;
3017     length = tvb_length_remaining(tvb, offset);
3018
3019     oct = tvb_get_guint8(tvb, offset);
3020     udhi = oct & 0x40;
3021     vp_form = ((oct & 0x18) >> 3);
3022
3023     proto_tree_add_item(tree, hf_gsm_sms_tp_rp, tvb, offset, 1, FALSE);
3024     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3025     proto_tree_add_item(tree, hf_gsm_sms_tp_srr, tvb, offset, 1, FALSE);
3026     proto_tree_add_item(tree, hf_gsm_sms_tp_vpf, tvb, offset, 1, FALSE);
3027     proto_tree_add_item(tree, hf_gsm_sms_tp_rd, tvb, offset, 1, FALSE);
3028     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, FALSE);
3029
3030     offset++;
3031     oct = tvb_get_guint8(tvb, offset);
3032
3033     proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, FALSE);
3034
3035     offset++;
3036
3037     dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
3038
3039     oct = tvb_get_guint8(tvb, offset);
3040
3041     dis_field_pid(tvb, tree, offset, oct);
3042
3043     offset++;
3044     oct = tvb_get_guint8(tvb, offset);
3045
3046     dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3047
3048     offset++;
3049     dis_field_vp(tvb, tree, &offset, vp_form);
3050
3051     oct = tvb_get_guint8(tvb, offset);
3052     udl = oct;
3053
3054     DIS_FIELD_UDL(tree, offset);
3055
3056     if (udl > 0)
3057     {
3058         offset++;
3059
3060         dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3061             seven_bit, eight_bit, ucs2, compressed);
3062     }
3063 }
3064
3065 /*
3066  * Ref. GSM 03.40
3067  * Section 9.2.2
3068  */
3069 static void
3070 dis_msg_submit_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3071 {
3072     guint32     saved_offset;
3073     guint32     length;
3074     guint8      oct;
3075     guint8      pi;
3076     guint8      udl;
3077     gboolean    seven_bit;
3078     gboolean    eight_bit;
3079     gboolean    ucs2;
3080     gboolean    compressed;
3081     gboolean    udhi;
3082
3083
3084     udl = 0;
3085     saved_offset = offset;
3086     length = tvb_length_remaining(tvb, offset);
3087
3088     oct = tvb_get_guint8(tvb, offset);
3089     udhi = oct & 0x40;
3090     
3091     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3092     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, FALSE);
3093
3094     /*
3095      * there does not seem to be a way to determine that this
3096      * deliver report is from an RP-ERROR or RP-ACK other
3097      * than to look at the next octet
3098      *
3099      * FCS values are 0x80 and higher
3100      * PI uses bit 7 as an extension indicator
3101      *
3102      * will assume that if bit 7 is set then this octet
3103      * is an FCS otherwise PI
3104      */
3105     offset++;
3106     oct = tvb_get_guint8(tvb, offset);
3107
3108     if (oct & 0x80)
3109     {
3110         dis_field_fcs(tvb, tree, offset, oct);
3111         offset++;
3112     }
3113
3114     pi = tvb_get_guint8(tvb, offset);
3115
3116     dis_field_pi(tvb, tree, offset, pi);
3117     offset++;
3118
3119     dis_field_scts(tvb, tree, &offset);
3120
3121     if (pi & 0x01) {
3122         if (length <= (offset - saved_offset)) {
3123             proto_tree_add_text(tree,
3124                 tvb, offset, -1,
3125                 "Short Data (?)");
3126             return;
3127         }
3128
3129         oct = tvb_get_guint8(tvb, offset);
3130
3131         dis_field_pid(tvb, tree, offset, oct);
3132         offset++;
3133     }
3134
3135     if (pi & 0x02)
3136     {
3137         if (length <= (offset - saved_offset))
3138         {
3139             proto_tree_add_text(tree,
3140                 tvb, offset, -1,
3141                 "Short Data (?)");
3142             return;
3143         }
3144
3145         oct = tvb_get_guint8(tvb, offset);
3146
3147         dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3148         offset++;
3149     }
3150
3151     if (pi & 0x04)
3152     {
3153         if (length <= (offset - saved_offset))
3154         {
3155             proto_tree_add_text(tree,
3156                 tvb, offset, -1,
3157                 "Short Data (?)");
3158             return;
3159         }
3160
3161         oct = tvb_get_guint8(tvb, offset);
3162         udl = oct;
3163
3164         DIS_FIELD_UDL(tree, offset);
3165         offset++;
3166     }
3167
3168     if (udl > 0)
3169     {
3170         dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3171             seven_bit, eight_bit, ucs2, compressed);
3172     }
3173 }
3174
3175 /*
3176  * Ref. GSM 03.40
3177  * Section 9.2.2
3178  */
3179 static void
3180 dis_msg_status_report(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3181 {
3182     guint32     saved_offset;
3183     guint32     length;
3184     guint8      oct;
3185     guint8      pi;
3186     guint8      udl;
3187     gboolean    seven_bit;
3188     gboolean    eight_bit;
3189     gboolean    ucs2;
3190     gboolean    compressed;
3191     gboolean    udhi; 
3192
3193
3194     udl = 0;
3195     saved_offset = offset;
3196     length = tvb_length_remaining(tvb, offset);
3197
3198     oct = tvb_get_guint8(tvb, offset);
3199     udhi = oct & 0x40;
3200
3201     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3202     proto_tree_add_item(tree, hf_gsm_sms_tp_srq, tvb, offset, 1, FALSE);
3203     proto_tree_add_item(tree, hf_gsm_sms_tp_mms, tvb, offset, 1, FALSE);
3204     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_down, tvb, offset, 1, FALSE);
3205
3206     offset++;
3207     oct = tvb_get_guint8(tvb, offset);
3208
3209     proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, FALSE);
3210
3211     offset++;
3212
3213     dis_field_addr(tvb, tree, &offset, "TP-Recipient-Address");
3214
3215     dis_field_scts(tvb, tree, &offset);
3216
3217     dis_field_dt(tvb, tree, &offset);
3218
3219     oct = tvb_get_guint8(tvb, offset);
3220
3221     dis_field_st(tvb, tree, offset, oct);
3222
3223     offset++;
3224         /* Parameter indicating the presence of any of
3225          * the optional parameters which follow
3226          * 4) Mandatory if any of the optional parameters following TP-PI is present,
3227          * otherwise optional.
3228          */
3229         if (length <= (offset - saved_offset))
3230         {
3231             return;
3232         }
3233     pi = tvb_get_guint8(tvb, offset);
3234
3235     dis_field_pi(tvb, tree, offset, pi);
3236
3237     if (pi & 0x01)
3238     {
3239         if (length <= (offset - saved_offset))
3240         {
3241             proto_tree_add_text(tree,
3242                 tvb, offset, -1,
3243                 "Short Data (?)");
3244             return;
3245         }
3246
3247         offset++;
3248         oct = tvb_get_guint8(tvb, offset);
3249
3250         dis_field_pid(tvb, tree, offset, oct);
3251     }
3252
3253     if (pi & 0x02)
3254     {
3255         if (length <= (offset - saved_offset))
3256         {
3257             proto_tree_add_text(tree,
3258                 tvb, offset, -1,
3259                 "Short Data (?)");
3260             return;
3261         }
3262
3263         offset++;
3264         oct = tvb_get_guint8(tvb, offset);
3265
3266         dis_field_dcs(tvb, tree, offset, oct, &seven_bit, &eight_bit, &ucs2, &compressed);
3267     }
3268
3269     if (pi & 0x04)
3270     {
3271         if (length <= (offset - saved_offset))
3272         {
3273             proto_tree_add_text(tree,
3274                 tvb, offset, -1,
3275                 "Short Data (?)");
3276             return;
3277         }
3278
3279         offset++;
3280         oct = tvb_get_guint8(tvb, offset);
3281         udl = oct;
3282
3283         DIS_FIELD_UDL(tree, offset);
3284     }
3285
3286     if (udl > 0)
3287     {
3288         offset++;
3289
3290         dis_field_ud(tvb, tree, offset, length - (offset - saved_offset), udhi, udl,
3291             seven_bit, eight_bit, ucs2, compressed);
3292     }
3293 }
3294
3295 /*
3296  * Ref. GSM 03.40
3297  * Section 9.2.2
3298  */
3299 static void
3300 dis_msg_command(tvbuff_t *tvb, proto_tree *tree, guint32 offset)
3301 {
3302     guint32     saved_offset;
3303     guint32     length;
3304     guint8      oct;
3305     guint8      cdl;
3306     const gchar *str = NULL;
3307     gboolean    udhi;
3308
3309
3310     cdl = 0;
3311     saved_offset = offset;
3312     length = tvb_length_remaining(tvb, offset);
3313
3314     oct = tvb_get_guint8(tvb, offset);
3315     udhi = oct & 0x40;
3316
3317     proto_tree_add_item(tree, hf_gsm_sms_tp_udhi, tvb, offset, 1, FALSE);
3318     proto_tree_add_item(tree, hf_gsm_sms_tp_srr, tvb, offset, 1, FALSE);
3319     proto_tree_add_item(tree, hf_gsm_sms_tp_mti_up, tvb, offset, 1, FALSE);
3320
3321     offset++;
3322     oct = tvb_get_guint8(tvb, offset);
3323
3324     proto_tree_add_item(tree, hf_gsm_sms_tp_mr, tvb, offset, 1, FALSE);
3325
3326     offset++;
3327     oct = tvb_get_guint8(tvb, offset);
3328
3329     dis_field_pid(tvb, tree, offset, oct);
3330
3331     offset++;
3332     oct = tvb_get_guint8(tvb, offset);
3333
3334     DIS_FIELD_CT(tree, offset);
3335
3336     offset++;
3337     oct = tvb_get_guint8(tvb, offset);
3338
3339     DIS_FIELD_MN(tree, offset);
3340
3341     offset++;
3342
3343     dis_field_addr(tvb, tree, &offset, "TP-Destination-Address");
3344
3345     oct = tvb_get_guint8(tvb, offset);
3346     cdl = oct;
3347
3348     DIS_FIELD_CDL(tree, offset);
3349
3350     if (cdl > 0)
3351     {
3352         offset++;
3353
3354         proto_tree_add_text(tree,
3355             tvb, offset, cdl,
3356             "TP-Command-Data");
3357     }
3358 }
3359
3360 #define NUM_MSGS (sizeof(msg_type_strings)/sizeof(value_string))
3361 static gint ett_msgs[NUM_MSGS];
3362 static void (*gsm_sms_msg_fcn[])(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = {
3363     dis_msg_deliver,            /* SMS-DELIVER */
3364     dis_msg_deliver_report,     /* SMS-DELIVER REPORT */
3365     dis_msg_submit,                     /* SMS-SUBMIT */
3366     dis_msg_submit_report,      /* SMS-SUBMIT REPORT */
3367     dis_msg_status_report,      /* SMS-STATUS REPORT */
3368     dis_msg_command,            /* SMS-COMMAND */
3369     NULL,                                       /* Reserved */
3370     NULL,                                       /* Reserved */
3371     NULL,                                       /* NONE */
3372 };
3373
3374 /* GENERIC DISSECTOR FUNCTIONS */
3375
3376 static void
3377 dissect_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3378 {
3379     void (*msg_fcn)(tvbuff_t *tvb, proto_tree *tree, guint32 offset) = NULL;
3380     proto_item  *gsm_sms_item;
3381     proto_tree  *gsm_sms_tree = NULL;
3382     guint32     offset;
3383     guint8      msg_type;
3384     guint8      oct;
3385     gint        idx;
3386     const gchar *str = NULL;
3387     gint        ett_msg_idx;
3388         
3389
3390     g_pinfo = pinfo;
3391         g_is_wsp = 0;
3392         g_sm_id = 0;
3393         g_frags = 0;
3394         g_frag = 0;     
3395         g_port_src = 0;
3396         g_port_dst = 0;
3397
3398     if (check_col(pinfo->cinfo, COL_PROTOCOL))
3399     {
3400         col_set_str(pinfo->cinfo, COL_PROTOCOL, gsm_sms_proto_name_short);
3401     }
3402
3403     /* In the interest of speed, if "tree" is NULL, don't do any work not
3404      * necessary to generate protocol tree items.
3405      */
3406     if (tree)
3407     {
3408         g_tree = tree;
3409
3410         offset = 0;
3411
3412         oct = tvb_get_guint8(tvb, offset);
3413
3414         oct &= 0x03;
3415         msg_type = oct;
3416
3417         /*
3418          * convert the 2 bit value to one based on direction
3419          */
3420         if (pinfo->p2p_dir == P2P_DIR_UNKNOWN)
3421         {
3422             /* Return Result ... */
3423             if (msg_type == 0) /* SMS-DELIVER */
3424             {
3425                 msg_type |= 0x04; /* see the msg_type_strings */
3426             }
3427         }
3428         else
3429         {
3430             msg_type |= ((pinfo->p2p_dir == P2P_DIR_RECV) ? 0x04 : 0x00);
3431         }
3432
3433         str = match_strval_idx(msg_type, msg_type_strings, &idx);
3434
3435         /*
3436          * create the GSM_SMS protocol tree
3437          */
3438         gsm_sms_item =
3439             proto_tree_add_protocol_format(tree, proto_gsm_sms, tvb, 0, -1,
3440                 "%s %s",
3441                 gsm_sms_proto_name,
3442                 (str == NULL) ? "Unknown message identifier" : str);
3443
3444         gsm_sms_tree =
3445             proto_item_add_subtree(gsm_sms_item, ett_gsm_sms);
3446
3447         if ((str == NULL) ||
3448             (msg_type == 0x03) ||
3449             (msg_type == 0x07))
3450         {
3451             return;
3452         }
3453         else
3454         {
3455             ett_msg_idx = ett_msgs[idx];
3456             msg_fcn = gsm_sms_msg_fcn[idx];
3457         }
3458
3459         if (msg_fcn == NULL)
3460         {
3461             proto_tree_add_text(gsm_sms_tree,
3462                 tvb, offset, -1,
3463                 "Message dissector not implemented");
3464         }
3465         else
3466         {
3467             (*msg_fcn)(tvb, gsm_sms_tree, offset);
3468         }
3469     }
3470 }
3471
3472
3473 /* Register the protocol with Wireshark */
3474 void
3475 proto_register_gsm_sms(void)
3476 {
3477     guint               i;
3478     guint               last_offset;
3479         module_t *gsm_sms_module; /* Preferences for GSM SMS UD */
3480
3481     /* Setup list of header fields */
3482     static hf_register_info hf[] =
3483     {
3484             { &hf_gsm_sms_coding_group_bits2,
3485               { "Coding Group Bits", "gsm_sms.coding_group_bits2",
3486                 FT_UINT8, BASE_DEC, VALS(gsm_sms_coding_group_bits_vals), 0xc0,
3487                 NULL, HFILL }
3488                 },
3489             { &hf_gsm_sms_coding_group_bits4,
3490               { "Coding Group Bits", "gsm_sms.coding_group_bits4",
3491                 FT_UINT8, BASE_DEC, VALS(gsm_sms_coding_group_bits_vals), 0xf0,
3492                 NULL, HFILL }
3493                 },
3494
3495                 /*
3496                  * Short Message fragment reassembly
3497                  */
3498                 {       &hf_gsm_sms_ud_fragments,
3499                         {       "Short Message fragments", "gsm-sms-ud.fragments",
3500                                 FT_NONE, BASE_NONE, NULL, 0x00,
3501                                 "GSM Short Message fragments",
3502                                 HFILL
3503                         }
3504                 },
3505                 {       &hf_gsm_sms_ud_fragment,
3506                         {       "Short Message fragment", "gsm-sms-ud.fragment",
3507                                 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3508                                 "GSM Short Message fragment",
3509                                 HFILL
3510                         }
3511                 },
3512                 {       &hf_gsm_sms_ud_fragment_overlap,
3513                         {       "Short Message fragment overlap", "gsm-sms-ud.fragment.overlap",
3514                                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3515                                 "GSM Short Message fragment overlaps with other fragment(s)",
3516                                 HFILL
3517                         }
3518                 },
3519                 {       &hf_gsm_sms_ud_fragment_overlap_conflicts,
3520                         {       "Short Message fragment overlapping with conflicting data",
3521                                 "gsm-sms-ud.fragment.overlap.conflicts",
3522                                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3523                                 "GSM Short Message fragment overlaps with conflicting data",
3524                                 HFILL
3525                         }
3526                 },
3527                 {       &hf_gsm_sms_ud_fragment_multiple_tails,
3528                         {       "Short Message has multiple tail fragments",
3529                                 "gsm-sms-ud.fragment.multiple_tails",
3530                                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3531                                 "GSM Short Message fragment has multiple tail fragments",
3532                                 HFILL
3533                         }
3534                 },
3535                 {       &hf_gsm_sms_ud_fragment_too_long_fragment,
3536                         {       "Short Message fragment too long",
3537                                 "gsm-sms-ud.fragment.too_long_fragment",
3538                                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3539                                 "GSM Short Message fragment data goes beyond the packet end",
3540                                 HFILL
3541                         }
3542                 },
3543                 {       &hf_gsm_sms_ud_fragment_error,
3544                         {       "Short Message defragmentation error", "gsm-sms-ud.fragment.error",
3545                                 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3546                                 "GSM Short Message defragmentation error due to illegal fragments",
3547                                 HFILL
3548                         }
3549                 },
3550                 {       &hf_gsm_sms_ud_reassembled_in,
3551                         {       "Reassembled in",
3552                                 "gsm-sms-ud.reassembled.in",
3553                                 FT_FRAMENUM, BASE_NONE, NULL, 0x00,
3554                                 "GSM Short Message has been reassembled in this packet.", HFILL
3555                         }
3556                 },
3557                 {   &hf_gsm_sms_ud_multiple_messages_msg_id,
3558             {   "Message identifier", "gsm-sms.udh.mm.msg_id",
3559                 FT_UINT16, BASE_DEC, NULL, 0x00,
3560                 "Identification of the message",
3561                 HFILL
3562             }
3563         },
3564         {   &hf_gsm_sms_ud_multiple_messages_msg_parts,
3565             {   "Message parts", "gsm-sms.udh.mm.msg_parts",
3566                 FT_UINT8, BASE_DEC, NULL, 0x00,
3567                 "Total number of message parts (fragments)",
3568                 HFILL
3569             }
3570         },
3571         {   &hf_gsm_sms_ud_multiple_messages_msg_part,
3572             {   "Message part number", "gsm-sms.udh.mm.msg_part",
3573                 FT_UINT8, BASE_DEC, NULL, 0x00,
3574                 "Message part (fragment) sequence number",
3575                 HFILL
3576             }
3577         },
3578         /* TPDU parameters */
3579         { &hf_gsm_sms_tp_mti_up,
3580               { "TP-MTI", "gsm_sms.tp-mti",
3581                 FT_UINT8, BASE_DEC, VALS(msg_type_strings_ms_to_sc), 0x03,
3582                 "TP-Message-Type-Indicator (in the direction MS to SC)", HFILL }
3583         },      
3584         { &hf_gsm_sms_tp_mti_down,
3585               { "TP-MTI", "gsm_sms.tp-mti",
3586                 FT_UINT8, BASE_DEC, VALS(msg_type_strings_sc_to_ms), 0x03,
3587                 "TP-Message-Type-Indicator (in the direction SC to MS)", HFILL }
3588         },      
3589         { &hf_gsm_sms_tp_oa,
3590               { "TP-OA Digits", "gsm_sms.tp-oa",
3591                 FT_STRING, BASE_NONE, NULL, 0x00,
3592                 "TP-Originating-Address Digits", HFILL }
3593         },
3594         { &hf_gsm_sms_tp_da,
3595               { "TP-DA Digits", "gsm_sms.tp-da",
3596                 FT_STRING, BASE_NONE, NULL, 0x00,
3597                 "TP-Destination-Address Digits", HFILL }
3598         },
3599         { &hf_gsm_sms_tp_ra,
3600               { "TP-RA Digits", "gsm_sms.tp-ra",
3601                 FT_STRING, BASE_NONE, NULL, 0x00,
3602                 "TP-Recipient-Address Digits", HFILL }
3603         },
3604         { &hf_gsm_sms_tp_pid,
3605               { "TP-PID", "gsm_sms.tp-pid",
3606                 FT_UINT8, BASE_DEC, NULL, 0x00,
3607                 "TP-Protocol-Identifier", HFILL }
3608         },
3609         { &hf_gsm_sms_tp_dcs,
3610               { "TP-DCS", "gsm_sms.tp-dcs",
3611                 FT_UINT8, BASE_DEC, NULL, 0x00,
3612                 "TP-Data-Coding-Scheme", HFILL }
3613         },
3614         { &hf_gsm_sms_tp_mr,
3615               { "TP-MR", "gsm_sms.tp-mr",
3616                 FT_UINT8, BASE_DEC, NULL, 0x00,
3617                 "TP-Message-Reference", HFILL }
3618         },
3619         { &hf_gsm_sms_tp_mms,
3620               { "TP-MMS", "gsm_sms.tp-mms",
3621                 FT_BOOLEAN, 8, TFS(&mms_bool_strings), 0x04,
3622                 "TP-More-Messages-to-Send", HFILL }
3623         },
3624         { &hf_gsm_sms_tp_sri,
3625               { "TP-SRI", "gsm_sms.tp-sri",
3626                 FT_BOOLEAN, 8, TFS(&sri_bool_strings), 0x20,
3627                 "TP-Status-Report-Indication", HFILL }
3628         },
3629         { &hf_gsm_sms_tp_srr,
3630               { "TP-SRR", "gsm_sms.tp-srr",
3631                 FT_BOOLEAN, 8, TFS(&srr_bool_strings), 0x20,
3632                 "TP-Status-Report-Request", HFILL }
3633         },
3634         { &hf_gsm_sms_tp_udhi,
3635               { "TP-UDHI", "gsm_sms.tp-udhi",
3636                 FT_BOOLEAN, 8, TFS(&udhi_bool_strings), 0x40,
3637                 "TP-User-Data-Header-Indicator", HFILL }
3638         },
3639         { &hf_gsm_sms_tp_rp,
3640               { "TP-RP", "gsm_sms.tp-rp",
3641                 FT_BOOLEAN, 8, TFS(&rp_bool_strings), 0x80,
3642                 "TP-Reply-Path", HFILL }
3643         },      
3644         { &hf_gsm_sms_tp_vpf,
3645               { "TP-VPF", "gsm_sms.tp-vpf",
3646                 FT_UINT8, BASE_DEC, VALS(vp_type_strings), 0x18,
3647                 "TP-Validity-Period-Format", HFILL }
3648         },      
3649         { &hf_gsm_sms_tp_rd,
3650               { "TP-RD", "gsm_sms.tp-rd",
3651                 FT_BOOLEAN, 8, TFS(&rd_bool_strings), 0x04,
3652                 "TP-Reject-Duplicates", HFILL }
3653         },      
3654         { &hf_gsm_sms_tp_srq,
3655               { "TP-SRQ", "gsm_sms.tp-srq",
3656                 FT_BOOLEAN, 8, TFS(&srq_bool_strings), 0x20,
3657                 "TP-Status-Report-Qualifier", HFILL }
3658         },      
3659     };
3660
3661     /* Setup protocol subtree array */
3662 #define NUM_INDIVIDUAL_PARMS    12
3663     gint *ett[NUM_INDIVIDUAL_PARMS+NUM_MSGS+NUM_UDH_IEIS+2];
3664
3665     ett[0] = &ett_gsm_sms;
3666     ett[1] = &ett_pid;
3667     ett[2] = &ett_pi;
3668     ett[3] = &ett_fcs;
3669     ett[4] = &ett_vp;
3670     ett[5] = &ett_scts;
3671     ett[6] = &ett_dt;
3672     ett[7] = &ett_st;
3673     ett[8] = &ett_addr;
3674     ett[9] = &ett_dcs;
3675     ett[10] = &ett_ud;
3676     ett[11] = &ett_udh;
3677
3678     last_offset = NUM_INDIVIDUAL_PARMS;
3679
3680     for (i=0; i < NUM_MSGS; i++, last_offset++)
3681     {
3682         ett_msgs[i] = -1;
3683         ett[last_offset] = &ett_msgs[i];
3684     }
3685
3686     for (i=0; i < NUM_UDH_IEIS; i++, last_offset++)
3687     {
3688         ett_udh_ieis[i] = -1;
3689         ett[last_offset] = &ett_udh_ieis[i];
3690     }
3691
3692     ett[last_offset++] = &ett_gsm_sms_ud_fragment;
3693     ett[last_offset] = &ett_gsm_sms_ud_fragments;
3694
3695     /* Register the protocol name and description */
3696
3697     proto_gsm_sms =
3698         proto_register_protocol(gsm_sms_proto_name, gsm_sms_proto_name_short, "gsm_sms");
3699
3700
3701     proto_register_field_array(proto_gsm_sms, hf, array_length(hf));
3702
3703     proto_register_subtree_array(ett, array_length(ett));
3704
3705     gsm_sms_dissector_tbl = register_dissector_table("gsm-sms.udh.port",
3706         "GSM SMS port IE in UDH", FT_UINT16, BASE_DEC);
3707
3708     gsm_sms_module = prefs_register_protocol (proto_gsm_sms, NULL);
3709     prefs_register_bool_preference (gsm_sms_module,
3710         "try_dissect_message_fragment",
3711         "Always try subdissection of the fragment of a fragmented",
3712         "Always try subdissection of 7bit, UCS2 Short Message fragment."
3713         "If checked, every msg decode will shown in its fragment",
3714         &msg_udh_frag);
3715
3716     /* register_dissector("gsm-sms", dissect_gsm_sms, proto_gsm_sms); */
3717
3718     /* GSM SMS UD dissector initialization routines */
3719     register_init_routine (gsm_sms_defragment_init);
3720 }
3721
3722
3723 void
3724 proto_reg_handoff_gsm_sms(void)
3725 {
3726     dissector_handle_t  gsm_sms_handle;
3727
3728     gsm_sms_handle = create_dissector_handle(dissect_gsm_sms, proto_gsm_sms);
3729
3730     dissector_add("gsm_a.sms_tpdu", 0, gsm_sms_handle);
3731     dissector_add("gsm_map.sms_tpdu", 0, gsm_sms_handle);
3732 }