2 * Routines for GSM SMS TPDU (GSM 03.40) dissection
4 * Copyright 2003, Michael Lum <mlum [AT] telostech.com>
5 * In association with Telos Technology Inc.
7 * TPDU User-Data unpack routines from GNOKII.
10 * Universal Mobile Telecommunications System (UMTS);
11 * Technical realization of Short Message Service (SMS)
12 * (3GPP TS 23.040 version 5.4.0 Release 5)
14 * Header field support for TPDU Parameters added by
19 * Wireshark - Network traffic analyzer
20 * By Gerald Combs <gerald@wireshark.org>
21 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
44 #include <epan/packet.h>
45 #include <epan/prefs.h>
46 #include <epan/reassemble.h>
47 #include <epan/wmem/wmem.h>
49 #include "packet-gsm_sms.h"
51 #define MAX_SMS_FRAG_LEN 134
53 /* PROTOTYPES/FORWARDS */
55 #define EXTRANEOUS_DATA_CHECK(edc_len, edc_max_len) \
56 if ((edc_len) > (edc_max_len)) \
58 proto_tree_add_text(tree, tvb, \
59 offset, (edc_len) - (edc_max_len), "Extraneous Data"); \
62 #define SHORT_DATA_CHECK(sdc_len, sdc_min_len) \
63 if ((sdc_len) < (sdc_min_len)) \
65 proto_tree_add_text(tree, tvb, \
66 offset, (sdc_len), "Short Data (?)"); \
70 #define EXACT_DATA_CHECK(edc_len, edc_eq_len) \
71 if ((edc_len) != (edc_eq_len)) \
73 proto_tree_add_text(tree, tvb, \
74 offset, (edc_len), "Unexpected Data Length"); \
78 #define SMS_SHIFTMASK(m_val, m_bitmask, m_sval); \
80 int _temp_val = m_val; \
81 int _temp_bm = m_bitmask; \
82 while (_temp_bm && !(_temp_bm & 0x01)) \
84 _temp_bm = _temp_bm >> 1; \
85 _temp_val = _temp_val >> 1; \
91 static const char *gsm_sms_proto_name
= "GSM SMS TPDU (GSM 03.40)";
92 static const char *gsm_sms_proto_name_short
= "GSM SMS";
94 /* Initialize the subtree pointers */
95 static gint ett_gsm_sms
= -1;
96 static gint ett_pid
= -1;
97 static gint ett_pi
= -1;
98 static gint ett_fcs
= -1;
99 static gint ett_vp
= -1;
100 static gint ett_scts
= -1;
101 static gint ett_dt
= -1;
102 static gint ett_st
= -1;
103 static gint ett_addr
= -1;
104 static gint ett_dcs
= -1;
105 static gint ett_ud
= -1;
106 static gint ett_udh
= -1;
108 static gint ett_udh_tfm
= -1;
109 static gint ett_udh_tfc
= -1;
111 /* Initialize the protocol and registered fields */
112 static int proto_gsm_sms
= -1;
114 static gint hf_gsm_sms_coding_group_bits2
= -1;
115 static gint hf_gsm_sms_coding_group_bits4
= -1;
116 static gint hf_gsm_sms_ud_multiple_messages_msg_id
= -1;
117 static gint hf_gsm_sms_ud_multiple_messages_msg_parts
= -1;
118 static gint hf_gsm_sms_ud_multiple_messages_msg_part
= -1;
120 /* TPDU Parameters */
121 static gint hf_gsm_sms_tp_mti_up
= -1;
122 static gint hf_gsm_sms_tp_mti_down
= -1;
123 static gint hf_gsm_sms_tp_mms
= -1;
124 static gint hf_gsm_sms_tp_vpf
= -1;
125 static gint hf_gsm_sms_tp_sri
= -1;
126 static gint hf_gsm_sms_tp_srr
= -1;
127 static gint hf_gsm_sms_tp_mr
= -1;
128 static gint hf_gsm_sms_tp_oa
= -1;
129 static gint hf_gsm_sms_tp_da
= -1;
130 static gint hf_gsm_sms_tp_pid
= -1;
131 static gint hf_gsm_sms_tp_dcs
= -1;
132 static gint hf_gsm_sms_tp_ra
= -1;
133 static gint hf_gsm_sms_tp_rp
= -1;
134 static gint hf_gsm_sms_tp_udhi
= -1;
135 static gint hf_gsm_sms_tp_rd
= -1;
136 static gint hf_gsm_sms_tp_srq
= -1;
137 static gint hf_gsm_sms_text
= -1;
138 static gint hf_gsm_sms_tp_fail_cause
= -1;
140 static gint hf_gsm_sms_tp_scts
= -1;
141 static gint hf_gsm_sms_tp_vp
= -1;
142 static gint hf_gsm_sms_tp_dt
= -1;
143 static gint hf_gsm_sms_tp_st
= -1;
144 static gint hf_gsm_sms_tp_udl
= -1;
145 static gint hf_gsm_sms_tp_mn
= -1;
146 static gint hf_gsm_sms_tp_ct
= -1;
147 static gint hf_gsm_sms_tp_cdl
= -1;
148 static gint hf_gsm_sms_tp_cd
= -1;
149 static gint hf_gsm_sms_tp_ud
= -1;
152 static gboolean reassemble_sms
= TRUE
;
153 static char bigbuf
[1024];
154 static proto_tree
*g_tree
;
156 /* 3GPP TS 23.038 version 7.0.0 Release 7
157 * The TP-Data-Coding-Scheme field, defined in 3GPP TS 23.040 [4],
158 * indicates the data coding scheme of the TP-UD field, and may indicate a message class.
159 * Any reserved codings shall be assumed to be the GSM 7 bit default alphabet
160 * (the same as codepoint 00000000) by a receiving entity.
161 * The octet is used according to a coding group which is indicated in bits 7..4.
164 /* Coding Group Bits */
165 static const value_string gsm_sms_coding_group_bits_vals
[] = {
166 { 0, "General Data Coding indication" }, /* 00xx */
167 { 1, "General Data Coding indication" }, /* 00xx */
168 { 2, "General Data Coding indication" }, /* 00xx */
169 { 3, "General Data Coding indication" }, /* 00xx */
170 { 4, "Message Marked for Automatic Deletion Group" }, /* 01xx */
171 { 5, "Message Marked for Automatic Deletion Group" }, /* 01xx */
172 { 6, "Message Marked for Automatic Deletion Group" }, /* 01xx */
173 { 7, "Message Marked for Automatic Deletion Group" }, /* 01xx */
174 { 8, "Reserved coding groups" }, /* 1000..1011 */
175 { 9, "Reserved coding groups" }, /* 1000..1011 */
176 { 10, "Reserved coding groups" }, /* 1000..1011 */
177 { 11, "Reserved coding groups" }, /* 1000..1011 */
178 { 12, "Message Waiting Indication Group: Discard Message" }, /* 1100 */
179 { 13, "Message Waiting Indication Group: Store Message" }, /* 1101 */
180 { 14, "Message Waiting Indication Group: Store Message" }, /* 1110 */
181 { 15, "Data coding/message class" }, /* 1111 */
185 static guint16 g_sm_id
;
186 static guint16 g_frags
;
187 static guint16 g_frag
;
189 static guint16 g_port_src
;
190 static guint16 g_port_dst
;
191 static gboolean g_is_wsp
;
193 static dissector_table_t gsm_sms_dissector_tbl
;
194 /* Short Message reassembly */
195 static reassembly_table g_sm_reassembly_table
;
196 static GHashTable
*g_sm_fragment_params_table
= NULL
;
197 static gint ett_gsm_sms_ud_fragment
= -1;
198 static gint ett_gsm_sms_ud_fragments
= -1;
200 * Short Message fragment handling
202 static int hf_gsm_sms_ud_fragments
= -1;
203 static int hf_gsm_sms_ud_fragment
= -1;
204 static int hf_gsm_sms_ud_fragment_overlap
= -1;
205 static int hf_gsm_sms_ud_fragment_overlap_conflicts
= -1;
206 static int hf_gsm_sms_ud_fragment_multiple_tails
= -1;
207 static int hf_gsm_sms_ud_fragment_too_long_fragment
= -1;
208 static int hf_gsm_sms_ud_fragment_error
= -1;
209 static int hf_gsm_sms_ud_fragment_count
= -1;
210 static int hf_gsm_sms_ud_reassembled_in
= -1;
211 static int hf_gsm_sms_ud_reassembled_length
= -1;
213 static const fragment_items sm_frag_items
= {
214 /* Fragment subtrees */
215 &ett_gsm_sms_ud_fragment
,
216 &ett_gsm_sms_ud_fragments
,
217 /* Fragment fields */
218 &hf_gsm_sms_ud_fragments
,
219 &hf_gsm_sms_ud_fragment
,
220 &hf_gsm_sms_ud_fragment_overlap
,
221 &hf_gsm_sms_ud_fragment_overlap_conflicts
,
222 &hf_gsm_sms_ud_fragment_multiple_tails
,
223 &hf_gsm_sms_ud_fragment_too_long_fragment
,
224 &hf_gsm_sms_ud_fragment_error
,
225 &hf_gsm_sms_ud_fragment_count
,
226 /* Reassembled in field */
227 &hf_gsm_sms_ud_reassembled_in
,
228 /* Reassembled length field */
229 &hf_gsm_sms_ud_reassembled_length
,
230 /* Reassembled data field */
233 "Short Message fragments"
240 } sm_fragment_params
;
243 gsm_sms_defragment_init (void)
245 reassembly_table_init(&g_sm_reassembly_table
,
246 &addresses_reassembly_table_functions
);
247 if (g_sm_fragment_params_table
) {
248 g_hash_table_destroy(g_sm_fragment_params_table
);
250 g_sm_fragment_params_table
= g_hash_table_new(g_direct_hash
, g_direct_equal
);
254 * this is the GSM 03.40 definition with the bit 2
255 * set to 1 for uplink messages
257 static const value_string msg_type_strings
[] = {
258 { 0, "SMS-DELIVER" },
259 { 4, "SMS-DELIVER REPORT" },
261 { 1, "SMS-SUBMIT REPORT" },
262 { 2, "SMS-STATUS REPORT" },
263 { 6, "SMS-COMMAND" },
269 static const value_string msg_type_strings_sc_to_ms
[] = {
270 { 0, "SMS-DELIVER" },
271 { 1, "SMS-SUBMIT REPORT" },
272 { 2, "SMS-STATUS REPORT" },
277 static const value_string msg_type_strings_ms_to_sc
[] = {
278 { 0, "SMS-DELIVER REPORT" },
280 { 2, "SMS-COMMAND" },
285 /* 9.2.3.3 TP-Validity-Period-Format (TP-VPF) */
286 static const value_string vp_type_strings
[] = {
287 { 0, "TP-VP field not present"},
288 { 2, "TP-VP field present - relative format"},
289 { 1, "TP-VP field present - enhanced format"},
290 { 3, "TP-VP field present - absolute format"},
294 static const true_false_string mms_bool_strings
= {
295 "No more messages are waiting for the MS in this SC",
296 "More messages are waiting for the MS in this SC"
299 static const true_false_string sri_bool_strings
= {
300 "A status report shall be returned to the SME",
301 "A status report shall not be returned to the SME"
304 static const true_false_string srr_bool_strings
= {
305 "A status report is requested",
306 "A status report is not requested"
309 static const true_false_string udhi_bool_strings
= {
310 "The beginning of the TP UD field contains a Header in addition to the short message",
311 "The TP UD field contains only the short message"
314 static const true_false_string rp_bool_strings
= {
315 "TP Reply Path parameter is set in this SMS SUBMIT/DELIVER",
316 "TP Reply Path parameter is not set in this SMS SUBMIT/DELIVER"
319 static const true_false_string rd_bool_strings
= {
320 "Instruct SC to reject duplicates",
321 "Instruct SC to accept duplicates"
324 static const true_false_string srq_bool_strings
= {
325 "The SMS STATUS REPORT is the result of an SMS COMMAND e.g. an Enquiry.",
326 "SMS STATUS REPORT is the result of a SMS SUBMIT."
329 #define NUM_UDH_IEIS 256
330 static gint ett_udh_ieis
[NUM_UDH_IEIS
];
332 #define MAX_ADDR_SIZE 20
334 dis_field_addr(tvbuff_t
*tvb
, proto_tree
*tree
, guint32
*offset_p
, const gchar
*title
)
336 static gchar digit_table
[] = {"0123456789*#abc\0"};
338 proto_tree
*subtree
= NULL
;
339 const gchar
*str
= NULL
;
343 guint32 length
, addrlength
;
345 char addrbuf
[MAX_ADDR_SIZE
+1];
350 addrlength
= tvb_get_guint8(tvb
, offset
);
351 numdigocts
= (addrlength
+ 1) / 2;
353 length
= tvb_length_remaining(tvb
, offset
);
355 if (length
<= numdigocts
)
357 proto_tree_add_text(tree
,
359 "%s: Short Data (?)",
366 item
= proto_tree_add_text(tree
, tvb
,
367 offset
, numdigocts
+ 2, "%s",
370 subtree
= proto_item_add_subtree(item
, ett_addr
);
372 proto_tree_add_text(subtree
,
374 "Length: %d address digits",
378 oct
= tvb_get_guint8(tvb
, offset
);
380 other_decode_bitfield_value(bigbuf
, oct
, 0x80, 8);
381 proto_tree_add_text(subtree
, tvb
,
385 (oct
& 0x80) ? "No extension" : "Extended");
387 switch ((oct
& 0x70) >> 4)
389 case 0x00: str
= "Unknown"; break;
390 case 0x01: str
= "International"; break;
391 case 0x02: str
= "National"; break;
392 case 0x03: str
= "Network specific"; break;
393 case 0x04: str
= "Subscriber"; break;
394 case 0x05: str
= "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)"; break;
395 case 0x06: str
= "Abbreviated number"; break;
396 case 0x07: str
= "Reserved for extension"; break;
397 default: str
= "Unknown, reserved (?)"; break;
400 other_decode_bitfield_value(bigbuf
, oct
, 0x70, 8);
401 proto_tree_add_text(subtree
,
403 "%s : Type of number: (%d) %s",
410 case 0x00: str
= "Unknown"; break;
411 case 0x01: str
= "ISDN/telephone (E.164/E.163)"; break;
412 case 0x03: str
= "Data numbering plan (X.121)"; break;
413 case 0x04: str
= "Telex numbering plan"; break;
414 case 0x05: str
= "Service Centre Specific plan"; break;
415 case 0x06: str
= "Service Centre Specific plan"; break;
416 case 0x08: str
= "National numbering plan"; break;
417 case 0x09: str
= "Private numbering plan"; break;
418 case 0x0a: str
= "ERMES numbering plan (ETSI DE/PS 3 01-3)"; break;
419 case 0x0f: str
= "Reserved for extension"; break;
420 default: str
= "Unknown, reserved (?)"; break;
423 other_decode_bitfield_value(bigbuf
, oct
, 0x0f, 8);
424 proto_tree_add_text(subtree
,
426 "%s : Numbering plan: (%d) %s",
434 switch ((oct
& 0x70) >> 4)
436 case 0x05: /* "Alphanumeric (coded according to 3GPP TS 23.038 GSM 7-bit default alphabet)" */
437 addrlength
= (addrlength
<< 2) / 7;
438 i
= gsm_sms_char_7bit_unpack(0, numdigocts
, ((addrlength
> MAX_ADDR_SIZE
) ? MAX_ADDR_SIZE
: addrlength
),
439 tvb_get_ptr(tvb
, offset
, numdigocts
), addrbuf
);
441 addrstr
= gsm_sms_chars_to_utf8(addrbuf
, i
);
444 addrstr
= (gchar
*)wmem_alloc(wmem_packet_scope(), numdigocts
*2 + 1);
445 for (i
= 0; i
< numdigocts
; i
++)
447 oct
= tvb_get_guint8(tvb
, offset
+ i
);
449 addrstr
[j
++] = digit_table
[oct
& 0x0f];
450 addrstr
[j
++] = digit_table
[(oct
& 0xf0) >> 4];
456 if (g_ascii_strncasecmp(title
, "TP-O", 4) == 0) {
457 proto_tree_add_string(subtree
, hf_gsm_sms_tp_oa
, tvb
,
458 offset
, numdigocts
, addrstr
);
459 } else if (g_ascii_strncasecmp(title
, "TP-D", 4) == 0) {
460 proto_tree_add_string(subtree
, hf_gsm_sms_tp_da
, tvb
,
461 offset
, numdigocts
, addrstr
);
462 } else if (g_ascii_strncasecmp(title
, "TP-R", 4) == 0) {
463 proto_tree_add_string(subtree
, hf_gsm_sms_tp_ra
, tvb
,
464 offset
, numdigocts
, addrstr
);
466 proto_tree_add_text(subtree
, tvb
,
467 offset
, numdigocts
, "Digits: %s", addrstr
);
470 proto_item_append_text(item
, " - (%s)", addrstr
);
472 *offset_p
= offset
+ numdigocts
;
476 /* use dis_field_addr() */
479 /* use dis_field_addr() */
483 dis_field_pid(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 oct
)
486 proto_tree
*subtree
= NULL
;
489 const gchar
*str
= NULL
;
492 item
= proto_tree_add_item(tree
, hf_gsm_sms_tp_pid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
494 subtree
= proto_item_add_subtree(item
, ett_pid
);
496 form
= (oct
& 0xc0) >> 6;
501 other_decode_bitfield_value(bigbuf
, oct
, 0xc0, 8);
502 proto_tree_add_text(subtree
, tvb
,
504 "%s : defines formatting for subsequent bits",
507 other_decode_bitfield_value(bigbuf
, oct
, 0x20, 8);
508 proto_tree_add_text(subtree
, tvb
,
513 "telematic interworking" :
514 "no telematic interworking, but SME-to-SME protocol");
518 telematic
= oct
& 0x1f;
522 case 0x00: str
= "implicit - device type is specific to this SC, or can be concluded on the basis of the address"; break;
523 case 0x01: str
= "telex (or teletex reduced to telex format)"; break;
524 case 0x02: str
= "group 3 telefax"; break;
525 case 0x03: str
= "group 4 telefax"; break;
526 case 0x04: str
= "voice telephone (i.e. conversion to speech)"; break;
527 case 0x05: str
= "ERMES (European Radio Messaging System)"; break;
528 case 0x06: str
= "National Paging system (known to the SC)"; break;
529 case 0x07: str
= "Videotex (T.100 [20] /T.101 [21])"; break;
530 case 0x08: str
= "teletex, carrier unspecified"; break;
531 case 0x09: str
= "teletex, in PSPDN"; break;
532 case 0x0a: str
= "teletex, in CSPDN"; break;
533 case 0x0b: str
= "teletex, in analog PSTN"; break;
534 case 0x0c: str
= "teletex, in digital ISDN"; break;
535 case 0x0d: str
= "UCI (Universal Computer Interface, ETSI DE/PS 3 01-3)"; break;
536 case 0x10: str
= "a message handling facility (known to the SC)"; break;
537 case 0x11: str
= "any public X.400-based message handling system"; break;
538 case 0x12: str
= "Internet Electronic Mail"; break;
539 case 0x1f: str
= "A GSM/UMTS mobile station"; break;
541 if ((telematic
>= 0x18) &&
544 str
= "values specific to each SC";
553 other_decode_bitfield_value(bigbuf
, oct
, 0x1f, 8);
554 proto_tree_add_text(subtree
, tvb
,
556 "%s : device type: (%d) %s",
563 other_decode_bitfield_value(bigbuf
, oct
, 0x1f, 8);
564 proto_tree_add_text(subtree
, tvb
,
566 "%s : the SM-AL protocol being used between the SME and the MS (%d)",
573 other_decode_bitfield_value(bigbuf
, oct
, 0xc0, 8);
574 proto_tree_add_text(subtree
, tvb
,
576 "%s : defines formatting for subsequent bits",
581 case 0x00: str
= "Short Message Type 0"; break;
582 case 0x01: str
= "Replace Short Message Type 1"; break;
583 case 0x02: str
= "Replace Short Message Type 2"; break;
584 case 0x03: str
= "Replace Short Message Type 3"; break;
585 case 0x04: str
= "Replace Short Message Type 4"; break;
586 case 0x05: str
= "Replace Short Message Type 5"; break;
587 case 0x06: str
= "Replace Short Message Type 6"; break;
588 case 0x07: str
= "Replace Short Message Type 7"; break;
589 case 0x1e: str
= "Enhanced Message Service (Obsolete)"; break;
590 case 0x1f: str
= "Return Call Message"; break;
591 case 0x3c: str
= "ANSI-136 R-DATA"; break;
592 case 0x3d: str
= "ME Data download"; break;
593 case 0x3e: str
= "ME De-personalization Short Message"; break;
594 case 0x3f: str
= "(U)SIM Data download"; break;
596 str
= "Reserved"; break;
599 other_decode_bitfield_value(bigbuf
, oct
, 0x3f, 8);
600 proto_tree_add_text(subtree
, tvb
,
609 other_decode_bitfield_value(bigbuf
, oct
, 0xc0, 8);
610 proto_tree_add_text(subtree
, tvb
,
615 other_decode_bitfield_value(bigbuf
, oct
, 0x3f, 8);
616 proto_tree_add_text(subtree
, tvb
,
623 other_decode_bitfield_value(bigbuf
, oct
, 0xc0, 8);
624 proto_tree_add_text(subtree
, tvb
,
626 "%s : bits 0-5 for SC specific use",
629 other_decode_bitfield_value(bigbuf
, oct
, 0x3f, 8);
630 proto_tree_add_text(subtree
, tvb
,
640 dis_field_dcs(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 oct
,
641 gboolean
*seven_bit
, gboolean
*eight_bit
, gboolean
*ucs2
, gboolean
*compressed
)
644 proto_tree
*subtree
= NULL
;
646 const gchar
*str
= NULL
;
647 gboolean default_5_bits
;
648 gboolean default_3_bits
;
649 gboolean default_data
;
657 item
= proto_tree_add_item(tree
, hf_gsm_sms_tp_dcs
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
659 subtree
= proto_item_add_subtree(item
, ett_dcs
);
661 proto_tree_add_item(subtree
, hf_gsm_sms_coding_group_bits4
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
663 proto_tree_add_item(subtree
, hf_gsm_sms_coding_group_bits2
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
668 proto_tree_add_text(subtree
, tvb
,
670 "Special case, GSM 7 bit default alphabet");
676 default_5_bits
= FALSE
;
677 default_3_bits
= FALSE
;
678 default_data
= FALSE
;
679 form
= (oct
& 0xc0) >> 6;
684 other_decode_bitfield_value(bigbuf
, oct
, 0xc0, 8);
685 proto_tree_add_text(subtree
, tvb
,
687 "%s : General Data Coding indication",
690 default_5_bits
= TRUE
;
694 other_decode_bitfield_value(bigbuf
, oct
, 0xc0, 8);
695 proto_tree_add_text(subtree
, tvb
,
697 "%s : Message Marked for Automatic Deletion Group",
700 default_5_bits
= TRUE
;
704 /* use top four bits */
705 other_decode_bitfield_value(bigbuf
, oct
, 0xf0, 8);
706 proto_tree_add_text(subtree
, tvb
,
708 "%s : Reserved coding groups",
713 switch ((oct
& 0x30) >> 4)
715 case 0x00: str
= "Message Waiting Indication Group: Discard Message (GSM 7 bit default alphabet)";
716 default_3_bits
= TRUE
;
719 case 0x01: str
= "Message Waiting Indication Group: Store Message (GSM 7 bit default alphabet)";
720 default_3_bits
= TRUE
;
723 case 0x02: str
= "Message Waiting Indication Group: Store Message (uncompressed UCS2 alphabet)";
724 default_3_bits
= TRUE
;
726 case 0x03: str
= "Data coding/message class";
731 /* use top four bits */
732 other_decode_bitfield_value(bigbuf
, oct
, 0xf0, 8);
733 proto_tree_add_text(subtree
, tvb
,
743 other_decode_bitfield_value(bigbuf
, oct
, 0x20, 8);
744 proto_tree_add_text(subtree
, tvb
,
746 "%s : Text is %scompressed",
748 (oct
& 0x20) ? "" : "not ");
750 *compressed
= (oct
& 0x20) >> 5;
752 other_decode_bitfield_value(bigbuf
, oct
, 0x10, 8);
753 proto_tree_add_text(subtree
, tvb
,
757 (oct
& 0x10) ? "Message class is defined below" :
758 "Reserved, no message class");
760 switch ((oct
& 0x0c) >> 2)
762 case 0x00: str
= "GSM 7 bit default alphabet";
765 case 0x01: str
= "8 bit data";
768 case 0x02: str
= "UCS2 (16 bit)";
771 case 0x03: str
= "Reserved"; break;
774 other_decode_bitfield_value(bigbuf
, oct
, 0x0c, 8);
775 proto_tree_add_text(subtree
, tvb
,
777 "%s : Character set: %s",
783 case 0x00: str
= "Class 0"; break;
784 case 0x01: str
= "Class 1 Default meaning: ME-specific"; break;
785 case 0x02: str
= "Class 2 (U)SIM specific message"; break;
786 case 0x03: str
= "Class 3 Default meaning: TE-specific"; break;
789 other_decode_bitfield_value(bigbuf
, oct
, 0x03, 8);
790 proto_tree_add_text(subtree
, tvb
,
792 "%s : Message Class: %s%s",
795 (oct
& 0x10) ? "" : " (reserved)");
797 else if (default_3_bits
)
799 other_decode_bitfield_value(bigbuf
, oct
, 0x08, 8);
800 proto_tree_add_text(subtree
, tvb
,
802 "%s : Indication Sense: %s",
804 (oct
& 0x08) ? "Set Indication Active" : "Set Indication Inactive");
806 other_decode_bitfield_value(bigbuf
, oct
, 0x04, 8);
807 proto_tree_add_text(subtree
, tvb
,
814 case 0x00: str
= "Voicemail Message Waiting"; break;
815 case 0x01: str
= "Fax Message Waiting"; break;
816 case 0x02: str
= "Electronic Mail Message Waiting"; break;
817 case 0x03: str
= "Other Message Waiting"; break;
820 other_decode_bitfield_value(bigbuf
, oct
, 0x03, 8);
821 proto_tree_add_text(subtree
, tvb
,
827 else if (default_data
)
829 other_decode_bitfield_value(bigbuf
, oct
, 0x08, 8);
830 proto_tree_add_text(subtree
, tvb
,
835 *seven_bit
= !(*eight_bit
= (oct
& 0x04) ? TRUE
: FALSE
);
837 other_decode_bitfield_value(bigbuf
, oct
, 0x04, 8);
838 proto_tree_add_text(subtree
, tvb
,
840 "%s : Message coding: %s",
842 (*eight_bit
) ? "8 bit data" : "GSM 7 bit default alphabet");
846 case 0x00: str
= "Class 0"; break;
847 case 0x01: str
= "Class 1 Default meaning: ME-specific"; break;
848 case 0x02: str
= "Class 2 (U)SIM specific message"; break;
849 case 0x03: str
= "Class 3 Default meaning: TE-specific"; break;
852 other_decode_bitfield_value(bigbuf
, oct
, 0x03, 8);
853 proto_tree_add_text(subtree
, tvb
,
855 "%s : Message Class: %s",
862 dis_field_scts_aux(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
)
864 guint8 oct
, oct2
, oct3
;
868 oct
= tvb_get_guint8(tvb
, offset
);
869 oct2
= tvb_get_guint8(tvb
, offset
+1);
870 oct3
= tvb_get_guint8(tvb
, offset
+2);
872 proto_tree_add_text(tree
,
874 "Year %d%d, Month %d%d, Day %d%d",
884 oct
= tvb_get_guint8(tvb
, offset
);
885 oct2
= tvb_get_guint8(tvb
, offset
+1);
886 oct3
= tvb_get_guint8(tvb
, offset
+2);
888 proto_tree_add_text(tree
,
890 "Hour %d%d, Minutes %d%d, Seconds %d%d",
900 oct
= tvb_get_guint8(tvb
, offset
);
902 sign
= (oct
& 0x08)?'-':'+';
903 oct
= (oct
>> 4) + (oct
& 0x07) * 10;
905 proto_tree_add_text(tree
,
907 "Timezone: GMT %c %d hours %d minutes",
908 sign
, oct
/ 4, oct
% 4 * 15);
913 dis_field_scts(tvbuff_t
*tvb
, proto_tree
*tree
, guint32
*offset_p
)
916 proto_tree
*subtree
= NULL
;
923 length
= tvb_length_remaining(tvb
, offset
);
927 proto_tree_add_text(tree
,
929 "TP-Service-Centre-Time-Stamp: Short Data (?)");
936 proto_tree_add_text(tree
, tvb
,
938 "TP-Service-Centre-Time-Stamp");
940 subtree
= proto_item_add_subtree(item
, ett_scts
);
942 dis_field_scts_aux(tvb
, subtree
, *offset_p
);
949 dis_field_vp(tvbuff_t
*tvb
, proto_tree
*tree
, guint32
*offset_p
, guint8 vp_form
)
952 proto_tree
*subtree
= NULL
;
955 guint8 oct
, oct2
, oct3
;
961 if (vp_form
== 0x00) return;
972 length
= tvb_length_remaining(tvb
, offset
);
976 proto_tree_add_text(tree
,
978 "TP-Validity-Period: Short Data (?)");
985 proto_tree_add_text(tree
, tvb
,
987 "TP-Validity-Period");
989 subtree
= proto_item_add_subtree(item
, ett_vp
);
991 oct
= tvb_get_guint8(tvb
, offset
);
993 other_decode_bitfield_value(bigbuf
, oct
, 0x80, 8);
994 proto_tree_add_text(subtree
, tvb
,
998 (oct
& 0x80) ? "Extended" : "No extension");
1002 proto_tree_add_text(subtree
,
1004 "Extension not implemented, ignored");
1010 other_decode_bitfield_value(bigbuf
, oct
, 0x40, 8);
1011 proto_tree_add_text(subtree
, tvb
,
1015 (oct
& 0x40) ? "Single shot SM" : "Not single shot SM");
1017 other_decode_bitfield_value(bigbuf
, oct
, 0x38, 8);
1018 proto_tree_add_text(subtree
, tvb
,
1023 loc_form
= oct
& 0x7;
1028 other_decode_bitfield_value(bigbuf
, oct
, 0x07, 8);
1029 proto_tree_add_text(subtree
, tvb
,
1031 "%s : No Validity Period specified",
1038 other_decode_bitfield_value(bigbuf
, oct
, 0x07, 8);
1039 proto_tree_add_text(subtree
, tvb
,
1041 "%s : Validity Period Format: relative",
1045 /* go around again */
1050 other_decode_bitfield_value(bigbuf
, oct
, 0x07, 8);
1051 proto_tree_add_text(subtree
, tvb
,
1053 "%s : Validity Period Format: relative",
1057 oct
= tvb_get_guint8(tvb
, offset
);
1059 proto_tree_add_text(subtree
, tvb
,
1068 other_decode_bitfield_value(bigbuf
, oct
, 0x07, 8);
1069 proto_tree_add_text(subtree
, tvb
,
1071 "%s : Validity Period Format: relative",
1075 oct
= tvb_get_guint8(tvb
, offset
);
1076 oct2
= tvb_get_guint8(tvb
, offset
+1);
1077 oct3
= tvb_get_guint8(tvb
, offset
+2);
1079 proto_tree_add_text(subtree
,
1081 "Hour %d%d, Minutes %d%d, Seconds %d%d",
1087 (oct3
& 0xf0) >> 4);
1093 other_decode_bitfield_value(bigbuf
, oct
, 0x07, 8);
1094 proto_tree_add_text(subtree
, tvb
,
1096 "%s : Validity Period Format: Reserved",
1105 oct
= tvb_get_guint8(tvb
, offset
);
1109 mins
= (oct
+ 1) * 5;
1115 proto_tree_add_text(subtree
, tvb
,
1117 "TP-Validity-Period: %d hours %d minutes",
1123 proto_tree_add_text(subtree
, tvb
,
1125 "TP-Validity-Period: %d minutes",
1129 else if ((oct
>= 144) &&
1132 mins
= (oct
- 143) * 30;
1133 hours
= 12 + (mins
/ 60);
1136 proto_tree_add_text(subtree
, tvb
,
1138 "TP-Validity-Period: %d hours %d minutes",
1142 else if ((oct
>= 168) &&
1145 proto_tree_add_text(subtree
, tvb
,
1147 "TP-Validity-Period: %d day(s)",
1150 else if (oct
>= 197)
1152 proto_tree_add_text(subtree
, tvb
,
1154 "TP-Validity-Period: %d week(s)",
1162 length
= tvb_length_remaining(tvb
, offset
);
1166 proto_tree_add_text(tree
,
1167 tvb
, offset
, length
,
1168 "TP-Validity-Period: Short Data (?)");
1170 *offset_p
+= length
;
1175 proto_tree_add_text(tree
, tvb
,
1177 "TP-Validity-Period: absolute");
1179 subtree
= proto_item_add_subtree(item
, ett_vp
);
1181 dis_field_scts_aux(tvb
, subtree
, *offset_p
);
1201 dis_field_dt(tvbuff_t
*tvb
, proto_tree
*tree
, guint32
*offset_p
)
1204 proto_tree
*subtree
= NULL
;
1211 length
= tvb_length_remaining(tvb
, offset
);
1215 proto_tree_add_text(tree
,
1216 tvb
, offset
, length
,
1217 "TP-Discharge-Time: Short Data (?)");
1219 *offset_p
+= length
;
1224 proto_tree_add_text(tree
, tvb
,
1226 "TP-Discharge-Time");
1228 subtree
= proto_item_add_subtree(item
, ett_dt
);
1230 dis_field_scts_aux(tvb
, subtree
, *offset_p
);
1236 /* use dis_field_addr() */
1240 dis_field_st(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 oct
)
1242 static const gchar
*sc_complete
= "Short message transaction completed";
1243 static const gchar
*sc_temporary
= "Temporary error, SC still trying to transfer SM";
1244 static const gchar
*sc_perm
= "Permanent error, SC is not making any more transfer attempts";
1245 static const gchar
*sc_tempfin
= "Temporary error, SC is not making any more transfer attempts";
1247 proto_tree
*subtree
= NULL
;
1249 const gchar
*str
= NULL
;
1250 const gchar
*str2
= NULL
;
1254 proto_tree_add_text(tree
, tvb
,
1258 subtree
= proto_item_add_subtree(item
, ett_st
);
1260 other_decode_bitfield_value(bigbuf
, oct
, 0x80, 8);
1261 proto_tree_add_text(subtree
, tvb
,
1263 "%s : Definition of bits 0-6: %s",
1265 (oct
& 0x80) ? "Reserved" : "as follows");
1271 case 0x00: str2
= sc_complete
; str
= "Short message received by the SME"; break;
1272 case 0x01: str2
= sc_complete
; str
= "Short message forwarded by the SC to the SME but the SC is unable to confirm delivery"; break;
1273 case 0x02: str2
= sc_complete
; str
= "Short message replaced by the SC Reserved values"; break;
1275 case 0x20: str2
= sc_temporary
; str
= "Congestion"; break;
1276 case 0x21: str2
= sc_temporary
; str
= "SME busy"; break;
1277 case 0x22: str2
= sc_temporary
; str
= "No response from SME"; break;
1278 case 0x23: str2
= sc_temporary
; str
= "Service rejected"; break;
1279 case 0x24: str2
= sc_temporary
; str
= "Quality of service not available"; break;
1280 case 0x25: str2
= sc_temporary
; str
= "Error in SME"; break;
1282 case 0x40: str2
= sc_perm
; str
= "Remote procedure error"; break;
1283 case 0x41: str2
= sc_perm
; str
= "Incompatible destination"; break;
1284 case 0x42: str2
= sc_perm
; str
= "Connection rejected by SME"; break;
1285 case 0x43: str2
= sc_perm
; str
= "Not obtainable"; break;
1286 case 0x44: str2
= sc_perm
; str
= "Quality of service not available"; break;
1287 case 0x45: str2
= sc_perm
; str
= "No interworking available"; break;
1288 case 0x46: str2
= sc_perm
; str
= "SM Validity Period Expired"; break;
1289 case 0x47: str2
= sc_perm
; str
= "SM Deleted by originating SME"; break;
1290 case 0x48: str2
= sc_perm
; str
= "SM Deleted by SC Administration"; break;
1291 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;
1293 case 0x60: str2
= sc_tempfin
; str
= "Congestion"; break;
1294 case 0x61: str2
= sc_tempfin
; str
= "SME busy"; break;
1295 case 0x62: str2
= sc_tempfin
; str
= "No response from SME"; break;
1296 case 0x63: str2
= sc_tempfin
; str
= "Service rejected"; break;
1297 case 0x64: str2
= sc_tempfin
; str
= "Quality of service not available"; break;
1298 case 0x65: str2
= sc_tempfin
; str
= "Error in SME"; break;
1301 if ((value
>= 0x03) &&
1307 else if ((value
>= 0x10) &&
1311 str
= "Values specific to each SC";
1313 else if ((value
>= 0x26) &&
1316 str2
= sc_temporary
;
1319 else if ((value
>= 0x30) &&
1322 str2
= sc_temporary
;
1323 str
= "Values specific to each SC";
1325 else if ((value
>= 0x4a) &&
1331 else if ((value
>= 0x50) &&
1335 str
= "Values specific to each SC";
1337 else if ((value
>= 0x66) &&
1343 else if ((value
>= 0x70) &&
1347 str
= "Values specific to each SC";
1352 other_decode_bitfield_value(bigbuf
, oct
, 0x7f, 8);
1353 proto_tree_add_text(subtree
, tvb
,
1363 #define DIS_FIELD_UDL(m_tree, m_offset) \
1365 proto_tree_add_text(m_tree, tvb, \
1367 "TP-User-Data-Length: (%d) %s", \
1369 oct ? "depends on Data-Coding-Scheme" : "no User-Data");\
1373 #define DIS_FIELD_RP(m_tree, m_bitmask, m_offset) \
1375 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1376 proto_tree_add_text(m_tree, tvb, \
1378 "%s : TP-Reply-Path: parameter is %sset in this SMS-SUBMIT/DELIVER", \
1380 (oct & m_bitmask) ? "" : "not "); \
1384 #define DIS_FIELD_MN(m_tree, m_offset) \
1386 proto_tree_add_text(m_tree, tvb, \
1388 "TP-Message-Number: %d", \
1393 #define DIS_FIELD_CT(m_tree, m_offset) \
1397 case 0: str = "Enquiry relating to previously submitted short message"; break; \
1398 case 1: str = "Cancel Status Report Request relating to previously submitted short message"; break; \
1399 case 2: str = "Delete previously submitted Short Message"; break; \
1400 case 3: str = "Enable Status Report Request relating to previously submitted short message"; break; \
1402 if ((oct >= 0x04) && \
1405 str = "Reserved unspecified"; \
1407 else if (oct >= 0xe0) \
1409 str = "Values specific for each SC"; \
1413 str = "undefined"; \
1417 proto_tree_add_text(m_tree, tvb, \
1419 "TP-Command-Type: (%d), %s", \
1425 #define DIS_FIELD_CDL(m_tree, m_offset) \
1427 proto_tree_add_text(m_tree, tvb, \
1429 "TP-Command-Data-Length: (%d)%s", \
1431 oct ? "" : " no Command-Data");\
1435 /* done in-line in the message functions */
1438 * 9.2.3.22 TP-Failure-Cause (TP-FCS)
1442 static const value_string gsm_sms_tp_failure_cause_values
[] = {
1443 /* 00 - 7F Reserved */
1444 /* 80 - 8F TP-PID errors */
1445 { 0x80, "Telematic interworking not supported" },
1446 { 0x81, "Short message Type 0 not supported" },
1447 { 0x82, "Cannot replace short message" },
1448 /* 83 - 8E Reserved */
1449 { 0x83, "Reserved" },
1450 { 0x84, "Reserved" },
1451 { 0x85, "Reserved" },
1452 { 0x86, "Reserved" },
1453 { 0x87, "Reserved" },
1454 { 0x88, "Reserved" },
1455 { 0x89, "Reserved" },
1456 { 0x8a, "Reserved" },
1457 { 0x8b, "Reserved" },
1458 { 0x8c, "Reserved" },
1459 { 0x8d, "Reserved" },
1460 { 0x8e, "Reserved" },
1462 { 0x8F, "Unspecified TP-PID error" },
1463 /* 90 - 9F TP-DCS errors */
1464 { 0x90, "Data coding scheme (alphabet) not supported" },
1465 { 0x91, "Message class not supported" },
1466 /* 92 - 9E Reserved */
1467 { 0x92, "Reserved" },
1468 { 0x93, "Reserved" },
1469 { 0x94, "Reserved" },
1470 { 0x95, "Reserved" },
1471 { 0x96, "Reserved" },
1472 { 0x97, "Reserved" },
1473 { 0x98, "Reserved" },
1474 { 0x99, "Reserved" },
1475 { 0x9a, "Reserved" },
1476 { 0x9b, "Reserved" },
1477 { 0x9c, "Reserved" },
1478 { 0x9d, "Reserved" },
1479 { 0x9e, "Reserved" },
1481 { 0x9F, "Unspecified TP-DCS error" },
1482 /* A0 - AF TP-Command Errors */
1483 { 0xA0, "Command cannot be actioned" },
1484 { 0xA1, "Command unsupported" },
1485 /* A2 - AE Reserved */
1486 { 0xa2, "Reserved" },
1487 { 0xa3, "Reserved" },
1488 { 0xa4, "Reserved" },
1489 { 0xa5, "Reserved" },
1490 { 0xa6, "Reserved" },
1491 { 0xa7, "Reserved" },
1492 { 0xa8, "Reserved" },
1493 { 0xa9, "Reserved" },
1494 { 0xaa, "Reserved" },
1495 { 0xab, "Reserved" },
1496 { 0xac, "Reserved" },
1497 { 0xad, "Reserved" },
1498 { 0xae, "Reserved" },
1500 { 0xAF, "Unspecified TP-Command error" },
1501 { 0xB0, "TPDU not supported" },
1502 /* B1 - BF Reserved */
1503 { 0xb1, "Reserved" },
1504 { 0xb2, "Reserved" },
1505 { 0xb3, "Reserved" },
1506 { 0xb4, "Reserved" },
1507 { 0xb5, "Reserved" },
1508 { 0xb6, "Reserved" },
1509 { 0xb7, "Reserved" },
1510 { 0xb8, "Reserved" },
1511 { 0xb9, "Reserved" },
1512 { 0xba, "Reserved" },
1513 { 0xbb, "Reserved" },
1514 { 0xbc, "Reserved" },
1515 { 0xbd, "Reserved" },
1516 { 0xbe, "Reserved" },
1517 { 0xbf, "Reserved" },
1519 { 0xC0, "SC busy" },
1520 { 0xC1, "No SC subscription" },
1521 { 0xC2, "SC system failure" },
1522 { 0xC3, "Invalid SME address" },
1523 { 0xC4, "Destination SME barred" },
1524 { 0xC5, "SM Rejected-Duplicate SM" },
1525 { 0xC6, "TP-VPF not supported" },
1526 { 0xC7, "TP-VP not supported" },
1527 /* C8 - CF Reserved */
1528 { 0xc8, "Reserved" },
1529 { 0xc9, "Reserved" },
1530 { 0xca, "Reserved" },
1531 { 0xcb, "Reserved" },
1532 { 0xcc, "Reserved" },
1533 { 0xcd, "Reserved" },
1534 { 0xce, "Reserved" },
1535 { 0xcf, "Reserved" },
1537 { 0xD0, "(U)SIM SMS storage full" },
1538 { 0xD1, "No SMS storage capability in (U)SIM" },
1539 { 0xD2, "Error in MS" },
1540 { 0xD3, "Memory Capacity Exceeded" },
1541 { 0xD4, "(U)SIM Application Toolkit Busy" },
1542 { 0xD5, "(U)SIM data download error" },
1543 /* D6 - DF Reserved */
1544 { 0xd6, "Reserved" },
1545 { 0xd7, "Reserved" },
1546 { 0xd8, "Reserved" },
1547 { 0xd9, "Reserved" },
1548 { 0xda, "Reserved" },
1549 { 0xdb, "Reserved" },
1550 { 0xdc, "Reserved" },
1551 { 0xdd, "Reserved" },
1552 { 0xde, "Reserved" },
1553 { 0xdf, "Reserved" },
1555 /* E0 - FE Values specific to an application */
1556 { 0xe0, "Value specific to an application" },
1557 { 0xe1, "Value specific to an application" },
1558 { 0xe2, "Value specific to an application" },
1559 { 0xe3, "Value specific to an application" },
1560 { 0xe4, "Value specific to an application" },
1561 { 0xe5, "Value specific to an application" },
1562 { 0xe6, "Value specific to an application" },
1563 { 0xe7, "Value specific to an application" },
1564 { 0xe8, "Value specific to an application" },
1565 { 0xe9, "Value specific to an application" },
1566 { 0xea, "Value specific to an application" },
1567 { 0xeb, "Value specific to an application" },
1568 { 0xec, "Value specific to an application" },
1569 { 0xed, "Value specific to an application" },
1570 { 0xee, "Value specific to an application" },
1571 { 0xef, "Value specific to an application" },
1572 { 0xf0, "Value specific to an application" },
1573 { 0xf1, "Value specific to an application" },
1574 { 0xf2, "Value specific to an application" },
1575 { 0xf3, "Value specific to an application" },
1576 { 0xf4, "Value specific to an application" },
1577 { 0xf5, "Value specific to an application" },
1578 { 0xf6, "Value specific to an application" },
1579 { 0xf7, "Value specific to an application" },
1580 { 0xf8, "Value specific to an application" },
1581 { 0xf9, "Value specific to an application" },
1582 { 0xfa, "Value specific to an application" },
1583 { 0xfb, "Value specific to an application" },
1584 { 0xfc, "Value specific to an application" },
1585 { 0xfd, "Value specific to an application" },
1586 { 0xfe, "Value specific to an application" },
1588 { 0xFF, "Unspecified error cause" },
1591 static value_string_ext gsm_sms_tp_failure_cause_values_ext
= VALUE_STRING_EXT_INIT(gsm_sms_tp_failure_cause_values
);
1594 dis_field_fcs(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 oct _U_
)
1596 proto_tree_add_item(tree
, hf_gsm_sms_tp_fail_cause
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
1600 #define DIS_FIELD_UDHI(m_tree, m_bitmask, m_offset, m_udhi) \
1602 SMS_SHIFTMASK(oct & m_bitmask, m_bitmask, m_udhi); \
1603 other_decode_bitfield_value(bigbuf, oct, m_bitmask, 8); \
1604 proto_tree_add_text(m_tree, tvb, \
1606 "%s : TP-User-Data-Header-Indicator: %s short message", \
1609 "The beginning of the TP-UD field contains a Header in addition to the" : \
1610 "The TP-UD field contains only the"); \
1618 #define GN_BYTE_MASK ((1 << bits) - 1)
1621 gsm_sms_char_7bit_unpack(unsigned int offset
, unsigned int in_length
, unsigned int out_length
,
1622 const guint8
*input
, unsigned char *output
)
1624 unsigned char *out_num
= output
; /* Current pointer to the output buffer */
1625 const guint8
*in_num
= input
; /* Current pointer to the input buffer */
1626 unsigned char rest
= 0x00;
1629 bits
= offset
? offset
: 7;
1631 while ((unsigned int)(in_num
- input
) < in_length
)
1633 *out_num
= ((*in_num
& GN_BYTE_MASK
) << (7 - bits
)) | rest
;
1634 rest
= *in_num
>> bits
;
1636 /* If we don't start from 0th bit, we shouldn't go to the
1637 next char. Under *out_num we have now 0 and under Rest -
1638 _first_ part of the char. */
1639 if ((in_num
!= input
) || (bits
== 7)) out_num
++;
1642 if ((unsigned int)(out_num
- output
) >= out_length
) break;
1644 /* After reading 7 octets we have read 7 full characters but
1645 we have 7 bits as well. This is the next character */
1659 return (int)(out_num
- output
);
1662 #define GN_CHAR_ALPHABET_SIZE 128
1664 #define GN_CHAR_ESCAPE 0x1b
1666 static gunichar gsm_default_alphabet
[GN_CHAR_ALPHABET_SIZE
] = {
1668 /* ETSI GSM 03.38, version 6.0.1, section 6.2.1; Default alphabet */
1669 /* Fixed to use unicode */
1670 /* Characters in hex position 10, [12 to 1a] and 24 are not present on
1671 latin1 charset, so we cannot reproduce on the screen, however they are
1672 greek symbol not present even on my Nokia */
1674 '@', 0xa3, '$', 0xa5, 0xe8, 0xe9, 0xf9, 0xec,
1675 0xf2, 0xc7, '\n', 0xd8, 0xf8, '\r', 0xc5, 0xe5,
1676 0x394, '_', 0x3a6, 0x393, 0x39b, 0x3a9, 0x3a0, 0x3a8,
1677 0x3a3, 0x398, 0x39e, 0xa0, 0xc6, 0xe6, 0xdf, 0xc9,
1678 ' ', '!', '\"', '#', 0xa4, '%', '&', '\'',
1679 '(', ')', '*', '+', ',', '-', '.', '/',
1680 '0', '1', '2', '3', '4', '5', '6', '7',
1681 '8', '9', ':', ';', '<', '=', '>', '?',
1682 0xa1, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
1683 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
1684 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
1685 'X', 'Y', 'Z', 0xc4, 0xd6, 0xd1, 0xdc, 0xa7,
1686 0xbf, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
1687 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
1688 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
1689 'x', 'y', 'z', 0xe4, 0xf6, 0xf1, 0xfc, 0xe0
1693 char_is_escape(unsigned char value
)
1695 return (value
== GN_CHAR_ESCAPE
);
1699 char_def_alphabet_ext_decode(unsigned char value
)
1703 case 0x0a: return 0x0c; /* form feed */
1704 case 0x14: return '^';
1705 case 0x28: return '{';
1706 case 0x29: return '}';
1707 case 0x2f: return '\\';
1708 case 0x3c: return '[';
1709 case 0x3d: return '~';
1710 case 0x3e: return ']';
1711 case 0x40: return '|';
1712 case 0x65: return 0x20ac; /* euro */
1713 default: return '?'; /* invalid character */
1718 char_def_alphabet_decode(unsigned char value
)
1720 if (value
< GN_CHAR_ALPHABET_SIZE
)
1722 return gsm_default_alphabet
[value
];
1731 gsm_sms_chars_to_utf8(const unsigned char* src
, int len
)
1737 /* Scan the input string to see how long the output string will be */
1738 for (outlen
= 0, j
= 0; j
< len
; j
++)
1740 if (char_is_escape(src
[j
])) {
1743 c
= '?'; /* escape with nothing following it - error */
1745 c
= char_def_alphabet_ext_decode(src
[j
]);
1748 c
= char_def_alphabet_decode(src
[j
]);
1749 outlen
+= g_unichar_to_utf8(c
,NULL
);
1752 /* Now allocate a buffer for the output string and fill it in */
1753 outbuf
= (gchar
*)wmem_alloc(wmem_packet_scope(), outlen
+ 1);
1754 for (i
= 0, j
= 0; j
< len
; j
++)
1756 if (char_is_escape(src
[j
])) {
1759 c
= '?'; /* escape with nothing following it - error */
1761 c
= char_def_alphabet_ext_decode(src
[j
]);
1764 c
= char_def_alphabet_decode(src
[j
]);
1765 i
+= g_unichar_to_utf8(c
,&(outbuf
[i
]));
1777 dis_iei_csm8(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
1781 EXACT_DATA_CHECK(length
, 3);
1782 oct
= tvb_get_guint8(tvb
, offset
);
1784 proto_tree_add_uint (tree
,
1785 hf_gsm_sms_ud_multiple_messages_msg_id
,
1786 tvb
, offset
, 1, g_sm_id
);
1789 oct
= tvb_get_guint8(tvb
, offset
);
1791 proto_tree_add_uint (tree
,
1792 hf_gsm_sms_ud_multiple_messages_msg_parts
,
1793 tvb
, offset
, 1, g_frags
);
1795 oct
= tvb_get_guint8(tvb
, offset
);
1797 proto_tree_add_uint (tree
,
1798 hf_gsm_sms_ud_multiple_messages_msg_part
,
1799 tvb
, offset
, 1, g_frag
);
1803 /* TODO 9.2.3.24.2 Special SMS Message Indication */
1807 dis_iei_apa_8bit(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
1809 const gchar
*str
= NULL
;
1813 EXACT_DATA_CHECK(length
, 2);
1815 oct
= tvb_get_guint8(tvb
, offset
);
1823 str
= "Available for allocation by applications";
1826 proto_tree_add_text(tree
,
1828 "Destination port: %d, %s",
1833 oct
= tvb_get_guint8(tvb
, offset
);
1841 str
= "Available for allocation by applications";
1844 proto_tree_add_text(tree
,
1846 "Originator port: %d, %s",
1853 dis_iei_apa_16bit(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
1855 const gchar
*str
= NULL
;
1859 EXACT_DATA_CHECK(length
, 4);
1861 value
= tvb_get_ntohs(tvb
, offset
);
1865 str
= "As allocated by IANA (http://www.IANA.com/)";
1867 else if (value
< 17000)
1869 str
= "Available for allocation by applications";
1876 proto_tree_add_text(tree
,
1878 "Destination port: %d, %s",
1883 value
= tvb_get_ntohs(tvb
, offset
);
1887 str
= "As allocated by IANA (http://www.IANA.com/)";
1889 else if (value
< 17000)
1891 str
= "Available for allocation by applications";
1898 proto_tree_add_text(tree
,
1900 "Originator port: %d, %s",
1909 dis_iei_scp(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
1913 EXACT_DATA_CHECK(length
, 1);
1915 oct
= tvb_get_guint8(tvb
, offset
);
1919 proto_tree_add_text(tree
,
1921 "Status Report for short message transaction completed");
1925 proto_tree_add_text(tree
,
1927 "No Status Report for short message transaction completed");
1932 proto_tree_add_text(tree
,
1934 "Status Report for permanent error when SC is not making any more transfer attempts");
1938 proto_tree_add_text(tree
,
1940 "No Status Report for permanent error when SC is not making any more transfer attempts");
1945 proto_tree_add_text(tree
,
1947 "Status Report for temporary error when SC is not making any more transfer attempts");
1951 proto_tree_add_text(tree
,
1953 "No Status Report for temporary error when SC is not making any more transfer attempts");
1959 proto_tree_add_text(tree
,
1961 "Status Report for temporary error when SC is still trying to transfer SM");
1965 proto_tree_add_text(tree
,
1967 "No Status Report for temporary error when SC is still trying to transfer SM");
1973 proto_tree_add_text(tree
,
1975 "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");
1979 proto_tree_add_text(tree
,
1987 proto_tree_add_text(tree
,
1989 "Include original UDH into the Status Report");
1993 proto_tree_add_text(tree
,
1995 "Do not include original UDH into the Status Report");
2002 dis_iei_udh_si(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2006 EXACT_DATA_CHECK(length
, 1);
2008 oct
= tvb_get_guint8(tvb
, offset
);
2013 proto_tree_add_text(tree
,
2015 "The following part of the UDH is created by the original sender (valid in case of Status Report)");
2018 proto_tree_add_text(tree
,
2020 "The following part of the UDH is created by the original receiver (valid in case of Status Report)");
2023 proto_tree_add_text(tree
,
2025 "The following part of the UDH is created by the SMSC (can occur in any message or report)");
2028 proto_tree_add_text(tree
,
2030 "The following part of the UDH is created by %d" , oct
);
2036 dis_iei_csm16(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2041 EXACT_DATA_CHECK(length
, 4);
2042 oct_ref
= tvb_get_ntohs(tvb
, offset
);
2044 proto_tree_add_uint (tree
,
2045 hf_gsm_sms_ud_multiple_messages_msg_id
,
2046 tvb
, offset
, 2, g_sm_id
);
2048 oct
= tvb_get_guint8(tvb
, offset
);
2050 proto_tree_add_uint (tree
,
2051 hf_gsm_sms_ud_multiple_messages_msg_parts
,
2052 tvb
, offset
, 1, g_frags
);
2055 oct
= tvb_get_guint8(tvb
, offset
);
2057 proto_tree_add_uint (tree
,
2058 hf_gsm_sms_ud_multiple_messages_msg_part
,
2059 tvb
, offset
, 1, g_frag
);
2062 static const value_string text_color_values
[] = {
2064 { 0x01, "Dark Grey" },
2065 { 0x02, "Dark Red" },
2066 { 0x03, "Dark Yellow" },
2067 { 0x04, "Dark Green" },
2068 { 0x05, "Dark Cyan" },
2069 { 0x06, "Dark Blue" },
2070 { 0x07, "Dark Magenta" },
2073 { 0x0A, "Bright Red" },
2074 { 0x0B, "Bright Yellow" },
2075 { 0x0C, "Bright Green" },
2076 { 0x0D, "Bright Cyan" },
2077 { 0x0E, "Bright Blue" },
2078 { 0x0F, "Bright Magenta" },
2082 /* 9.2.3.24.10.1.1 */
2084 dis_iei_tf(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2086 const gchar
*str
= NULL
;
2089 proto_item
*item_colour
;
2090 proto_tree
*subtree
= NULL
;
2091 proto_tree
*subtree_colour
= NULL
;
2094 EXACT_DATA_CHECK(length
, 4);
2095 oct
= tvb_get_guint8(tvb
, offset
);
2097 proto_tree_add_text(tree
, tvb
, offset
, 1,
2098 "Start position of the text formatting: %d", oct
);
2101 oct
= tvb_get_guint8(tvb
, offset
);
2103 proto_tree_add_text(tree
, tvb
, offset
, 1, "Text formatting length: %d",
2107 oct
= tvb_get_guint8(tvb
, offset
);
2109 item
= proto_tree_add_text(tree
, tvb
, offset
, 1, "formatting mode");
2111 subtree
= proto_item_add_subtree(item
, ett_udh_tfm
);
2124 str
= "Language dependent";
2128 proto_tree_add_text(subtree
, tvb
, offset
, 1, "Alignment : %d %s",
2131 switch((oct
>> 2) & 0x03)
2147 proto_tree_add_text(subtree
, tvb
, offset
, 1, "Font Size : %d %s",
2148 (oct
>> 2) & 0x03 , str
);
2154 proto_tree_add_text(subtree
, tvb
, offset
, 1, "Style bold : %d %s",
2161 proto_tree_add_text(subtree
, tvb
, offset
, 1, "Style Italic : %d %s",
2168 proto_tree_add_text(subtree
, tvb
, offset
, 1, "Style Underlined : %d %s",
2175 proto_tree_add_text(subtree
, tvb
, offset
, 1, "Style Strikethrough : %d %s",
2179 oct
= tvb_get_guint8(tvb
, offset
);
2180 item_colour
= proto_tree_add_text(tree
, tvb
, offset
, 1, "Text Colour");
2182 subtree_colour
= proto_item_add_subtree(item_colour
, ett_udh_tfc
);
2185 str
= val_to_str_const(oct
& 0x0f, text_color_values
, "Unknown");
2186 proto_tree_add_text(subtree_colour
, tvb
, offset
, 1,
2187 "Foreground Colour : 0x%x %s",
2190 str
= val_to_str_const((oct
>> 4) & 0x0f, text_color_values
, "Unknown");
2191 proto_tree_add_text(subtree_colour
,
2193 "Background Colour : 0x%x %s",
2194 (oct
>> 4) & 0x0f , str
);
2198 /* 9.2.3.24.10.1.2 */
2200 dis_iei_ps(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2204 EXACT_DATA_CHECK(length
, 2);
2205 oct
= tvb_get_guint8(tvb
, offset
);
2207 proto_tree_add_text(tree
,
2213 oct
= tvb_get_guint8(tvb
, offset
);
2215 proto_tree_add_text(tree
,
2221 /* 9.2.3.24.10.1.3 */
2223 dis_iei_uds(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2227 SHORT_DATA_CHECK(length
, 2);
2228 oct
= tvb_get_guint8(tvb
, offset
);
2230 proto_tree_add_text(tree
,
2236 proto_tree_add_text(tree
,
2237 tvb
, offset
, length
- 1,
2238 "User Defined Sound ");
2242 /* 9.2.3.24.10.1.4 */
2244 dis_iei_pa(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2248 EXACT_DATA_CHECK(length
, 2);
2249 oct
= tvb_get_guint8(tvb
, offset
);
2251 proto_tree_add_text(tree
,
2257 oct
= tvb_get_guint8(tvb
, offset
);
2259 proto_tree_add_text(tree
,
2261 "animation number: %d",
2266 /* 9.2.3.24.10.1.5 */
2268 dis_iei_la(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2272 SHORT_DATA_CHECK(length
, 2);
2273 oct
= tvb_get_guint8(tvb
, offset
);
2275 proto_tree_add_text(tree
,
2281 proto_tree_add_text(tree
,
2282 tvb
, offset
, length
- 1,
2283 "Large Animation ");
2286 /* 9.2.3.24.10.1.6 */
2288 dis_iei_sa(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2292 SHORT_DATA_CHECK(length
, 2);
2293 oct
= tvb_get_guint8(tvb
, offset
);
2295 proto_tree_add_text(tree
,
2301 proto_tree_add_text(tree
,
2302 tvb
, offset
, length
- 1,
2303 "Small Animation ");
2307 /* 9.2.3.24.10.1.7 */
2309 dis_iei_lp(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2313 SHORT_DATA_CHECK(length
, 2);
2314 oct
= tvb_get_guint8(tvb
, offset
);
2316 proto_tree_add_text(tree
,
2322 proto_tree_add_text(tree
,
2323 tvb
, offset
, length
- 1,
2327 /* 9.2.3.24.10.1.8 */
2329 dis_iei_sp(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2333 SHORT_DATA_CHECK(length
, 2);
2334 oct
= tvb_get_guint8(tvb
, offset
);
2336 proto_tree_add_text(tree
,
2342 proto_tree_add_text(tree
,
2343 tvb
, offset
, length
- 1,
2348 /* 9.2.3.24.10.1.9 */
2350 dis_iei_vp(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2354 SHORT_DATA_CHECK(length
, 4);
2355 oct
= tvb_get_guint8(tvb
, offset
);
2357 proto_tree_add_text(tree
,
2363 oct
= tvb_get_guint8(tvb
, offset
);
2364 proto_tree_add_text(tree
,
2366 "Horizontal dimension: %d",
2370 oct
= tvb_get_guint8(tvb
, offset
);
2371 proto_tree_add_text(tree
,
2373 "Vertical dimension: %d",
2377 proto_tree_add_text(tree
,
2378 tvb
, offset
, length
- 3,
2379 "Variable Picture ");
2382 /* 9.2.3.24.10.1.10 */
2384 dis_iei_upi(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2388 EXACT_DATA_CHECK(length
, 1);
2389 oct
= tvb_get_guint8(tvb
, offset
);
2391 proto_tree_add_text(tree
,
2393 "Number of corresponding objects: %d",
2400 * 9.2.3.24 TP-User Data (TP-UD)
2401 * Information Element Identifier octet
2405 /* TS 123 040 V9.3.0 (2010-10) */
2406 static const value_string gsm_sms_tp_ud_ie_id_vals
[] = {
2407 { 0x00, "Concatenated short messages, 8-bit reference number (SMS Control)" },
2408 { 0x01, "Special SMS Message Indication (SMS Control)" },
2409 { 0x02, "Reserved" },
2410 { 0x03, "Value not used to avoid misinterpretation as <LF> character" },
2411 { 0x04, "Application port addressing scheme, 8 bit address (SMS Control)" },
2412 { 0x05, "Application port addressing scheme, 16 bit address (SMS Control)" },
2413 { 0x06, "SMSC Control Parameters (SMS Control)" },
2414 { 0x07, "UDH Source Indicator (SMS Control)" },
2415 { 0x08, "Concatenated short message, 16-bit reference number (SMS Control)" },
2416 { 0x09, "Wireless Control Message Protocol (SMS Control)" },
2417 { 0x0A, "Text Formatting (EMS Control)" },
2418 { 0x0B, "Predefined Sound (EMS Content)" },
2419 { 0x0C, "User Defined Sound (iMelody max 128 bytes) (EMS Content)" },
2420 { 0x0D, "Predefined Animation (EMS Content)" },
2421 { 0x0E, "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)" },
2422 { 0x0F, "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)" },
2423 { 0x10, "Large Picture (32*32 = 128 bytes) (EMS Content)" },
2424 { 0x11, "Small Picture (16*16 = 32 bytes) (EMS Content)" },
2425 { 0x12, "Variable Picture (EMS Content)" },
2426 { 0x13, "User prompt indicator (EMS Control)" },
2427 { 0x14, "Extended Object (EMS Content)" },
2428 { 0x15, "Reused Extended Object (EMS Control)" },
2429 { 0x16, "Compression Control (EMS Control)" },
2430 { 0x17, "Object Distribution Indicator (EMS Control)" },
2431 { 0x18, "Standard WVG object (EMS Content)" },
2432 { 0x19, "Character Size WVG object (EMS Content)" },
2433 { 0x1A, "Extended Object Data Request Command (EMS Control)" },
2434 /*1B-1F Reserved for future EMS features (see subclause 3.10) */
2435 { 0x20, "RFC 822 E-Mail Header (SMS Control)" },
2436 { 0x21, "Hyperlink format element (SMS Control)" },s
2437 { 0x22, "Reply Address Element (SMS Control)" },
2438 { 0x23, "Enhanced Voice Mail Information (SMS Control)" },
2439 { 0x24, "National Language Single Shift (SMS Control)" },
2440 { 0x25, "National Language Locking Shift (SMS Control)" },
2441 /*26-6F Reserved for future use */
2442 /*70-7F (U)SIM Toolkit Security Headers (SMS Control) */
2443 /*80-9F SME to SME specific use (SMS Control) */
2444 /*A0-BF Reserved for future use */
2445 /*C0-DF SC specific use (SMS Control) */
2446 /*E0-FF Reserved for future use */
2452 dis_field_ud_iei(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
)
2454 void (*iei_fcn
)(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 length
);
2457 proto_tree
*subtree
= NULL
;
2458 const gchar
*str
= NULL
;
2466 oct
= tvb_get_guint8(tvb
, offset
);
2470 case 0x00: str
= "Concatenated short messages, 8-bit reference number (SMS Control)"; iei_fcn
= dis_iei_csm8
; break;
2471 case 0x01: str
= "Special SMS Message Indication (SMS Control)"; break;
2472 case 0x02: str
= "Reserved N/A"; break;
2473 case 0x03: str
= "Value not used to avoid misinterpretation as <LF> character N/A"; break;
2474 case 0x04: str
= "Application port addressing scheme, 8 bit address (SMS Control)"; iei_fcn
= dis_iei_apa_8bit
; break;
2475 case 0x05: str
= "Application port addressing scheme, 16 bit address (SMS Control)"; iei_fcn
= dis_iei_apa_16bit
; break;
2476 case 0x06: str
= "SMSC Control Parameters (SMS Control)"; iei_fcn
= dis_iei_scp
; break;
2477 case 0x07: str
= "UDH Source Indicator (SMS Control)"; iei_fcn
= dis_iei_udh_si
; break;
2478 case 0x08: str
= "Concatenated short message, 16-bit reference number (SMS Control)"; iei_fcn
= dis_iei_csm16
; break;
2479 case 0x09: str
= "Wireless Control Message Protocol (SMS Control)"; break;
2480 case 0x0A: str
= "Text Formatting (EMS Control)"; iei_fcn
= dis_iei_tf
;break;
2481 case 0x0B: str
= "Predefined Sound (EMS Content)"; iei_fcn
= dis_iei_ps
;break;
2482 case 0x0C: str
= "User Defined Sound (iMelody max 128 bytes) (EMS Content)"; iei_fcn
= dis_iei_uds
;break;
2483 case 0x0D: str
= "Predefined Animation (EMS Content)"; iei_fcn
= dis_iei_pa
;break;
2484 case 0x0E: str
= "Large Animation (16*16 times 4 = 32*4 =128 bytes) (EMS Content)"; iei_fcn
= dis_iei_la
;break;
2485 case 0x0F: str
= "Small Animation (8*8 times 4 = 8*4 =32 bytes) (EMS Content)"; iei_fcn
= dis_iei_sa
;break;
2486 case 0x10: str
= "Large Picture (32*32 = 128 bytes) (EMS Content)"; iei_fcn
= dis_iei_lp
;break;
2487 case 0x11: str
= "Small Picture (16*16 = 32 bytes) (EMS Content)"; iei_fcn
= dis_iei_sp
;break;
2488 case 0x12: str
= "Variable Picture (EMS Content)"; iei_fcn
= dis_iei_vp
;break;
2489 case 0x13: str
= "User prompt indicator (EMS Control)"; iei_fcn
= dis_iei_upi
;break;
2490 case 0x14: str
= "Extended Object (EMS Content)"; break;
2491 case 0x15: str
= "Reused Extended Object (EMS Control)"; break;
2492 case 0x16: str
= "Compression Control (EMS Control)"; break;
2493 case 0x17: str
= "Object Distribution Indicator (EMS Control)"; break;
2494 case 0x18: str
= "Standard WVG object (EMS Content)"; break;
2495 case 0x19: str
= "Character Size WVG object (EMS Content)"; break;
2496 case 0x1A: str
= "Extended Object Data Request Command (EMS Control)"; break;
2497 case 0x20: str
= "RFC 822 E-Mail Header (SMS Control)"; break;
2498 case 0x21: str
= "Hyperlink format element (SMS Control)"; break;
2499 case 0x22: str
= "Reply Address Element (SMS Control)"; break;
2501 if ((oct
>= 0x1b) &&
2504 str
= "Reserved for future EMS features (see subclause 3.10) N/A"; break;
2506 else if ((oct
>= 0x23) &&
2509 str
= "Reserved for future use N/A"; break;
2511 else if ((oct
>= 0x70) &&
2514 str
= "(U)SIM Toolkit Security Headers (SMS Control)"; break;
2516 else if ((oct
>= 0x80) &&
2519 str
= "SME to SME specific use (SMS Control)"; break;
2521 else if ((oct
>= 0xa0) &&
2524 str
= "Reserved for future use N/A"; break;
2526 else if ((oct
>= 0xc0) &&
2529 str
= "SC specific use (SMS Control)"; break;
2533 str
= "Reserved for future use N/A"; break;
2537 iei_len
= tvb_get_guint8(tvb
, offset
+ 1);
2540 proto_tree_add_text(tree
,
2541 tvb
, offset
, iei_len
+ 2,
2545 subtree
= proto_item_add_subtree(item
, ett_udh_ieis
[oct
]);
2547 proto_tree_add_text(subtree
,
2549 "Information Element Identifier: 0x%02X",
2554 proto_tree_add_text(subtree
,
2563 if (iei_fcn
== NULL
)
2565 proto_tree_add_text(subtree
,
2566 tvb
, offset
, iei_len
,
2571 iei_fcn(tvb
, subtree
, offset
, iei_len
);
2575 length
-= 2 + iei_len
;
2581 dis_field_udh(tvbuff_t
*tvb
, proto_tree
*tree
, guint32
*offset
, guint32
*length
,
2582 guint8
*udl
, gboolean uncomp_7bits
, guint8
*fill_bits
)
2585 proto_item
*udh_item
;
2586 proto_tree
*udh_subtree
= NULL
;
2587 static guint8 fill_bits_mask
[7] = { 0x0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f };
2589 /* step over header */
2591 oct
= tvb_get_guint8(tvb
, *offset
);
2594 proto_tree_add_text(tree
, tvb
,
2596 "User-Data Header");
2598 udh_subtree
= proto_item_add_subtree(udh_item
, ett_udh
);
2600 proto_tree_add_text(udh_subtree
,
2602 "User Data Header Length (%u)",
2608 dis_field_ud_iei(tvb
, udh_subtree
, *offset
, oct
);
2615 /* step over fill bits ? */
2617 *fill_bits
= 6 - ((oct
* 8) % 7);
2618 *udl
-= (((oct
+ 1)*8) + *fill_bits
) / 7;
2621 oct
= tvb_get_guint8(tvb
, *offset
);
2623 other_decode_bitfield_value(bigbuf
, oct
, fill_bits_mask
[*fill_bits
], 8);
2624 proto_tree_add_text(udh_subtree
,
2628 /* Note: Could add an expert item here if ((oct & fill_bits_mask[*fill_bits]) != 0) */
2638 #define SMS_MAX_MESSAGE_SIZE 160
2639 static char messagebuf
[SMS_MAX_MESSAGE_SIZE
+1];
2641 dis_field_ud(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint32 offset
, guint32 length
, gboolean udhi
, guint8 udl
,
2642 gboolean seven_bit
, gboolean eight_bit
, gboolean ucs2
, gboolean compressed
)
2645 proto_tree
*subtree
= NULL
;
2646 tvbuff_t
*sm_tvb
= NULL
;
2647 fragment_head
*fd_sm
= NULL
;
2649 guint32 out_len
, total_sms_len
, len_sms
, length_ucs2
, i
;
2651 proto_item
*ucs2_item
;
2652 gchar
*utf8_text
= NULL
;
2653 gchar save_byte
= 0, save_byte2
= 0;
2655 GError
*l_conv_error
= NULL
;
2657 gboolean reassembled
= FALSE
;
2658 guint32 reassembled_in
= 0;
2659 gboolean is_fragmented
= FALSE
;
2660 gboolean save_fragmented
= FALSE
, try_gsm_sms_ud_reassemble
= FALSE
;
2663 sm_fragment_params
*p_frag_params
;
2668 proto_tree_add_text(tree
, tvb
,
2671 subtree
= proto_item_add_subtree(item
, ett_ud
);
2675 dis_field_udh(tvb
, subtree
, &offset
, &length
, &udl
, (seven_bit
&& !compressed
), &fill_bits
);
2679 is_fragmented
= TRUE
;
2681 if ( is_fragmented
&& reassemble_sms
)
2683 try_gsm_sms_ud_reassemble
= TRUE
;
2684 save_fragmented
= pinfo
->fragmented
;
2685 pinfo
->fragmented
= TRUE
;
2686 fd_sm
= fragment_add_seq_check (&g_sm_reassembly_table
, tvb
, offset
,
2688 g_sm_id
, /* guint32 ID for fragments belonging together */
2690 g_frag
-1, /* guint32 fragment sequence number */
2691 length
, /* guint32 fragment length */
2692 (g_frag
!= g_frags
)); /* More fragments? */
2696 reassembled_in
= fd_sm
->reassembled_in
;
2699 sm_tvb
= process_reassembled_data(tvb
, offset
, pinfo
,
2700 "Reassembled Short Message", fd_sm
, &sm_frag_items
,
2703 if(reassembled
&& pinfo
->fd
->num
== reassembled_in
)
2706 col_append_str (pinfo
->cinfo
, COL_INFO
,
2707 " (Short Message Reassembled)");
2711 /* Not last packet of reassembled Short Message */
2712 col_append_fstr (pinfo
->cinfo
, COL_INFO
,
2713 " (Short Message fragment %u of %u)", g_frag
, g_frags
);
2716 /* Store udl and length for later decoding of reassembled SMS */
2717 p_frag_params
= wmem_new0(wmem_file_scope(), sm_fragment_params
);
2718 p_frag_params
->udl
= udl
;
2719 p_frag_params
->fill_bits
= fill_bits
;
2720 p_frag_params
->length
= length
;
2721 g_hash_table_insert(g_sm_fragment_params_table
,
2722 GUINT_TO_POINTER((guint
)((g_sm_id
<<16)|(g_frag
-1))),
2724 } /* Else: not fragmented */
2725 if (! sm_tvb
) /* One single Short Message, or not reassembled */
2726 sm_tvb
= tvb_new_subset_remaining (tvb
, offset
);
2730 proto_tree_add_text(subtree
, tvb
, offset
, length
, "Compressed data");
2736 if(!(reassembled
&& pinfo
->fd
->num
== reassembled_in
))
2738 /* Show unassembled SMS */
2740 gsm_sms_char_7bit_unpack(fill_bits
, length
,
2741 (udl
> SMS_MAX_MESSAGE_SIZE
? SMS_MAX_MESSAGE_SIZE
: udl
),
2742 tvb_get_ptr(tvb
, offset
, length
) , messagebuf
);
2743 messagebuf
[out_len
] = '\0';
2744 proto_tree_add_unicode_string(subtree
, hf_gsm_sms_text
, tvb
, offset
,
2746 gsm_sms_chars_to_utf8(messagebuf
, out_len
));
2750 /* Show reassembled SMS. We show each fragment separately
2751 * so that the text doesn't get truncated when we add it to
2755 for(i
= 0 ; i
< g_frags
; i
++)
2757 p_frag_params
= (sm_fragment_params
*)g_hash_table_lookup(g_sm_fragment_params_table
,
2758 GUINT_TO_POINTER((guint
)((g_sm_id
<<16)|i
)));
2760 if (p_frag_params
) {
2762 gsm_sms_char_7bit_unpack(p_frag_params
->fill_bits
, p_frag_params
->length
,
2763 (p_frag_params
->udl
> SMS_MAX_MESSAGE_SIZE
? SMS_MAX_MESSAGE_SIZE
: p_frag_params
->udl
),
2764 tvb_get_ptr(sm_tvb
, total_sms_len
, p_frag_params
->length
), messagebuf
);
2766 messagebuf
[out_len
] = '\0';
2767 proto_tree_add_unicode_string(subtree
, hf_gsm_sms_text
, sm_tvb
,
2768 total_sms_len
, p_frag_params
->length
,
2769 gsm_sms_chars_to_utf8(messagebuf
, out_len
));
2771 total_sms_len
+= p_frag_params
->length
;
2778 /*proto_tree_add_text(subtree, tvb , offset , length, "%s",
2779 tvb_format_text(tvb, offset, length)); */
2780 if (! dissector_try_uint(gsm_sms_dissector_tbl
, g_port_src
, sm_tvb
, pinfo
, subtree
))
2782 if (! dissector_try_uint(gsm_sms_dissector_tbl
, g_port_dst
,sm_tvb
, pinfo
, subtree
))
2785 { /* Only display if needed */
2786 proto_tree_add_text (subtree
, sm_tvb
, 0, -1,
2787 "Short Message body");
2794 /* XXX, use tvb_get_unicode_string(.., ENC_BIG_ENDIAN); */
2795 if ((cd
= g_iconv_open("UTF-8","UCS-2BE")) != (GIConv
)-1)
2797 guint8 rep_len
= tvb_reported_length(sm_tvb
);
2799 if(!(reassembled
&& pinfo
->fd
->num
== reassembled_in
))
2801 /* Show unreassembled SMS */
2802 utf8_text
= g_convert_with_iconv(tvb_get_ptr(sm_tvb
, 0, rep_len
), rep_len
, cd
, NULL
, NULL
, &l_conv_error
);
2804 ucs2_item
= proto_tree_add_unicode_string(subtree
, hf_gsm_sms_text
, tvb
,
2805 offset
, length
, utf8_text
);
2807 ucs2_item
= proto_tree_add_text(subtree
, tvb
, offset
, length
, "Failed to decode UCS2!");
2809 PROTO_ITEM_SET_GENERATED(ucs2_item
);
2811 /* Show reassembled SMS. We show each fragment separately
2812 * so that the text doesn't get truncated when we add it to
2815 utf8_text
= g_convert_with_iconv(tvb_get_ptr(sm_tvb
, 0, rep_len
), rep_len
, cd
, NULL
, NULL
, &l_conv_error
);
2818 len_sms
= (int)strlen(utf8_text
);
2819 num_labels
= len_sms
/ MAX_SMS_FRAG_LEN
;
2820 num_labels
+= (len_sms
% MAX_SMS_FRAG_LEN
) ? 1 : 0;
2821 for(i
= 0; i
< num_labels
;i
++) {
2822 if(i
* MAX_SMS_FRAG_LEN
< len_sms
) {
2823 /* set '\0' to byte number 134 text_node MAX size*/
2824 save_byte
= utf8_text
[i
* MAX_SMS_FRAG_LEN
];
2825 save_byte2
= utf8_text
[i
* MAX_SMS_FRAG_LEN
+ 1];
2828 utf8_text
[i
* MAX_SMS_FRAG_LEN
] = '\0';
2829 utf8_text
[i
* MAX_SMS_FRAG_LEN
+ 1] = '\0';
2832 length_ucs2
= MAX_SMS_FRAG_LEN
;
2834 length_ucs2
= len_sms
% MAX_SMS_FRAG_LEN
;
2836 ucs2_item
= proto_tree_add_unicode_string(subtree
, hf_gsm_sms_text
, sm_tvb
,
2837 i
* MAX_SMS_FRAG_LEN
, length_ucs2
,
2838 &utf8_text
[i
* MAX_SMS_FRAG_LEN
]);
2839 PROTO_ITEM_SET_GENERATED(ucs2_item
);
2841 /* return the save byte to utf8 buffer*/
2842 if(i
* MAX_SMS_FRAG_LEN
< len_sms
) {
2843 utf8_text
[i
* MAX_SMS_FRAG_LEN
] = save_byte
;
2844 utf8_text
[i
* MAX_SMS_FRAG_LEN
+ 1] = save_byte2
;
2848 ucs2_item
= proto_tree_add_text(subtree
, tvb
, offset
, length
, "Failed to decode UCS2!");
2849 PROTO_ITEM_SET_GENERATED(ucs2_item
);
2856 ustr
= tvb_get_unicode_string(wmem_packet_scope(), tvb
, offset
, length
, ENC_BIG_ENDIAN
);
2857 proto_tree_add_text(subtree
, tvb
, offset
, length
, "%s", ustr
);
2862 if (try_gsm_sms_ud_reassemble
) /* Clean up defragmentation */
2863 pinfo
->fragmented
= save_fragmented
;
2868 dis_field_pi(tvbuff_t
*tvb
, proto_tree
*tree
, guint32 offset
, guint8 oct
)
2871 proto_tree
*subtree
= NULL
;
2875 proto_tree_add_text(tree
, tvb
,
2877 "TP-Parameter-Indicator");
2879 subtree
= proto_item_add_subtree(item
, ett_pi
);
2881 other_decode_bitfield_value(bigbuf
, oct
, 0x80, 8);
2882 proto_tree_add_text(subtree
, tvb
,
2886 (oct
& 0x80) ? "Extended" : "No extension");
2888 other_decode_bitfield_value(bigbuf
, oct
, 0x78, 8);
2889 proto_tree_add_text(subtree
, tvb
,
2894 other_decode_bitfield_value(bigbuf
, oct
, 0x04, 8);
2895 proto_tree_add_text(subtree
, tvb
,
2897 "%s : TP-UDL %spresent",
2899 (oct
& 0x04) ? "" : "not ");
2901 other_decode_bitfield_value(bigbuf
, oct
, 0x02, 8);
2902 proto_tree_add_text(subtree
, tvb
,
2904 "%s : TP-DCS %spresent",
2906 (oct
& 0x02) ? "" : "not ");
2908 other_decode_bitfield_value(bigbuf
, oct
, 0x01, 8);
2909 proto_tree_add_text(subtree
, tvb
,
2911 "%s : TP-PID %spresent",
2913 (oct
& 0x01) ? "" : "not ");
2921 dis_msg_deliver(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint32 offset
)
2923 guint32 saved_offset
;
2930 gboolean compressed
;
2933 saved_offset
= offset
;
2934 length
= tvb_length_remaining(tvb
, offset
);
2936 oct
= tvb_get_guint8(tvb
, offset
);
2939 proto_tree_add_item(tree
, hf_gsm_sms_tp_rp
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2940 proto_tree_add_item(tree
, hf_gsm_sms_tp_udhi
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2941 proto_tree_add_item(tree
, hf_gsm_sms_tp_sri
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2942 proto_tree_add_item(tree
, hf_gsm_sms_tp_mms
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2943 proto_tree_add_item(tree
, hf_gsm_sms_tp_mti_down
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2947 dis_field_addr(tvb
, tree
, &offset
, "TP-Originating-Address");
2949 oct
= tvb_get_guint8(tvb
, offset
);
2951 dis_field_pid(tvb
, tree
, offset
, oct
);
2954 oct
= tvb_get_guint8(tvb
, offset
);
2956 dis_field_dcs(tvb
, tree
, offset
, oct
, &seven_bit
, &eight_bit
, &ucs2
, &compressed
);
2959 dis_field_scts(tvb
, tree
, &offset
);
2961 oct
= tvb_get_guint8(tvb
, offset
);
2964 DIS_FIELD_UDL(tree
, offset
);
2970 dis_field_ud(tvb
, pinfo
, tree
, offset
, length
- (offset
- saved_offset
), udhi
, udl
,
2971 seven_bit
, eight_bit
, ucs2
, compressed
);
2980 dis_msg_deliver_report(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint32 offset
)
2982 guint32 saved_offset
;
2987 gboolean seven_bit
= FALSE
;
2988 gboolean eight_bit
= FALSE
;
2989 gboolean ucs2
= FALSE
;
2990 gboolean compressed
= FALSE
;
2995 saved_offset
= offset
;
2996 length
= tvb_length_remaining(tvb
, offset
);
2998 oct
= tvb_get_guint8(tvb
, offset
);
3001 proto_tree_add_item(tree
, hf_gsm_sms_tp_udhi
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3002 proto_tree_add_item(tree
, hf_gsm_sms_tp_mms
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3003 proto_tree_add_item(tree
, hf_gsm_sms_tp_mti_up
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3007 proto_tree_add_text(tree
,
3008 tvb
, offset
, length
,
3014 * there does not seem to be a way to determine that this
3015 * deliver report is from an RP-ERROR or RP-ACK other
3016 * than to look at the next octet
3018 * FCS values are 0x80 and higher
3019 * PI uses bit 7 as an extension indicator
3021 * will assume that if bit 7 is set then this octet
3022 * is an FCS otherwise PI
3025 oct
= tvb_get_guint8(tvb
, offset
);
3029 dis_field_fcs(tvb
, tree
, offset
, oct
);
3033 pi
= tvb_get_guint8(tvb
, offset
);
3035 dis_field_pi(tvb
, tree
, offset
, pi
);
3039 if (length
<= (offset
- saved_offset
))
3041 proto_tree_add_text(tree
,
3048 oct
= tvb_get_guint8(tvb
, offset
);
3050 dis_field_pid(tvb
, tree
, offset
, oct
);
3055 if (length
<= (offset
- saved_offset
))
3057 proto_tree_add_text(tree
,
3064 oct
= tvb_get_guint8(tvb
, offset
);
3066 dis_field_dcs(tvb
, tree
, offset
, oct
, &seven_bit
, &eight_bit
, &ucs2
, &compressed
);
3071 if (length
<= (offset
- saved_offset
))
3073 proto_tree_add_text(tree
,
3080 oct
= tvb_get_guint8(tvb
, offset
);
3083 DIS_FIELD_UDL(tree
, offset
);
3090 dis_field_ud(tvb
, pinfo
, tree
, offset
, length
- (offset
- saved_offset
), udhi
, udl
,
3091 seven_bit
, eight_bit
, ucs2
, compressed
);
3100 dis_msg_submit(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint32 offset
)
3102 guint32 saved_offset
;
3110 gboolean compressed
;
3114 saved_offset
= offset
;
3115 length
= tvb_length_remaining(tvb
, offset
);
3117 oct
= tvb_get_guint8(tvb
, offset
);
3119 vp_form
= ((oct
& 0x18) >> 3);
3121 proto_tree_add_item(tree
, hf_gsm_sms_tp_rp
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3122 proto_tree_add_item(tree
, hf_gsm_sms_tp_udhi
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3123 proto_tree_add_item(tree
, hf_gsm_sms_tp_srr
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3124 proto_tree_add_item(tree
, hf_gsm_sms_tp_vpf
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3125 proto_tree_add_item(tree
, hf_gsm_sms_tp_rd
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3126 proto_tree_add_item(tree
, hf_gsm_sms_tp_mti_up
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3130 proto_tree_add_item(tree
, hf_gsm_sms_tp_mr
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3134 dis_field_addr(tvb
, tree
, &offset
, "TP-Destination-Address");
3136 oct
= tvb_get_guint8(tvb
, offset
);
3138 dis_field_pid(tvb
, tree
, offset
, oct
);
3141 oct
= tvb_get_guint8(tvb
, offset
);
3143 dis_field_dcs(tvb
, tree
, offset
, oct
, &seven_bit
, &eight_bit
, &ucs2
, &compressed
);
3146 dis_field_vp(tvb
, tree
, &offset
, vp_form
);
3148 oct
= tvb_get_guint8(tvb
, offset
);
3151 DIS_FIELD_UDL(tree
, offset
);
3157 dis_field_ud(tvb
, pinfo
, tree
, offset
, length
- (offset
- saved_offset
), udhi
, udl
,
3158 seven_bit
, eight_bit
, ucs2
, compressed
);
3167 dis_msg_submit_report(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint32 offset
)
3169 guint32 saved_offset
;
3174 gboolean seven_bit
= FALSE
;
3175 gboolean eight_bit
= FALSE
;
3176 gboolean ucs2
= FALSE
;
3177 gboolean compressed
= FALSE
;
3182 saved_offset
= offset
;
3183 length
= tvb_length_remaining(tvb
, offset
);
3185 oct
= tvb_get_guint8(tvb
, offset
);
3188 proto_tree_add_item(tree
, hf_gsm_sms_tp_udhi
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3189 proto_tree_add_item(tree
, hf_gsm_sms_tp_mti_down
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3192 * there does not seem to be a way to determine that this
3193 * deliver report is from an RP-ERROR or RP-ACK other
3194 * than to look at the next octet
3196 * FCS values are 0x80 and higher
3197 * PI uses bit 7 as an extension indicator
3199 * will assume that if bit 7 is set then this octet
3200 * is an FCS otherwise PI
3203 oct
= tvb_get_guint8(tvb
, offset
);
3207 dis_field_fcs(tvb
, tree
, offset
, oct
);
3211 pi
= tvb_get_guint8(tvb
, offset
);
3213 dis_field_pi(tvb
, tree
, offset
, pi
);
3216 dis_field_scts(tvb
, tree
, &offset
);
3219 if (length
<= (offset
- saved_offset
)) {
3220 proto_tree_add_text(tree
,
3226 oct
= tvb_get_guint8(tvb
, offset
);
3228 dis_field_pid(tvb
, tree
, offset
, oct
);
3234 if (length
<= (offset
- saved_offset
))
3236 proto_tree_add_text(tree
,
3242 oct
= tvb_get_guint8(tvb
, offset
);
3244 dis_field_dcs(tvb
, tree
, offset
, oct
, &seven_bit
, &eight_bit
, &ucs2
, &compressed
);
3250 if (length
<= (offset
- saved_offset
))
3252 proto_tree_add_text(tree
,
3258 oct
= tvb_get_guint8(tvb
, offset
);
3261 DIS_FIELD_UDL(tree
, offset
);
3267 dis_field_ud(tvb
, pinfo
, tree
, offset
, length
- (offset
- saved_offset
), udhi
, udl
,
3268 seven_bit
, eight_bit
, ucs2
, compressed
);
3277 dis_msg_status_report(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint32 offset
)
3279 guint32 saved_offset
;
3284 gboolean seven_bit
= FALSE
;
3285 gboolean eight_bit
= FALSE
;
3286 gboolean ucs2
= FALSE
;
3287 gboolean compressed
= FALSE
;
3292 saved_offset
= offset
;
3293 length
= tvb_length_remaining(tvb
, offset
);
3295 oct
= tvb_get_guint8(tvb
, offset
);
3298 proto_tree_add_item(tree
, hf_gsm_sms_tp_udhi
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3299 proto_tree_add_item(tree
, hf_gsm_sms_tp_srq
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3300 proto_tree_add_item(tree
, hf_gsm_sms_tp_mms
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3301 proto_tree_add_item(tree
, hf_gsm_sms_tp_mti_down
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3305 proto_tree_add_item(tree
, hf_gsm_sms_tp_mr
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3309 dis_field_addr(tvb
, tree
, &offset
, "TP-Recipient-Address");
3311 dis_field_scts(tvb
, tree
, &offset
);
3313 dis_field_dt(tvb
, tree
, &offset
);
3315 oct
= tvb_get_guint8(tvb
, offset
);
3317 dis_field_st(tvb
, tree
, offset
, oct
);
3320 /* Parameter indicating the presence of any of
3321 * the optional parameters which follow
3322 * 4) Mandatory if any of the optional parameters following TP-PI is present,
3323 * otherwise optional.
3325 if (length
<= (offset
- saved_offset
))
3329 pi
= tvb_get_guint8(tvb
, offset
);
3331 dis_field_pi(tvb
, tree
, offset
, pi
);
3335 if (length
<= (offset
- saved_offset
))
3337 proto_tree_add_text(tree
,
3344 oct
= tvb_get_guint8(tvb
, offset
);
3346 dis_field_pid(tvb
, tree
, offset
, oct
);
3351 if (length
<= (offset
- saved_offset
))
3353 proto_tree_add_text(tree
,
3360 oct
= tvb_get_guint8(tvb
, offset
);
3362 dis_field_dcs(tvb
, tree
, offset
, oct
, &seven_bit
, &eight_bit
, &ucs2
, &compressed
);
3367 if (length
<= (offset
- saved_offset
))
3369 proto_tree_add_text(tree
,
3376 oct
= tvb_get_guint8(tvb
, offset
);
3379 DIS_FIELD_UDL(tree
, offset
);
3386 dis_field_ud(tvb
, pinfo
, tree
, offset
, length
- (offset
- saved_offset
), udhi
, udl
,
3387 seven_bit
, eight_bit
, ucs2
, compressed
);
3396 dis_msg_command(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, guint32 offset
)
3400 const gchar
*str
= NULL
;
3402 proto_tree_add_item(tree
, hf_gsm_sms_tp_udhi
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3403 proto_tree_add_item(tree
, hf_gsm_sms_tp_srr
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3404 proto_tree_add_item(tree
, hf_gsm_sms_tp_mti_up
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3408 proto_tree_add_item(tree
, hf_gsm_sms_tp_mr
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3411 oct
= tvb_get_guint8(tvb
, offset
);
3413 dis_field_pid(tvb
, tree
, offset
, oct
);
3416 oct
= tvb_get_guint8(tvb
, offset
);
3418 DIS_FIELD_CT(tree
, offset
);
3421 oct
= tvb_get_guint8(tvb
, offset
);
3423 DIS_FIELD_MN(tree
, offset
);
3427 dis_field_addr(tvb
, tree
, &offset
, "TP-Destination-Address");
3429 oct
= tvb_get_guint8(tvb
, offset
);
3432 DIS_FIELD_CDL(tree
, offset
);
3438 proto_tree_add_text(tree
,
3445 #define NUM_MSGS (sizeof(msg_type_strings)/sizeof(value_string))
3446 static gint ett_msgs
[NUM_MSGS
];
3449 static void (*gsm_sms_msg_fcn
[])(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint32 offset
) = {
3450 dis_msg_deliver
, /* SMS-DELIVER */
3451 dis_msg_deliver_report
, /* SMS-DELIVER REPORT */
3452 dis_msg_submit
, /* SMS-SUBMIT */
3453 dis_msg_submit_report
, /* SMS-SUBMIT REPORT */
3454 dis_msg_status_report
, /* SMS-STATUS REPORT */
3455 dis_msg_command
, /* SMS-COMMAND */
3456 NULL
, /* Reserved */
3457 NULL
, /* Reserved */
3461 /* GENERIC DISSECTOR FUNCTIONS */
3464 dissect_gsm_sms(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
3466 void (*msg_fcn
)(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, guint32 offset
) = NULL
;
3467 proto_item
*gsm_sms_item
;
3468 proto_tree
*gsm_sms_tree
= NULL
;
3473 const gchar
*str
= NULL
;
3474 /*gint ett_msg_idx;*/
3483 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, gsm_sms_proto_name_short
);
3485 /* In the interest of speed, if "tree" is NULL, don't do any work not
3486 * necessary to generate protocol tree items.
3488 if (tree
|| reassemble_sms
)
3494 oct
= tvb_get_guint8(tvb
, offset
);
3500 * convert the 2 bit value to one based on direction
3502 msg_type
|= ((pinfo
->p2p_dir
== P2P_DIR_RECV
) ? 0x04 : 0x00);
3504 str
= try_val_to_str_idx(msg_type
, msg_type_strings
, &idx
);
3507 * create the GSM_SMS protocol tree
3510 proto_tree_add_protocol_format(tree
, proto_gsm_sms
, tvb
, 0, -1,
3513 (str
== NULL
) ? "Unknown message identifier" : str
);
3516 proto_item_add_subtree(gsm_sms_item
, ett_gsm_sms
);
3518 if ((str
== NULL
) ||
3519 (msg_type
== 0x03) ||
3526 /*ett_msg_idx = ett_msgs[idx];*/ /* XXX: Not actually used */
3527 msg_fcn
= gsm_sms_msg_fcn
[idx
];
3530 if (msg_fcn
== NULL
)
3532 proto_tree_add_text(gsm_sms_tree
,
3534 "Message dissector not implemented");
3538 (*msg_fcn
)(tvb
, pinfo
, gsm_sms_tree
, offset
);
3544 /* Register the protocol with Wireshark */
3546 proto_register_gsm_sms(void)
3550 module_t
*gsm_sms_module
; /* Preferences for GSM SMS UD */
3552 /* Setup list of header fields */
3553 static hf_register_info hf
[] =
3555 { &hf_gsm_sms_coding_group_bits2
,
3556 { "Coding Group Bits", "gsm_sms.coding_group_bits2",
3557 FT_UINT8
, BASE_DEC
, VALS(gsm_sms_coding_group_bits_vals
), 0xc0,
3560 { &hf_gsm_sms_coding_group_bits4
,
3561 { "Coding Group Bits", "gsm_sms.coding_group_bits4",
3562 FT_UINT8
, BASE_DEC
, VALS(gsm_sms_coding_group_bits_vals
), 0xf0,
3567 * Short Message fragment reassembly
3569 { &hf_gsm_sms_ud_fragments
,
3570 { "Short Message fragments", "gsm_sms.fragments",
3571 FT_NONE
, BASE_NONE
, NULL
, 0x00,
3572 "GSM Short Message fragments", HFILL
}
3574 { &hf_gsm_sms_ud_fragment
,
3575 { "Short Message fragment", "gsm_sms.fragment",
3576 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
3577 "GSM Short Message fragment", HFILL
}
3579 { &hf_gsm_sms_ud_fragment_overlap
,
3580 { "Short Message fragment overlap", "gsm_sms.fragment.overlap",
3581 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3582 "GSM Short Message fragment overlaps with other fragment(s)", HFILL
}
3584 { &hf_gsm_sms_ud_fragment_overlap_conflicts
,
3585 { "Short Message fragment overlapping with conflicting data", "gsm_sms.fragment.overlap.conflicts",
3586 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3587 "GSM Short Message fragment overlaps with conflicting data", HFILL
}
3589 { &hf_gsm_sms_ud_fragment_multiple_tails
,
3590 { "Short Message has multiple tail fragments", "gsm_sms.fragment.multiple_tails",
3591 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3592 "GSM Short Message fragment has multiple tail fragments", HFILL
}
3594 { &hf_gsm_sms_ud_fragment_too_long_fragment
,
3595 { "Short Message fragment too long", "gsm_sms.fragment.too_long_fragment",
3596 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
3597 "GSM Short Message fragment data goes beyond the packet end", HFILL
}
3599 { &hf_gsm_sms_ud_fragment_error
,
3600 { "Short Message defragmentation error", "gsm_sms.fragment.error",
3601 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
3602 "GSM Short Message defragmentation error due to illegal fragments", HFILL
}
3604 { &hf_gsm_sms_ud_fragment_count
,
3605 { "Short Message fragment count", "gsm_sms.fragment.count",
3606 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
3609 { &hf_gsm_sms_ud_reassembled_in
,
3610 { "Reassembled in", "gsm_sms.reassembled.in",
3611 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x00,
3612 "GSM Short Message has been reassembled in this packet.", HFILL
}
3614 { &hf_gsm_sms_ud_reassembled_length
,
3615 { "Reassembled Short Message length", "gsm_sms.reassembled.length",
3616 FT_UINT32
, BASE_DEC
, NULL
, 0x00,
3617 "The total length of the reassembled payload", HFILL
}
3619 { &hf_gsm_sms_ud_multiple_messages_msg_id
,
3620 { "Message identifier", "gsm_sms.udh.mm.msg_id",
3621 FT_UINT16
, BASE_DEC
, NULL
, 0x00,
3622 "Identification of the message", HFILL
}
3624 { &hf_gsm_sms_ud_multiple_messages_msg_parts
,
3625 { "Message parts", "gsm_sms.udh.mm.msg_parts",
3626 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
3627 "Total number of message parts (fragments)", HFILL
}
3629 { &hf_gsm_sms_ud_multiple_messages_msg_part
,
3630 { "Message part number", "gsm_sms.udh.mm.msg_part",
3631 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
3632 "Message part (fragment) sequence number", HFILL
}
3634 /* TPDU parameters */
3635 { &hf_gsm_sms_tp_mti_up
,
3636 { "TP-MTI", "gsm_sms.tp-mti",
3637 FT_UINT8
, BASE_DEC
, VALS(msg_type_strings_ms_to_sc
), 0x03,
3638 "TP-Message-Type-Indicator (in the direction MS to SC)", HFILL
}
3640 { &hf_gsm_sms_tp_mti_down
,
3641 { "TP-MTI", "gsm_sms.tp-mti",
3642 FT_UINT8
, BASE_DEC
, VALS(msg_type_strings_sc_to_ms
), 0x03,
3643 "TP-Message-Type-Indicator (in the direction SC to MS)", HFILL
}
3645 { &hf_gsm_sms_tp_oa
,
3646 { "TP-OA Digits", "gsm_sms.tp-oa",
3647 FT_STRING
, BASE_NONE
, NULL
, 0x00,
3648 "TP-Originating-Address Digits", HFILL
}
3650 { &hf_gsm_sms_tp_da
,
3651 { "TP-DA Digits", "gsm_sms.tp-da",
3652 FT_STRING
, BASE_NONE
, NULL
, 0x00,
3653 "TP-Destination-Address Digits", HFILL
}
3655 { &hf_gsm_sms_tp_ra
,
3656 { "TP-RA Digits", "gsm_sms.tp-ra",
3657 FT_STRING
, BASE_NONE
, NULL
, 0x00,
3658 "TP-Recipient-Address Digits", HFILL
}
3660 { &hf_gsm_sms_tp_pid
,
3661 { "TP-PID", "gsm_sms.tp-pid",
3662 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
3663 "TP-Protocol-Identifier", HFILL
}
3665 { &hf_gsm_sms_tp_dcs
,
3666 { "TP-DCS", "gsm_sms.tp-dcs",
3667 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
3668 "TP-Data-Coding-Scheme", HFILL
}
3670 { &hf_gsm_sms_tp_mr
,
3671 { "TP-MR", "gsm_sms.tp-mr",
3672 FT_UINT8
, BASE_DEC
, NULL
, 0x00,
3673 "TP-Message-Reference", HFILL
}
3675 { &hf_gsm_sms_tp_mms
,
3676 { "TP-MMS", "gsm_sms.tp-mms",
3677 FT_BOOLEAN
, 8, TFS(&mms_bool_strings
), 0x04,
3678 "TP-More-Messages-to-Send", HFILL
}
3680 { &hf_gsm_sms_tp_sri
,
3681 { "TP-SRI", "gsm_sms.tp-sri",
3682 FT_BOOLEAN
, 8, TFS(&sri_bool_strings
), 0x20,
3683 "TP-Status-Report-Indication", HFILL
}
3685 { &hf_gsm_sms_tp_srr
,
3686 { "TP-SRR", "gsm_sms.tp-srr",
3687 FT_BOOLEAN
, 8, TFS(&srr_bool_strings
), 0x20,
3688 "TP-Status-Report-Request", HFILL
}
3690 { &hf_gsm_sms_tp_udhi
,
3691 { "TP-UDHI", "gsm_sms.tp-udhi",
3692 FT_BOOLEAN
, 8, TFS(&udhi_bool_strings
), 0x40,
3693 "TP-User-Data-Header-Indicator", HFILL
}
3695 { &hf_gsm_sms_tp_rp
,
3696 { "TP-RP", "gsm_sms.tp-rp",
3697 FT_BOOLEAN
, 8, TFS(&rp_bool_strings
), 0x80,
3698 "TP-Reply-Path", HFILL
}
3700 { &hf_gsm_sms_tp_vpf
,
3701 { "TP-VPF", "gsm_sms.tp-vpf",
3702 FT_UINT8
, BASE_DEC
, VALS(vp_type_strings
), 0x18,
3703 "TP-Validity-Period-Format", HFILL
}
3705 { &hf_gsm_sms_tp_rd
,
3706 { "TP-RD", "gsm_sms.tp-rd",
3707 FT_BOOLEAN
, 8, TFS(&rd_bool_strings
), 0x04,
3708 "TP-Reject-Duplicates", HFILL
}
3710 { &hf_gsm_sms_tp_srq
,
3711 { "TP-SRQ", "gsm_sms.tp-srq",
3712 FT_BOOLEAN
, 8, TFS(&srq_bool_strings
), 0x20,
3713 "TP-Status-Report-Qualifier", HFILL
}
3716 { "SMS text", "gsm_sms.sms_text",
3717 FT_STRING
, BASE_NONE
, NULL
, 0x00,
3718 "The text of the SMS", HFILL
}
3720 { &hf_gsm_sms_tp_fail_cause
,
3721 { "TP-Failure-Cause (TP-FCS)", "gsm_sms.tp-fcs",
3722 FT_UINT8
, BASE_HEX_DEC
|BASE_EXT_STRING
, &gsm_sms_tp_failure_cause_values_ext
, 0x0,
3723 "TP-Validity-Period-Format", HFILL
}
3727 /* Setup protocol subtree array */
3728 #define NUM_INDIVIDUAL_PARMS 12
3729 gint
*ett
[NUM_INDIVIDUAL_PARMS
/*+NUM_MSGS*/+NUM_UDH_IEIS
+2];
3731 ett
[0] = &ett_gsm_sms
;
3744 last_offset
= NUM_INDIVIDUAL_PARMS
;
3747 for (i
=0; i
< NUM_MSGS
; i
++, last_offset
++)
3750 ett
[last_offset
] = &ett_msgs
[i
];
3754 for (i
=0; i
< NUM_UDH_IEIS
; i
++, last_offset
++)
3756 ett_udh_ieis
[i
] = -1;
3757 ett
[last_offset
] = &ett_udh_ieis
[i
];
3760 ett
[last_offset
++] = &ett_gsm_sms_ud_fragment
;
3761 ett
[last_offset
] = &ett_gsm_sms_ud_fragments
;
3763 /* Register the protocol name and description */
3766 proto_register_protocol(gsm_sms_proto_name
, gsm_sms_proto_name_short
, "gsm_sms");
3769 proto_register_field_array(proto_gsm_sms
, hf
, array_length(hf
));
3771 proto_register_subtree_array(ett
, array_length(ett
));
3773 gsm_sms_dissector_tbl
= register_dissector_table("gsm_sms.udh.port",
3774 "GSM SMS port IE in UDH", FT_UINT16
, BASE_DEC
);
3776 gsm_sms_module
= prefs_register_protocol (proto_gsm_sms
, NULL
);
3778 prefs_register_obsolete_preference(gsm_sms_module
,
3779 "try_dissect_message_fragment");
3780 prefs_register_bool_preference (gsm_sms_module
, "reassemble",
3781 "Reassemble fragmented SMS",
3782 "Whether the dissector should reassemble SMS spanning multiple packets",
3785 register_dissector("gsm_sms", dissect_gsm_sms
, proto_gsm_sms
);
3787 /* GSM SMS UD dissector initialization routines */
3788 register_init_routine (gsm_sms_defragment_init
);
3793 proto_reg_handoff_gsm_sms(void)