bdaf7d29d234fb29d5a94d790d6613e87253478d
[obnox/wireshark/wip.git] / packet-smpp.c
1 /* packet-smpp.c
2  * Routines for Short Message Peer to Peer dissection
3  * Copyright 2001, Tom Uijldert <tom.uijldert@cmg.nl>
4  *
5  * UDH and WSP dissection of SMS message, Short Message reassembly,
6  * "Decode Short Message with Port Number UDH as CL-WSP" preference,
7  * "Always try subdissection of 1st fragment" preference,
8  * Data Coding Scheme decoding for GSM (SMS and CBS),
9  * provided by Olivier Biot.
10  *
11  * Dissection of multiple SMPP PDUs within one packet
12  * provided by Chris Wilson.
13  *
14  * $Id: packet-smpp.c,v 1.27 2004/01/20 17:58:37 obiot Exp $
15  *
16  * Note on SMS Message reassembly
17  * ------------------------------
18  *   The current Short Message reassembly is possible thanks to the
19  *   message identifier (8 or 16 bit identifier). It is able to reassemble
20  *   short messages that are sent over either the same SMPP connection or
21  *   distinct SMPP connections. Normally the reassembly code is able to deal
22  *   with duplicate message identifiers since the fragment_add_seq_check()
23  *   call is used.
24  *
25  *   The SMPP preference "always try subdissection of 1st fragment" allows
26  *   a subdissector to be called for the first Short Message fragment,
27  *   even if reassembly is not possible. This way partial dissection
28  *   is still possible. This preference is switched off by default.
29  *
30  * Note on Short Message decoding as CL-WSP
31  * ----------------------------------------
32  *    The SMPP preference "port_number_udh_means_wsp" is switched off
33  *    by default. If it is enabled, then any Short Message with a Port Number
34  *    UDH will be decoded as CL-WSP if:
35  *    -  The Short Message is not segmented
36  *    -  The entire segmented Short Message is reassembled
37  *    -  It is the 1st segment of an unreassembled Short Message (if the
38  *       "always try subdissection of 1st fragment" preference is enabled)
39  *
40  * Ethereal - Network traffic analyzer
41  * By Gerald Combs <gerald@ethereal.com>
42  * Copyright 1998 Gerald Combs
43  *
44  * This program is free software; you can redistribute it and/or
45  * modify it under the terms of the GNU General Public License
46  * as published by the Free Software Foundation; either version 2
47  * of the License, or (at your option) any later version.
48  *
49  * This program is distributed in the hope that it will be useful,
50  * but WITHOUT ANY WARRANTY; without even the implied warranty of
51  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
52  * GNU General Public License for more details.
53  *
54  * You should have received a copy of the GNU General Public License
55  * along with this program; if not, write to the Free Software
56  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
57  * ----------
58  *
59  * Dissector of an SMPP (Short Message Peer to Peer) PDU, as defined by the
60  * SMS forum (www.smsforum.net) in "SMPP protocol specification v3.4"
61  * (document version: 12-Oct-1999 Issue 1.2)
62  */
63
64 #ifdef HAVE_CONFIG_H
65 # include "config.h"
66 #endif
67
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <time.h>
72
73 #include <glib.h>
74
75 #include <epan/packet.h>
76
77 #include "prefs.h"
78 #include "reassemble.h"
79 #include "packet-tcp.h"
80
81 /* General-purpose debug logger.
82  * Requires double parentheses because of variable arguments of printf().
83  *
84  * Enable debug logging for SMPP by defining AM_CFLAGS
85  * so that it contains "-DDEBUG_smpp"
86  */
87 #ifdef DEBUG_smpp
88 #define DebugLog(x) \
89         printf("%s:%u: ", __FILE__, __LINE__); \
90         printf x; \
91         fflush(stdout)
92 #else
93 #define DebugLog(x) ;
94 #endif
95
96 /* Forward declarations         */
97 static void dissect_smpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
98 static guint get_smpp_pdu_len(tvbuff_t *tvb, int offset);
99 static void dissect_smpp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
100
101 static void dissect_smpp_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
102
103 /*
104  * Initialize the protocol and registered fields
105  *
106  * Fixed header section
107  */
108 static int proto_smpp                           = -1;
109 static int proto_smpp_gsm_sms           = -1;
110
111 static int hf_smpp_command_id                   = -1;
112 static int hf_smpp_command_length               = -1;
113 static int hf_smpp_command_status               = -1;
114 static int hf_smpp_sequence_number              = -1;
115
116 /*
117  * Fixed body section
118  */
119 static int hf_smpp_system_id                    = -1;
120 static int hf_smpp_password                     = -1;
121 static int hf_smpp_system_type                  = -1;
122 static int hf_smpp_interface_version            = -1;
123 static int hf_smpp_addr_ton                     = -1;
124 static int hf_smpp_addr_npi                     = -1;
125 static int hf_smpp_address_range                = -1;
126 static int hf_smpp_service_type                 = -1;
127 static int hf_smpp_source_addr_ton              = -1;
128 static int hf_smpp_source_addr_npi              = -1;
129 static int hf_smpp_source_addr                  = -1;
130 static int hf_smpp_dest_addr_ton                = -1;
131 static int hf_smpp_dest_addr_npi                = -1;
132 static int hf_smpp_destination_addr             = -1;
133 static int hf_smpp_esm_submit_msg_mode          = -1;
134 static int hf_smpp_esm_submit_msg_type          = -1;
135 static int hf_smpp_esm_submit_features          = -1;
136 static int hf_smpp_protocol_id                  = -1;
137 static int hf_smpp_priority_flag                = -1;
138 static int hf_smpp_schedule_delivery_time       = -1;
139 static int hf_smpp_schedule_delivery_time_r     = -1;
140 static int hf_smpp_validity_period              = -1;
141 static int hf_smpp_validity_period_r            = -1;
142 static int hf_smpp_regdel_receipt               = -1;
143 static int hf_smpp_regdel_acks                  = -1;
144 static int hf_smpp_regdel_notif                 = -1;
145 static int hf_smpp_replace_if_present_flag      = -1;
146 static int hf_smpp_data_coding                  = -1;
147 static int hf_smpp_sm_default_msg_id            = -1;
148 static int hf_smpp_sm_length                    = -1;
149 static int hf_smpp_short_message                = -1;
150 static int hf_smpp_message_id                   = -1;
151 static int hf_smpp_dlist                        = -1;
152 static int hf_smpp_dlist_resp                   = -1;
153 static int hf_smpp_dl_name                      = -1;
154 static int hf_smpp_final_date                   = -1;
155 static int hf_smpp_final_date_r                 = -1;
156 static int hf_smpp_message_state                = -1;
157 static int hf_smpp_error_code                   = -1;
158 static int hf_smpp_error_status_code            = -1;
159 static int hf_smpp_esme_addr_ton                = -1;
160 static int hf_smpp_esme_addr_npi                = -1;
161 static int hf_smpp_esme_addr                    = -1;
162
163 /*
164  * Optional parameter section
165  */
166 static int hf_smpp_opt_param                    = -1;
167 static int hf_smpp_vendor_op                    = -1;
168 static int hf_smpp_reserved_op                  = -1;
169
170 static int hf_smpp_dest_addr_subunit            = -1;
171 static int hf_smpp_dest_network_type            = -1;
172 static int hf_smpp_dest_bearer_type             = -1;
173 static int hf_smpp_dest_telematics_id           = -1;
174 static int hf_smpp_source_addr_subunit          = -1;
175 static int hf_smpp_source_network_type          = -1;
176 static int hf_smpp_source_bearer_type           = -1;
177 static int hf_smpp_source_telematics_id         = -1;
178 static int hf_smpp_qos_time_to_live             = -1;
179 static int hf_smpp_payload_type                 = -1;
180 static int hf_smpp_additional_status_info_text  = -1;
181 static int hf_smpp_receipted_message_id         = -1;
182 static int hf_smpp_msg_wait_ind                 = -1;
183 static int hf_smpp_msg_wait_type                = -1;
184 static int hf_smpp_privacy_indicator            = -1;
185 static int hf_smpp_source_subaddress            = -1;
186 static int hf_smpp_dest_subaddress              = -1;
187 static int hf_smpp_user_message_reference       = -1;
188 static int hf_smpp_user_response_code           = -1;
189 static int hf_smpp_source_port                  = -1;
190 static int hf_smpp_destination_port             = -1;
191 static int hf_smpp_sar_msg_ref_num              = -1;
192 static int hf_smpp_language_indicator           = -1;
193 static int hf_smpp_sar_total_segments           = -1;
194 static int hf_smpp_sar_segment_seqnum           = -1;
195 static int hf_smpp_SC_interface_version         = -1;
196 static int hf_smpp_callback_num_pres            = -1;
197 static int hf_smpp_callback_num_scrn            = -1;
198 static int hf_smpp_callback_num_atag            = -1;
199 static int hf_smpp_number_of_messages           = -1;
200 static int hf_smpp_callback_num                 = -1;
201 static int hf_smpp_dpf_result                   = -1;
202 static int hf_smpp_set_dpf                      = -1;
203 static int hf_smpp_ms_availability_status       = -1;
204 static int hf_smpp_network_error_type           = -1;
205 static int hf_smpp_network_error_code           = -1;
206 static int hf_smpp_message_payload              = -1;
207 static int hf_smpp_delivery_failure_reason      = -1;
208 static int hf_smpp_more_messages_to_send        = -1;
209 static int hf_smpp_ussd_service_op              = -1;
210 static int hf_smpp_display_time                 = -1;
211 static int hf_smpp_sms_signal                   = -1;
212 static int hf_smpp_ms_validity                  = -1;
213 static int hf_smpp_alert_on_message_delivery    = -1;
214 static int hf_smpp_its_reply_type               = -1;
215 static int hf_smpp_its_session_number           = -1;
216 static int hf_smpp_its_session_sequence         = -1;
217 static int hf_smpp_its_session_ind              = -1;
218
219 /*
220  * Data Coding Scheme section
221  */
222 static int hf_smpp_dcs = -1;
223 static int hf_smpp_dcs_sms_coding_group = -1;
224 static int hf_smpp_dcs_text_compression = -1;
225 static int hf_smpp_dcs_class_present = -1;
226 static int hf_smpp_dcs_charset = -1;
227 static int hf_smpp_dcs_class = -1;
228 static int hf_smpp_dcs_cbs_coding_group = -1;
229 static int hf_smpp_dcs_cbs_language = -1;
230 static int hf_smpp_dcs_wap_charset = -1;
231 static int hf_smpp_dcs_wap_class = -1;
232 static int hf_smpp_dcs_cbs_class = -1;
233
234 /*
235  * User Data Header section
236  */
237 static int hf_smpp_udh_length   = -1;
238 static int hf_smpp_udh_iei              = -1;
239 static int hf_smpp_udh_multiple_messages                        = -1;
240 static int hf_smpp_udh_multiple_messages_msg_id         = -1;
241 static int hf_smpp_udh_multiple_messages_msg_parts      = -1;
242 static int hf_smpp_udh_multiple_messages_msg_part       = -1;
243 static int hf_smpp_udh_ports            = -1;
244 static int hf_smpp_udh_ports_src        = -1;
245 static int hf_smpp_udh_ports_dst        = -1;
246
247 /*
248  * Short Message fragment handling
249  */
250 static int hf_sm_fragments                                      = -1;
251 static int hf_sm_fragment                                       = -1;
252 static int hf_sm_fragment_overlap                       = -1;
253 static int hf_sm_fragment_overlap_conflicts     = -1;
254 static int hf_sm_fragment_multiple_tails        = -1;
255 static int hf_sm_fragment_too_long_fragment     = -1;
256 static int hf_sm_fragment_error                         = -1;
257 static int hf_sm_reassembled_in                         = -1;
258
259 /* Initialize the subtree pointers */
260 static gint ett_smpp            = -1;
261 static gint ett_dlist           = -1;
262 static gint ett_dlist_resp      = -1;
263 static gint ett_opt_param       = -1;
264 static gint ett_dcs             = -1;
265 static gint ett_gsm_sms         = -1;
266 static gint ett_udh             = -1;
267 static gint ett_udh_ie          = -1;
268 static gint ett_sm_fragment     = -1;
269 static gint ett_sm_fragments    = -1;
270
271 /* Subdissector declarations */
272 static dissector_table_t gsm_sms_dissector_table;
273
274 /* Short Message reassembly */
275 static GHashTable *sm_fragment_table = NULL;
276 static GHashTable *sm_reassembled_table = NULL;
277
278 static const fragment_items sm_frag_items = {
279         /* Fragment subtrees */
280         &ett_sm_fragment,
281         &ett_sm_fragments,
282         /* Fragment fields */
283         &hf_sm_fragments,
284         &hf_sm_fragment,
285         &hf_sm_fragment_overlap,
286         &hf_sm_fragment_overlap_conflicts,
287         &hf_sm_fragment_multiple_tails,
288         &hf_sm_fragment_too_long_fragment,
289         &hf_sm_fragment_error,
290         /* Reassembled in field */
291         &hf_sm_reassembled_in,
292         /* Tag */
293         "Short Message fragments"
294 };
295
296 /* Reassemble SMPP TCP segments */
297 static gboolean reassemble_over_tcp = FALSE;
298 /* Dissect all SM data as WSP if the UDH contains a Port Number IE */
299 static gboolean port_number_udh_means_wsp = FALSE;
300 /* Always try dissecting the 1st fragment of a SM,
301  * even if it is not reassembled */
302 static gboolean try_dissect_1st_frag = FALSE;
303
304 /* For SMPP */
305 static dissector_handle_t wsp_handle;
306 static dissector_handle_t gsm_sms_handle;
307
308 static void
309 sm_defragment_init (void)
310 {
311         fragment_table_init (&sm_fragment_table);
312         reassembled_table_init(&sm_reassembled_table);
313 }
314
315 /*
316  * Value-arrays for field-contents
317  */
318 static const value_string vals_command_id[] = {         /* Operation    */
319     { 0x80000000, "Generic_nack" },
320     { 0x00000001, "Bind_receiver" },
321     { 0x80000001, "Bind_receiver - resp" },
322     { 0x00000002, "Bind_transmitter" },
323     { 0x80000002, "Bind_transmitter - resp" },
324     { 0x00000003, "Query_sm" },
325     { 0x80000003, "Query_sm - resp" },
326     { 0x00000004, "Submit_sm" },
327     { 0x80000004, "Submit_sm - resp" },
328     { 0x00000005, "Deliver_sm" },
329     { 0x80000005, "Deliver_sm - resp" },
330     { 0x00000006, "Unbind" },
331     { 0x80000006, "Unbind - resp" },
332     { 0x00000007, "Replace_sm" },
333     { 0x80000007, "Replace_sm - resp" },
334     { 0x00000008, "Cancel_sm" },
335     { 0x80000008, "Cancel_sm - resp" },
336     { 0x00000009, "Bind_transceiver" },
337     { 0x80000009, "Bind_transceiver - resp" },
338     { 0x0000000B, "Outbind" },
339     { 0x00000015, "Enquire_link" },
340     { 0x80000015, "Enquire_link - resp" },
341     { 0x00000021, "Submit_multi" },
342     { 0x80000021, "Submit_multi - resp" },
343     { 0x00000102, "Alert_notification" },
344     { 0x00000103, "Data_sm" },
345     { 0x80000103, "Data_sm - resp" },
346     { 0, NULL }
347 };
348
349 static const value_string vals_command_status[] = {     /* Status       */
350     { 0x00000000, "Ok" },
351     { 0x00000001, "Message length is invalid" },
352     { 0x00000002, "Command length is invalid" },
353     { 0x00000003, "Invalid command ID" },
354     { 0x00000004, "Incorrect BIND status for given command" },
355     { 0x00000005, "ESME already in bound state" },
356     { 0x00000006, "Invalid priority flag" },
357     { 0x00000007, "Invalid registered delivery flag" },
358     { 0x00000008, "System error" },
359     { 0x00000009, "[Reserved]" },
360     { 0x0000000A, "Invalid source address" },
361     { 0x0000000B, "Invalid destination address" },
362     { 0x0000000C, "Message ID is invalid" },
363     { 0x0000000D, "Bind failed" },
364     { 0x0000000E, "Invalid password" },
365     { 0x0000000F, "Invalid system ID" },
366     { 0x00000010, "[Reserved]" },
367     { 0x00000011, "Cancel SM failed" },
368     { 0x00000012, "[Reserved]" },
369     { 0x00000013, "Replace SM failed" },
370     { 0x00000014, "Message queue full" },
371     { 0x00000015, "Invalid service type" },
372     { 0x00000033, "Invalid number of destinations" },
373     { 0x00000034, "Invalid distribution list name" },
374     { 0x00000040, "Destination flag is invalid (submit_multi)" },
375     { 0x00000041, "[Reserved]" },
376     { 0x00000042, "Invalid 'submit with replace' request" },
377     { 0x00000043, "Invalid esm_class field data" },
378     { 0x00000044, "Cannot submit to distribution list" },
379     { 0x00000045, "submit_sm or submit_multi failed" },
380     { 0x00000046, "[Reserved]" },
381     { 0x00000047, "[Reserved]" },
382     { 0x00000048, "Invalid source address TON" },
383     { 0x00000049, "Invalid source address NPI" },
384     { 0x00000050, "Invalid destination address TON" },
385     { 0x00000051, "Invalid destination address NPI" },
386     { 0x00000052, "[Reserved]" },
387     { 0x00000053, "Invalid system_type field" },
388     { 0x00000054, "Invalid replace_if_present flag" },
389     { 0x00000055, "Invalid number of messages" },
390     { 0x00000056, "[Reserved]" },
391     { 0x00000057, "[Reserved]" },
392     { 0x00000058, "Throttling error (ESME exceeded allowed message limits)" },
393     { 0x00000059, "[Reserved]" },
394     { 0x00000060, "[Reserved]" },
395     { 0x00000061, "Invalid scheduled delivery time" },
396     { 0x00000062, "Invalid message validity period (expirey time)" },
397     { 0x00000063, "Predefined message invalid or not found" },
398     { 0x00000064, "ESME receiver temporary app error code" },
399     { 0x00000065, "ESME receiver permanent app error code" },
400     { 0x00000066, "ESME receiver reject message error code" },
401     { 0x00000067, "query_sm request failed" },
402     { 0x000000C0, "Error in the optional part of the PDU body" },
403     { 0x000000C1, "Optional parameter not allowed" },
404     { 0x000000C2, "Invalid parameter length" },
405     { 0x000000C3, "Expected optional parameter missing" },
406     { 0x000000C4, "Invalid optional parameter  value" },
407     { 0x000000FE, "Delivery failure (used for data_sm_resp)" },
408     { 0x000000FF, "Unknown error" },
409     { 0, NULL }
410 };
411
412 static const value_string vals_addr_ton[] = {
413     { 0, "Unknown" },
414     { 1, "International" },
415     { 2, "National" },
416     { 3, "Network specific" },
417     { 4, "Subscriber number" },
418     { 5, "Alphanumeric" },
419     { 6, "Abbreviated" },
420     { 0, NULL }
421 };
422
423 static const value_string vals_addr_npi[] = {
424     {  0, "Unknown" },
425     {  1, "ISDN (E163/E164)" },
426     {  3, "Data (X.121)" },
427     {  4, "Telex (F.69)" },
428     {  6, "Land mobile (E.212)" },
429     {  8, "National" },
430     {  9, "Private" },
431     { 10, "ERMES" },
432     { 14, "Internet (IP)" },
433     { 18, "WAP client Id" },
434     {  0, NULL }
435 };
436
437 static const value_string vals_esm_submit_msg_mode[] = {
438     {  0x0, "Default SMSC mode" },
439     {  0x1, "Datagram mode" },
440     {  0x2, "Forward mode" },
441     {  0x3, "Store and forward mode" },
442     {  0, NULL }
443 };
444
445 static const value_string vals_esm_submit_msg_type[] = {
446     {  0x0, "Default message type" },
447     {  0x1, "Short message contains SMSC Delivery Receipt" },
448     {  0x2, "Short message contains (E)SME delivery acknowledgement" },
449     {  0x3, "Reserved" },
450     {  0x4, "Short message contains (E)SME manual/user acknowledgement" },
451     {  0x5, "Reserved" },
452     {  0x6, "Short message contains conversation abort" },
453     {  0x7, "Reserved" },
454     {  0x8, "Short message contains intermediate delivery notification" },
455     {  0, NULL }
456 };
457
458 static const value_string vals_esm_submit_features[] = {
459     {  0x0, "No specific features selected" },
460     {  0x1, "UDHI indicator" },
461     {  0x2, "Reply path" },
462     {  0x3, "UDHI and reply path" },
463     {  0, NULL }
464 };
465
466 static const value_string vals_priority_flag[] = {
467     {  0, "GSM: None      ANSI-136: Bulk         IS-95: Normal" },
468     {  1, "GSM: priority  ANSI-136: Normal       IS-95: Interactive" },
469     {  2, "GSM: priority  ANSI-136: Urgent       IS-95: Urgent" },
470     {  3, "GSM: priority  ANSI-136: Very Urgent  IS-95: Emergency" },
471     {  0, NULL }
472 };
473
474 static const value_string vals_regdel_receipt[] = {
475     {  0x0, "No SMSC delivery receipt requested" },
476     {  0x1, "Delivery receipt requested (for success or failure)" },
477     {  0x2, "Delivery receipt requested (for failure)" },
478     {  0x3, "Reserved" },
479     {  0, NULL }
480 };
481
482 static const value_string vals_regdel_acks[] = {
483     {  0x0, "No recipient SME acknowledgement requested" },
484     {  0x1, "SME delivery acknowledgement requested" },
485     {  0x2, "SME manual/user acknowledgement requested" },
486     {  0x3, "Both delivery and manual/user acknowledgement requested" },
487     {  0, NULL }
488 };
489
490 static const value_string vals_regdel_notif[] = {
491     {  0x0, "No intermediate notification requested" },
492     {  0x1, "Intermediate notification requested" },
493     {  0, NULL }
494 };
495
496 static const value_string vals_replace_if_present_flag[] = {
497     {  0x0, "Don't replace" },
498     {  0x1, "Replace" },
499     {  0, NULL }
500 };
501
502 static const value_string vals_data_coding[] = {
503     {  0, "SMSC default alphabet" },
504     {  1, "IA5 (CCITT T.50/ASCII (ANSI X3.4)" },
505     {  2, "Octet unspecified (8-bit binary)" },
506     {  3, "Latin 1 (ISO-8859-1)" },
507     {  4, "Octet unspecified (8-bit binary)" },
508     {  5, "JIS (X 0208-1990)" },
509     {  6, "Cyrillic (ISO-8859-5)" },
510     {  7, "Latin/Hebrew (ISO-8859-8)" },
511     {  8, "UCS2 (ISO/IEC-10646)" },
512     {  9, "Pictogram encoding" },
513     {  10, "ISO-2022-JP (Music codes)" },
514     {  11, "reserved" },
515     {  12, "reserved" },
516     {  13, "Extended Kanji JIS(X 0212-1990)" },
517     {  14, "KS C 5601" },
518     /*! \todo Rest to be defined (bitmask?) according GSM 03.38 */
519     {  0, NULL }
520 };
521
522 static const value_string vals_message_state[] = {
523     {  1, "ENROUTE" },
524     {  2, "DELIVERED" },
525     {  3, "EXPIRED" },
526     {  4, "DELETED" },
527     {  5, "UNDELIVERABLE" },
528     {  6, "ACCEPTED" },
529     {  7, "UNKNOWN" },
530     {  8, "REJECTED" },
531     {  0, NULL }
532 };
533
534 static const value_string vals_addr_subunit[] = {
535     {  0, "Unknown -default-" },
536     {  1, "MS Display" },
537     {  2, "Mobile equipment" },
538     {  3, "Smart card 1" },
539     {  4, "External unit 1" },
540     {  0, NULL }
541 };
542
543 static const value_string vals_network_type[] = {
544     {  0, "Unknown" },
545     {  1, "GSM" },
546     {  2, "ANSI-136/TDMA" },
547     {  3, "IS-95/CDMA" },
548     {  4, "PDC" },
549     {  5, "PHS" },
550     {  6, "iDEN" },
551     {  7, "AMPS" },
552     {  8, "Paging network" },
553     {  0, NULL }
554 };
555
556 static const value_string vals_bearer_type[] = {
557     {  0, "Unknown" },
558     {  1, "SMS" },
559     {  2, "Circuit Switched Data (CSD)" },
560     {  3, "Packet data" },
561     {  4, "USSD" },
562     {  5, "CDPD" },
563     {  6, "DataTAC" },
564     {  7, "FLEX/ReFLEX" },
565     {  8, "Cell Broadcast" },
566     {  0, NULL }
567 };
568
569 static const value_string vals_payload_type[] = {
570     {  0, "Default" },
571     {  1, "WCMP message" },
572     {  0, NULL }
573 };
574
575 static const value_string vals_privacy_indicator[] = {
576     {  0, "Not restricted -default-" },
577     {  1, "Restricted" },
578     {  2, "Confidential" },
579     {  3, "Secret" },
580     {  0, NULL }
581 };
582
583 static const value_string vals_language_indicator[] = {
584     {  0, "Unspecified -default-" },
585     {  1, "english" },
586     {  2, "french" },
587     {  3, "spanish" },
588     {  4, "german" },
589     {  5, "portuguese" },
590     {  0, NULL }
591 };
592
593 static const value_string vals_display_time[] = {
594     {  0, "Temporary" },
595     {  1, "Default -default-" },
596     {  2, "Invoke" },
597     {  0, NULL }
598 };
599
600 static const value_string vals_ms_validity[] = {
601     {  0, "Store indefinitely -default-" },
602     {  1, "Power down" },
603     {  2, "SID based registration area" },
604     {  3, "Display only" },
605     {  0, NULL }
606 };
607
608 static const value_string vals_dpf_result[] = {
609     {  0, "DPF not set" },
610     {  1, "DPF set" },
611     {  0, NULL }
612 };
613
614 static const value_string vals_set_dpf[] = {
615     {  0, "Not requested (Set DPF for delivery failure)" },
616     {  1, "Requested (Set DPF for delivery failure)" },
617     {  0, NULL }
618 };
619
620 static const value_string vals_ms_availability_status[] = {
621     {  0, "Available -default-" },
622     {  1, "Denied" },
623     {  2, "Unavailable" },
624     {  0, NULL }
625 };
626
627 static const value_string vals_delivery_failure_reason[] = {
628     {  0, "Destination unavailable" },
629     {  1, "Destination address invalid" },
630     {  2, "Permanent network error" },
631     {  3, "Temporary network error" },
632     {  0, NULL }
633 };
634
635 static const value_string vals_more_messages_to_send[] = {
636     {  0, "No more messages" },
637     {  1, "More messages -default-" },
638     {  0, NULL }
639 };
640
641 static const value_string vals_its_reply_type[] = {
642     {  0, "Digit" },
643     {  1, "Number" },
644     {  2, "Telephone no." },
645     {  3, "Password" },
646     {  4, "Character line" },
647     {  5, "Menu" },
648     {  6, "Date" },
649     {  7, "Time" },
650     {  8, "Continue" },
651     {  0, NULL }
652 };
653
654 static const value_string vals_ussd_service_op[] = {
655     {  0, "PSSD indication" },
656     {  1, "PSSR indication" },
657     {  2, "USSR request" },
658     {  3, "USSN request" },
659     { 16, "PSSD response" },
660     { 17, "PSSR response" },
661     { 18, "USSR confirm" },
662     { 19, "USSN confirm" },
663     {  0, NULL }
664 };
665
666 static const value_string vals_msg_wait_ind[] = {
667     {  0, "Set indication inactive" },
668     {  1, "Set indication active" },
669     {  0, NULL }
670 };
671
672 static const value_string vals_msg_wait_type[] = {
673     {  0, "Voicemail message waiting" },
674     {  1, "Fax message waiting" },
675     {  2, "Electronic mail message waiting" },
676     {  3, "Other message waiting" },
677     {  0, NULL }
678 };
679
680 static const value_string vals_callback_num_pres[] = {
681     {  0, "Presentation allowed" },
682     {  1, "Presentation restricted" },
683     {  2, "Number not available" },
684     {  3, "[Reserved]" },
685     {  0, NULL }
686 };
687
688 static const value_string vals_callback_num_scrn[] = {
689     {  0, "User provided, not screened" },
690     {  1, "User provided, verified and passed" },
691     {  2, "User provided, verified and failed" },
692     {  3, "Network provided" },
693     {  0, NULL }
694 };
695
696 static const value_string vals_network_error_type[] = {
697     {  1, "ANSI-136" },
698     {  2, "IS-95" },
699     {  3, "GSM" },
700     {  4, "[Reserved]" },
701     {  0, NULL }
702 };
703
704 static const value_string vals_its_session_ind[] = {
705     {  0, "End of session indicator inactive" },
706     {  1, "End of session indicator active" },
707     {  0, NULL }
708 };
709
710 /* Data Coding Scheme: see 3GPP TS 23.040 and 3GPP TS 23.038 */
711 static const value_string vals_dcs_sms_coding_group[] = {
712         { 0x00, "SMS DCS: General Data Coding indication - Uncompressed text, no message class" },
713         { 0x01, "SMS DCS: General Data Coding indication - Uncompressed text" },
714         { 0x02, "SMS DCS: General Data Coding indication - Compressed text, no message class" },
715         { 0x03, "SMS DCS: General Data Coding indication - Compressed text" },
716         { 0x04, "SMS DCS: Message Marked for Automatic Deletion - Uncompressed text, no message class" },
717         { 0x05, "SMS DCS: Message Marked for Automatic Deletion - Uncompressed text" },
718         { 0x06, "SMS DCS: Message Marked for Automatic Deletion - Compressed text, no message class" },
719         { 0x07, "SMS DCS: Message Marked for Automatic Deletion - Compressed text" },
720         { 0x08, "SMS DCS: Reserved" },
721         { 0x09, "SMS DCS: Reserved" },
722         { 0x0A, "SMS DCS: Reserved" },
723         { 0x0B, "SMS DCS: Reserved" },
724         { 0x0C, "SMS DCS: Message Waiting Indication - Discard Message" },
725         { 0x0D, "SMS DCS: Message Waiting Indication - Store Message (GSM 7-bit default alphabet)" },
726         { 0x0E, "SMS DCS: Message Waiting Indication - Store Message (UCS-2 character set)" },
727         { 0x0F, "SMS DCS: Data coding / message class" },
728         { 0x00, NULL }
729 };
730
731 static const true_false_string tfs_dcs_text_compression = {
732         "Compressed text",
733         "Uncompressed text"
734 };
735
736 static const true_false_string tfs_dcs_class_present = {
737         "Message class is present",
738         "No message class"
739 };
740
741 static const value_string vals_dcs_charset[] = {
742         { 0x00, "GSM 7-bit default alphabet" },
743         { 0x01, "8-bit data" },
744         { 0x02, "UCS-2 (16-bit) data" },
745         { 0x03, "Reserved" },
746         { 0x00, NULL }
747 };
748
749 static const value_string vals_dcs_class[] = {
750         { 0x00, "Class 0" },
751         { 0x01, "Class 1 - ME specific" },
752         { 0x02, "Class 2 - (U)SIM specific" },
753         { 0x03, "Class 3 - TE specific" },
754         { 0x00, NULL }
755 };
756
757 static const value_string vals_dcs_cbs_coding_group[] = {
758         { 0x00, "CBS DCS: Language using the GSM 7-bit default alphabet" },
759         { 0x01, "CBS DCS: Language indication at beginning of message" },
760         { 0x02, "CBS DCS: Language using the GSM 7-bit default alphabet" },
761         { 0x03, "CBS DCS: Reserved" },
762         { 0x04, "CBS DCS: General Data Coding indication - Uncompressed text, no message class" },
763         { 0x05, "CBS DCS: General Data Coding indication - Uncompressed text" },
764         { 0x06, "CBS DCS: General Data Coding indication - Compressed text, no message class" },
765         { 0x07, "CBS DCS: General Data Coding indication - Compressed text" },
766         { 0x08, "CBS DCS: Reserved" },
767         { 0x09, "CBS DCS: Message with User Data Header structure" },
768         { 0x0A, "CBS DCS: Reserved" },
769         { 0x0B, "CBS DCS: Reserved" },
770         { 0x0C, "CBS DCS: Reserved" },
771         { 0x0D, "CBS DCS: Reserved" },
772         { 0x0E, "CBS DCS: Defined by the WAP Forum" },
773         { 0x0F, "SMS DCS: Data coding / message class" },
774         { 0x00, NULL }
775 };
776
777 static const value_string vals_dcs_cbs_language[] = {
778         { 0x00, "German" },
779         { 0x01, "English" },
780         { 0x02, "Italian" },
781         { 0x03, "French" },
782         { 0x04, "Spanish" },
783         { 0x05, "Dutch" },
784         { 0x06, "Swedish" },
785         { 0x07, "Danish" },
786         { 0x08, "Portuguese" },
787         { 0x09, "Finnish" },
788         { 0x0A, "Norwegian" },
789         { 0x0B, "Greek" },
790         { 0x0C, "Turkish" },
791         { 0x0D, "Hungarian" },
792         { 0x0E, "Polish" },
793         { 0x0F, "Language not specified" },
794         { 0x10, "GSM 7-bit default alphabet - message preceeded by language indication" },
795         { 0x11, "UCS-2 (16-bit) - message preceeded by language indication" },
796         { 0x20, "Czech" },
797         { 0x21, "Hebrew" },
798         { 0x22, "Arabic" },
799         { 0x23, "Russian" },
800         { 0x24, "Icelandic" },
801         { 0x00, NULL }
802 };
803
804 static const value_string vals_dcs_cbs_class[] = {
805         { 0x00, "No message class" },
806         { 0x01, "Class 1 - User defined" },
807         { 0x02, "Class 2 - User defined" },
808         { 0x03, "Class 3 - TE specific" },
809         { 0x00, NULL }
810 };
811
812 static const value_string vals_dcs_wap_class[] = {
813         { 0x00, "No message class" },
814         { 0x01, "Class 1 - ME specific" },
815         { 0x02, "Class 2 - (U)SIM specific" },
816         { 0x03, "Class 3 - TE specific" },
817         { 0x00, NULL }
818 };
819
820 static const value_string vals_dcs_wap_charset[] = {
821         { 0x00, "Reserved" },
822         { 0x01, "8-bit data" },
823         { 0x02, "Reserved" },
824         { 0x03, "Reserved" },
825         { 0x00, NULL }
826 };
827
828
829 /* 3GPP TS 23.040 V6.1.0 (2003-06) */
830 static const value_string vals_udh_iei[] = {
831         { 0x00, "SMS - Concatenated short messages, 8-bit reference number" },
832         { 0x01, "SMS - Special SMS Message Indication" },
833         { 0x02, "Reserved" },
834         { 0x03, "Value not used to avoid misinterpretation as <LF> character" },
835         { 0x04, "SMS - Application port addressing scheme, 8 bit address" },
836         { 0x05, "SMS - Application port addressing scheme, 16 bit address" },
837         { 0x06, "SMS - SMSC Control Parameters" },
838         { 0x07, "SMS - UDH Source Indicator" },
839         { 0x08, "SMS - Concatenated short message, 16-bit reference number" },
840         { 0x09, "SMS - Wireless Control Message Protocol" },
841         { 0x0A, "EMS - Text Formatting" },
842         { 0x0B, "EMS - Predefined Sound" },
843         { 0x0C, "EMS - User Defined Sound (iMelody max 128 bytes)" },
844         { 0x0D, "EMS - Predefined Animation" },
845         { 0x0E, "EMS - Large Animation (16*16 times 4 = 32*4 =128 bytes)" },
846         { 0x0F, "EMS - Small Animation (8*8 times 4 = 8*4 =32 bytes)" },
847         { 0x10, "EMS - Large Picture (32*32 = 128 bytes)" },
848         { 0x11, "EMS - Small Picture (16*16 = 32 bytes)" },
849         { 0x12, "EMS - Variable Picture" },
850         { 0x13, "EMS - User prompt indicator" },
851         { 0x14, "EMS - Extended Object" },
852         { 0x15, "EMS - Reused Extended Object" },
853         { 0x16, "EMS - Compression Control" },
854         { 0x17, "EMS - Object Distribution Indicator" },
855         { 0x18, "EMS - Standard WVG object" },
856         { 0x19, "EMS - Character Size WVG object" },
857         { 0x1A, "EMS - Extended Object Data Request Command" },
858         { 0x20, "SMS - RFC 822 E-Mail Header" },
859         { 0x21, "SMS - Hyperlink format element" },
860         { 0x22, "SMS - Reply Address Element" },
861         { 0x00, NULL }
862 };      
863
864 /*!
865  * SMPP equivalent of mktime() (3). Convert date to standard 'time_t' format
866  *
867  * \param       datestr The SMPP-formatted date to convert
868  * \param       secs    Returns the 'time_t' equivalent
869  * \param       nsecs   Returns the additional nano-seconds
870  *
871  * \return              Whether time is specified relative or absolute
872  * \retval      TRUE    Relative time
873  * \retval      FALSE   Absolute time
874  */
875 static gboolean
876 smpp_mktime(const char *datestr, time_t *secs, int *nsecs)
877 {
878     struct tm    r_time;
879     time_t       t_diff;
880     gboolean     relative = FALSE;
881
882     r_time.tm_year = 10 * (datestr[0] - '0') + (datestr[1] - '0');
883     /*
884      * Y2K rollover date as recommended in appendix C
885      */
886     if (r_time.tm_year < 38)
887         r_time.tm_year += 100;
888     r_time.tm_mon  = 10 * (datestr[2] - '0') + (datestr[3] - '0');
889     r_time.tm_mon--;
890     r_time.tm_mday = 10 * (datestr[4] - '0') + (datestr[5] - '0');
891     r_time.tm_hour = 10 * (datestr[6] - '0') + (datestr[7] - '0');
892     r_time.tm_min  = 10 * (datestr[8] - '0') + (datestr[9] - '0');
893     r_time.tm_sec  = 10 * (datestr[10] - '0') + (datestr[11] - '0');
894     r_time.tm_isdst = -1;
895     *secs = mktime(&r_time);
896     *nsecs = (datestr[12] - '0') * 100000000;
897     t_diff = (10 * (datestr[13] - '0') + (datestr[14] - '0')) * 900;
898     if (datestr[15] == '+')
899         *secs += t_diff;
900     else if (datestr[15] == '-')
901         *secs -= t_diff;
902     else                                /* Must be relative ('R')       */
903         relative = TRUE;
904     return relative;
905 }
906
907 /*!
908  * Scanning routines to add standard types (byte, int, string...) to the
909  * protocol tree.
910  *
911  * \param       tree    The protocol tree to add to
912  * \param       tvb     Buffer containing the data
913  * \param       field   Actual field whose value needs displaying
914  * \param       offset  Location of field in buffer, returns location of
915  *                      next field
916  */
917 static void
918 smpp_handle_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
919 {
920     guint        len;
921
922     len = tvb_strsize(tvb, *offset);
923     if (len > 1) {
924       proto_tree_add_string(tree, field, tvb, *offset, len,
925           (const char *) tvb_get_ptr(tvb, *offset, len));
926     }
927     (*offset) += len;
928 }
929
930 /* NOTE - caller must free the returned string! */
931 static char *
932 smpp_handle_string_return(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
933 {
934     gint         len;
935     char        *str;
936
937     len = tvb_strsize(tvb, *offset);
938     if (len > 1) {
939         str = (char *)tvb_get_stringz(tvb, *offset, &len);
940         proto_tree_add_string(tree, field, tvb, *offset, len, str);
941     } else {
942         str = g_malloc(1 * sizeof(char));
943         str[0] = '\0';
944     }
945     (*offset) += len;
946     return str;
947 }
948
949 static void
950 smpp_handle_string_z(proto_tree *tree, tvbuff_t *tvb, int field, int *offset,
951                 const char *null_string)
952 {
953     gint         len;
954
955     len = tvb_strsize(tvb, *offset);
956     if (len > 1) {
957         proto_tree_add_string(tree, field, tvb, *offset, len,
958                 (const char *)tvb_get_ptr(tvb, *offset, len));
959     } else {
960         proto_tree_add_string(tree, field, tvb, *offset, len, null_string);
961     }
962     (*offset) += len;
963 }
964
965 static void
966 smpp_handle_int1(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
967 {
968     guint8       val;
969
970     val = tvb_get_guint8(tvb, *offset);
971     proto_tree_add_uint(tree, field, tvb, *offset, 1, val);
972     (*offset)++;
973 }
974
975 static void
976 smpp_handle_int2(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
977 {
978     guint        val;
979
980     val = tvb_get_ntohs(tvb, *offset);
981     proto_tree_add_uint(tree, field, tvb, *offset, 2, val);
982     (*offset) += 2;
983 }
984
985 static void
986 smpp_handle_int4(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
987 {
988     guint        val;
989
990     val = tvb_get_ntohl(tvb, *offset);
991     proto_tree_add_uint(tree, field, tvb, *offset, 4, val);
992     (*offset) += 4;
993 }
994
995 static void
996 smpp_handle_time(proto_tree *tree, tvbuff_t *tvb,
997                  int field, int field_R, int *offset)
998 {
999     char         *strval;
1000     gint         len;
1001     nstime_t     tmptime;
1002
1003     strval = (char *) tvb_get_stringz(tvb, *offset, &len);
1004     if (*strval)
1005     {
1006         if (smpp_mktime(strval, &tmptime.secs, &tmptime.nsecs))
1007             proto_tree_add_time(tree, field_R, tvb, *offset, len, &tmptime);
1008         else
1009             proto_tree_add_time(tree, field, tvb, *offset, len, &tmptime);
1010     }
1011     g_free(strval);
1012     *offset += len;
1013 }
1014
1015 /*!
1016  * Scanning routine to handle the destination-list of 'submit_multi'
1017  *
1018  * \param       tree    The protocol tree to add to
1019  * \param       tvb     Buffer containing the data
1020  * \param       offset  Location of field in buffer, returns location of
1021  *                      next field
1022  */
1023 static void
1024 smpp_handle_dlist(proto_tree *tree, tvbuff_t *tvb, int *offset)
1025 {
1026     guint8       entries;
1027     int          tmpoff = *offset;
1028     proto_item  *sub_tree = NULL;
1029     guint8       dest_flag;
1030
1031     if ((entries = tvb_get_guint8(tvb, tmpoff++)))
1032     {
1033         sub_tree = proto_tree_add_item(tree, hf_smpp_dlist,
1034                                         tvb, *offset, 1, FALSE);
1035         proto_item_add_subtree(sub_tree, ett_dlist);
1036     }
1037     while (entries--)
1038     {
1039         dest_flag = tvb_get_guint8(tvb, tmpoff++);
1040         if (dest_flag == 1)                     /* SME address  */
1041         {
1042             smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff);
1043             smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff);
1044             smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff);
1045         }
1046         else                                    /* Distribution list    */
1047         {
1048             smpp_handle_string(sub_tree, tvb, hf_smpp_dl_name, &tmpoff);
1049         }
1050     }
1051     *offset = tmpoff;
1052 }
1053
1054 /*!
1055  * Scanning routine to handle the destination result list
1056  * of 'submit_multi_resp'
1057  *
1058  * \param       tree    The protocol tree to add to
1059  * \param       tvb     Buffer containing the data
1060  * \param       offset  Location of field in buffer, returns location of
1061  *                      next field
1062  */
1063 static void
1064 smpp_handle_dlist_resp(proto_tree *tree, tvbuff_t *tvb, int *offset)
1065 {
1066     guint8       entries;
1067     int          tmpoff = *offset;
1068     proto_item  *sub_tree = NULL;
1069
1070     if ((entries = tvb_get_guint8(tvb, tmpoff++)))
1071     {
1072         sub_tree = proto_tree_add_item(tree, hf_smpp_dlist_resp,
1073                                        tvb, *offset, 1, FALSE);
1074         proto_item_add_subtree(sub_tree, ett_dlist_resp);
1075     }
1076     while (entries--)
1077     {
1078         smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff);
1079         smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff);
1080         smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff);
1081         smpp_handle_int4(sub_tree, tvb, hf_smpp_error_status_code, &tmpoff);
1082     }
1083     *offset = tmpoff;
1084 }
1085
1086 /*!
1087  * Scanning routine to handle all optional parameters of SMPP-operations.
1088  * The parameters have the format Tag Length Value (TLV), with a 2-byte tag
1089  * and 2-byte length.
1090  *
1091  * \param       tree    The protocol tree to add to
1092  * \param       tvb     Buffer containing the data
1093  * \param       offset  Location of field in buffer, returns location of
1094  *                      next field
1095  */
1096 static void
1097 smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset)
1098 {
1099     proto_item  *sub_tree = NULL;
1100     guint        tag;
1101     guint        length;
1102     guint8       field;
1103     guint8       major, minor;
1104     char         strval[BUFSIZ];
1105
1106     if (tvb_reported_length_remaining(tvb, *offset) >= 4)
1107     {
1108         sub_tree = proto_tree_add_item(tree, hf_smpp_opt_param,
1109                                        tvb, *offset, 0, FALSE);
1110         proto_item_add_subtree(sub_tree, ett_opt_param);
1111     }
1112
1113     while (tvb_reported_length_remaining(tvb, *offset) >= 4)
1114     {
1115         tag = tvb_get_ntohs(tvb, *offset);
1116         *offset += 2;
1117         length = tvb_get_ntohs(tvb, *offset);
1118         *offset += 2;
1119         switch (tag) {
1120             case  0x0005:       /* dest_addr_subunit    */
1121                 smpp_handle_int1(sub_tree, tvb,
1122                                  hf_smpp_dest_addr_subunit, offset);
1123                 break;
1124             case  0x0006:       /* dest_network_type    */
1125                 smpp_handle_int1(sub_tree, tvb,
1126                                  hf_smpp_dest_network_type, offset);
1127                 break;
1128             case  0x0007:       /* dest_bearer_type     */
1129                 smpp_handle_int1(sub_tree, tvb,
1130                                  hf_smpp_dest_bearer_type, offset);
1131                 break;
1132             case  0x0008:       /* dest_telematics_id   */
1133                 smpp_handle_int2(sub_tree, tvb,
1134                                  hf_smpp_dest_telematics_id, offset);
1135                 break;
1136             case  0x000D:       /* source_addr_subunit  */
1137                 smpp_handle_int1(sub_tree, tvb,
1138                                  hf_smpp_source_addr_subunit, offset);
1139                 break;
1140             case  0x000E:       /* source_network_type  */
1141                 smpp_handle_int1(sub_tree, tvb,
1142                                  hf_smpp_source_network_type, offset);
1143                 break;
1144             case  0x000F:       /* source_bearer_type   */
1145                 smpp_handle_int1(sub_tree, tvb,
1146                                  hf_smpp_source_bearer_type, offset);
1147                 break;
1148             case  0x0010:       /* source_telematics_id */
1149                 smpp_handle_int2(sub_tree, tvb,
1150                                  hf_smpp_source_telematics_id, offset);
1151                 break;
1152             case  0x0017:       /* qos_time_to_live     */
1153                 smpp_handle_int4(sub_tree, tvb,
1154                                  hf_smpp_qos_time_to_live, offset);
1155                 break;
1156             case  0x0019:       /* payload_type */
1157                 smpp_handle_int1(sub_tree, tvb,
1158                                  hf_smpp_payload_type, offset);
1159                 break;
1160             case  0x001D:       /* additional_status_info_text  */
1161                 smpp_handle_string(sub_tree, tvb,
1162                                    hf_smpp_additional_status_info_text, offset);
1163                 break;
1164             case  0x001E:       /* receipted_message_id */
1165                 smpp_handle_string(sub_tree, tvb,
1166                                    hf_smpp_receipted_message_id, offset);
1167                 break;
1168             case  0x0030:       /* ms_msg_wait_facilities       */
1169                 field = tvb_get_guint8(tvb, *offset);
1170                 proto_tree_add_item(sub_tree, hf_smpp_msg_wait_ind,
1171                                     tvb, *offset, 1, field);
1172                 proto_tree_add_item(sub_tree, hf_smpp_msg_wait_type,
1173                                     tvb, *offset, 1, field);
1174                 (*offset)++;
1175                 break;
1176             case  0x0201:       /* privacy_indicator    */
1177                 smpp_handle_int1(sub_tree, tvb,
1178                                  hf_smpp_privacy_indicator, offset);
1179                 break;
1180             case  0x0202:       /* source_subaddress    */
1181                 smpp_handle_string(sub_tree, tvb,
1182                                    hf_smpp_source_subaddress, offset);
1183                 break;
1184             case  0x0203:       /* dest_subaddress      */
1185                 smpp_handle_string(sub_tree, tvb,
1186                                    hf_smpp_dest_subaddress, offset);
1187                 break;
1188             case  0x0204:       /* user_message_reference       */
1189                 smpp_handle_int2(sub_tree, tvb,
1190                                  hf_smpp_user_message_reference, offset);
1191                 break;
1192             case  0x0205:       /* user_response_code   */
1193                 smpp_handle_int1(sub_tree, tvb,
1194                                  hf_smpp_user_response_code, offset);
1195                 break;
1196             case  0x020A:       /* source_port  */
1197                 smpp_handle_int2(sub_tree, tvb,
1198                                  hf_smpp_source_port, offset);
1199                 break;
1200             case  0x020B:       /* destination_port     */
1201                 smpp_handle_int2(sub_tree, tvb,
1202                                  hf_smpp_destination_port, offset);
1203                 break;
1204             case  0x020C:       /* sar_msg_ref_num      */
1205                 smpp_handle_int2(sub_tree, tvb,
1206                                  hf_smpp_sar_msg_ref_num, offset);
1207                 break;
1208             case  0x020D:       /* language_indicator   */
1209                 smpp_handle_int1(sub_tree, tvb,
1210                                  hf_smpp_language_indicator, offset);
1211                 break;
1212             case  0x020E:       /* sar_total_segments   */
1213                 smpp_handle_int1(sub_tree, tvb,
1214                                  hf_smpp_sar_total_segments, offset);
1215                 break;
1216             case  0x020F:       /* sar_segment_seqnum   */
1217                 smpp_handle_int1(sub_tree, tvb,
1218                                  hf_smpp_sar_segment_seqnum, offset);
1219                 break;
1220             case  0x0210:       /* SC_interface_version */
1221                 field = tvb_get_guint8(tvb, *offset);
1222                 minor = field & 0x0F;
1223                 major = (field & 0xF0) >> 4;
1224                 sprintf(strval, "%u.%u", major, minor);
1225                 proto_tree_add_string(sub_tree, hf_smpp_SC_interface_version,
1226                                       tvb, *offset, 1, strval);
1227                 (*offset)++;
1228                 break;
1229             case  0x0302:       /* callback_num_pres_ind        */
1230                 field = tvb_get_guint8(tvb, *offset);
1231                 proto_tree_add_item(sub_tree, hf_smpp_callback_num_pres,
1232                                     tvb, *offset, 1, field);
1233                 proto_tree_add_item(sub_tree, hf_smpp_callback_num_scrn,
1234                                     tvb, *offset, 1, field);
1235                 (*offset)++;
1236                 break;
1237             case  0x0303:       /* callback_num_atag    */
1238                 if (length)
1239                     proto_tree_add_item(sub_tree, hf_smpp_callback_num_atag,
1240                                         tvb, *offset, length, FALSE);
1241                 (*offset) += length;
1242                 break;
1243             case  0x0304:       /* number_of_messages   */
1244                 smpp_handle_int1(sub_tree, tvb,
1245                                  hf_smpp_number_of_messages, offset);
1246                 break;
1247             case  0x0381:       /* callback_num */
1248                 if (length)
1249                     proto_tree_add_item(sub_tree, hf_smpp_callback_num,
1250                                         tvb, *offset, length, FALSE);
1251                 (*offset) += length;
1252                 break;
1253             case  0x0420:       /* dpf_result   */
1254                 smpp_handle_int1(sub_tree, tvb,
1255                                  hf_smpp_dpf_result, offset);
1256                 break;
1257             case  0x0421:       /* set_dpf      */
1258                 smpp_handle_int1(sub_tree, tvb,
1259                                  hf_smpp_set_dpf, offset);
1260                 break;
1261             case  0x0422:       /* ms_availability_status       */
1262                 smpp_handle_int1(sub_tree, tvb,
1263                                  hf_smpp_ms_availability_status, offset);
1264                 break;
1265             case  0x0423:       /* network_error_code   */
1266                 smpp_handle_int1(sub_tree, tvb,
1267                                  hf_smpp_network_error_type, offset);
1268                 smpp_handle_int2(sub_tree, tvb,
1269                                  hf_smpp_network_error_code, offset);
1270                 (*offset) += length;
1271                 break;
1272             case  0x0424:       /* message_payload      */
1273                 if (length)
1274                     proto_tree_add_item(sub_tree, hf_smpp_message_payload,
1275                                         tvb, *offset, length, FALSE);
1276                 (*offset) += length;
1277                 break;
1278             case  0x0425:       /* delivery_failure_reason      */
1279                 smpp_handle_int1(sub_tree, tvb,
1280                                  hf_smpp_delivery_failure_reason, offset);
1281                 break;
1282             case  0x0426:       /* more_messages_to_send        */
1283                 smpp_handle_int1(sub_tree, tvb,
1284                                  hf_smpp_more_messages_to_send, offset);
1285                 break;
1286             case  0x0427:       /* message_state        */
1287                 smpp_handle_int1(sub_tree, tvb,
1288                                  hf_smpp_message_state, offset);
1289                 break;
1290             case  0x0501:       /* ussd_service_op      */
1291                 smpp_handle_int1(sub_tree, tvb,
1292                                  hf_smpp_ussd_service_op, offset);
1293                 break;
1294             case  0x1201:       /* display_time */
1295                 smpp_handle_int1(sub_tree, tvb,
1296                                  hf_smpp_display_time, offset);
1297                 break;
1298             case  0x1203:       /* sms_signal   */
1299                 smpp_handle_int2(sub_tree, tvb,
1300                                  hf_smpp_sms_signal, offset);
1301                 /*! \todo Fill as per TIA/EIA-136-710-A         */
1302                 break;
1303             case  0x1204:       /* ms_validity  */
1304                 smpp_handle_int1(sub_tree, tvb,
1305                                  hf_smpp_ms_validity, offset);
1306                 break;
1307             case  0x130C:       /* alert_on_message_delivery    */
1308                 proto_tree_add_item(sub_tree,
1309                                     hf_smpp_alert_on_message_delivery,
1310                                     tvb, *offset, length, FALSE);
1311                 (*offset) += length;
1312                 break;
1313             case  0x1380:       /* its_reply_type       */
1314                 smpp_handle_int1(sub_tree, tvb,
1315                                  hf_smpp_its_reply_type, offset);
1316                 break;
1317             case  0x1383:       /* its_session_info     */
1318                 smpp_handle_int1(sub_tree, tvb,
1319                                  hf_smpp_its_session_number, offset);
1320                 field = tvb_get_guint8(tvb, *offset);
1321                 proto_tree_add_item(sub_tree, hf_smpp_its_session_sequence,
1322                                     tvb, *offset, 1, field);
1323                 proto_tree_add_item(sub_tree, hf_smpp_its_session_ind,
1324                                     tvb, *offset, 1, field);
1325                 (*offset)++;
1326                 break;
1327             default:
1328                 if ((tag >= 0x1400) && (tag <= 0x3FFF))
1329                     proto_tree_add_item(sub_tree, hf_smpp_vendor_op, tvb,
1330                                         *offset, length, FALSE);
1331                 else
1332                     proto_tree_add_item(sub_tree, hf_smpp_reserved_op, tvb,
1333                                         *offset, length, FALSE);
1334                 (*offset) += length;
1335                 break;
1336         }
1337     }
1338 }
1339
1340 static void
1341 smpp_handle_dcs(proto_tree *tree, tvbuff_t *tvb, int *offset)
1342 {
1343     guint8       val;
1344         int off = *offset;
1345         proto_item *subtree = NULL;
1346
1347     val = tvb_get_guint8(tvb, off);
1348         subtree = proto_tree_add_uint(tree,
1349                         hf_smpp_data_coding, tvb, off, 1, val);
1350         proto_item_add_subtree(subtree, ett_dcs);
1351         /* SMPP Data Coding Scheme */
1352         proto_tree_add_uint(subtree, hf_smpp_dcs, tvb, off, 1, val);
1353         /* GSM SMS Data Coding Scheme */
1354         proto_tree_add_text(subtree, tvb, off, 1,
1355                                         "GSM SMS Data Coding");
1356         proto_tree_add_uint(subtree,
1357                         hf_smpp_dcs_sms_coding_group, tvb, off, 1, val);
1358         if (val>>6 == 2) { /* Reserved */
1359                         ;
1360         } else if (val < 0xF0) {
1361                 proto_tree_add_boolean(subtree,
1362                                 hf_smpp_dcs_text_compression, tvb, off, 1, val);
1363                 proto_tree_add_boolean(subtree,
1364                                 hf_smpp_dcs_class_present, tvb, off, 1, val);
1365                 proto_tree_add_uint(subtree,
1366                                 hf_smpp_dcs_charset, tvb, off, 1, val);
1367                 if (val & 0x10)
1368                         proto_tree_add_uint(subtree,
1369                                         hf_smpp_dcs_class, tvb, off, 1, val);
1370         } else {
1371                 if (val & 0x08)
1372                         proto_tree_add_text(subtree, tvb, off, 1,
1373                                         "SMPP: Bit .... 1... should be 0 (reserved)");
1374                 proto_tree_add_uint(subtree,
1375                                 hf_smpp_dcs_charset, tvb, off, 1, val);
1376                 proto_tree_add_uint(subtree,
1377                                 hf_smpp_dcs_class, tvb, off, 1, val);
1378         }
1379         /* Cell Broadcast Service (CBS) Data Coding Scheme */
1380         proto_tree_add_text(subtree, tvb, off, 1,
1381                                         "GSM CBS Data Coding");
1382         proto_tree_add_uint(subtree,
1383                         hf_smpp_dcs_cbs_coding_group, tvb, off, 1, val);
1384         if (val < 0x40) { /* Language specified */
1385                 proto_tree_add_uint(subtree,
1386                                 hf_smpp_dcs_cbs_language, tvb, off, 1, val);
1387         } else if (val>>6 == 1) { /* General Data Coding indication */
1388                 proto_tree_add_boolean(subtree,
1389                                 hf_smpp_dcs_text_compression, tvb, off, 1, val);
1390                 proto_tree_add_boolean(subtree,
1391                                 hf_smpp_dcs_class_present, tvb, off, 1, val);
1392                 proto_tree_add_uint(subtree,
1393                                 hf_smpp_dcs_charset, tvb, off, 1, val);
1394                 if (val & 0x10)
1395                         proto_tree_add_uint(subtree,
1396                                         hf_smpp_dcs_class, tvb, off, 1, val);
1397         } else if (val>>6 == 2) { /* Message with UDH structure */
1398                 proto_tree_add_uint(subtree,
1399                                 hf_smpp_dcs_charset, tvb, off, 1, val);
1400                 proto_tree_add_uint(subtree,
1401                                 hf_smpp_dcs_class, tvb, off, 1, val);
1402         } else if (val>>4 == 14) { /* WAP Forum */
1403                 proto_tree_add_uint(subtree,
1404                                 hf_smpp_dcs_wap_charset, tvb, off, 1, val);
1405                 proto_tree_add_uint(subtree,
1406                                 hf_smpp_dcs_wap_class, tvb, off, 1, val);
1407         } else if (val>>4 == 15) { /* Data coding / message handling */
1408                 if (val & 0x08)
1409                         proto_tree_add_text(subtree, tvb, off, 1,
1410                                         "SMPP: Bit .... 1... should be 0 (reserved)");
1411                 proto_tree_add_uint(subtree,
1412                                 hf_smpp_dcs_charset, tvb, off, 1, val);
1413                 proto_tree_add_uint(subtree,
1414                                 hf_smpp_dcs_cbs_class, tvb, off, 1, val);
1415         }
1416
1417     (*offset)++;
1418 }
1419
1420 /*!
1421  * The next set of routines handle the different operations, associated
1422  * with SMPP.
1423  */
1424 static void
1425 bind_receiver(proto_tree *tree, tvbuff_t *tvb)
1426 {
1427     int          offset = 0;
1428     guint8       field;
1429     guint8       major, minor;
1430     char         strval[BUFSIZ];
1431
1432     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1433     smpp_handle_string(tree, tvb, hf_smpp_password, &offset);
1434     smpp_handle_string(tree, tvb, hf_smpp_system_type, &offset);
1435     field = tvb_get_guint8(tvb, offset++);
1436     minor = field & 0x0F;
1437     major = (field & 0xF0) >> 4;
1438     sprintf(strval, "%u.%u", major, minor);
1439     proto_tree_add_string(tree, hf_smpp_interface_version, tvb,
1440                           offset - 1, 1, strval);
1441     smpp_handle_int1(tree, tvb, hf_smpp_addr_ton, &offset);
1442     smpp_handle_int1(tree, tvb, hf_smpp_addr_npi, &offset);
1443     smpp_handle_string(tree, tvb, hf_smpp_address_range, &offset);
1444 }
1445
1446 #define bind_transmitter(a, b) bind_receiver(a, b)
1447
1448 static void
1449 query_sm(proto_tree *tree, tvbuff_t *tvb)
1450 {
1451     int          offset = 0;
1452
1453     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1454     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1455     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1456     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1457 }
1458
1459 #define bind_transceiver(a, b) bind_receiver(a, b)
1460
1461 static void
1462 outbind(proto_tree *tree, tvbuff_t *tvb)
1463 {
1464     int          offset = 0;
1465
1466     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1467     smpp_handle_string(tree, tvb, hf_smpp_password, &offset);
1468 }
1469
1470 /* Parse Short Message, only if UDH present
1471  * (otherwise this function is not called).
1472  * Call WSP dissector if port matches WSP traffic.
1473  */
1474 static void
1475 parse_sm_message(proto_tree *sm_tree, tvbuff_t *tvb, packet_info *pinfo,
1476                 proto_tree *top_tree)
1477 {
1478         tvbuff_t *sm_tvb = NULL;
1479         proto_item *subtree, *tree;
1480         guint8 udh_len, udh, len;
1481         guint sm_len = tvb_reported_length (tvb);
1482         guint sm_data_len;
1483         guint32 i = 0;
1484         /* Multiple Messages UDH */
1485         gboolean is_fragmented = FALSE;
1486         fragment_data *fd_sm = NULL;
1487         guint16 sm_id = 0, frags = 0, frag = 0;
1488         gboolean save_fragmented = FALSE, try_sm_reassemble = FALSE;
1489         /* SMS Message reassembly */
1490         gboolean reassembled = FALSE;
1491         guint32 reassembled_in = 0;
1492         /* Port Number UDH */
1493         guint16 p_src = 0, p_dst = 0;
1494         gboolean ports_available = FALSE;
1495
1496         udh_len = tvb_get_guint8(tvb, i++);
1497         tree = proto_tree_add_uint(sm_tree, hf_smpp_udh_length, tvb, 0, 1, udh_len);
1498         tree = proto_item_add_subtree(tree, ett_udh);
1499         while (i < udh_len) {
1500                 udh = tvb_get_guint8(tvb, i++);
1501                 len = tvb_get_guint8(tvb, i++);
1502                 subtree = proto_tree_add_uint(tree, hf_smpp_udh_iei,
1503                                 tvb, i-2, 2+len, udh);
1504                 switch (udh) {
1505                         case 0x00: /* Multiple messages - 8-bit message ID */
1506                                 if (len == 3) {
1507                                         is_fragmented = TRUE;
1508                                         sm_id = tvb_get_guint8(tvb, i++);
1509                                         frags = tvb_get_guint8(tvb, i++);
1510                                         frag  = tvb_get_guint8(tvb, i++);
1511                                         proto_item_append_text(subtree,
1512                                                         ": message %u, part %u of %u", sm_id, frag, frags);
1513                                         subtree = proto_item_add_subtree(subtree,
1514                                                         ett_udh_ie);
1515                                         proto_tree_add_uint (subtree,
1516                                                         hf_smpp_udh_multiple_messages_msg_id,
1517                                                         tvb, i-3, 1, sm_id);
1518                                         proto_tree_add_uint (subtree,
1519                                                         hf_smpp_udh_multiple_messages_msg_parts,
1520                                                         tvb, i-2, 1, frags);
1521                                         proto_tree_add_uint (subtree,
1522                                                         hf_smpp_udh_multiple_messages_msg_part,
1523                                                         tvb, i-1, 1, frag);
1524                                 } else {
1525                                         proto_item_append_text(subtree, " - Invalid format!");
1526                                         i += len;
1527                                 }
1528                                 break;
1529
1530                         case 0x08: /* Multiple messages - 16-bit message ID */
1531                                 if (len == 4) {
1532                                         is_fragmented = TRUE;
1533                                         sm_id = tvb_get_ntohs(tvb, i); i += 2;
1534                                         frags = tvb_get_guint8(tvb, i++);
1535                                         frag  = tvb_get_guint8(tvb, i++);
1536                                         proto_item_append_text(subtree,
1537                                                         ": message %u, part %u of %u", sm_id, frag, frags);
1538                                         subtree = proto_item_add_subtree(subtree,
1539                                                         ett_udh_ie);
1540                                         proto_tree_add_uint (subtree,
1541                                                         hf_smpp_udh_multiple_messages_msg_id,
1542                                                         tvb, i-4, 2, sm_id);
1543                                         proto_tree_add_uint (subtree,
1544                                                         hf_smpp_udh_multiple_messages_msg_parts,
1545                                                         tvb, i-2, 1, frags);
1546                                         proto_tree_add_uint (subtree,
1547                                                         hf_smpp_udh_multiple_messages_msg_part,
1548                                                         tvb, i-1, 1, frag);
1549                                 } else {
1550                                         proto_item_append_text(subtree, " - Invalid format!");
1551                                         i += len;
1552                                 }
1553                                 break;
1554
1555                         case 0x04: /* Port Number UDH - 8-bit address */
1556                                 if (len == 2) { /* Port fields */
1557                                         p_dst = tvb_get_guint8(tvb, i++);
1558                                         p_src = tvb_get_guint8(tvb, i++);
1559                                         proto_item_append_text(subtree,
1560                                                         ": source port %u, destination port %u",
1561                                                         p_src, p_dst);
1562                                         subtree = proto_item_add_subtree(subtree, ett_udh_ie);
1563                                         proto_tree_add_uint (subtree, hf_smpp_udh_ports_dst,
1564                                                         tvb, i-2, 1, p_dst);
1565                                         proto_tree_add_uint (subtree, hf_smpp_udh_ports_src,
1566                                                         tvb, i-1, 1, p_src);
1567                                         ports_available = TRUE;
1568                                 } else {
1569                                         proto_item_append_text(subtree, " - Invalid format!");
1570                                         i += len;
1571                                 }
1572                                 break;
1573
1574                         case 0x05: /* Port Number UDH - 16-bit address */
1575                                 if (len == 4) { /* Port fields */
1576                                         p_dst = tvb_get_ntohs(tvb, i); i += 2;
1577                                         p_src = tvb_get_ntohs(tvb, i); i += 2;
1578                                         proto_item_append_text(subtree,
1579                                                         ": source port %u, destination port %u",
1580                                                         p_src, p_dst);
1581                                         subtree = proto_item_add_subtree(subtree, ett_udh_ie);
1582                                         proto_tree_add_uint (subtree, hf_smpp_udh_ports_dst,
1583                                                         tvb, i-4, 2, p_dst);
1584                                         proto_tree_add_uint (subtree, hf_smpp_udh_ports_src,
1585                                                         tvb, i-2, 2, p_src);
1586                                         ports_available = TRUE;
1587                                 } else {
1588                                         proto_item_append_text(subtree, " - Invalid format!");
1589                                         i += len;
1590                                 }
1591                                 break;
1592
1593                         default:
1594                                 i += len;
1595                                 break;
1596                 }
1597         }
1598         if (tvb_reported_length_remaining(tvb, i) <= 0)
1599                 return; /* No more data */
1600
1601         /*
1602          * XXX - where does the "1" come from?  If it weren't there,
1603          * "sm_data_len" would, I think, be the same as
1604          * "tvb_reported_length_remaining(tvb, i)".
1605          *
1606          * I think that the above check ensures that "sm_len" won't
1607          * be less than or equal to "udh_len", so it ensures that
1608          * "sm_len" won't be less than "1 + udh_len", so we don't
1609          * have to worry about "sm_data_len" being negative.
1610          */
1611         sm_data_len = sm_len - (1 + udh_len);
1612         if (sm_data_len == 0)
1613                 return; /* no more data */
1614
1615         /*
1616          * Try reassembling the packets.
1617          * XXX - fragment numbers are 1-origin, but the fragment number
1618          * field could be 0.
1619          * Should we flag a fragmented message with a fragment number field
1620          * of 0?
1621          * What if the fragment count is 0?  Should we flag that as well?
1622          */
1623         if ( is_fragmented && frag != 0 && frags != 0 &&
1624             tvb_bytes_exist (tvb, i, sm_data_len) ) {
1625                 try_sm_reassemble = TRUE;
1626                 save_fragmented = pinfo->fragmented;
1627                 pinfo->fragmented = TRUE;
1628                 fd_sm = fragment_add_seq_check (tvb, i, pinfo,
1629                                 sm_id, /* guint32 ID for fragments belonging together */
1630                                 sm_fragment_table, /* list of message fragments */
1631                                 sm_reassembled_table, /* list of reassembled messages */
1632                                 frag-1, /* guint32 fragment sequence number */
1633                                 sm_data_len, /* guint32 fragment length */
1634                                 (frag != frags)); /* More fragments? */
1635                 if (fd_sm) {
1636                         reassembled = TRUE;
1637                         reassembled_in = fd_sm->reassembled_in;
1638                 }
1639                 sm_tvb = process_reassembled_data(tvb, i, pinfo,
1640                     "Reassembled Short Message", fd_sm, &sm_frag_items,
1641                     NULL, sm_tree);
1642                 if (reassembled) { /* Reassembled */
1643                         if (check_col (pinfo->cinfo, COL_INFO))
1644                                 col_append_str (pinfo->cinfo, COL_INFO,
1645                                                 " (Short Message Reassembled)");
1646                 } else {
1647                         /* Not last packet of reassembled Short Message */
1648                         if (check_col (pinfo->cinfo, COL_INFO))
1649                                 col_append_fstr (pinfo->cinfo, COL_INFO,
1650                                                 " (Short Message fragment %u of %u)", frag, frags);
1651                 }
1652         } /* Else: not fragmented */
1653
1654         if (! sm_tvb) /* One single Short Message, or not reassembled */
1655                 sm_tvb = tvb_new_subset (tvb, i, -1, -1);
1656         /* Try calling a subdissector */
1657         if (sm_tvb) {
1658                 if ((reassembled && pinfo->fd->num == reassembled_in)
1659                         || frag==0 || (frag==1 && try_dissect_1st_frag)) {
1660                         /* Try calling a subdissector only if:
1661                          *  - the Short Message is reassembled in this very packet,
1662                          *  - the Short Message consists of only one "fragment",
1663                          *  - the preference "Always Try Dissection for 1st SM fragment"
1664                          *    is switched on, and this is the SM's 1st fragment. */
1665                         if ( ports_available ) {
1666                                 if ( port_number_udh_means_wsp ) {
1667                                         call_dissector (wsp_handle, sm_tvb, pinfo, top_tree);
1668                                 } else {
1669                                         if (! dissector_try_port(gsm_sms_dissector_table, p_src,
1670                                                                 sm_tvb, pinfo, top_tree)) {
1671                                                 if (! dissector_try_port(gsm_sms_dissector_table, p_dst,
1672                                                                         sm_tvb, pinfo, top_tree)) {
1673                                                         if (sm_tree) { /* Only display if needed */
1674                                                                 proto_tree_add_text (sm_tree, sm_tvb, 0, -1,
1675                                                                                 "Short Message body");
1676                                                         }
1677                                                 }
1678                                         }
1679                                 }
1680                         } else { /* No ports IE */
1681                                 proto_tree_add_text (sm_tree, sm_tvb, 0, -1,
1682                                                 "Short Message body");
1683                         }
1684                 } else {
1685                         /* The packet is not reassembled,
1686                          * or it is reassembled in another packet */
1687                         proto_tree_add_text (sm_tree, sm_tvb, 0, -1,
1688                                         "Unreassembled Short Message fragment %u of %u",
1689                                         frag, frags);
1690                 }
1691         }
1692
1693         if (try_sm_reassemble) /* Clean up defragmentation */
1694                 pinfo->fragmented = save_fragmented;
1695         return;
1696 }
1697
1698 static void
1699 submit_sm(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
1700                 proto_tree *top_tree)
1701 {
1702     tvbuff_t    *tvb_msg;
1703     int          offset = 0;
1704     guint8       flag, udhi;
1705     guint8       length;
1706         char *src_str = NULL;
1707         char *dst_str = NULL;
1708         address save_src, save_dst;
1709
1710     smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
1711     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1712     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1713     src_str = smpp_handle_string_return(tree, tvb, hf_smpp_source_addr, &offset);
1714     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1715     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1716     dst_str = smpp_handle_string_return(tree, tvb, hf_smpp_destination_addr, &offset);
1717     flag = tvb_get_guint8(tvb, offset);
1718     udhi = flag & 0x40;
1719     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1720                         tvb, offset, 1, flag);
1721     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1722                         tvb, offset, 1, flag);
1723     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1724                         tvb, offset, 1, flag);
1725     offset++;
1726     smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset);
1727     smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset);
1728         if (tvb_get_guint8(tvb,offset)) {
1729     smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1730                                 hf_smpp_schedule_delivery_time_r, &offset);
1731         } else { /* Time = NULL means Immediate delivery */
1732                 proto_tree_add_text(tree, tvb, offset++, 1,
1733                                 "Scheduled delivery time: Immediate delivery");
1734         }
1735         if (tvb_get_guint8(tvb,offset)) {
1736     smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1737                                 hf_smpp_validity_period_r, &offset);
1738         } else { /* Time = NULL means SMSC default validity */
1739                 proto_tree_add_text(tree, tvb, offset++, 1,
1740                                 "Validity period: SMSC default validity period");
1741         }
1742     flag = tvb_get_guint8(tvb, offset);
1743     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1744     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1745     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1746     offset++;
1747     smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset);
1748         smpp_handle_dcs(tree, tvb, &offset);
1749     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1750     length = tvb_get_guint8(tvb, offset);
1751     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1752     if (length)
1753     {
1754         proto_tree_add_item(tree, hf_smpp_short_message,
1755                             tvb, offset, length, FALSE);
1756         if (udhi) /* UDHI indicator present */
1757         {
1758             DebugLog(("UDHI present - set addresses\n"));
1759             /* Save original addresses */
1760             COPY_ADDRESS(&save_src, &(pinfo->src));
1761             COPY_ADDRESS(&save_dst, &(pinfo->dst));
1762             /* Set SMPP source and destination address */
1763             SET_ADDRESS(&(pinfo->src), AT_STRINGZ, 1+strlen(src_str), src_str);
1764             SET_ADDRESS(&(pinfo->dst), AT_STRINGZ, 1+strlen(dst_str), dst_str);
1765             tvb_msg = tvb_new_subset (tvb, offset,
1766                     MIN(length, tvb_reported_length(tvb) - offset), length);
1767             call_dissector (gsm_sms_handle, tvb_msg, pinfo, top_tree);
1768             /* Restore original addresses */
1769             COPY_ADDRESS(&(pinfo->src), &save_src);
1770             COPY_ADDRESS(&(pinfo->dst), &save_dst);
1771             /* Get rid of SMPP text string addresses */
1772             g_free(src_str);
1773             g_free(dst_str);
1774         }
1775         offset += length;
1776     }
1777     smpp_handle_tlv(tree, tvb, &offset);
1778 }
1779
1780 #define deliver_sm(a, b, c, d) submit_sm(a, b, c, d)
1781
1782 static void
1783 replace_sm(proto_tree *tree, tvbuff_t *tvb)
1784 {
1785     int          offset = 0;
1786     guint8       flag;
1787     guint8       length;
1788
1789     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1790     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1791     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1792     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1793         if (tvb_get_guint8(tvb,offset)) {
1794     smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1795                                 hf_smpp_schedule_delivery_time_r, &offset);
1796         } else { /* Time = NULL */
1797                 proto_tree_add_text(tree, tvb, offset++, 1,
1798                                 "Scheduled delivery time: Keep initial delivery time setting");
1799         }
1800         if (tvb_get_guint8(tvb,offset)) {
1801     smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1802                                 hf_smpp_validity_period_r, &offset);
1803         } else { /* Time = NULL */
1804                 proto_tree_add_text(tree, tvb, offset++, 1,
1805                                 "Validity period: Keep initial validity period setting");
1806         }
1807     flag = tvb_get_guint8(tvb, offset);
1808     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1809     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1810     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1811     offset++;
1812     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1813     length = tvb_get_guint8(tvb, offset);
1814     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1815     if (length)
1816         proto_tree_add_item(tree, hf_smpp_short_message,
1817                             tvb, offset, length, FALSE);
1818     offset += length;
1819 }
1820
1821 static void
1822 cancel_sm(proto_tree *tree, tvbuff_t *tvb)
1823 {
1824     int          offset = 0;
1825
1826     smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
1827     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1828     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1829     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1830     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1831     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1832     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1833     smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
1834 }
1835
1836 static void
1837 submit_multi(proto_tree *tree, tvbuff_t *tvb)
1838 {
1839     int          offset = 0;
1840     guint8       flag;
1841     guint8       length;
1842
1843     smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
1844     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1845     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1846     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1847
1848     smpp_handle_dlist(tree, tvb, &offset);
1849
1850     flag = tvb_get_guint8(tvb, offset);
1851     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1852             tvb, offset, 1, flag);
1853     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1854             tvb, offset, 1, flag);
1855     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1856             tvb, offset, 1, flag);
1857     offset++;
1858     smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset);
1859     smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset);
1860     if (tvb_get_guint8(tvb,offset)) {
1861         smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1862                 hf_smpp_schedule_delivery_time_r, &offset);
1863     } else { /* Time = NULL means Immediate delivery */
1864         proto_tree_add_text(tree, tvb, offset++, 1,
1865                 "Scheduled delivery time: Immediate delivery");
1866     }
1867     if (tvb_get_guint8(tvb,offset)) {
1868         smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1869                 hf_smpp_validity_period_r, &offset);
1870     } else { /* Time = NULL means SMSC default validity */
1871         proto_tree_add_text(tree, tvb, offset++, 1,
1872                 "Validity period: SMSC default validity period");
1873     }
1874     flag = tvb_get_guint8(tvb, offset);
1875     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1876     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1877     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1878     offset++;
1879     smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset);
1880     smpp_handle_dcs(tree, tvb, &offset);
1881     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1882     length = tvb_get_guint8(tvb, offset);
1883     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1884     if (length)
1885         proto_tree_add_item(tree, hf_smpp_short_message,
1886                 tvb, offset, length, FALSE);
1887     offset += length;
1888     smpp_handle_tlv(tree, tvb, &offset);
1889 }
1890
1891 static void
1892 alert_notification(proto_tree *tree, tvbuff_t *tvb)
1893 {
1894     int          offset = 0;
1895
1896     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1897     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1898     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1899     smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_ton, &offset);
1900     smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_npi, &offset);
1901     smpp_handle_string(tree, tvb, hf_smpp_esme_addr, &offset);
1902     smpp_handle_tlv(tree, tvb, &offset);
1903 }
1904
1905 static void
1906 data_sm(proto_tree *tree, tvbuff_t *tvb)
1907 {
1908     int          offset = 0;
1909     guint8       flag;
1910
1911     smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
1912     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1913     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1914     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1915     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1916     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1917     smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
1918     flag = tvb_get_guint8(tvb, offset);
1919     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1920                         tvb, offset, 1, flag);
1921     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1922                         tvb, offset, 1, flag);
1923     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1924                         tvb, offset, 1, flag);
1925     offset++;
1926     flag = tvb_get_guint8(tvb, offset);
1927     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1928     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1929     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1930     offset++;
1931         smpp_handle_dcs(tree, tvb, &offset);
1932     smpp_handle_tlv(tree, tvb, &offset);
1933 }
1934
1935 /*!
1936  * The next set of routines handle the different operation-responses,
1937  * associated with SMPP.
1938  */
1939 static void
1940 bind_receiver_resp(proto_tree *tree, tvbuff_t *tvb)
1941 {
1942     int          offset = 0;
1943
1944     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1945     smpp_handle_tlv(tree, tvb, &offset);
1946 }
1947
1948 #define bind_transmitter_resp(a, b) bind_receiver_resp(a, b)
1949
1950 static void
1951 query_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1952 {
1953     int          offset = 0;
1954
1955     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1956     smpp_handle_time(tree, tvb, hf_smpp_final_date,
1957                                 hf_smpp_final_date_r, &offset);
1958     smpp_handle_int1(tree, tvb, hf_smpp_message_state, &offset);
1959     smpp_handle_int1(tree, tvb, hf_smpp_error_code, &offset);
1960 }
1961
1962 #define bind_transceiver_resp(a, b) bind_receiver_resp(a, b)
1963
1964 static void
1965 submit_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1966 {
1967     int          offset = 0;
1968
1969     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1970 }
1971
1972 #define deliver_sm_resp(a, b) submit_sm_resp(a, b)
1973
1974 static void
1975 submit_multi_resp(proto_tree *tree, tvbuff_t *tvb)
1976 {
1977     int          offset = 0;
1978
1979     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1980     smpp_handle_dlist_resp(tree, tvb, &offset);
1981 }
1982
1983 static void
1984 data_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1985 {
1986     int          offset = 0;
1987
1988     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1989     smpp_handle_tlv(tree, tvb, &offset);
1990 }
1991
1992 /*
1993  * A 'heuristic dissector' that attemtps to establish whether we have
1994  * a genuine SMPP PDU here.
1995  * Only works when:
1996  *      at least the fixed header is there
1997  *      it has a correct overall PDU length
1998  *      it is a 'well-known' operation
1999  *      has a 'well-known' status
2000  */
2001 static gboolean
2002 dissect_smpp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2003 {
2004     guint        command_id;            /* SMPP command         */
2005     guint        command_status;        /* Status code          */
2006     guint        command_length;        /* length of PDU        */
2007
2008     if (tvb_reported_length(tvb) < 4 * 4)       /* Mandatory header     */
2009         return FALSE;
2010     command_length = tvb_get_ntohl(tvb, 0);
2011     if (command_length > 64 * 1024)
2012         return FALSE;
2013     command_id = tvb_get_ntohl(tvb, 4);         /* Only known commands  */
2014     if (match_strval(command_id, vals_command_id) == NULL)
2015         return FALSE;
2016     command_status = tvb_get_ntohl(tvb, 8);     /* ..with known status  */
2017     if (match_strval(command_status, vals_command_status) == NULL)
2018         return FALSE;
2019     dissect_smpp(tvb, pinfo, tree);
2020     return TRUE;
2021 }
2022
2023 static guint
2024 get_smpp_pdu_len(tvbuff_t *tvb, int offset)
2025 {
2026     return tvb_get_ntohl(tvb, offset);
2027 }
2028
2029 /*
2030  * This global SMPP variable is used to determine whether the PDU to dissect
2031  * is the first SMPP PDU in the packet (or reassembled buffer), requiring
2032  * different column update code than subsequent SMPP PDUs within this packet
2033  * (or reassembled buffer).
2034  *
2035  * FIXME - This approach is NOT dissection multi-thread safe!
2036  */
2037 static gboolean first = TRUE;
2038
2039 static void
2040 dissect_smpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2041 {
2042     first = TRUE;
2043     if (pinfo->ptype == PT_TCP) {       /* are we running on top of TCP */
2044         tcp_dissect_pdus(tvb, pinfo, tree,
2045                 reassemble_over_tcp,    /* Do we try to reassemble      */
2046                 16,                     /* Length of fixed header       */
2047                 get_smpp_pdu_len,       /* Function returning PDU len   */
2048                 dissect_smpp_pdu);      /* PDU dissector                */
2049     } else {                            /* no? probably X.25            */
2050         guint32 offset = 0;
2051         while (tvb_reported_length_remaining(tvb, offset) > 0) {
2052             guint16 pdu_len = tvb_get_ntohl(tvb, offset);
2053             gint pdu_real_len = tvb_length_remaining(tvb, offset);
2054             tvbuff_t *pdu_tvb;
2055
2056             if (pdu_real_len <= 0)
2057                 return;
2058             if (pdu_real_len > pdu_len)
2059                 pdu_real_len = pdu_len;
2060             pdu_tvb = tvb_new_subset(tvb, offset, pdu_real_len, pdu_len);
2061             dissect_smpp_pdu(pdu_tvb, pinfo, tree);
2062             offset += pdu_len;
2063             first = FALSE;
2064         }
2065     }
2066 }
2067
2068
2069 /* Dissect a single SMPP PDU contained within "tvb". */
2070 static void
2071 dissect_smpp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2072 {
2073     int          offset = 0;            /* Offset within tvbuff */
2074     guint        command_length;        /* length of PDU        */
2075     guint        command_id;            /* SMPP command         */
2076     guint        command_status;        /* Status code          */
2077     guint        sequence_number;       /* ...of command        */
2078     gchar       *command_str;
2079     gchar       *command_status_str = NULL;
2080     /* Set up structures needed to add the protocol subtree and manage it */
2081     proto_item  *ti = NULL;
2082     proto_tree  *smpp_tree = NULL;
2083
2084     /*
2085      * Safety: don't even try to dissect the PDU
2086      * when the mandatory header isn't present.
2087      */
2088     if (tvb_reported_length(tvb) < 4 * 4)
2089         return;
2090     command_length = tvb_get_ntohl(tvb, offset);
2091     offset += 4;
2092     command_id = tvb_get_ntohl(tvb, offset);
2093     command_str = val_to_str(command_id, vals_command_id,
2094             "(Unknown SMPP Operation 0x%08X)");
2095     offset += 4;
2096     command_status = tvb_get_ntohl(tvb, offset);
2097     if (command_id & 0x80000000) {
2098         command_status_str = val_to_str(command_status, vals_command_status,
2099                 "(Reserved Error 0x%08X)");
2100     }
2101     offset += 4;
2102     sequence_number = tvb_get_ntohl(tvb, offset);
2103     offset += 4;
2104
2105     /*
2106      * Update the protocol column.
2107      */
2108     if (first == TRUE) {
2109         if (check_col(pinfo->cinfo, COL_PROTOCOL))
2110             col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMPP");
2111     }
2112
2113     /*
2114      * Create display subtree for the protocol
2115      */
2116     if (tree) {
2117         ti = proto_tree_add_item (tree, proto_smpp, tvb, 0, tvb->length, FALSE);
2118         smpp_tree = proto_item_add_subtree (ti, ett_smpp);
2119     }
2120
2121     /*
2122      * Cycle over the encapsulated PDUs
2123      */
2124     {
2125         tvbuff_t *pdu_tvb;
2126
2127         /*
2128          * Make entries in the Info column on the summary display
2129          */
2130         if (check_col(pinfo->cinfo, COL_INFO)) {
2131             if (first == TRUE) {
2132                 /*
2133                  * First PDU - We already computed the fixed header
2134                  */
2135                 col_clear(pinfo->cinfo, COL_INFO);
2136                 col_add_fstr(pinfo->cinfo, COL_INFO, "SMPP %s", command_str);
2137                 first = FALSE;
2138             } else {
2139                 /*
2140                  * Subsequent PDUs
2141                  */
2142                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", command_str);
2143             }
2144             /*
2145              * Display command status of responses in Info column
2146              */
2147             if (command_id & 0x80000000) {
2148                 col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"",
2149                         command_status_str);
2150             }
2151         }
2152
2153         /*
2154          * Create a tvb for the current PDU.
2155          * Physical length: at most command_length
2156          * Reported length: command_length
2157          */
2158         if (tvb_length_remaining(tvb, offset - 16 + command_length) > 0) {
2159             pdu_tvb = tvb_new_subset(tvb, offset - 16,
2160                     command_length,     /* Physical length */
2161                     command_length);    /* Length reported by the protocol */
2162         } else {
2163             pdu_tvb = tvb_new_subset(tvb, offset - 16,
2164                     tvb_length_remaining(tvb, offset - 16),/* Physical length */
2165                     command_length);    /* Length reported by the protocol */
2166         }
2167
2168         /*
2169          * Dissect the PDU
2170          *
2171          * If "tree" is NULL, Ethereal is only interested in creation
2172          * of conversations, reassembly and subdissection but not in
2173          * the detailed protocol tree.
2174          * In the interest of speed, skip the generation of protocol tree
2175          * items when "tree" is NULL.
2176          *
2177          * The only PDU which requires subdissection currently is the
2178          * sm_submit PDU (command ID = 0x00000004).
2179          */
2180         if (tree || (command_id == 4))
2181         {
2182             /*
2183              * Create display subtree for the PDU
2184              */
2185             if (tree) {
2186                 proto_tree_add_uint(smpp_tree, hf_smpp_command_length,
2187                         pdu_tvb, 0, 4, command_length);
2188                 proto_tree_add_uint(smpp_tree, hf_smpp_command_id,
2189                         pdu_tvb, 4, 4, command_id);
2190                 proto_item_append_text(ti, ", Command: %s", command_str);
2191
2192                 /*
2193                  * Status is only meaningful with responses
2194                  */
2195                 if (command_id & 0x80000000) {
2196                     proto_tree_add_uint(smpp_tree, hf_smpp_command_status,
2197                             pdu_tvb, 8, 4, command_status);
2198                     proto_item_append_text (ti, ", Status: \"%s\"",
2199                             command_status_str);
2200                 }
2201                 proto_tree_add_uint(smpp_tree, hf_smpp_sequence_number,
2202                         pdu_tvb, 12, 4, sequence_number);
2203                 proto_item_append_text(ti, ", Seq: %u, Len: %u",
2204                         sequence_number, command_length);
2205             }
2206
2207             /*
2208              * End of fixed header.
2209              * Don't dissect variable part if it is shortened.
2210              *
2211              * FIXME - We then do not report a Short Frame or Malformed Packet
2212              */
2213             if (command_length <= tvb_reported_length(pdu_tvb))
2214             {
2215                 tvbuff_t *tmp_tvb = tvb_new_subset(pdu_tvb, 16,
2216                         -1, command_length - 16);
2217                 if (command_id & 0x80000000)
2218                 {
2219                     switch (command_id & 0x7FFFFFFF) {
2220                         /*
2221                          * All of these only have a fixed header
2222                          */
2223                         case   0:       /* Generic nack         */
2224                         case   6:       /* Unbind resp          */
2225                         case   7:       /* Replace SM resp      */
2226                         case   8:       /* Cancel SM resp       */
2227                         case  21:       /* Enquire link resp    */
2228                             break;
2229                         case   1:
2230                             if (!command_status)
2231                                 bind_receiver_resp(smpp_tree, tmp_tvb);
2232                             break;
2233                         case   2:
2234                             if (!command_status)
2235                                 bind_transmitter_resp(smpp_tree, tmp_tvb);
2236                             break;
2237                         case   3:
2238                             if (!command_status)
2239                                 query_sm_resp(smpp_tree, tmp_tvb);
2240                             break;
2241                         case   4:
2242                             if (!command_status)
2243                                 submit_sm_resp(smpp_tree, tmp_tvb);
2244                             break;
2245                         case   5:
2246                             if (!command_status)
2247                                 deliver_sm_resp(smpp_tree, tmp_tvb);
2248                             break;
2249                         case   9:
2250                             if (!command_status)
2251                                 bind_transceiver_resp(smpp_tree, tmp_tvb);
2252                             break;
2253                         case  33:
2254                             if (!command_status)
2255                                 submit_multi_resp(smpp_tree, tmp_tvb);
2256                             break;
2257                         case 259:
2258                             if (!command_status)
2259                                 data_sm_resp(smpp_tree, tmp_tvb);
2260                             break;
2261                         default:
2262                             break;
2263                     } /* switch (command_id & 0x7FFFFFFF) */
2264                 }
2265                 else
2266                 {
2267                     switch (command_id) {
2268                         case   1:
2269                             bind_receiver(smpp_tree, tmp_tvb);
2270                             break;
2271                         case   2:
2272                             bind_transmitter(smpp_tree, tmp_tvb);
2273                             break;
2274                         case   3:
2275                             query_sm(smpp_tree, tmp_tvb);
2276                             break;
2277                         case   4:
2278                             submit_sm(smpp_tree, tmp_tvb, pinfo, tree);
2279                             break;
2280                         case   5:
2281                             deliver_sm(smpp_tree, tmp_tvb, pinfo, tree);
2282                             break;
2283                         case   6:       /* Unbind               */
2284                         case  21:       /* Enquire link         */
2285                             break;
2286                         case   7:
2287                             replace_sm(smpp_tree, tmp_tvb);
2288                             break;
2289                         case   8:
2290                             cancel_sm(smpp_tree, tmp_tvb);
2291                             break;
2292                         case   9:
2293                             bind_transceiver(smpp_tree, tmp_tvb);
2294                             break;
2295                         case  11:
2296                             outbind(smpp_tree, tmp_tvb);
2297                             break;
2298                         case  33:
2299                             submit_multi(smpp_tree, tmp_tvb);
2300                             break;
2301                         case  258:
2302                             alert_notification(smpp_tree, tmp_tvb);
2303                             break;
2304                         case  259:
2305                             data_sm(smpp_tree, tmp_tvb);
2306                             break;
2307                         default:
2308                             break;
2309                     } /* switch (command_id) */
2310                 } /* if (command_id & 0x80000000) */
2311             } /* if (command_length <= tvb_reported_length(pdu_tvb)) */
2312             offset += command_length;
2313         } /* if (tree || (command_id == 4)) */
2314         first = FALSE;
2315     }
2316
2317     return;
2318 }
2319
2320
2321 /*
2322  * GSM SMS dissection
2323  */
2324 static void
2325 dissect_smpp_gsm_sms(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2326 {
2327         proto_item *ti;
2328         proto_tree *subtree;
2329         DebugLog(("dissect_smpp_gsm_sms() - START\n"));
2330         ti = proto_tree_add_item(tree, proto_smpp_gsm_sms, tvb, 0, -1, TRUE);
2331         subtree = proto_item_add_subtree(ti, ett_gsm_sms);
2332         parse_sm_message(subtree, tvb, pinfo, tree);
2333         DebugLog(("dissect_smpp_gsm_sms() - END\n"));
2334 }
2335
2336 /* Register the protocol with Ethereal */
2337 void
2338 proto_register_smpp_gsm_sms(void)
2339 {
2340         module_t *smpp_gsm_sms_module; /* Preferences for SMPP */
2341
2342     /* Setup list of header fields      */
2343     static hf_register_info hf[] = {
2344         /*
2345          * User Data Header
2346          */
2347         {   &hf_smpp_udh_iei,
2348                 {       "IE Id", "smpp.gsm-sms.udh.iei",
2349                 FT_UINT8, BASE_HEX, VALS(vals_udh_iei), 0x00,
2350                 "Name of the User Data Header Information Element.",
2351                 HFILL
2352                 }
2353         },
2354         {   &hf_smpp_udh_length,
2355             {   "UDH Length", "smpp.gsm-sms.udh.len",
2356                 FT_UINT8, BASE_DEC, NULL, 0x00,
2357                 "Length of the User Data Header (bytes)",
2358                 HFILL
2359             }
2360         },
2361         {   &hf_smpp_udh_multiple_messages,
2362             {   "Multiple messages UDH", "smpp.gsm-sms.udh.mm",
2363                 FT_NONE, BASE_NONE, NULL, 0x00,
2364                 "Multiple messages User Data Header",
2365                 HFILL
2366             }
2367         },
2368         {   &hf_smpp_udh_multiple_messages_msg_id,
2369             {   "Message identifier", "smpp.gsm-sms.udh.mm.msg_id",
2370                 FT_UINT16, BASE_DEC, NULL, 0x00,
2371                 "Identification of the message",
2372                 HFILL
2373             }
2374         },
2375         {   &hf_smpp_udh_multiple_messages_msg_parts,
2376             {   "Message parts", "smpp.gsm-sms.udh.mm.msg_parts",
2377                 FT_UINT8, BASE_DEC, NULL, 0x00,
2378                 "Total number of message parts (fragments)",
2379                 HFILL
2380             }
2381         },
2382         {   &hf_smpp_udh_multiple_messages_msg_part,
2383             {   "Message part number", "smpp.gsm-sms.udh.mm.msg_part",
2384                 FT_UINT8, BASE_DEC, NULL, 0x00,
2385                 "Message part (fragment) sequence number",
2386                 HFILL
2387             }
2388         },
2389         {   &hf_smpp_udh_ports,
2390             {   "Port number UDH", "smpp.gsm-sms.udh.ports",
2391                 FT_NONE, BASE_NONE, NULL, 0x00,
2392                 "Port number User Data Header",
2393                 HFILL
2394             }
2395         },
2396         {   &hf_smpp_udh_ports_src,
2397             {   "Source port", "smpp.gsm-sms.udh.ports.src",
2398                 FT_UINT8, BASE_DEC, NULL, 0x00,
2399                 "Source port",
2400                 HFILL
2401             }
2402         },
2403         {   &hf_smpp_udh_ports_dst,
2404             {   "Destination port", "smpp.gsm-sms.udh.ports.dst",
2405                 FT_UINT8, BASE_DEC, NULL, 0x00,
2406                 "Destination port",
2407                 HFILL
2408             }
2409         },
2410         /*
2411          * Short Message fragment reassembly
2412          */
2413         {       &hf_sm_fragments,
2414                 {       "Short Message fragments", "smpp.gsm-sms.fragments",
2415                         FT_NONE, BASE_NONE, NULL, 0x00,
2416                         "SMPP Short Message fragments",
2417                         HFILL
2418                 }
2419         },
2420         {       &hf_sm_fragment,
2421                 {       "Short Message fragment", "smpp.gsm-sms.fragment",
2422                         FT_FRAMENUM, BASE_NONE, NULL, 0x00,
2423                         "SMPP Short Message fragment",
2424                         HFILL
2425                 }
2426         },
2427         {       &hf_sm_fragment_overlap,
2428                 {       "Short Message fragment overlap", "smpp.gsm-sms.fragment.overlap",
2429                         FT_BOOLEAN, BASE_NONE, NULL, 0x00,
2430                         "SMPP Short Message fragment overlaps with other fragment(s)",
2431                         HFILL
2432                 }
2433         },
2434         {       &hf_sm_fragment_overlap_conflicts,
2435                 {       "Short Message fragment overlapping with conflicting data",
2436                         "smpp.gsm-sms.fragment.overlap.conflicts",
2437                         FT_BOOLEAN, BASE_NONE, NULL, 0x00,
2438                         "SMPP Short Message fragment overlaps with conflicting data",
2439                         HFILL
2440                 }
2441         },
2442         {       &hf_sm_fragment_multiple_tails,
2443                 {       "Short Message has multiple tail fragments",
2444                         "smpp.gsm-sms.fragment.multiple_tails",
2445                         FT_BOOLEAN, BASE_NONE, NULL, 0x00,
2446                         "SMPP Short Message fragment has multiple tail fragments",
2447                         HFILL
2448                 }
2449         },
2450         {       &hf_sm_fragment_too_long_fragment,
2451                 {       "Short Message fragment too long",
2452                         "smpp.gsm-sms.fragment.too_long_fragment",
2453                         FT_BOOLEAN, BASE_NONE, NULL, 0x00,
2454                         "SMPP Short Message fragment data goes beyond the packet end",
2455                         HFILL
2456                 }
2457         },
2458         {       &hf_sm_fragment_error,
2459                 {       "Short Message defragmentation error", "smpp.gsm-sms.fragment.error",
2460                         FT_FRAMENUM, BASE_NONE, NULL, 0x00,
2461                         "SMPP Short Message defragmentation error due to illegal fragments",
2462                         HFILL
2463                 }
2464         },
2465         {       &hf_sm_reassembled_in,
2466                 {       "Reassembled in",
2467                         "smpp.gsm-sms.reassembled.in",
2468                         FT_FRAMENUM, BASE_NONE, NULL, 0x00,
2469                         "SMPP Short Message has been reassembled in this packet.", HFILL
2470                 }
2471         },
2472         };
2473
2474     static gint *ett[] = {
2475         &ett_gsm_sms,
2476         &ett_udh,
2477         &ett_udh_ie,
2478         &ett_sm_fragment,
2479         &ett_sm_fragments,
2480     };
2481     DebugLog(("Registering SMPP GSM SMS dissector\n"));
2482     /* Register the protocol name and description */
2483     proto_smpp_gsm_sms = proto_register_protocol(
2484             "SMPP - GSM Short Message Service", /* Name */
2485             "SMPP GSM SMS",                     /* Short name */
2486             "smpp-gsm-sms");                    /* Filter name */
2487
2488     /* Required function calls to register header fields and subtrees used */
2489     proto_register_field_array(proto_smpp, hf, array_length(hf));
2490     proto_register_subtree_array(ett, array_length(ett));
2491
2492     /* Subdissector code */
2493     gsm_sms_dissector_table = register_dissector_table("smpp.gsm-sms.udh.port",
2494             "GSM SMS port IE in UDH", FT_UINT16, BASE_DEC);
2495
2496     /* Preferences for SMPP */
2497     smpp_gsm_sms_module = prefs_register_protocol (proto_smpp_gsm_sms, NULL);
2498     prefs_register_bool_preference (smpp_gsm_sms_module,
2499             "port_number_udh_means_wsp",
2500             "Port Number IE in UDH always triggers CL-WSP dissection",
2501             "Always decode a GSM Short Message as Connectionless WSP "
2502             "if a Port Number Information Element is present "
2503             "in the SMS User Data Header.",
2504             &port_number_udh_means_wsp);
2505     prefs_register_bool_preference (smpp_gsm_sms_module, "try_dissect_1st_fragment",
2506             "Always try subdissection of 1st Short Message fragment",
2507             "Always try subdissection of the 1st fragment of a fragmented "
2508             "GSM Short Message. If reassembly is possible, the Short Message "
2509             "may be dissected twice (once as a short frame, once in its "
2510             "entirety).",
2511             &try_dissect_1st_frag);
2512
2513     register_dissector("smpp-gsm-sms", dissect_smpp_gsm_sms, proto_smpp_gsm_sms);
2514
2515     /* SMPP dissector initialization routines */
2516     register_init_routine (sm_defragment_init);
2517 }
2518
2519 void
2520 proto_reg_handoff_smpp_gsm_sms(void)
2521 {
2522         dissector_handle_t smpp_gsm_sms_handle;
2523         DebugLog(("Creating SMPP GSM SMS dissector handle\n"));
2524         smpp_gsm_sms_handle = create_dissector_handle(dissect_smpp_gsm_sms,
2525                         proto_smpp_gsm_sms);
2526 }
2527
2528
2529
2530
2531 /* Register the protocol with Ethereal */
2532 void
2533 proto_register_smpp(void)
2534 {
2535     module_t *smpp_module; /* Preferences for SMPP */
2536
2537     /* Setup list of header fields      */
2538     static hf_register_info hf[] = {
2539         {   &hf_smpp_command_length,
2540             {   "Length    ", "smpp.command_length",
2541                 FT_UINT32, BASE_DEC, NULL, 0x00,
2542                 "Total length of the SMPP PDU.",
2543                 HFILL
2544             }
2545         },
2546         {   &hf_smpp_command_id,
2547             {   "Operation ", "smpp.command_id",
2548                 FT_UINT32, BASE_HEX, VALS(vals_command_id), 0x00,
2549                 "Defines the SMPP PDU.",
2550                 HFILL
2551             }
2552         },
2553         {   &hf_smpp_command_status,
2554             {   "Result    ", "smpp.command_status",
2555                 FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00,
2556                 "Indicates success or failure of the SMPP request.",
2557                 HFILL
2558             }
2559         },
2560         {   &hf_smpp_sequence_number,
2561             {   "Sequence #", "smpp.sequence_number",
2562                 FT_UINT32, BASE_DEC, NULL, 0x00,
2563                 "A number to correlate requests with responses.",
2564                 HFILL
2565             }
2566         },
2567         {   &hf_smpp_system_id,
2568             {   "System ID", "smpp.system_id",
2569                 FT_STRING, BASE_NONE, NULL, 0x00,
2570                 "Identifies a system.",
2571                 HFILL
2572             }
2573         },
2574         {   &hf_smpp_password,
2575             {   "Password", "smpp.password",
2576                 FT_STRING, BASE_NONE, NULL, 0x00,
2577                 "Password used for authentication.",
2578                 HFILL
2579             }
2580         },
2581         {   &hf_smpp_system_type,
2582             {   "System type", "smpp.system_type",
2583                 FT_STRING, BASE_NONE, NULL, 0x00,
2584                 "Categorises the system.",
2585                 HFILL
2586             }
2587         },
2588         {   &hf_smpp_interface_version,
2589             {   "Version (if)", "smpp.interface_version",
2590                 FT_STRING, BASE_NONE, NULL, 0x00,
2591                 "Version of SMPP interface supported.",
2592                 HFILL
2593             }
2594         },
2595         {   &hf_smpp_service_type,
2596             {   "Service type", "smpp.service_type",
2597                 FT_STRING, BASE_NONE, NULL, 0x00,
2598                 "SMS application service associated with the message.",
2599                 HFILL
2600             }
2601         },
2602         {   &hf_smpp_addr_ton,
2603             {   "Type of number", "smpp.addr_ton",
2604                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
2605                 "Indicates the type of number, given in the address.",
2606                 HFILL
2607             }
2608         },
2609         {   &hf_smpp_source_addr_ton,
2610             {   "Type of number (originator)", "smpp.source_addr_ton",
2611                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
2612                 "Indicates originator type of number, given in the address.",
2613                 HFILL
2614             }
2615         },
2616         {   &hf_smpp_dest_addr_ton,
2617             {   "Type of number (recipient)", "smpp.dest_addr_ton",
2618                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
2619                 "Indicates recipient type of number, given in the address.",
2620                 HFILL
2621             }
2622         },
2623         {   &hf_smpp_addr_npi,
2624             {   "Numbering plan indicator", "smpp.addr_npi",
2625                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
2626                 "Gives the numbering plan this address belongs to.",
2627                 HFILL
2628             }
2629         },
2630         {   &hf_smpp_source_addr_npi,
2631             {   "Numbering plan indicator (originator)", "smpp.source_addr_npi",
2632                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
2633                 "Gives originator numbering plan this address belongs to.",
2634                 HFILL
2635             }
2636         },
2637         {   &hf_smpp_dest_addr_npi,
2638             {   "Numbering plan indicator (recipient)", "smpp.dest_addr_npi",
2639                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
2640                 "Gives recipient numbering plan this address belongs to.",
2641                 HFILL
2642             }
2643         },
2644         {   &hf_smpp_address_range,
2645             {   "Address", "smpp.address_range",
2646                 FT_STRING, BASE_NONE, NULL, 0x00,
2647                 "Given address or address range.",
2648                 HFILL
2649             }
2650         },
2651         {   &hf_smpp_source_addr,
2652             {   "Originator address", "smpp.source_addr",
2653                 FT_STRING, BASE_NONE, NULL, 0x00,
2654                 "Address of SME originating this message.",
2655                 HFILL
2656             }
2657         },
2658         {   &hf_smpp_destination_addr,
2659             {   "Recipient address", "smpp.destination_addr",
2660                 FT_STRING, BASE_NONE, NULL, 0x00,
2661                 "Address of SME receiving this message.",
2662                 HFILL
2663             }
2664         },
2665         {   &hf_smpp_esm_submit_msg_mode,
2666             {   "Messaging mode", "smpp.esm.submit.msg_mode",
2667                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_msg_mode), 0x03,
2668                 "Mode attribute for this message.",
2669                 HFILL
2670             }
2671         },
2672         {   &hf_smpp_esm_submit_msg_type,
2673             {   "Message type  ", "smpp.esm.submit.msg_type",
2674                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_msg_type), 0x3C,
2675                 "Type attribute for this message.",
2676                 HFILL
2677             }
2678         },
2679         {   &hf_smpp_esm_submit_features,
2680             {   "GSM features  ", "smpp.esm.submit.features",
2681                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_features), 0xC0,
2682                 "GSM network specific features.",
2683                 HFILL
2684             }
2685         },
2686         /*! \todo Get proper values from GSM-spec.      */
2687         {   &hf_smpp_protocol_id,
2688             {   "Protocol id.", "smpp.protocol_id",
2689                 FT_UINT8, BASE_HEX, NULL, 0x00,
2690                 "Protocol identifier according GSM 03.40.",
2691                 HFILL
2692             }
2693         },
2694         {   &hf_smpp_priority_flag,
2695             {   "Priority level", "smpp.priority_flag",
2696                 FT_UINT8, BASE_HEX, VALS(vals_priority_flag), 0x00,
2697                 "The priority level of the short message.",
2698                 HFILL
2699             }
2700         },
2701         {   &hf_smpp_schedule_delivery_time,
2702             {   "Scheduled delivery time", "smpp.schedule_delivery_time",
2703                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2704                 "Scheduled time for delivery of short message.",
2705                 HFILL
2706             }
2707         },
2708         {   &hf_smpp_schedule_delivery_time_r,
2709             {   "Scheduled delivery time", "smpp.schedule_delivery_time_r",
2710                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
2711                 "Scheduled time for delivery of short message.",
2712                 HFILL
2713             }
2714         },
2715         {   &hf_smpp_validity_period,
2716             {   "Validity period", "smpp.validity_period",
2717                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2718                 "Validity period of this message.",
2719                 HFILL
2720             }
2721         },
2722         {   &hf_smpp_validity_period_r,
2723             {   "Validity period", "smpp.validity_period_r",
2724                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
2725                 "Validity period of this message.",
2726                 HFILL
2727             }
2728         },
2729         {   &hf_smpp_regdel_receipt,
2730             {   "Delivery receipt  ", "smpp.regdel.receipt",
2731                 FT_UINT8, BASE_HEX, VALS(vals_regdel_receipt), 0x03,
2732                 "SMSC delivery receipt request.",
2733                 HFILL
2734             }
2735         },
2736         {   &hf_smpp_regdel_acks,
2737             {   "Message type      ", "smpp.regdel.acks",
2738                 FT_UINT8, BASE_HEX, VALS(vals_regdel_acks), 0x0C,
2739                 "SME acknowledgement request.",
2740                 HFILL
2741             }
2742         },
2743         {   &hf_smpp_regdel_notif,
2744             {   "Intermediate notif", "smpp.regdel.notif",
2745                 FT_UINT8, BASE_HEX, VALS(vals_regdel_notif), 0x10,
2746                 "Intermediate notification request.",
2747                 HFILL
2748             }
2749         },
2750         {   &hf_smpp_replace_if_present_flag,
2751             {   "Replace           ", "smpp.replace_if_present_flag",
2752                 FT_UINT8, BASE_HEX, VALS(vals_replace_if_present_flag), 0x01,
2753                 "Replace the short message with this one or not.",
2754                 HFILL
2755             }
2756         },
2757         {   &hf_smpp_data_coding,
2758             {   "Data coding", "smpp.data_coding",
2759                 FT_UINT8, BASE_HEX, NULL, 0x00,
2760                 "Defines the encoding scheme of the message.",
2761                 HFILL
2762             }
2763         },
2764         {   &hf_smpp_sm_default_msg_id,
2765             {   "Predefined message", "smpp.sm_default_msg_id",
2766                 FT_UINT8, BASE_DEC, NULL, 0x00,
2767                 "Index of a predefined ('canned') short message.",
2768                 HFILL
2769             }
2770         },
2771         {   &hf_smpp_sm_length,
2772             {   "Message length", "smpp.sm_length",
2773                 FT_UINT8, BASE_DEC, NULL, 0x00,
2774                 "Length of the message content.",
2775                 HFILL
2776             }
2777         },
2778         {   &hf_smpp_short_message,
2779             {   "Message", "smpp.message",
2780                 FT_NONE, BASE_NONE, NULL, 0x00,
2781                 "The actual message or data.",
2782                 HFILL
2783             }
2784         },
2785         {   &hf_smpp_message_id,
2786             {   "Message id.", "smpp.message_id",
2787                 FT_STRING, BASE_NONE, NULL, 0x00,
2788                 "Identifier of the submitted short message.",
2789                 HFILL
2790             }
2791         },
2792         {   &hf_smpp_dlist,
2793             {   "Destination list", "smpp.dlist",
2794                 FT_NONE, BASE_NONE, NULL, 0x00,
2795                 "The list of destinations for a short message.",
2796                 HFILL
2797             }
2798         },
2799         {   &hf_smpp_dlist_resp,
2800             {   "Unsuccesfull delivery list", "smpp.dlist_resp",
2801                 FT_NONE, BASE_NONE, NULL, 0x00,
2802                 "The list of unsuccesfull deliveries to destinations.",
2803                 HFILL
2804             }
2805         },
2806         {   &hf_smpp_dl_name,
2807             {   "Distr. list name", "smpp.dl_name",
2808                 FT_STRING, BASE_NONE, NULL, 0x00,
2809                 "The name of the distribution list.",
2810                 HFILL
2811             }
2812         },
2813         {   &hf_smpp_final_date,
2814             {   "Final date", "smpp.final_date",
2815                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2816                 "Date-time when the queried message reached a final state.",
2817                 HFILL
2818             }
2819         },
2820         {   &hf_smpp_final_date_r,
2821             {   "Final date", "smpp.final_date_r",
2822                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
2823                 "Date-time when the queried message reached a final state.",
2824                 HFILL
2825             }
2826         },
2827         {   &hf_smpp_message_state,
2828             {   "Message state", "smpp.message_state",
2829                 FT_UINT8, BASE_DEC, VALS(vals_message_state), 0x00,
2830                 "Specifies the status of the queried short message.",
2831                 HFILL
2832             }
2833         },
2834         {   &hf_smpp_error_code,
2835             {   "Error code", "smpp.error_code",
2836                 FT_UINT8, BASE_DEC, NULL, 0x00,
2837                 "Network specific error code defining reason for failure.",
2838                 HFILL
2839             }
2840         },
2841         {   &hf_smpp_error_status_code,
2842             {   "Status", "smpp.error_status_code",
2843                 FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00,
2844                 "Indicates success/failure of request for this address.",
2845                 HFILL
2846             }
2847         },
2848         {   &hf_smpp_esme_addr_ton,
2849             {   "Type of number (ESME)", "smpp.esme_addr_ton",
2850                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
2851                 "Indicates recipient type of number, given in the address.",
2852                 HFILL
2853             }
2854         },
2855         {   &hf_smpp_esme_addr_npi,
2856             {   "Numbering plan indicator (ESME)", "smpp.esme_addr_npi",
2857                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
2858                 "Gives the numbering plan this address belongs to.",
2859                 HFILL
2860             }
2861         },
2862         {   &hf_smpp_esme_addr,
2863             {   "ESME address", "smpp.esme_addr",
2864                 FT_STRING, BASE_NONE, NULL, 0x00,
2865                 "Address of ESME originating this message.",
2866                 HFILL
2867             }
2868         },
2869         {   &hf_smpp_dest_addr_subunit,
2870             {   "Subunit destination", "smpp.dest_addr_subunit",
2871                 FT_UINT8, BASE_HEX, VALS(vals_addr_subunit), 0x00,
2872                 "Subunit address within mobile to route message to.",
2873                 HFILL
2874             }
2875         },
2876         {   &hf_smpp_source_addr_subunit,
2877             {   "Subunit origin", "smpp.source_addr_subunit",
2878                 FT_UINT8, BASE_HEX, VALS(vals_addr_subunit), 0x00,
2879                 "Subunit address within mobile that generated the message.",
2880                 HFILL
2881             }
2882         },
2883         {   &hf_smpp_dest_network_type,
2884             {   "Destination network", "smpp.dest_network_type",
2885                 FT_UINT8, BASE_HEX, VALS(vals_network_type), 0x00,
2886                 "Network associated with the destination address.",
2887                 HFILL
2888             }
2889         },
2890         {   &hf_smpp_source_network_type,
2891             {   "Originator network", "smpp.source_network_type",
2892                 FT_UINT8, BASE_HEX, VALS(vals_network_type), 0x00,
2893                 "Network associated with the originator address.",
2894                 HFILL
2895             }
2896         },
2897         {   &hf_smpp_dest_bearer_type,
2898             {   "Destination bearer", "smpp.dest_bearer_type",
2899                 FT_UINT8, BASE_HEX, VALS(vals_bearer_type), 0x00,
2900                 "Desired bearer for delivery of message.",
2901                 HFILL
2902             }
2903         },
2904         {   &hf_smpp_source_bearer_type,
2905             {   "Originator bearer", "smpp.source_bearer_type",
2906                 FT_UINT8, BASE_HEX, VALS(vals_bearer_type), 0x00,
2907                 "Bearer over which the message originated.",
2908                 HFILL
2909             }
2910         },
2911         {   &hf_smpp_dest_telematics_id,
2912             {   "Telematic interworking (dest)", "smpp.dest_telematics_id",
2913                 FT_UINT16, BASE_HEX, NULL, 0x00,
2914                 "Telematic interworking to be used for message delivery.",
2915                 HFILL
2916             }
2917         },
2918         {   &hf_smpp_source_telematics_id,
2919             {   "Telematic interworking (orig)", "smpp.source_telematics_id",
2920                 FT_UINT16, BASE_HEX, NULL, 0x00,
2921                 "Telematic interworking used for message submission.",
2922                 HFILL
2923             }
2924         },
2925         {   &hf_smpp_qos_time_to_live,
2926             {   "Validity period", "smpp.qos_time_to_live",
2927                 FT_UINT32, BASE_DEC, NULL, 0x00,
2928                 "Number of seconds to retain message before expiry.",
2929                 HFILL
2930             }
2931         },
2932         {   &hf_smpp_payload_type,
2933             {   "Payload", "smpp.payload_type",
2934                 FT_UINT8, BASE_DEC, VALS(vals_payload_type), 0x00,
2935                 "PDU type contained in the message payload.",
2936                 HFILL
2937             }
2938         },
2939         {   &hf_smpp_additional_status_info_text,
2940             {   "Information", "smpp.additional_status_info_text",
2941                 FT_STRING, BASE_NONE, NULL, 0x00,
2942                 "Description of the meaning of a response PDU.",
2943                 HFILL
2944             }
2945         },
2946         {   &hf_smpp_receipted_message_id,
2947             {   "SMSC identifier", "smpp.receipted_message_id",
2948                 FT_STRING, BASE_NONE, NULL, 0x00,
2949                 "SMSC handle of the message being received.",
2950                 HFILL
2951             }
2952         },
2953         {   &hf_smpp_privacy_indicator,
2954             {   "Privacy indicator", "smpp.privacy_indicator",
2955                 FT_UINT8, BASE_DEC, VALS(vals_privacy_indicator), 0x00,
2956                 "Indicates the privacy level of the message.",
2957                 HFILL
2958             }
2959         },
2960         {   &hf_smpp_user_message_reference,
2961             {   "Message reference", "smpp.user_message_reference",
2962                 FT_UINT16, BASE_HEX, NULL, 0x00,
2963                 "Reference to the message, assigned by the user.",
2964                 HFILL
2965             }
2966         },
2967         {   &hf_smpp_user_response_code,
2968             {   "Application response code", "smpp.user_response_code",
2969                 FT_UINT8, BASE_HEX, NULL, 0x00,
2970                 "A response code set by the user.",
2971                 HFILL
2972             }
2973         },
2974         {   &hf_smpp_language_indicator,
2975             {   "Language", "smpp.language_indicator",
2976                 FT_UINT8, BASE_DEC, VALS(vals_language_indicator), 0x00,
2977                 "Indicates the language of the short message.",
2978                 HFILL
2979             }
2980         },
2981         {   &hf_smpp_source_port,
2982             {   "Source port", "smpp.source_port",
2983                 FT_UINT16, BASE_HEX, NULL, 0x00,
2984                 "Application port associated with the source of the message.",
2985                 HFILL
2986             }
2987         },
2988         {   &hf_smpp_destination_port,
2989             {   "Destination port", "smpp.destination_port",
2990                 FT_UINT16, BASE_HEX, NULL, 0x00,
2991                 "Application port associated with the destination of the message.",
2992                 HFILL
2993             }
2994         },
2995         {   &hf_smpp_sar_msg_ref_num,
2996             {   "SAR reference number", "smpp.sar_msg_ref_num",
2997                 FT_UINT16, BASE_DEC, NULL, 0x00,
2998                 "Reference number for a concatenated short message.",
2999                 HFILL
3000             }
3001         },
3002         {   &hf_smpp_sar_total_segments,
3003             {   "SAR size", "smpp.sar_total_segments",
3004                 FT_UINT16, BASE_DEC, NULL, 0x00,
3005                 "Number of segments of a concatenated short message.",
3006                 HFILL
3007             }
3008         },
3009         {   &hf_smpp_sar_segment_seqnum,
3010             {   "SAR sequence number", "smpp.sar_segment_seqnum",
3011                 FT_UINT8, BASE_DEC, NULL, 0x00,
3012                 "Segment number within a concatenated short message.",
3013                 HFILL
3014             }
3015         },
3016         {   &hf_smpp_display_time,
3017             {   "Display time", "smpp.display_time",
3018                 FT_UINT8, BASE_DEC, VALS(vals_display_time), 0x00,
3019                 "Associates a display time with the message on the handset.",
3020                 HFILL
3021             }
3022         },
3023         {   &hf_smpp_ms_validity,
3024             {   "Validity info", "smpp.ms_validity",
3025                 FT_UINT8, BASE_DEC, VALS(vals_ms_validity), 0x00,
3026                 "Associates validity info with the message on the handset.",
3027                 HFILL
3028             }
3029         },
3030         {   &hf_smpp_dpf_result,
3031             {   "Delivery pending set?", "smpp.dpf_result",
3032                 FT_UINT8, BASE_DEC, VALS(vals_dpf_result), 0x00,
3033                 "Indicates whether Delivery Pending Flag was set.",
3034                 HFILL
3035             }
3036         },
3037         {   &hf_smpp_set_dpf,
3038             {   "Request DPF set", "smpp.set_dpf",
3039                 FT_UINT8, BASE_DEC, VALS(vals_set_dpf), 0x00,
3040                 "Request to set the DPF for certain failure scenario's.",
3041                 HFILL
3042             }
3043         },
3044         {   &hf_smpp_ms_availability_status,
3045             {   "Availability status", "smpp.ms_availability_status",
3046                 FT_UINT8, BASE_DEC, VALS(vals_ms_availability_status), 0x00,
3047                 "Indicates the availability state of the handset.",
3048                 HFILL
3049             }
3050         },
3051         {   &hf_smpp_delivery_failure_reason,
3052             {   "Delivery failure reason", "smpp.delivery_failure_reason",
3053                 FT_UINT8, BASE_DEC, VALS(vals_delivery_failure_reason), 0x00,
3054                 "Indicates the reason for a failed delivery attempt.",
3055                 HFILL
3056             }
3057         },
3058         {   &hf_smpp_more_messages_to_send,
3059             {   "More messages?", "smpp.more_messages_to_send",
3060                 FT_UINT8, BASE_DEC, VALS(vals_more_messages_to_send), 0x00,
3061                 "Indicates more messages pending for the same destination.",
3062                 HFILL
3063             }
3064         },
3065         {   &hf_smpp_number_of_messages,
3066             {   "Number of messages", "smpp.number_of_messages",
3067                 FT_UINT8, BASE_DEC, NULL, 0x00,
3068                 "Indicates number of messages stored in a mailbox.",
3069                 HFILL
3070             }
3071         },
3072         {   &hf_smpp_its_reply_type,
3073             {   "Reply method", "smpp.its_reply_type",
3074                 FT_UINT8, BASE_DEC, VALS(vals_its_reply_type), 0x00,
3075                 "Indicates the handset reply method on message receipt.",
3076                 HFILL
3077             }
3078         },
3079         {   &hf_smpp_ussd_service_op,
3080             {   "USSD service operation", "smpp.ussd_service_op",
3081                 FT_UINT8, BASE_DEC, VALS(vals_ussd_service_op), 0x00,
3082                 "Indicates the USSD service operation.",
3083                 HFILL
3084             }
3085         },
3086         {   &hf_smpp_vendor_op,
3087             {   "Optional parameter - Vendor-specific", "smpp.vendor_op",
3088                 FT_NONE, BASE_NONE, NULL, 0x00,
3089                 "A supplied optional parameter specific to an SMSC-vendor.",
3090                 HFILL
3091             }
3092         },
3093         {   &hf_smpp_reserved_op,
3094             {   "Optional parameter - Reserved", "smpp.reserved_op",
3095                 FT_NONE, BASE_NONE, NULL, 0x00,
3096                 "An optional parameter that is reserved in this version.",
3097                 HFILL
3098             }
3099         },
3100         {   &hf_smpp_msg_wait_ind,
3101             {   "Indication", "smpp.msg_wait.ind",
3102                 FT_UINT8, BASE_HEX, VALS(vals_msg_wait_ind), 0x80,
3103                 "Indicates to the handset that a message is waiting.",
3104                 HFILL
3105             }
3106         },
3107         {   &hf_smpp_msg_wait_type,
3108             {   "Type      ", "smpp.msg_wait.type",
3109                 FT_UINT8, BASE_HEX, VALS(vals_msg_wait_type), 0x03,
3110                 "Indicates type of message that is waiting.",
3111                 HFILL
3112             }
3113         },
3114         {   &hf_smpp_SC_interface_version,
3115             {   "SMSC-supported version", "smpp.SC_interface_version",
3116                 FT_STRING, BASE_NONE, NULL, 0x00,
3117                 "Version of SMPP interface supported by the SMSC.",
3118                 HFILL
3119             }
3120         },
3121         {   &hf_smpp_callback_num_pres,
3122             {   "Presentation", "smpp.callback_num.pres",
3123                 FT_UINT8, BASE_HEX, VALS(vals_callback_num_pres), 0x0C,
3124                 "Controls the presentation indication.",
3125                 HFILL
3126             }
3127         },
3128         {   &hf_smpp_callback_num_scrn,
3129             {   "Screening   ", "smpp.callback_num.scrn",
3130                 FT_UINT8, BASE_HEX, VALS(vals_callback_num_scrn), 0x03,
3131                 "Controls screening of the callback-number.",
3132                 HFILL
3133             }
3134         },
3135         {   &hf_smpp_callback_num_atag,
3136             {   "Callback number - alphanumeric display tag",
3137                 "smpp.callback_num_atag",
3138                 FT_NONE, BASE_NONE, NULL, 0x00,
3139                 "Associates an alphanumeric display with call back number.",
3140                 HFILL
3141             }
3142         },
3143         {   &hf_smpp_callback_num,
3144             {   "Callback number", "smpp.callback_num",
3145                 FT_NONE, BASE_NONE, NULL, 0x00,
3146                 "Associates a call back number with the message.",
3147                 HFILL
3148             }
3149         },
3150         {   &hf_smpp_network_error_type,
3151             {   "Error type", "smpp.network_error.type",
3152                 FT_UINT8, BASE_DEC, VALS(vals_network_error_type), 0x00,
3153                 "Indicates the network type.",
3154                 HFILL
3155             }
3156         },
3157         {   &hf_smpp_network_error_code,
3158             {   "Error code", "smpp.network_error.code",
3159                 FT_UINT16, BASE_HEX, NULL, 0x00,
3160                 "Gives the actual network error code.",
3161                 HFILL
3162             }
3163         },
3164         {   &hf_smpp_message_payload,
3165             {   "Payload", "smpp.message_payload",
3166                 FT_NONE, BASE_NONE, NULL, 0x00,
3167                 "Short message user data.",
3168                 HFILL
3169             }
3170         },
3171         {   &hf_smpp_alert_on_message_delivery,
3172             {   "Alert on delivery", "smpp.alert_on_message_delivery",
3173                 FT_NONE, BASE_NONE, NULL, 0x00,
3174                 "Instructs the handset to alert user on message delivery.",
3175                 HFILL
3176             }
3177         },
3178         {   &hf_smpp_its_session_number,
3179             {   "Session number", "smpp.its_session.number",
3180                 FT_UINT8, BASE_DEC, NULL, 0x00,
3181                 "Session number of interactive teleservice.",
3182                 HFILL
3183             }
3184         },
3185         {   &hf_smpp_its_session_sequence,
3186             {   "Sequence number  ", "smpp.its_session.sequence",
3187                 FT_UINT8, BASE_HEX, NULL, 0xFE,
3188                 "Sequence number of the dialogue unit.",
3189                 HFILL
3190             }
3191         },
3192         {   &hf_smpp_its_session_ind,
3193             {   "Session indicator", "smpp.its_session.ind",
3194                 FT_UINT8, BASE_HEX, VALS(vals_its_session_ind), 0x01,
3195                 "Indicates whether this message is end of conversation.",
3196                 HFILL
3197             }
3198         },
3199         {   &hf_smpp_opt_param,
3200             {   "Optional parameters", "smpp.opt_param",
3201                 FT_NONE, BASE_NONE, NULL, 0x00,
3202                 "The list of optional parameters in this operation.",
3203                 HFILL
3204             }
3205         },
3206         /*
3207          * Data Coding Scheme
3208          */
3209         {       &hf_smpp_dcs,
3210                 { "SMPP Data Coding Scheme", "smpp.dcs",
3211                 FT_UINT8, BASE_HEX, VALS(vals_data_coding), 0x00,
3212                 "Data Coding Scheme according to SMPP.",
3213                 HFILL
3214             }
3215         },
3216         {       &hf_smpp_dcs_sms_coding_group,
3217                 {       "DCS Coding Group for SMS", "smpp.dcs.sms_coding_group",
3218                         FT_UINT8, BASE_HEX, VALS(vals_dcs_sms_coding_group), 0xF0,
3219                         "Data Coding Scheme coding group for GSM Short Message Service.",
3220                         HFILL
3221                 }
3222         },
3223         {       &hf_smpp_dcs_text_compression,
3224                 {       "DCS Text compression", "smpp.dcs.text_compression",
3225                         FT_BOOLEAN, 8, TFS(&tfs_dcs_text_compression), 0x20,
3226                         "Indicates if text compression is used.", HFILL
3227                 }
3228         },
3229         {       &hf_smpp_dcs_class_present,
3230                 {       "DCS Class present", "smpp.dcs.class_present",
3231                         FT_BOOLEAN, 8, TFS(&tfs_dcs_class_present), 0x10,
3232                         "Indicates if the message class is present (defined).", HFILL
3233                 }
3234         },
3235         {       &hf_smpp_dcs_charset,
3236                 {       "DCS Character set", "smpp.dcs.charset",
3237                         FT_UINT8, BASE_HEX, VALS(vals_dcs_charset), 0x0C,
3238                         "Specifies the character set used in the message.", HFILL
3239                 }
3240         },
3241         {       &hf_smpp_dcs_class,
3242                 {       "DCS Message class", "smpp.dcs.class",
3243                         FT_UINT8, BASE_HEX, VALS(vals_dcs_class), 0x03,
3244                         "Specifies the message class.", HFILL
3245                 }
3246         },
3247         {       &hf_smpp_dcs_cbs_coding_group,
3248                 {       "DCS Coding Group for CBS", "smpp.dcs.cbs_coding_group",
3249                         FT_UINT8, BASE_HEX, VALS(vals_dcs_cbs_coding_group), 0xF0,
3250                         "Data Coding Scheme coding group for GSM Cell Broadcast Service.",
3251                         HFILL
3252                 }
3253         },
3254         {       &hf_smpp_dcs_cbs_language,
3255                 {       "DCS CBS Message language", "smpp.dcs.cbs_language",
3256                         FT_UINT8, BASE_HEX, VALS(vals_dcs_cbs_language), 0x3F,
3257                         "Language of the GSM Cell Broadcast Service message.", HFILL
3258                 }
3259         },
3260         {       &hf_smpp_dcs_cbs_class,
3261                 {       "DCS CBS Message class", "smpp.dcs.cbs_class",
3262                         FT_UINT8, BASE_HEX, VALS(vals_dcs_cbs_class), 0x03,
3263                         "Specifies the message class for GSM Cell Broadcast Service, "
3264                         "for the Data coding / message handling code group.", HFILL
3265                 }
3266         },
3267         {       &hf_smpp_dcs_wap_charset,
3268                 {       "DCS Message coding", "smpp.dcs.wap_coding",
3269                         FT_UINT8, BASE_HEX, VALS(vals_dcs_wap_charset), 0x0C,
3270                         "Specifies the used message encoding, "
3271                         "as specified by the WAP Forum (WAP over GSM USSD).", HFILL
3272                 }
3273         },
3274         {       &hf_smpp_dcs_wap_class,
3275                 {       "DCS CBS Message class", "smpp.dcs.wap_class",
3276                         FT_UINT8, BASE_HEX, VALS(vals_dcs_wap_class), 0x03,
3277                         "Specifies the message class for GSM Cell Broadcast Service, "
3278                         "as specified by the WAP Forum (WAP over GSM USSD).", HFILL
3279                 }
3280         },
3281     };
3282     /* Setup protocol subtree array */
3283     static gint *ett[] = {
3284         &ett_smpp,
3285         &ett_dlist,
3286         &ett_dlist_resp,
3287         &ett_opt_param,
3288         &ett_dcs,
3289     };
3290     DebugLog(("Registering SMPP dissector\n"));
3291     /* Register the protocol name and description */
3292     proto_smpp = proto_register_protocol("Short Message Peer to Peer",
3293                                          "SMPP", "smpp");
3294
3295     /* Required function calls to register header fields and subtrees used */
3296     proto_register_field_array(proto_smpp, hf, array_length(hf));
3297     proto_register_subtree_array(ett, array_length(ett));
3298
3299     /* Preferences */
3300     smpp_module = prefs_register_protocol (proto_smpp, NULL);
3301     prefs_register_bool_preference (smpp_module,
3302             "reassemble_smpp_over_tcp",
3303             "Reassemble SMPP over TCP",
3304             "Reassemble TCP segments that convey SMPP traffic.",
3305             &reassemble_over_tcp);
3306 }
3307
3308 /*
3309  * If dissector uses sub-dissector registration add a registration routine.
3310  * This format is required because a script is used to find these routines and
3311  * create the code that calls these routines.
3312  */
3313 void
3314 proto_reg_handoff_smpp(void)
3315 {
3316     dissector_handle_t smpp_handle;
3317
3318     /*
3319      * SMPP can be spoken on any port under TCP or X.25
3320      * ...how *do* we do that under X.25?
3321      *
3322      * We can register the heuristic SMPP dissector with X.25, for one
3323      * thing.  We don't currently have any mechanism to allow the user
3324      * to specify that a given X.25 circuit is to be dissected as SMPP,
3325      * however.
3326      */
3327     smpp_handle = create_dissector_handle(dissect_smpp, proto_smpp);
3328     dissector_add_handle("tcp.port", smpp_handle);
3329     heur_dissector_add("tcp", dissect_smpp_heur, proto_smpp);
3330     heur_dissector_add("x.25", dissect_smpp_heur, proto_smpp);
3331
3332         /* Required for call_dissector() */
3333         wsp_handle = find_dissector ("wsp-cl");
3334         g_assert (wsp_handle);
3335         DebugLog(("Finding smpp-gsm-sms subdissector\n"));
3336         gsm_sms_handle = find_dissector("smpp-gsm-sms");
3337         g_assert (gsm_sms_handle);
3338 }