update to netlogon to show DsrGetDcNameEx2() Client account name, domain name and...
[obnox/wireshark/wip.git] / packet-smpp.c
1 /* packet-smpp.c
2  * Routines for Short Message Peer to Peer dissection
3  * Copyright 2001, Tom Uijldert.
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: packet-smpp.c,v 1.29 2004/03/08 22:03:59 obiot Exp $
12  *
13  * Refer to the AUTHORS file or the AUTHORS section in the man page
14  * for contacting the author(s) of this file.
15  *
16  * Ethereal - Network traffic analyzer
17  * By Gerald Combs <gerald@ethereal.com>
18  * Copyright 1998 Gerald Combs
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
33  * ----------
34  *
35  * Dissector of an SMPP (Short Message Peer to Peer) PDU, as defined by the
36  * SMS forum (www.smsforum.net) in "SMPP protocol specification v3.4"
37  * (document version: 12-Oct-1999 Issue 1.2)
38  */
39
40 #ifdef HAVE_CONFIG_H
41 # include "config.h"
42 #endif
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <time.h>
48
49 #include <glib.h>
50
51 #include <epan/packet.h>
52
53 #include "prefs.h"
54 #include "packet-tcp.h"
55
56 /* General-purpose debug logger.
57  * Requires double parentheses because of variable arguments of printf().
58  *
59  * Enable debug logging for SMPP by defining AM_CFLAGS
60  * so that it contains "-DDEBUG_smpp"
61  */
62 #ifdef DEBUG_smpp
63 #define DebugLog(x) \
64         printf("%s:%u: ", __FILE__, __LINE__); \
65         printf x; \
66         fflush(stdout)
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(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 = FALSE;
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 preceeded by language indication" },
696         { 0x11, "UCS-2 (16-bit) - message preceeded 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_stringz(tvb, *offset, &len);
807         proto_tree_add_string(tree, field, tvb, *offset, len, str);
808     } else {
809         str = g_malloc(1 * sizeof(char));
810         str[0] = '\0';
811     }
812     (*offset) += len;
813     return str;
814 }
815
816 static void
817 smpp_handle_string_z(proto_tree *tree, tvbuff_t *tvb, int field, int *offset,
818                 const char *null_string)
819 {
820     gint         len;
821
822     len = tvb_strsize(tvb, *offset);
823     if (len > 1) {
824         proto_tree_add_string(tree, field, tvb, *offset, len,
825                 (const char *)tvb_get_ptr(tvb, *offset, len));
826     } else {
827         proto_tree_add_string(tree, field, tvb, *offset, len, null_string);
828     }
829     (*offset) += len;
830 }
831
832 static void
833 smpp_handle_int1(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
834 {
835     guint8       val;
836
837     val = tvb_get_guint8(tvb, *offset);
838     proto_tree_add_uint(tree, field, tvb, *offset, 1, val);
839     (*offset)++;
840 }
841
842 static void
843 smpp_handle_int2(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
844 {
845     guint        val;
846
847     val = tvb_get_ntohs(tvb, *offset);
848     proto_tree_add_uint(tree, field, tvb, *offset, 2, val);
849     (*offset) += 2;
850 }
851
852 static void
853 smpp_handle_int4(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
854 {
855     guint        val;
856
857     val = tvb_get_ntohl(tvb, *offset);
858     proto_tree_add_uint(tree, field, tvb, *offset, 4, val);
859     (*offset) += 4;
860 }
861
862 static void
863 smpp_handle_time(proto_tree *tree, tvbuff_t *tvb,
864                  int field, int field_R, int *offset)
865 {
866     char         *strval;
867     gint         len;
868     nstime_t     tmptime;
869
870     strval = (char *) tvb_get_stringz(tvb, *offset, &len);
871     if (*strval)
872     {
873         if (smpp_mktime(strval, &tmptime.secs, &tmptime.nsecs))
874             proto_tree_add_time(tree, field_R, tvb, *offset, len, &tmptime);
875         else
876             proto_tree_add_time(tree, field, tvb, *offset, len, &tmptime);
877     }
878     g_free(strval);
879     *offset += len;
880 }
881
882 /*!
883  * Scanning routine to handle the destination-list of 'submit_multi'
884  *
885  * \param       tree    The protocol tree to add to
886  * \param       tvb     Buffer containing the data
887  * \param       offset  Location of field in buffer, returns location of
888  *                      next field
889  */
890 static void
891 smpp_handle_dlist(proto_tree *tree, tvbuff_t *tvb, int *offset)
892 {
893     guint8       entries;
894     int          tmpoff = *offset;
895     proto_item  *sub_tree = NULL;
896     guint8       dest_flag;
897
898     if ((entries = tvb_get_guint8(tvb, tmpoff++)))
899     {
900         sub_tree = proto_tree_add_item(tree, hf_smpp_dlist,
901                                         tvb, *offset, 1, FALSE);
902         proto_item_add_subtree(sub_tree, ett_dlist);
903     }
904     while (entries--)
905     {
906         dest_flag = tvb_get_guint8(tvb, tmpoff++);
907         if (dest_flag == 1)                     /* SME address  */
908         {
909             smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff);
910             smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff);
911             smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff);
912         }
913         else                                    /* Distribution list    */
914         {
915             smpp_handle_string(sub_tree, tvb, hf_smpp_dl_name, &tmpoff);
916         }
917     }
918     *offset = tmpoff;
919 }
920
921 /*!
922  * Scanning routine to handle the destination result list
923  * of 'submit_multi_resp'
924  *
925  * \param       tree    The protocol tree to add to
926  * \param       tvb     Buffer containing the data
927  * \param       offset  Location of field in buffer, returns location of
928  *                      next field
929  */
930 static void
931 smpp_handle_dlist_resp(proto_tree *tree, tvbuff_t *tvb, int *offset)
932 {
933     guint8       entries;
934     int          tmpoff = *offset;
935     proto_item  *sub_tree = NULL;
936
937     if ((entries = tvb_get_guint8(tvb, tmpoff++)))
938     {
939         sub_tree = proto_tree_add_item(tree, hf_smpp_dlist_resp,
940                                        tvb, *offset, 1, FALSE);
941         proto_item_add_subtree(sub_tree, ett_dlist_resp);
942     }
943     while (entries--)
944     {
945         smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff);
946         smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff);
947         smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff);
948         smpp_handle_int4(sub_tree, tvb, hf_smpp_error_status_code, &tmpoff);
949     }
950     *offset = tmpoff;
951 }
952
953 /*!
954  * Scanning routine to handle all optional parameters of SMPP-operations.
955  * The parameters have the format Tag Length Value (TLV), with a 2-byte tag
956  * and 2-byte length.
957  *
958  * \param       tree    The protocol tree to add to
959  * \param       tvb     Buffer containing the data
960  * \param       offset  Location of field in buffer, returns location of
961  *                      next field
962  */
963 static void
964 smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset)
965 {
966     proto_item  *sub_tree = NULL;
967     guint        tag;
968     guint        length;
969     guint8       field;
970     guint8       major, minor;
971     char         strval[BUFSIZ];
972
973     if (tvb_reported_length_remaining(tvb, *offset) >= 4)
974     {
975         sub_tree = proto_tree_add_item(tree, hf_smpp_opt_param,
976                                        tvb, *offset, 0, FALSE);
977         proto_item_add_subtree(sub_tree, ett_opt_param);
978     }
979
980     while (tvb_reported_length_remaining(tvb, *offset) >= 4)
981     {
982         tag = tvb_get_ntohs(tvb, *offset);
983         *offset += 2;
984         length = tvb_get_ntohs(tvb, *offset);
985         *offset += 2;
986         switch (tag) {
987             case  0x0005:       /* dest_addr_subunit    */
988                 smpp_handle_int1(sub_tree, tvb,
989                                  hf_smpp_dest_addr_subunit, offset);
990                 break;
991             case  0x0006:       /* dest_network_type    */
992                 smpp_handle_int1(sub_tree, tvb,
993                                  hf_smpp_dest_network_type, offset);
994                 break;
995             case  0x0007:       /* dest_bearer_type     */
996                 smpp_handle_int1(sub_tree, tvb,
997                                  hf_smpp_dest_bearer_type, offset);
998                 break;
999             case  0x0008:       /* dest_telematics_id   */
1000                 smpp_handle_int2(sub_tree, tvb,
1001                                  hf_smpp_dest_telematics_id, offset);
1002                 break;
1003             case  0x000D:       /* source_addr_subunit  */
1004                 smpp_handle_int1(sub_tree, tvb,
1005                                  hf_smpp_source_addr_subunit, offset);
1006                 break;
1007             case  0x000E:       /* source_network_type  */
1008                 smpp_handle_int1(sub_tree, tvb,
1009                                  hf_smpp_source_network_type, offset);
1010                 break;
1011             case  0x000F:       /* source_bearer_type   */
1012                 smpp_handle_int1(sub_tree, tvb,
1013                                  hf_smpp_source_bearer_type, offset);
1014                 break;
1015             case  0x0010:       /* source_telematics_id */
1016                 smpp_handle_int2(sub_tree, tvb,
1017                                  hf_smpp_source_telematics_id, offset);
1018                 break;
1019             case  0x0017:       /* qos_time_to_live     */
1020                 smpp_handle_int4(sub_tree, tvb,
1021                                  hf_smpp_qos_time_to_live, offset);
1022                 break;
1023             case  0x0019:       /* payload_type */
1024                 smpp_handle_int1(sub_tree, tvb,
1025                                  hf_smpp_payload_type, offset);
1026                 break;
1027             case  0x001D:       /* additional_status_info_text  */
1028                 smpp_handle_string(sub_tree, tvb,
1029                                    hf_smpp_additional_status_info_text, offset);
1030                 break;
1031             case  0x001E:       /* receipted_message_id */
1032                 smpp_handle_string(sub_tree, tvb,
1033                                    hf_smpp_receipted_message_id, offset);
1034                 break;
1035             case  0x0030:       /* ms_msg_wait_facilities       */
1036                 field = tvb_get_guint8(tvb, *offset);
1037                 proto_tree_add_item(sub_tree, hf_smpp_msg_wait_ind,
1038                                     tvb, *offset, 1, field);
1039                 proto_tree_add_item(sub_tree, hf_smpp_msg_wait_type,
1040                                     tvb, *offset, 1, field);
1041                 (*offset)++;
1042                 break;
1043             case  0x0201:       /* privacy_indicator    */
1044                 smpp_handle_int1(sub_tree, tvb,
1045                                  hf_smpp_privacy_indicator, offset);
1046                 break;
1047             case  0x0202:       /* source_subaddress    */
1048                 smpp_handle_string(sub_tree, tvb,
1049                                    hf_smpp_source_subaddress, offset);
1050                 break;
1051             case  0x0203:       /* dest_subaddress      */
1052                 smpp_handle_string(sub_tree, tvb,
1053                                    hf_smpp_dest_subaddress, offset);
1054                 break;
1055             case  0x0204:       /* user_message_reference       */
1056                 smpp_handle_int2(sub_tree, tvb,
1057                                  hf_smpp_user_message_reference, offset);
1058                 break;
1059             case  0x0205:       /* user_response_code   */
1060                 smpp_handle_int1(sub_tree, tvb,
1061                                  hf_smpp_user_response_code, offset);
1062                 break;
1063             case  0x020A:       /* source_port  */
1064                 smpp_handle_int2(sub_tree, tvb,
1065                                  hf_smpp_source_port, offset);
1066                 break;
1067             case  0x020B:       /* destination_port     */
1068                 smpp_handle_int2(sub_tree, tvb,
1069                                  hf_smpp_destination_port, offset);
1070                 break;
1071             case  0x020C:       /* sar_msg_ref_num      */
1072                 smpp_handle_int2(sub_tree, tvb,
1073                                  hf_smpp_sar_msg_ref_num, offset);
1074                 break;
1075             case  0x020D:       /* language_indicator   */
1076                 smpp_handle_int1(sub_tree, tvb,
1077                                  hf_smpp_language_indicator, offset);
1078                 break;
1079             case  0x020E:       /* sar_total_segments   */
1080                 smpp_handle_int1(sub_tree, tvb,
1081                                  hf_smpp_sar_total_segments, offset);
1082                 break;
1083             case  0x020F:       /* sar_segment_seqnum   */
1084                 smpp_handle_int1(sub_tree, tvb,
1085                                  hf_smpp_sar_segment_seqnum, offset);
1086                 break;
1087             case  0x0210:       /* SC_interface_version */
1088                 field = tvb_get_guint8(tvb, *offset);
1089                 minor = field & 0x0F;
1090                 major = (field & 0xF0) >> 4;
1091                 sprintf(strval, "%u.%u", major, minor);
1092                 proto_tree_add_string(sub_tree, hf_smpp_SC_interface_version,
1093                                       tvb, *offset, 1, strval);
1094                 (*offset)++;
1095                 break;
1096             case  0x0302:       /* callback_num_pres_ind        */
1097                 field = tvb_get_guint8(tvb, *offset);
1098                 proto_tree_add_item(sub_tree, hf_smpp_callback_num_pres,
1099                                     tvb, *offset, 1, field);
1100                 proto_tree_add_item(sub_tree, hf_smpp_callback_num_scrn,
1101                                     tvb, *offset, 1, field);
1102                 (*offset)++;
1103                 break;
1104             case  0x0303:       /* callback_num_atag    */
1105                 if (length)
1106                     proto_tree_add_item(sub_tree, hf_smpp_callback_num_atag,
1107                                         tvb, *offset, length, FALSE);
1108                 (*offset) += length;
1109                 break;
1110             case  0x0304:       /* number_of_messages   */
1111                 smpp_handle_int1(sub_tree, tvb,
1112                                  hf_smpp_number_of_messages, offset);
1113                 break;
1114             case  0x0381:       /* callback_num */
1115                 if (length)
1116                     proto_tree_add_item(sub_tree, hf_smpp_callback_num,
1117                                         tvb, *offset, length, FALSE);
1118                 (*offset) += length;
1119                 break;
1120             case  0x0420:       /* dpf_result   */
1121                 smpp_handle_int1(sub_tree, tvb,
1122                                  hf_smpp_dpf_result, offset);
1123                 break;
1124             case  0x0421:       /* set_dpf      */
1125                 smpp_handle_int1(sub_tree, tvb,
1126                                  hf_smpp_set_dpf, offset);
1127                 break;
1128             case  0x0422:       /* ms_availability_status       */
1129                 smpp_handle_int1(sub_tree, tvb,
1130                                  hf_smpp_ms_availability_status, offset);
1131                 break;
1132             case  0x0423:       /* network_error_code   */
1133                 smpp_handle_int1(sub_tree, tvb,
1134                                  hf_smpp_network_error_type, offset);
1135                 smpp_handle_int2(sub_tree, tvb,
1136                                  hf_smpp_network_error_code, offset);
1137                 (*offset) += length;
1138                 break;
1139             case  0x0424:       /* message_payload      */
1140                 if (length)
1141                     proto_tree_add_item(sub_tree, hf_smpp_message_payload,
1142                                         tvb, *offset, length, FALSE);
1143                 (*offset) += length;
1144                 break;
1145             case  0x0425:       /* delivery_failure_reason      */
1146                 smpp_handle_int1(sub_tree, tvb,
1147                                  hf_smpp_delivery_failure_reason, offset);
1148                 break;
1149             case  0x0426:       /* more_messages_to_send        */
1150                 smpp_handle_int1(sub_tree, tvb,
1151                                  hf_smpp_more_messages_to_send, offset);
1152                 break;
1153             case  0x0427:       /* message_state        */
1154                 smpp_handle_int1(sub_tree, tvb,
1155                                  hf_smpp_message_state, offset);
1156                 break;
1157             case  0x0501:       /* ussd_service_op      */
1158                 smpp_handle_int1(sub_tree, tvb,
1159                                  hf_smpp_ussd_service_op, offset);
1160                 break;
1161             case  0x1201:       /* display_time */
1162                 smpp_handle_int1(sub_tree, tvb,
1163                                  hf_smpp_display_time, offset);
1164                 break;
1165             case  0x1203:       /* sms_signal   */
1166                 smpp_handle_int2(sub_tree, tvb,
1167                                  hf_smpp_sms_signal, offset);
1168                 /*! \todo Fill as per TIA/EIA-136-710-A         */
1169                 break;
1170             case  0x1204:       /* ms_validity  */
1171                 smpp_handle_int1(sub_tree, tvb,
1172                                  hf_smpp_ms_validity, offset);
1173                 break;
1174             case  0x130C:       /* alert_on_message_delivery    */
1175                 proto_tree_add_item(sub_tree,
1176                                     hf_smpp_alert_on_message_delivery,
1177                                     tvb, *offset, length, FALSE);
1178                 (*offset) += length;
1179                 break;
1180             case  0x1380:       /* its_reply_type       */
1181                 smpp_handle_int1(sub_tree, tvb,
1182                                  hf_smpp_its_reply_type, offset);
1183                 break;
1184             case  0x1383:       /* its_session_info     */
1185                 smpp_handle_int1(sub_tree, tvb,
1186                                  hf_smpp_its_session_number, offset);
1187                 field = tvb_get_guint8(tvb, *offset);
1188                 proto_tree_add_item(sub_tree, hf_smpp_its_session_sequence,
1189                                     tvb, *offset, 1, field);
1190                 proto_tree_add_item(sub_tree, hf_smpp_its_session_ind,
1191                                     tvb, *offset, 1, field);
1192                 (*offset)++;
1193                 break;
1194             default:
1195                 if ((tag >= 0x1400) && (tag <= 0x3FFF))
1196                     proto_tree_add_item(sub_tree, hf_smpp_vendor_op, tvb,
1197                                         *offset, length, FALSE);
1198                 else
1199                     proto_tree_add_item(sub_tree, hf_smpp_reserved_op, tvb,
1200                                         *offset, length, FALSE);
1201                 (*offset) += length;
1202                 break;
1203         }
1204     }
1205 }
1206
1207 static void
1208 smpp_handle_dcs(proto_tree *tree, tvbuff_t *tvb, int *offset)
1209 {
1210     guint8       val;
1211         int off = *offset;
1212         proto_item *subtree = NULL;
1213
1214     val = tvb_get_guint8(tvb, off);
1215         subtree = proto_tree_add_uint(tree,
1216                         hf_smpp_data_coding, tvb, off, 1, val);
1217         proto_item_add_subtree(subtree, ett_dcs);
1218         /* SMPP Data Coding Scheme */
1219         proto_tree_add_uint(subtree, hf_smpp_dcs, tvb, off, 1, val);
1220         /* GSM SMS Data Coding Scheme */
1221         proto_tree_add_text(subtree, tvb, off, 1,
1222                                         "GSM SMS Data Coding");
1223         proto_tree_add_uint(subtree,
1224                         hf_smpp_dcs_sms_coding_group, tvb, off, 1, val);
1225         if (val>>6 == 2) { /* Reserved */
1226                         ;
1227         } else if (val < 0xF0) {
1228                 proto_tree_add_boolean(subtree,
1229                                 hf_smpp_dcs_text_compression, tvb, off, 1, val);
1230                 proto_tree_add_boolean(subtree,
1231                                 hf_smpp_dcs_class_present, tvb, off, 1, val);
1232                 proto_tree_add_uint(subtree,
1233                                 hf_smpp_dcs_charset, tvb, off, 1, val);
1234                 if (val & 0x10)
1235                         proto_tree_add_uint(subtree,
1236                                         hf_smpp_dcs_class, tvb, off, 1, val);
1237         } else {
1238                 if (val & 0x08)
1239                         proto_tree_add_text(subtree, tvb, off, 1,
1240                                         "SMPP: Bit .... 1... should be 0 (reserved)");
1241                 proto_tree_add_uint(subtree,
1242                                 hf_smpp_dcs_charset, tvb, off, 1, val);
1243                 proto_tree_add_uint(subtree,
1244                                 hf_smpp_dcs_class, tvb, off, 1, val);
1245         }
1246         /* Cell Broadcast Service (CBS) Data Coding Scheme */
1247         proto_tree_add_text(subtree, tvb, off, 1,
1248                                         "GSM CBS Data Coding");
1249         proto_tree_add_uint(subtree,
1250                         hf_smpp_dcs_cbs_coding_group, tvb, off, 1, val);
1251         if (val < 0x40) { /* Language specified */
1252                 proto_tree_add_uint(subtree,
1253                                 hf_smpp_dcs_cbs_language, tvb, off, 1, val);
1254         } else if (val>>6 == 1) { /* General Data Coding indication */
1255                 proto_tree_add_boolean(subtree,
1256                                 hf_smpp_dcs_text_compression, tvb, off, 1, val);
1257                 proto_tree_add_boolean(subtree,
1258                                 hf_smpp_dcs_class_present, tvb, off, 1, val);
1259                 proto_tree_add_uint(subtree,
1260                                 hf_smpp_dcs_charset, tvb, off, 1, val);
1261                 if (val & 0x10)
1262                         proto_tree_add_uint(subtree,
1263                                         hf_smpp_dcs_class, tvb, off, 1, val);
1264         } else if (val>>6 == 2) { /* Message with UDH structure */
1265                 proto_tree_add_uint(subtree,
1266                                 hf_smpp_dcs_charset, tvb, off, 1, val);
1267                 proto_tree_add_uint(subtree,
1268                                 hf_smpp_dcs_class, tvb, off, 1, val);
1269         } else if (val>>4 == 14) { /* WAP Forum */
1270                 proto_tree_add_uint(subtree,
1271                                 hf_smpp_dcs_wap_charset, tvb, off, 1, val);
1272                 proto_tree_add_uint(subtree,
1273                                 hf_smpp_dcs_wap_class, tvb, off, 1, val);
1274         } else if (val>>4 == 15) { /* Data coding / message handling */
1275                 if (val & 0x08)
1276                         proto_tree_add_text(subtree, tvb, off, 1,
1277                                         "SMPP: Bit .... 1... should be 0 (reserved)");
1278                 proto_tree_add_uint(subtree,
1279                                 hf_smpp_dcs_charset, tvb, off, 1, val);
1280                 proto_tree_add_uint(subtree,
1281                                 hf_smpp_dcs_cbs_class, tvb, off, 1, val);
1282         }
1283
1284     (*offset)++;
1285 }
1286
1287 /*!
1288  * The next set of routines handle the different operations, associated
1289  * with SMPP.
1290  */
1291 static void
1292 bind_receiver(proto_tree *tree, tvbuff_t *tvb)
1293 {
1294     int          offset = 0;
1295     guint8       field;
1296     guint8       major, minor;
1297     char         strval[BUFSIZ];
1298
1299     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1300     smpp_handle_string(tree, tvb, hf_smpp_password, &offset);
1301     smpp_handle_string(tree, tvb, hf_smpp_system_type, &offset);
1302     field = tvb_get_guint8(tvb, offset++);
1303     minor = field & 0x0F;
1304     major = (field & 0xF0) >> 4;
1305     sprintf(strval, "%u.%u", major, minor);
1306     proto_tree_add_string(tree, hf_smpp_interface_version, tvb,
1307                           offset - 1, 1, strval);
1308     smpp_handle_int1(tree, tvb, hf_smpp_addr_ton, &offset);
1309     smpp_handle_int1(tree, tvb, hf_smpp_addr_npi, &offset);
1310     smpp_handle_string(tree, tvb, hf_smpp_address_range, &offset);
1311 }
1312
1313 #define bind_transmitter(a, b) bind_receiver(a, b)
1314
1315 static void
1316 query_sm(proto_tree *tree, tvbuff_t *tvb)
1317 {
1318     int          offset = 0;
1319
1320     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1321     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1322     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1323     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1324 }
1325
1326 #define bind_transceiver(a, b) bind_receiver(a, b)
1327
1328 static void
1329 outbind(proto_tree *tree, tvbuff_t *tvb)
1330 {
1331     int          offset = 0;
1332
1333     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1334     smpp_handle_string(tree, tvb, hf_smpp_password, &offset);
1335 }
1336
1337 static void
1338 submit_sm(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
1339                 proto_tree *top_tree)
1340 {
1341     tvbuff_t    *tvb_msg;
1342     int          offset = 0;
1343     guint8       flag, udhi;
1344     guint8       length;
1345         char *src_str = NULL;
1346         char *dst_str = NULL;
1347         address save_src, save_dst;
1348
1349     smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
1350     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1351     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1352     src_str = smpp_handle_string_return(tree, tvb, hf_smpp_source_addr, &offset);
1353     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1354     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1355     dst_str = smpp_handle_string_return(tree, tvb, hf_smpp_destination_addr, &offset);
1356     flag = tvb_get_guint8(tvb, offset);
1357     udhi = flag & 0x40;
1358     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1359                         tvb, offset, 1, flag);
1360     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1361                         tvb, offset, 1, flag);
1362     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1363                         tvb, offset, 1, flag);
1364     offset++;
1365     smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset);
1366     smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset);
1367         if (tvb_get_guint8(tvb,offset)) {
1368     smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1369                                 hf_smpp_schedule_delivery_time_r, &offset);
1370         } else { /* Time = NULL means Immediate delivery */
1371                 proto_tree_add_text(tree, tvb, offset++, 1,
1372                                 "Scheduled delivery time: Immediate delivery");
1373         }
1374         if (tvb_get_guint8(tvb,offset)) {
1375     smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1376                                 hf_smpp_validity_period_r, &offset);
1377         } else { /* Time = NULL means SMSC default validity */
1378                 proto_tree_add_text(tree, tvb, offset++, 1,
1379                                 "Validity period: SMSC default validity period");
1380         }
1381     flag = tvb_get_guint8(tvb, offset);
1382     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1383     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1384     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1385     offset++;
1386     smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset);
1387         smpp_handle_dcs(tree, tvb, &offset);
1388     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1389     length = tvb_get_guint8(tvb, offset);
1390     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1391     if (length)
1392     {
1393         proto_tree_add_item(tree, hf_smpp_short_message,
1394                             tvb, offset, length, FALSE);
1395         if (udhi) /* UDHI indicator present */
1396         {
1397             DebugLog(("UDHI present - set addresses\n"));
1398             /* Save original addresses */
1399             COPY_ADDRESS(&save_src, &(pinfo->src));
1400             COPY_ADDRESS(&save_dst, &(pinfo->dst));
1401             /* Set SMPP source and destination address */
1402             SET_ADDRESS(&(pinfo->src), AT_STRINGZ, 1+strlen(src_str), src_str);
1403             SET_ADDRESS(&(pinfo->dst), AT_STRINGZ, 1+strlen(dst_str), dst_str);
1404             tvb_msg = tvb_new_subset (tvb, offset,
1405                     MIN(length, tvb_reported_length(tvb) - offset), length);
1406             call_dissector (gsm_sms_handle, tvb_msg, pinfo, top_tree);
1407             /* Restore original addresses */
1408             COPY_ADDRESS(&(pinfo->src), &save_src);
1409             COPY_ADDRESS(&(pinfo->dst), &save_dst);
1410             /* Get rid of SMPP text string addresses */
1411             g_free(src_str);
1412             g_free(dst_str);
1413         }
1414         offset += length;
1415     }
1416     smpp_handle_tlv(tree, tvb, &offset);
1417 }
1418
1419 #define deliver_sm(a, b, c, d) submit_sm(a, b, c, d)
1420
1421 static void
1422 replace_sm(proto_tree *tree, tvbuff_t *tvb)
1423 {
1424     int          offset = 0;
1425     guint8       flag;
1426     guint8       length;
1427
1428     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1429     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1430     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1431     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1432         if (tvb_get_guint8(tvb,offset)) {
1433     smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1434                                 hf_smpp_schedule_delivery_time_r, &offset);
1435         } else { /* Time = NULL */
1436                 proto_tree_add_text(tree, tvb, offset++, 1,
1437                                 "Scheduled delivery time: Keep initial delivery time setting");
1438         }
1439         if (tvb_get_guint8(tvb,offset)) {
1440     smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1441                                 hf_smpp_validity_period_r, &offset);
1442         } else { /* Time = NULL */
1443                 proto_tree_add_text(tree, tvb, offset++, 1,
1444                                 "Validity period: Keep initial validity period setting");
1445         }
1446     flag = tvb_get_guint8(tvb, offset);
1447     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1448     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1449     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1450     offset++;
1451     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1452     length = tvb_get_guint8(tvb, offset);
1453     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1454     if (length)
1455         proto_tree_add_item(tree, hf_smpp_short_message,
1456                             tvb, offset, length, FALSE);
1457     offset += length;
1458 }
1459
1460 static void
1461 cancel_sm(proto_tree *tree, tvbuff_t *tvb)
1462 {
1463     int          offset = 0;
1464
1465     smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
1466     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1467     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1468     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1469     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1470     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1471     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1472     smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
1473 }
1474
1475 static void
1476 submit_multi(proto_tree *tree, tvbuff_t *tvb)
1477 {
1478     int          offset = 0;
1479     guint8       flag;
1480     guint8       length;
1481
1482     smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
1483     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1484     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1485     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1486
1487     smpp_handle_dlist(tree, tvb, &offset);
1488
1489     flag = tvb_get_guint8(tvb, offset);
1490     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1491             tvb, offset, 1, flag);
1492     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1493             tvb, offset, 1, flag);
1494     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1495             tvb, offset, 1, flag);
1496     offset++;
1497     smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset);
1498     smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset);
1499     if (tvb_get_guint8(tvb,offset)) {
1500         smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1501                 hf_smpp_schedule_delivery_time_r, &offset);
1502     } else { /* Time = NULL means Immediate delivery */
1503         proto_tree_add_text(tree, tvb, offset++, 1,
1504                 "Scheduled delivery time: Immediate delivery");
1505     }
1506     if (tvb_get_guint8(tvb,offset)) {
1507         smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1508                 hf_smpp_validity_period_r, &offset);
1509     } else { /* Time = NULL means SMSC default validity */
1510         proto_tree_add_text(tree, tvb, offset++, 1,
1511                 "Validity period: SMSC default validity period");
1512     }
1513     flag = tvb_get_guint8(tvb, offset);
1514     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1515     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1516     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1517     offset++;
1518     smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset);
1519     smpp_handle_dcs(tree, tvb, &offset);
1520     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1521     length = tvb_get_guint8(tvb, offset);
1522     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1523     if (length)
1524         proto_tree_add_item(tree, hf_smpp_short_message,
1525                 tvb, offset, length, FALSE);
1526     offset += length;
1527     smpp_handle_tlv(tree, tvb, &offset);
1528 }
1529
1530 static void
1531 alert_notification(proto_tree *tree, tvbuff_t *tvb)
1532 {
1533     int          offset = 0;
1534
1535     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1536     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1537     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1538     smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_ton, &offset);
1539     smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_npi, &offset);
1540     smpp_handle_string(tree, tvb, hf_smpp_esme_addr, &offset);
1541     smpp_handle_tlv(tree, tvb, &offset);
1542 }
1543
1544 static void
1545 data_sm(proto_tree *tree, tvbuff_t *tvb)
1546 {
1547     int          offset = 0;
1548     guint8       flag;
1549
1550     smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)");
1551     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1552     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1553     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1554     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1555     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1556     smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
1557     flag = tvb_get_guint8(tvb, offset);
1558     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1559                         tvb, offset, 1, flag);
1560     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1561                         tvb, offset, 1, flag);
1562     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1563                         tvb, offset, 1, flag);
1564     offset++;
1565     flag = tvb_get_guint8(tvb, offset);
1566     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1567     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1568     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1569     offset++;
1570         smpp_handle_dcs(tree, tvb, &offset);
1571     smpp_handle_tlv(tree, tvb, &offset);
1572 }
1573
1574 /*!
1575  * The next set of routines handle the different operation-responses,
1576  * associated with SMPP.
1577  */
1578 static void
1579 bind_receiver_resp(proto_tree *tree, tvbuff_t *tvb)
1580 {
1581     int          offset = 0;
1582
1583     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1584     smpp_handle_tlv(tree, tvb, &offset);
1585 }
1586
1587 #define bind_transmitter_resp(a, b) bind_receiver_resp(a, b)
1588
1589 static void
1590 query_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1591 {
1592     int          offset = 0;
1593
1594     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1595     smpp_handle_time(tree, tvb, hf_smpp_final_date,
1596                                 hf_smpp_final_date_r, &offset);
1597     smpp_handle_int1(tree, tvb, hf_smpp_message_state, &offset);
1598     smpp_handle_int1(tree, tvb, hf_smpp_error_code, &offset);
1599 }
1600
1601 #define bind_transceiver_resp(a, b) bind_receiver_resp(a, b)
1602
1603 static void
1604 submit_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1605 {
1606     int          offset = 0;
1607
1608     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1609 }
1610
1611 #define deliver_sm_resp(a, b) submit_sm_resp(a, b)
1612
1613 static void
1614 submit_multi_resp(proto_tree *tree, tvbuff_t *tvb)
1615 {
1616     int          offset = 0;
1617
1618     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1619     smpp_handle_dlist_resp(tree, tvb, &offset);
1620 }
1621
1622 static void
1623 data_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1624 {
1625     int          offset = 0;
1626
1627     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1628     smpp_handle_tlv(tree, tvb, &offset);
1629 }
1630
1631 /*
1632  * A 'heuristic dissector' that attemtps to establish whether we have
1633  * a genuine SMPP PDU here.
1634  * Only works when:
1635  *      at least the fixed header is there
1636  *      it has a correct overall PDU length
1637  *      it is a 'well-known' operation
1638  *      has a 'well-known' status
1639  */
1640 static gboolean
1641 dissect_smpp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1642 {
1643     guint        command_id;            /* SMPP command         */
1644     guint        command_status;        /* Status code          */
1645     guint        command_length;        /* length of PDU        */
1646
1647     if (tvb_reported_length(tvb) < 4 * 4)       /* Mandatory header     */
1648         return FALSE;
1649     command_length = tvb_get_ntohl(tvb, 0);
1650     if (command_length > 64 * 1024)
1651         return FALSE;
1652     command_id = tvb_get_ntohl(tvb, 4);         /* Only known commands  */
1653     if (match_strval(command_id, vals_command_id) == NULL)
1654         return FALSE;
1655     command_status = tvb_get_ntohl(tvb, 8);     /* ..with known status  */
1656     if (match_strval(command_status, vals_command_status) == NULL)
1657         return FALSE;
1658     dissect_smpp(tvb, pinfo, tree);
1659     return TRUE;
1660 }
1661
1662 static guint
1663 get_smpp_pdu_len(tvbuff_t *tvb, int offset)
1664 {
1665     return tvb_get_ntohl(tvb, offset);
1666 }
1667
1668 /*
1669  * This global SMPP variable is used to determine whether the PDU to dissect
1670  * is the first SMPP PDU in the packet (or reassembled buffer), requiring
1671  * different column update code than subsequent SMPP PDUs within this packet
1672  * (or reassembled buffer).
1673  *
1674  * FIXME - This approach is NOT dissection multi-thread safe!
1675  */
1676 static gboolean first = TRUE;
1677
1678 static void
1679 dissect_smpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1680 {
1681     first = TRUE;
1682     if (pinfo->ptype == PT_TCP) {       /* are we running on top of TCP */
1683         tcp_dissect_pdus(tvb, pinfo, tree,
1684                 reassemble_over_tcp,    /* Do we try to reassemble      */
1685                 16,                     /* Length of fixed header       */
1686                 get_smpp_pdu_len,       /* Function returning PDU len   */
1687                 dissect_smpp_pdu);      /* PDU dissector                */
1688     } else {                            /* no? probably X.25            */
1689         guint32 offset = 0;
1690         while (tvb_reported_length_remaining(tvb, offset) > 0) {
1691             guint16 pdu_len = tvb_get_ntohl(tvb, offset);
1692             gint pdu_real_len = tvb_length_remaining(tvb, offset);
1693             tvbuff_t *pdu_tvb;
1694
1695             if (pdu_real_len <= 0)
1696                 return;
1697             if (pdu_real_len > pdu_len)
1698                 pdu_real_len = pdu_len;
1699             pdu_tvb = tvb_new_subset(tvb, offset, pdu_real_len, pdu_len);
1700             dissect_smpp_pdu(pdu_tvb, pinfo, tree);
1701             offset += pdu_len;
1702             first = FALSE;
1703         }
1704     }
1705 }
1706
1707
1708 /* Dissect a single SMPP PDU contained within "tvb". */
1709 static void
1710 dissect_smpp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1711 {
1712     int          offset = 0;            /* Offset within tvbuff */
1713     guint        command_length;        /* length of PDU        */
1714     guint        command_id;            /* SMPP command         */
1715     guint        command_status;        /* Status code          */
1716     guint        sequence_number;       /* ...of command        */
1717     gchar       *command_str;
1718     gchar       *command_status_str = NULL;
1719     /* Set up structures needed to add the protocol subtree and manage it */
1720     proto_item  *ti = NULL;
1721     proto_tree  *smpp_tree = NULL;
1722
1723     /*
1724      * Safety: don't even try to dissect the PDU
1725      * when the mandatory header isn't present.
1726      */
1727     if (tvb_reported_length(tvb) < 4 * 4)
1728         return;
1729     command_length = tvb_get_ntohl(tvb, offset);
1730     offset += 4;
1731     command_id = tvb_get_ntohl(tvb, offset);
1732     command_str = val_to_str(command_id, vals_command_id,
1733             "(Unknown SMPP Operation 0x%08X)");
1734     offset += 4;
1735     command_status = tvb_get_ntohl(tvb, offset);
1736     if (command_id & 0x80000000) {
1737         command_status_str = val_to_str(command_status, vals_command_status,
1738                 "(Reserved Error 0x%08X)");
1739     }
1740     offset += 4;
1741     sequence_number = tvb_get_ntohl(tvb, offset);
1742     offset += 4;
1743
1744     /*
1745      * Update the protocol column.
1746      */
1747     if (first == TRUE) {
1748         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1749             col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMPP");
1750     }
1751
1752     /*
1753      * Create display subtree for the protocol
1754      */
1755     if (tree) {
1756         ti = proto_tree_add_item (tree, proto_smpp, tvb, 0, tvb->length, FALSE);
1757         smpp_tree = proto_item_add_subtree (ti, ett_smpp);
1758     }
1759
1760     /*
1761      * Cycle over the encapsulated PDUs
1762      */
1763     {
1764         tvbuff_t *pdu_tvb;
1765
1766         /*
1767          * Make entries in the Info column on the summary display
1768          */
1769         if (check_col(pinfo->cinfo, COL_INFO)) {
1770             if (first == TRUE) {
1771                 /*
1772                  * First PDU - We already computed the fixed header
1773                  */
1774                 col_clear(pinfo->cinfo, COL_INFO);
1775                 col_add_fstr(pinfo->cinfo, COL_INFO, "SMPP %s", command_str);
1776                 first = FALSE;
1777             } else {
1778                 /*
1779                  * Subsequent PDUs
1780                  */
1781                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", command_str);
1782             }
1783             /*
1784              * Display command status of responses in Info column
1785              */
1786             if (command_id & 0x80000000) {
1787                 col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"",
1788                         command_status_str);
1789             }
1790         }
1791
1792         /*
1793          * Create a tvb for the current PDU.
1794          * Physical length: at most command_length
1795          * Reported length: command_length
1796          */
1797         if (tvb_length_remaining(tvb, offset - 16 + command_length) > 0) {
1798             pdu_tvb = tvb_new_subset(tvb, offset - 16,
1799                     command_length,     /* Physical length */
1800                     command_length);    /* Length reported by the protocol */
1801         } else {
1802             pdu_tvb = tvb_new_subset(tvb, offset - 16,
1803                     tvb_length_remaining(tvb, offset - 16),/* Physical length */
1804                     command_length);    /* Length reported by the protocol */
1805         }
1806
1807         /*
1808          * Dissect the PDU
1809          *
1810          * If "tree" is NULL, Ethereal is only interested in creation
1811          * of conversations, reassembly and subdissection but not in
1812          * the detailed protocol tree.
1813          * In the interest of speed, skip the generation of protocol tree
1814          * items when "tree" is NULL.
1815          *
1816          * The only PDU which requires subdissection currently is the
1817          * sm_submit PDU (command ID = 0x00000004).
1818          */
1819         if (tree || (command_id == 4))
1820         {
1821             /*
1822              * Create display subtree for the PDU
1823              */
1824             if (tree) {
1825                 proto_tree_add_uint(smpp_tree, hf_smpp_command_length,
1826                         pdu_tvb, 0, 4, command_length);
1827                 proto_tree_add_uint(smpp_tree, hf_smpp_command_id,
1828                         pdu_tvb, 4, 4, command_id);
1829                 proto_item_append_text(ti, ", Command: %s", command_str);
1830
1831                 /*
1832                  * Status is only meaningful with responses
1833                  */
1834                 if (command_id & 0x80000000) {
1835                     proto_tree_add_uint(smpp_tree, hf_smpp_command_status,
1836                             pdu_tvb, 8, 4, command_status);
1837                     proto_item_append_text (ti, ", Status: \"%s\"",
1838                             command_status_str);
1839                 }
1840                 proto_tree_add_uint(smpp_tree, hf_smpp_sequence_number,
1841                         pdu_tvb, 12, 4, sequence_number);
1842                 proto_item_append_text(ti, ", Seq: %u, Len: %u",
1843                         sequence_number, command_length);
1844             }
1845
1846             /*
1847              * End of fixed header.
1848              * Don't dissect variable part if it is shortened.
1849              *
1850              * FIXME - We then do not report a Short Frame or Malformed Packet
1851              */
1852             if (command_length <= tvb_reported_length(pdu_tvb))
1853             {
1854                 tvbuff_t *tmp_tvb = tvb_new_subset(pdu_tvb, 16,
1855                         -1, command_length - 16);
1856                 if (command_id & 0x80000000)
1857                 {
1858                     switch (command_id & 0x7FFFFFFF) {
1859                         /*
1860                          * All of these only have a fixed header
1861                          */
1862                         case   0:       /* Generic nack         */
1863                         case   6:       /* Unbind resp          */
1864                         case   7:       /* Replace SM resp      */
1865                         case   8:       /* Cancel SM resp       */
1866                         case  21:       /* Enquire link resp    */
1867                             break;
1868                         case   1:
1869                             if (!command_status)
1870                                 bind_receiver_resp(smpp_tree, tmp_tvb);
1871                             break;
1872                         case   2:
1873                             if (!command_status)
1874                                 bind_transmitter_resp(smpp_tree, tmp_tvb);
1875                             break;
1876                         case   3:
1877                             if (!command_status)
1878                                 query_sm_resp(smpp_tree, tmp_tvb);
1879                             break;
1880                         case   4:
1881                             if (!command_status)
1882                                 submit_sm_resp(smpp_tree, tmp_tvb);
1883                             break;
1884                         case   5:
1885                             if (!command_status)
1886                                 deliver_sm_resp(smpp_tree, tmp_tvb);
1887                             break;
1888                         case   9:
1889                             if (!command_status)
1890                                 bind_transceiver_resp(smpp_tree, tmp_tvb);
1891                             break;
1892                         case  33:
1893                             if (!command_status)
1894                                 submit_multi_resp(smpp_tree, tmp_tvb);
1895                             break;
1896                         case 259:
1897                             if (!command_status)
1898                                 data_sm_resp(smpp_tree, tmp_tvb);
1899                             break;
1900                         default:
1901                             break;
1902                     } /* switch (command_id & 0x7FFFFFFF) */
1903                 }
1904                 else
1905                 {
1906                     switch (command_id) {
1907                         case   1:
1908                             bind_receiver(smpp_tree, tmp_tvb);
1909                             break;
1910                         case   2:
1911                             bind_transmitter(smpp_tree, tmp_tvb);
1912                             break;
1913                         case   3:
1914                             query_sm(smpp_tree, tmp_tvb);
1915                             break;
1916                         case   4:
1917                             submit_sm(smpp_tree, tmp_tvb, pinfo, tree);
1918                             break;
1919                         case   5:
1920                             deliver_sm(smpp_tree, tmp_tvb, pinfo, tree);
1921                             break;
1922                         case   6:       /* Unbind               */
1923                         case  21:       /* Enquire link         */
1924                             break;
1925                         case   7:
1926                             replace_sm(smpp_tree, tmp_tvb);
1927                             break;
1928                         case   8:
1929                             cancel_sm(smpp_tree, tmp_tvb);
1930                             break;
1931                         case   9:
1932                             bind_transceiver(smpp_tree, tmp_tvb);
1933                             break;
1934                         case  11:
1935                             outbind(smpp_tree, tmp_tvb);
1936                             break;
1937                         case  33:
1938                             submit_multi(smpp_tree, tmp_tvb);
1939                             break;
1940                         case  258:
1941                             alert_notification(smpp_tree, tmp_tvb);
1942                             break;
1943                         case  259:
1944                             data_sm(smpp_tree, tmp_tvb);
1945                             break;
1946                         default:
1947                             break;
1948                     } /* switch (command_id) */
1949                 } /* if (command_id & 0x80000000) */
1950             } /* if (command_length <= tvb_reported_length(pdu_tvb)) */
1951             offset += command_length;
1952         } /* if (tree || (command_id == 4)) */
1953         first = FALSE;
1954     }
1955
1956     return;
1957 }
1958
1959
1960 /* Register the protocol with Ethereal */
1961 void
1962 proto_register_smpp(void)
1963 {
1964     module_t *smpp_module; /* Preferences for SMPP */
1965
1966     /* Setup list of header fields      */
1967     static hf_register_info hf[] = {
1968         {   &hf_smpp_command_length,
1969             {   "Length    ", "smpp.command_length",
1970                 FT_UINT32, BASE_DEC, NULL, 0x00,
1971                 "Total length of the SMPP PDU.",
1972                 HFILL
1973             }
1974         },
1975         {   &hf_smpp_command_id,
1976             {   "Operation ", "smpp.command_id",
1977                 FT_UINT32, BASE_HEX, VALS(vals_command_id), 0x00,
1978                 "Defines the SMPP PDU.",
1979                 HFILL
1980             }
1981         },
1982         {   &hf_smpp_command_status,
1983             {   "Result    ", "smpp.command_status",
1984                 FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00,
1985                 "Indicates success or failure of the SMPP request.",
1986                 HFILL
1987             }
1988         },
1989         {   &hf_smpp_sequence_number,
1990             {   "Sequence #", "smpp.sequence_number",
1991                 FT_UINT32, BASE_DEC, NULL, 0x00,
1992                 "A number to correlate requests with responses.",
1993                 HFILL
1994             }
1995         },
1996         {   &hf_smpp_system_id,
1997             {   "System ID", "smpp.system_id",
1998                 FT_STRING, BASE_NONE, NULL, 0x00,
1999                 "Identifies a system.",
2000                 HFILL
2001             }
2002         },
2003         {   &hf_smpp_password,
2004             {   "Password", "smpp.password",
2005                 FT_STRING, BASE_NONE, NULL, 0x00,
2006                 "Password used for authentication.",
2007                 HFILL
2008             }
2009         },
2010         {   &hf_smpp_system_type,
2011             {   "System type", "smpp.system_type",
2012                 FT_STRING, BASE_NONE, NULL, 0x00,
2013                 "Categorises the system.",
2014                 HFILL
2015             }
2016         },
2017         {   &hf_smpp_interface_version,
2018             {   "Version (if)", "smpp.interface_version",
2019                 FT_STRING, BASE_NONE, NULL, 0x00,
2020                 "Version of SMPP interface supported.",
2021                 HFILL
2022             }
2023         },
2024         {   &hf_smpp_service_type,
2025             {   "Service type", "smpp.service_type",
2026                 FT_STRING, BASE_NONE, NULL, 0x00,
2027                 "SMS application service associated with the message.",
2028                 HFILL
2029             }
2030         },
2031         {   &hf_smpp_addr_ton,
2032             {   "Type of number", "smpp.addr_ton",
2033                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
2034                 "Indicates the type of number, given in the address.",
2035                 HFILL
2036             }
2037         },
2038         {   &hf_smpp_source_addr_ton,
2039             {   "Type of number (originator)", "smpp.source_addr_ton",
2040                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
2041                 "Indicates originator type of number, given in the address.",
2042                 HFILL
2043             }
2044         },
2045         {   &hf_smpp_dest_addr_ton,
2046             {   "Type of number (recipient)", "smpp.dest_addr_ton",
2047                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
2048                 "Indicates recipient type of number, given in the address.",
2049                 HFILL
2050             }
2051         },
2052         {   &hf_smpp_addr_npi,
2053             {   "Numbering plan indicator", "smpp.addr_npi",
2054                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
2055                 "Gives the numbering plan this address belongs to.",
2056                 HFILL
2057             }
2058         },
2059         {   &hf_smpp_source_addr_npi,
2060             {   "Numbering plan indicator (originator)", "smpp.source_addr_npi",
2061                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
2062                 "Gives originator numbering plan this address belongs to.",
2063                 HFILL
2064             }
2065         },
2066         {   &hf_smpp_dest_addr_npi,
2067             {   "Numbering plan indicator (recipient)", "smpp.dest_addr_npi",
2068                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
2069                 "Gives recipient numbering plan this address belongs to.",
2070                 HFILL
2071             }
2072         },
2073         {   &hf_smpp_address_range,
2074             {   "Address", "smpp.address_range",
2075                 FT_STRING, BASE_NONE, NULL, 0x00,
2076                 "Given address or address range.",
2077                 HFILL
2078             }
2079         },
2080         {   &hf_smpp_source_addr,
2081             {   "Originator address", "smpp.source_addr",
2082                 FT_STRING, BASE_NONE, NULL, 0x00,
2083                 "Address of SME originating this message.",
2084                 HFILL
2085             }
2086         },
2087         {   &hf_smpp_destination_addr,
2088             {   "Recipient address", "smpp.destination_addr",
2089                 FT_STRING, BASE_NONE, NULL, 0x00,
2090                 "Address of SME receiving this message.",
2091                 HFILL
2092             }
2093         },
2094         {   &hf_smpp_esm_submit_msg_mode,
2095             {   "Messaging mode", "smpp.esm.submit.msg_mode",
2096                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_msg_mode), 0x03,
2097                 "Mode attribute for this message.",
2098                 HFILL
2099             }
2100         },
2101         {   &hf_smpp_esm_submit_msg_type,
2102             {   "Message type  ", "smpp.esm.submit.msg_type",
2103                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_msg_type), 0x3C,
2104                 "Type attribute for this message.",
2105                 HFILL
2106             }
2107         },
2108         {   &hf_smpp_esm_submit_features,
2109             {   "GSM features  ", "smpp.esm.submit.features",
2110                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_features), 0xC0,
2111                 "GSM network specific features.",
2112                 HFILL
2113             }
2114         },
2115         /*! \todo Get proper values from GSM-spec.      */
2116         {   &hf_smpp_protocol_id,
2117             {   "Protocol id.", "smpp.protocol_id",
2118                 FT_UINT8, BASE_HEX, NULL, 0x00,
2119                 "Protocol identifier according GSM 03.40.",
2120                 HFILL
2121             }
2122         },
2123         {   &hf_smpp_priority_flag,
2124             {   "Priority level", "smpp.priority_flag",
2125                 FT_UINT8, BASE_HEX, VALS(vals_priority_flag), 0x00,
2126                 "The priority level of the short message.",
2127                 HFILL
2128             }
2129         },
2130         {   &hf_smpp_schedule_delivery_time,
2131             {   "Scheduled delivery time", "smpp.schedule_delivery_time",
2132                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2133                 "Scheduled time for delivery of short message.",
2134                 HFILL
2135             }
2136         },
2137         {   &hf_smpp_schedule_delivery_time_r,
2138             {   "Scheduled delivery time", "smpp.schedule_delivery_time_r",
2139                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
2140                 "Scheduled time for delivery of short message.",
2141                 HFILL
2142             }
2143         },
2144         {   &hf_smpp_validity_period,
2145             {   "Validity period", "smpp.validity_period",
2146                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2147                 "Validity period of this message.",
2148                 HFILL
2149             }
2150         },
2151         {   &hf_smpp_validity_period_r,
2152             {   "Validity period", "smpp.validity_period_r",
2153                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
2154                 "Validity period of this message.",
2155                 HFILL
2156             }
2157         },
2158         {   &hf_smpp_regdel_receipt,
2159             {   "Delivery receipt  ", "smpp.regdel.receipt",
2160                 FT_UINT8, BASE_HEX, VALS(vals_regdel_receipt), 0x03,
2161                 "SMSC delivery receipt request.",
2162                 HFILL
2163             }
2164         },
2165         {   &hf_smpp_regdel_acks,
2166             {   "Message type      ", "smpp.regdel.acks",
2167                 FT_UINT8, BASE_HEX, VALS(vals_regdel_acks), 0x0C,
2168                 "SME acknowledgement request.",
2169                 HFILL
2170             }
2171         },
2172         {   &hf_smpp_regdel_notif,
2173             {   "Intermediate notif", "smpp.regdel.notif",
2174                 FT_UINT8, BASE_HEX, VALS(vals_regdel_notif), 0x10,
2175                 "Intermediate notification request.",
2176                 HFILL
2177             }
2178         },
2179         {   &hf_smpp_replace_if_present_flag,
2180             {   "Replace           ", "smpp.replace_if_present_flag",
2181                 FT_UINT8, BASE_HEX, VALS(vals_replace_if_present_flag), 0x01,
2182                 "Replace the short message with this one or not.",
2183                 HFILL
2184             }
2185         },
2186         {   &hf_smpp_data_coding,
2187             {   "Data coding", "smpp.data_coding",
2188                 FT_UINT8, BASE_HEX, NULL, 0x00,
2189                 "Defines the encoding scheme of the message.",
2190                 HFILL
2191             }
2192         },
2193         {   &hf_smpp_sm_default_msg_id,
2194             {   "Predefined message", "smpp.sm_default_msg_id",
2195                 FT_UINT8, BASE_DEC, NULL, 0x00,
2196                 "Index of a predefined ('canned') short message.",
2197                 HFILL
2198             }
2199         },
2200         {   &hf_smpp_sm_length,
2201             {   "Message length", "smpp.sm_length",
2202                 FT_UINT8, BASE_DEC, NULL, 0x00,
2203                 "Length of the message content.",
2204                 HFILL
2205             }
2206         },
2207         {   &hf_smpp_short_message,
2208             {   "Message", "smpp.message",
2209                 FT_NONE, BASE_NONE, NULL, 0x00,
2210                 "The actual message or data.",
2211                 HFILL
2212             }
2213         },
2214         {   &hf_smpp_message_id,
2215             {   "Message id.", "smpp.message_id",
2216                 FT_STRING, BASE_NONE, NULL, 0x00,
2217                 "Identifier of the submitted short message.",
2218                 HFILL
2219             }
2220         },
2221         {   &hf_smpp_dlist,
2222             {   "Destination list", "smpp.dlist",
2223                 FT_NONE, BASE_NONE, NULL, 0x00,
2224                 "The list of destinations for a short message.",
2225                 HFILL
2226             }
2227         },
2228         {   &hf_smpp_dlist_resp,
2229             {   "Unsuccesfull delivery list", "smpp.dlist_resp",
2230                 FT_NONE, BASE_NONE, NULL, 0x00,
2231                 "The list of unsuccesfull deliveries to destinations.",
2232                 HFILL
2233             }
2234         },
2235         {   &hf_smpp_dl_name,
2236             {   "Distr. list name", "smpp.dl_name",
2237                 FT_STRING, BASE_NONE, NULL, 0x00,
2238                 "The name of the distribution list.",
2239                 HFILL
2240             }
2241         },
2242         {   &hf_smpp_final_date,
2243             {   "Final date", "smpp.final_date",
2244                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
2245                 "Date-time when the queried message reached a final state.",
2246                 HFILL
2247             }
2248         },
2249         {   &hf_smpp_final_date_r,
2250             {   "Final date", "smpp.final_date_r",
2251                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
2252                 "Date-time when the queried message reached a final state.",
2253                 HFILL
2254             }
2255         },
2256         {   &hf_smpp_message_state,
2257             {   "Message state", "smpp.message_state",
2258                 FT_UINT8, BASE_DEC, VALS(vals_message_state), 0x00,
2259                 "Specifies the status of the queried short message.",
2260                 HFILL
2261             }
2262         },
2263         {   &hf_smpp_error_code,
2264             {   "Error code", "smpp.error_code",
2265                 FT_UINT8, BASE_DEC, NULL, 0x00,
2266                 "Network specific error code defining reason for failure.",
2267                 HFILL
2268             }
2269         },
2270         {   &hf_smpp_error_status_code,
2271             {   "Status", "smpp.error_status_code",
2272                 FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00,
2273                 "Indicates success/failure of request for this address.",
2274                 HFILL
2275             }
2276         },
2277         {   &hf_smpp_esme_addr_ton,
2278             {   "Type of number (ESME)", "smpp.esme_addr_ton",
2279                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
2280                 "Indicates recipient type of number, given in the address.",
2281                 HFILL
2282             }
2283         },
2284         {   &hf_smpp_esme_addr_npi,
2285             {   "Numbering plan indicator (ESME)", "smpp.esme_addr_npi",
2286                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
2287                 "Gives the numbering plan this address belongs to.",
2288                 HFILL
2289             }
2290         },
2291         {   &hf_smpp_esme_addr,
2292             {   "ESME address", "smpp.esme_addr",
2293                 FT_STRING, BASE_NONE, NULL, 0x00,
2294                 "Address of ESME originating this message.",
2295                 HFILL
2296             }
2297         },
2298         {   &hf_smpp_dest_addr_subunit,
2299             {   "Subunit destination", "smpp.dest_addr_subunit",
2300                 FT_UINT8, BASE_HEX, VALS(vals_addr_subunit), 0x00,
2301                 "Subunit address within mobile to route message to.",
2302                 HFILL
2303             }
2304         },
2305         {   &hf_smpp_source_addr_subunit,
2306             {   "Subunit origin", "smpp.source_addr_subunit",
2307                 FT_UINT8, BASE_HEX, VALS(vals_addr_subunit), 0x00,
2308                 "Subunit address within mobile that generated the message.",
2309                 HFILL
2310             }
2311         },
2312         {   &hf_smpp_dest_network_type,
2313             {   "Destination network", "smpp.dest_network_type",
2314                 FT_UINT8, BASE_HEX, VALS(vals_network_type), 0x00,
2315                 "Network associated with the destination address.",
2316                 HFILL
2317             }
2318         },
2319         {   &hf_smpp_source_network_type,
2320             {   "Originator network", "smpp.source_network_type",
2321                 FT_UINT8, BASE_HEX, VALS(vals_network_type), 0x00,
2322                 "Network associated with the originator address.",
2323                 HFILL
2324             }
2325         },
2326         {   &hf_smpp_dest_bearer_type,
2327             {   "Destination bearer", "smpp.dest_bearer_type",
2328                 FT_UINT8, BASE_HEX, VALS(vals_bearer_type), 0x00,
2329                 "Desired bearer for delivery of message.",
2330                 HFILL
2331             }
2332         },
2333         {   &hf_smpp_source_bearer_type,
2334             {   "Originator bearer", "smpp.source_bearer_type",
2335                 FT_UINT8, BASE_HEX, VALS(vals_bearer_type), 0x00,
2336                 "Bearer over which the message originated.",
2337                 HFILL
2338             }
2339         },
2340         {   &hf_smpp_dest_telematics_id,
2341             {   "Telematic interworking (dest)", "smpp.dest_telematics_id",
2342                 FT_UINT16, BASE_HEX, NULL, 0x00,
2343                 "Telematic interworking to be used for message delivery.",
2344                 HFILL
2345             }
2346         },
2347         {   &hf_smpp_source_telematics_id,
2348             {   "Telematic interworking (orig)", "smpp.source_telematics_id",
2349                 FT_UINT16, BASE_HEX, NULL, 0x00,
2350                 "Telematic interworking used for message submission.",
2351                 HFILL
2352             }
2353         },
2354         {   &hf_smpp_qos_time_to_live,
2355             {   "Validity period", "smpp.qos_time_to_live",
2356                 FT_UINT32, BASE_DEC, NULL, 0x00,
2357                 "Number of seconds to retain message before expiry.",
2358                 HFILL
2359             }
2360         },
2361         {   &hf_smpp_payload_type,
2362             {   "Payload", "smpp.payload_type",
2363                 FT_UINT8, BASE_DEC, VALS(vals_payload_type), 0x00,
2364                 "PDU type contained in the message payload.",
2365                 HFILL
2366             }
2367         },
2368         {   &hf_smpp_additional_status_info_text,
2369             {   "Information", "smpp.additional_status_info_text",
2370                 FT_STRING, BASE_NONE, NULL, 0x00,
2371                 "Description of the meaning of a response PDU.",
2372                 HFILL
2373             }
2374         },
2375         {   &hf_smpp_receipted_message_id,
2376             {   "SMSC identifier", "smpp.receipted_message_id",
2377                 FT_STRING, BASE_NONE, NULL, 0x00,
2378                 "SMSC handle of the message being received.",
2379                 HFILL
2380             }
2381         },
2382         {   &hf_smpp_privacy_indicator,
2383             {   "Privacy indicator", "smpp.privacy_indicator",
2384                 FT_UINT8, BASE_DEC, VALS(vals_privacy_indicator), 0x00,
2385                 "Indicates the privacy level of the message.",
2386                 HFILL
2387             }
2388         },
2389         {   &hf_smpp_user_message_reference,
2390             {   "Message reference", "smpp.user_message_reference",
2391                 FT_UINT16, BASE_HEX, NULL, 0x00,
2392                 "Reference to the message, assigned by the user.",
2393                 HFILL
2394             }
2395         },
2396         {   &hf_smpp_user_response_code,
2397             {   "Application response code", "smpp.user_response_code",
2398                 FT_UINT8, BASE_HEX, NULL, 0x00,
2399                 "A response code set by the user.",
2400                 HFILL
2401             }
2402         },
2403         {   &hf_smpp_language_indicator,
2404             {   "Language", "smpp.language_indicator",
2405                 FT_UINT8, BASE_DEC, VALS(vals_language_indicator), 0x00,
2406                 "Indicates the language of the short message.",
2407                 HFILL
2408             }
2409         },
2410         {   &hf_smpp_source_port,
2411             {   "Source port", "smpp.source_port",
2412                 FT_UINT16, BASE_HEX, NULL, 0x00,
2413                 "Application port associated with the source of the message.",
2414                 HFILL
2415             }
2416         },
2417         {   &hf_smpp_destination_port,
2418             {   "Destination port", "smpp.destination_port",
2419                 FT_UINT16, BASE_HEX, NULL, 0x00,
2420                 "Application port associated with the destination of the message.",
2421                 HFILL
2422             }
2423         },
2424         {   &hf_smpp_sar_msg_ref_num,
2425             {   "SAR reference number", "smpp.sar_msg_ref_num",
2426                 FT_UINT16, BASE_DEC, NULL, 0x00,
2427                 "Reference number for a concatenated short message.",
2428                 HFILL
2429             }
2430         },
2431         {   &hf_smpp_sar_total_segments,
2432             {   "SAR size", "smpp.sar_total_segments",
2433                 FT_UINT16, BASE_DEC, NULL, 0x00,
2434                 "Number of segments of a concatenated short message.",
2435                 HFILL
2436             }
2437         },
2438         {   &hf_smpp_sar_segment_seqnum,
2439             {   "SAR sequence number", "smpp.sar_segment_seqnum",
2440                 FT_UINT8, BASE_DEC, NULL, 0x00,
2441                 "Segment number within a concatenated short message.",
2442                 HFILL
2443             }
2444         },
2445         {   &hf_smpp_display_time,
2446             {   "Display time", "smpp.display_time",
2447                 FT_UINT8, BASE_DEC, VALS(vals_display_time), 0x00,
2448                 "Associates a display time with the message on the handset.",
2449                 HFILL
2450             }
2451         },
2452         {   &hf_smpp_ms_validity,
2453             {   "Validity info", "smpp.ms_validity",
2454                 FT_UINT8, BASE_DEC, VALS(vals_ms_validity), 0x00,
2455                 "Associates validity info with the message on the handset.",
2456                 HFILL
2457             }
2458         },
2459         {   &hf_smpp_dpf_result,
2460             {   "Delivery pending set?", "smpp.dpf_result",
2461                 FT_UINT8, BASE_DEC, VALS(vals_dpf_result), 0x00,
2462                 "Indicates whether Delivery Pending Flag was set.",
2463                 HFILL
2464             }
2465         },
2466         {   &hf_smpp_set_dpf,
2467             {   "Request DPF set", "smpp.set_dpf",
2468                 FT_UINT8, BASE_DEC, VALS(vals_set_dpf), 0x00,
2469                 "Request to set the DPF for certain failure scenario's.",
2470                 HFILL
2471             }
2472         },
2473         {   &hf_smpp_ms_availability_status,
2474             {   "Availability status", "smpp.ms_availability_status",
2475                 FT_UINT8, BASE_DEC, VALS(vals_ms_availability_status), 0x00,
2476                 "Indicates the availability state of the handset.",
2477                 HFILL
2478             }
2479         },
2480         {   &hf_smpp_delivery_failure_reason,
2481             {   "Delivery failure reason", "smpp.delivery_failure_reason",
2482                 FT_UINT8, BASE_DEC, VALS(vals_delivery_failure_reason), 0x00,
2483                 "Indicates the reason for a failed delivery attempt.",
2484                 HFILL
2485             }
2486         },
2487         {   &hf_smpp_more_messages_to_send,
2488             {   "More messages?", "smpp.more_messages_to_send",
2489                 FT_UINT8, BASE_DEC, VALS(vals_more_messages_to_send), 0x00,
2490                 "Indicates more messages pending for the same destination.",
2491                 HFILL
2492             }
2493         },
2494         {   &hf_smpp_number_of_messages,
2495             {   "Number of messages", "smpp.number_of_messages",
2496                 FT_UINT8, BASE_DEC, NULL, 0x00,
2497                 "Indicates number of messages stored in a mailbox.",
2498                 HFILL
2499             }
2500         },
2501         {   &hf_smpp_its_reply_type,
2502             {   "Reply method", "smpp.its_reply_type",
2503                 FT_UINT8, BASE_DEC, VALS(vals_its_reply_type), 0x00,
2504                 "Indicates the handset reply method on message receipt.",
2505                 HFILL
2506             }
2507         },
2508         {   &hf_smpp_ussd_service_op,
2509             {   "USSD service operation", "smpp.ussd_service_op",
2510                 FT_UINT8, BASE_DEC, VALS(vals_ussd_service_op), 0x00,
2511                 "Indicates the USSD service operation.",
2512                 HFILL
2513             }
2514         },
2515         {   &hf_smpp_vendor_op,
2516             {   "Optional parameter - Vendor-specific", "smpp.vendor_op",
2517                 FT_NONE, BASE_NONE, NULL, 0x00,
2518                 "A supplied optional parameter specific to an SMSC-vendor.",
2519                 HFILL
2520             }
2521         },
2522         {   &hf_smpp_reserved_op,
2523             {   "Optional parameter - Reserved", "smpp.reserved_op",
2524                 FT_NONE, BASE_NONE, NULL, 0x00,
2525                 "An optional parameter that is reserved in this version.",
2526                 HFILL
2527             }
2528         },
2529         {   &hf_smpp_msg_wait_ind,
2530             {   "Indication", "smpp.msg_wait.ind",
2531                 FT_UINT8, BASE_HEX, VALS(vals_msg_wait_ind), 0x80,
2532                 "Indicates to the handset that a message is waiting.",
2533                 HFILL
2534             }
2535         },
2536         {   &hf_smpp_msg_wait_type,
2537             {   "Type      ", "smpp.msg_wait.type",
2538                 FT_UINT8, BASE_HEX, VALS(vals_msg_wait_type), 0x03,
2539                 "Indicates type of message that is waiting.",
2540                 HFILL
2541             }
2542         },
2543         {   &hf_smpp_SC_interface_version,
2544             {   "SMSC-supported version", "smpp.SC_interface_version",
2545                 FT_STRING, BASE_NONE, NULL, 0x00,
2546                 "Version of SMPP interface supported by the SMSC.",
2547                 HFILL
2548             }
2549         },
2550         {   &hf_smpp_callback_num_pres,
2551             {   "Presentation", "smpp.callback_num.pres",
2552                 FT_UINT8, BASE_HEX, VALS(vals_callback_num_pres), 0x0C,
2553                 "Controls the presentation indication.",
2554                 HFILL
2555             }
2556         },
2557         {   &hf_smpp_callback_num_scrn,
2558             {   "Screening   ", "smpp.callback_num.scrn",
2559                 FT_UINT8, BASE_HEX, VALS(vals_callback_num_scrn), 0x03,
2560                 "Controls screening of the callback-number.",
2561                 HFILL
2562             }
2563         },
2564         {   &hf_smpp_callback_num_atag,
2565             {   "Callback number - alphanumeric display tag",
2566                 "smpp.callback_num_atag",
2567                 FT_NONE, BASE_NONE, NULL, 0x00,
2568                 "Associates an alphanumeric display with call back number.",
2569                 HFILL
2570             }
2571         },
2572         {   &hf_smpp_callback_num,
2573             {   "Callback number", "smpp.callback_num",
2574                 FT_NONE, BASE_NONE, NULL, 0x00,
2575                 "Associates a call back number with the message.",
2576                 HFILL
2577             }
2578         },
2579         {   &hf_smpp_network_error_type,
2580             {   "Error type", "smpp.network_error.type",
2581                 FT_UINT8, BASE_DEC, VALS(vals_network_error_type), 0x00,
2582                 "Indicates the network type.",
2583                 HFILL
2584             }
2585         },
2586         {   &hf_smpp_network_error_code,
2587             {   "Error code", "smpp.network_error.code",
2588                 FT_UINT16, BASE_HEX, NULL, 0x00,
2589                 "Gives the actual network error code.",
2590                 HFILL
2591             }
2592         },
2593         {   &hf_smpp_message_payload,
2594             {   "Payload", "smpp.message_payload",
2595                 FT_NONE, BASE_NONE, NULL, 0x00,
2596                 "Short message user data.",
2597                 HFILL
2598             }
2599         },
2600         {   &hf_smpp_alert_on_message_delivery,
2601             {   "Alert on delivery", "smpp.alert_on_message_delivery",
2602                 FT_NONE, BASE_NONE, NULL, 0x00,
2603                 "Instructs the handset to alert user on message delivery.",
2604                 HFILL
2605             }
2606         },
2607         {   &hf_smpp_its_session_number,
2608             {   "Session number", "smpp.its_session.number",
2609                 FT_UINT8, BASE_DEC, NULL, 0x00,
2610                 "Session number of interactive teleservice.",
2611                 HFILL
2612             }
2613         },
2614         {   &hf_smpp_its_session_sequence,
2615             {   "Sequence number  ", "smpp.its_session.sequence",
2616                 FT_UINT8, BASE_HEX, NULL, 0xFE,
2617                 "Sequence number of the dialogue unit.",
2618                 HFILL
2619             }
2620         },
2621         {   &hf_smpp_its_session_ind,
2622             {   "Session indicator", "smpp.its_session.ind",
2623                 FT_UINT8, BASE_HEX, VALS(vals_its_session_ind), 0x01,
2624                 "Indicates whether this message is end of conversation.",
2625                 HFILL
2626             }
2627         },
2628         {   &hf_smpp_opt_param,
2629             {   "Optional parameters", "smpp.opt_param",
2630                 FT_NONE, BASE_NONE, NULL, 0x00,
2631                 "The list of optional parameters in this operation.",
2632                 HFILL
2633             }
2634         },
2635         /*
2636          * Data Coding Scheme
2637          */
2638         {       &hf_smpp_dcs,
2639                 { "SMPP Data Coding Scheme", "smpp.dcs",
2640                 FT_UINT8, BASE_HEX, VALS(vals_data_coding), 0x00,
2641                 "Data Coding Scheme according to SMPP.",
2642                 HFILL
2643             }
2644         },
2645         {       &hf_smpp_dcs_sms_coding_group,
2646                 {       "DCS Coding Group for SMS", "smpp.dcs.sms_coding_group",
2647                         FT_UINT8, BASE_HEX, VALS(vals_dcs_sms_coding_group), 0xF0,
2648                         "Data Coding Scheme coding group for GSM Short Message Service.",
2649                         HFILL
2650                 }
2651         },
2652         {       &hf_smpp_dcs_text_compression,
2653                 {       "DCS Text compression", "smpp.dcs.text_compression",
2654                         FT_BOOLEAN, 8, TFS(&tfs_dcs_text_compression), 0x20,
2655                         "Indicates if text compression is used.", HFILL
2656                 }
2657         },
2658         {       &hf_smpp_dcs_class_present,
2659                 {       "DCS Class present", "smpp.dcs.class_present",
2660                         FT_BOOLEAN, 8, TFS(&tfs_dcs_class_present), 0x10,
2661                         "Indicates if the message class is present (defined).", HFILL
2662                 }
2663         },
2664         {       &hf_smpp_dcs_charset,
2665                 {       "DCS Character set", "smpp.dcs.charset",
2666                         FT_UINT8, BASE_HEX, VALS(vals_dcs_charset), 0x0C,
2667                         "Specifies the character set used in the message.", HFILL
2668                 }
2669         },
2670         {       &hf_smpp_dcs_class,
2671                 {       "DCS Message class", "smpp.dcs.class",
2672                         FT_UINT8, BASE_HEX, VALS(vals_dcs_class), 0x03,
2673                         "Specifies the message class.", HFILL
2674                 }
2675         },
2676         {       &hf_smpp_dcs_cbs_coding_group,
2677                 {       "DCS Coding Group for CBS", "smpp.dcs.cbs_coding_group",
2678                         FT_UINT8, BASE_HEX, VALS(vals_dcs_cbs_coding_group), 0xF0,
2679                         "Data Coding Scheme coding group for GSM Cell Broadcast Service.",
2680                         HFILL
2681                 }
2682         },
2683         {       &hf_smpp_dcs_cbs_language,
2684                 {       "DCS CBS Message language", "smpp.dcs.cbs_language",
2685                         FT_UINT8, BASE_HEX, VALS(vals_dcs_cbs_language), 0x3F,
2686                         "Language of the GSM Cell Broadcast Service message.", HFILL
2687                 }
2688         },
2689         {       &hf_smpp_dcs_cbs_class,
2690                 {       "DCS CBS Message class", "smpp.dcs.cbs_class",
2691                         FT_UINT8, BASE_HEX, VALS(vals_dcs_cbs_class), 0x03,
2692                         "Specifies the message class for GSM Cell Broadcast Service, "
2693                         "for the Data coding / message handling code group.", HFILL
2694                 }
2695         },
2696         {       &hf_smpp_dcs_wap_charset,
2697                 {       "DCS Message coding", "smpp.dcs.wap_coding",
2698                         FT_UINT8, BASE_HEX, VALS(vals_dcs_wap_charset), 0x0C,
2699                         "Specifies the used message encoding, "
2700                         "as specified by the WAP Forum (WAP over GSM USSD).", HFILL
2701                 }
2702         },
2703         {       &hf_smpp_dcs_wap_class,
2704                 {       "DCS CBS Message class", "smpp.dcs.wap_class",
2705                         FT_UINT8, BASE_HEX, VALS(vals_dcs_wap_class), 0x03,
2706                         "Specifies the message class for GSM Cell Broadcast Service, "
2707                         "as specified by the WAP Forum (WAP over GSM USSD).", HFILL
2708                 }
2709         },
2710     };
2711     /* Setup protocol subtree array */
2712     static gint *ett[] = {
2713         &ett_smpp,
2714         &ett_dlist,
2715         &ett_dlist_resp,
2716         &ett_opt_param,
2717         &ett_dcs,
2718     };
2719     DebugLog(("Registering SMPP dissector\n"));
2720     /* Register the protocol name and description */
2721     proto_smpp = proto_register_protocol("Short Message Peer to Peer",
2722                                          "SMPP", "smpp");
2723
2724     /* Required function calls to register header fields and subtrees used */
2725     proto_register_field_array(proto_smpp, hf, array_length(hf));
2726     proto_register_subtree_array(ett, array_length(ett));
2727
2728     /* Preferences */
2729     smpp_module = prefs_register_protocol (proto_smpp, NULL);
2730     prefs_register_bool_preference (smpp_module,
2731             "reassemble_smpp_over_tcp",
2732             "Reassemble SMPP over TCP",
2733             "Reassemble TCP segments that convey SMPP traffic.",
2734             &reassemble_over_tcp);
2735 }
2736
2737 /*
2738  * If dissector uses sub-dissector registration add a registration routine.
2739  * This format is required because a script is used to find these routines and
2740  * create the code that calls these routines.
2741  */
2742 void
2743 proto_reg_handoff_smpp(void)
2744 {
2745     dissector_handle_t smpp_handle;
2746
2747     /*
2748      * SMPP can be spoken on any port under TCP or X.25
2749      * ...how *do* we do that under X.25?
2750      *
2751      * We can register the heuristic SMPP dissector with X.25, for one
2752      * thing.  We don't currently have any mechanism to allow the user
2753      * to specify that a given X.25 circuit is to be dissected as SMPP,
2754      * however.
2755      */
2756     smpp_handle = create_dissector_handle(dissect_smpp, proto_smpp);
2757     dissector_add_handle("tcp.port", smpp_handle);
2758     heur_dissector_add("tcp", dissect_smpp_heur, proto_smpp);
2759     heur_dissector_add("x.25", dissect_smpp_heur, proto_smpp);
2760
2761         /* Required for call_dissector() */
2762         DebugLog(("Finding gsm-sms-ud subdissector\n"));
2763         gsm_sms_handle = find_dissector("gsm-sms-ud");
2764         g_assert (gsm_sms_handle);
2765 }