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