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