62ac09601758df15e68ec62075ea25272790cd64
[obnox/wireshark/wip.git] / packet-smpp.c
1 /* packet-smpp.c
2  * Routines for Short Message Peer to Peer dissection
3  * Copyright 2001, Tom Uijldert <tom.uijldert@cmg.nl>
4  *
5  * $Id: packet-smpp.c,v 1.6 2002/03/10 03:08:31 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24  * ----------
25  *
26  * Dissector of an SMPP (Short Message Peer to Peer) PDU, as defined by the
27  * SMS forum (www.smsforum.net) in "SMPP protocol specification v3.4"
28  * (document version: 12-Oct-1999 Issue 1.2)
29  */
30
31 #ifdef HAVE_CONFIG_H
32 # include "config.h"
33 #endif
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <time.h>
39
40 #ifdef HAVE_SYS_TYPES_H
41 # include <sys/types.h>
42 #endif
43
44 #ifdef HAVE_NETINET_IN_H
45 # include <netinet/in.h>
46 #endif
47
48 #include <glib.h>
49
50 #ifdef NEED_SNPRINTF_H
51 # include "snprintf.h"
52 #endif
53
54 #include <epan/packet.h>
55 /* #include "packet-smpp.h"     */              /* We autoregister      */
56
57 /* Forward declarations         */
58 static void dissect_smpp(tvbuff_t *, packet_info *, proto_tree *t);
59
60 /*
61  * Initialize the protocol and registered fields
62  *
63  * Fixed header section
64  */
65 static int proto_smpp                           = -1;
66
67 static int hf_smpp_command_id                   = -1;
68 static int hf_smpp_command_length               = -1;
69 static int hf_smpp_command_status               = -1;
70 static int hf_smpp_sequence_number              = -1;
71
72 /*
73  * Fixed body section
74  */
75 static int hf_smpp_system_id                    = -1;
76 static int hf_smpp_password                     = -1;
77 static int hf_smpp_system_type                  = -1;
78 static int hf_smpp_interface_version            = -1;
79 static int hf_smpp_addr_ton                     = -1;
80 static int hf_smpp_addr_npi                     = -1;
81 static int hf_smpp_address_range                = -1;
82 static int hf_smpp_service_type                 = -1;
83 static int hf_smpp_source_addr_ton              = -1;
84 static int hf_smpp_source_addr_npi              = -1;
85 static int hf_smpp_source_addr                  = -1;
86 static int hf_smpp_dest_addr_ton                = -1;
87 static int hf_smpp_dest_addr_npi                = -1;
88 static int hf_smpp_destination_addr             = -1;
89 static int hf_smpp_esm_submit_msg_mode          = -1;
90 static int hf_smpp_esm_submit_msg_type          = -1;
91 static int hf_smpp_esm_submit_features          = -1;
92 static int hf_smpp_protocol_id                  = -1;
93 static int hf_smpp_priority_flag                = -1;
94 static int hf_smpp_schedule_delivery_time       = -1;
95 static int hf_smpp_schedule_delivery_time_r     = -1;
96 static int hf_smpp_validity_period              = -1;
97 static int hf_smpp_validity_period_r            = -1;
98 static int hf_smpp_regdel_receipt               = -1;
99 static int hf_smpp_regdel_acks                  = -1;
100 static int hf_smpp_regdel_notif                 = -1;
101 static int hf_smpp_replace_if_present_flag      = -1;
102 static int hf_smpp_data_coding                  = -1;
103 static int hf_smpp_sm_default_msg_id            = -1;
104 static int hf_smpp_sm_length                    = -1;
105 static int hf_smpp_short_message                = -1;
106 static int hf_smpp_message_id                   = -1;
107 static int hf_smpp_dlist                        = -1;
108 static int hf_smpp_dlist_resp                   = -1;
109 static int hf_smpp_dl_name                      = -1;
110 static int hf_smpp_final_date                   = -1;
111 static int hf_smpp_final_date_r                 = -1;
112 static int hf_smpp_message_state                = -1;
113 static int hf_smpp_error_code                   = -1;
114 static int hf_smpp_error_status_code            = -1;
115 static int hf_smpp_esme_addr_ton                = -1;
116 static int hf_smpp_esme_addr_npi                = -1;
117 static int hf_smpp_esme_addr                    = -1;
118
119 /*
120  * Optional parameter section
121  */
122 static int hf_smpp_opt_param                    = -1;
123 static int hf_smpp_vendor_op                    = -1;
124 static int hf_smpp_reserved_op                  = -1;
125
126 static int hf_smpp_dest_addr_subunit            = -1;
127 static int hf_smpp_dest_network_type            = -1;
128 static int hf_smpp_dest_bearer_type             = -1;
129 static int hf_smpp_dest_telematics_id           = -1;
130 static int hf_smpp_source_addr_subunit          = -1;
131 static int hf_smpp_source_network_type          = -1;
132 static int hf_smpp_source_bearer_type           = -1;
133 static int hf_smpp_source_telematics_id         = -1;
134 static int hf_smpp_qos_time_to_live             = -1;
135 static int hf_smpp_payload_type                 = -1;
136 static int hf_smpp_additional_status_info_text  = -1;
137 static int hf_smpp_receipted_message_id         = -1;
138 static int hf_smpp_msg_wait_ind                 = -1;
139 static int hf_smpp_msg_wait_type                = -1;
140 static int hf_smpp_privacy_indicator            = -1;
141 static int hf_smpp_source_subaddress            = -1;
142 static int hf_smpp_dest_subaddress              = -1;
143 static int hf_smpp_user_message_reference       = -1;
144 static int hf_smpp_user_response_code           = -1;
145 static int hf_smpp_source_port                  = -1;
146 static int hf_smpp_destination_port             = -1;
147 static int hf_smpp_sar_msg_ref_num              = -1;
148 static int hf_smpp_language_indicator           = -1;
149 static int hf_smpp_sar_total_segments           = -1;
150 static int hf_smpp_sar_segment_seqnum           = -1;
151 static int hf_smpp_SC_interface_version         = -1;
152 static int hf_smpp_callback_num_pres            = -1;
153 static int hf_smpp_callback_num_scrn            = -1;
154 static int hf_smpp_callback_num_atag            = -1;
155 static int hf_smpp_number_of_messages           = -1;
156 static int hf_smpp_callback_num                 = -1;
157 static int hf_smpp_dpf_result                   = -1;
158 static int hf_smpp_set_dpf                      = -1;
159 static int hf_smpp_ms_availability_status       = -1;
160 static int hf_smpp_network_error_type           = -1;
161 static int hf_smpp_network_error_code           = -1;
162 static int hf_smpp_message_payload              = -1;
163 static int hf_smpp_delivery_failure_reason      = -1;
164 static int hf_smpp_more_messages_to_send        = -1;
165 static int hf_smpp_ussd_service_op              = -1;
166 static int hf_smpp_display_time                 = -1;
167 static int hf_smpp_sms_signal                   = -1;
168 static int hf_smpp_ms_validity                  = -1;
169 static int hf_smpp_alert_on_message_delivery    = -1;
170 static int hf_smpp_its_reply_type               = -1;
171 static int hf_smpp_its_session_number           = -1;
172 static int hf_smpp_its_session_sequence         = -1;
173 static int hf_smpp_its_session_ind              = -1;
174
175 /* Initialize the subtree pointers */
176 static gint ett_smpp            = -1;
177 static gint ett_dlist           = -1;
178 static gint ett_dlist_resp      = -1;
179 static gint ett_opt_param       = -1;
180
181 /*
182  * Value-arrays for field-contents
183  */
184 static const value_string vals_command_id[] = {         /* Operation    */
185     { 0x80000000, "Generic_nack" },
186     { 0x00000001, "Bind_receiver" },
187     { 0x80000001, "Bind_receiver - resp" },
188     { 0x00000002, "Bind_transmitter" },
189     { 0x80000002, "Bind_transmitter - resp" },
190     { 0x00000003, "Query_sm" },
191     { 0x80000003, "Query_sm - resp" },
192     { 0x00000004, "Submit_sm" },
193     { 0x80000004, "Submit_sm - resp" },
194     { 0x00000005, "Deliver_sm" },
195     { 0x80000005, "Deliver_sm - resp" },
196     { 0x00000006, "Unbind" },
197     { 0x80000006, "Unbind - resp" },
198     { 0x00000007, "Replace_sm" },
199     { 0x80000007, "Replace_sm - resp" },
200     { 0x00000008, "Cancel_sm" },
201     { 0x80000008, "Cancel_sm - resp" },
202     { 0x00000009, "Bind_transceiver" },
203     { 0x80000009, "Bind_transceiver - resp" },
204     { 0x0000000B, "Outbind" },
205     { 0x00000015, "Enquire_link" },
206     { 0x80000015, "Enquire_link - resp" },
207     { 0x00000021, "Submit_multi" },
208     { 0x80000021, "Submit_multi - resp" },
209     { 0x00000102, "Alert_notification" },
210     { 0x00000103, "Data_sm" },
211     { 0x80000103, "Data_sm - resp" },
212     { 0, NULL }
213 };
214
215 static const value_string vals_command_status[] = {     /* Status       */
216     { 0x00000000, "Ok" },
217     { 0x00000001, "Message length is invalid" },
218     { 0x00000002, "Command length is invalid" },
219     { 0x00000003, "Invalid command ID" },
220     { 0x00000004, "Incorrect BIND status for given command" },
221     { 0x00000005, "ESME already in bound state" },
222     { 0x00000006, "Invalid priority flag" },
223     { 0x00000007, "Invalid registered delivery flag" },
224     { 0x00000008, "System error" },
225     { 0x00000009, "[Reserved]" },
226     { 0x0000000A, "Invalid source address" },
227     { 0x0000000B, "Invalid destination address" },
228     { 0x0000000C, "Message ID is invalid" },
229     { 0x0000000D, "Bind failed" },
230     { 0x0000000E, "Invalid password" },
231     { 0x0000000F, "Invalid system ID" },
232     { 0x00000010, "[Reserved]" },
233     { 0x00000011, "Cancel SM failed" },
234     { 0x00000012, "[Reserved]" },
235     { 0x00000013, "Replace SM failed" },
236     { 0x00000014, "Message queue full" },
237     { 0x00000015, "Invalid service type" },
238     { 0x00000033, "Invalid number of destinations" },
239     { 0x00000034, "Invalid distribution list name" },
240     { 0x00000040, "Destination flag is invalid (submit_multi)" },
241     { 0x00000041, "[Reserved]" },
242     { 0x00000042, "Invalid 'submit with replace' request" },
243     { 0x00000043, "Invalid esm_class field data" },
244     { 0x00000044, "Cannot submit to distribution list" },
245     { 0x00000045, "submit_sm or submit_multi failed" },
246     { 0x00000046, "[Reserved]" },
247     { 0x00000047, "[Reserved]" },
248     { 0x00000048, "Invalid source address TON" },
249     { 0x00000049, "Invalid source address NPI" },
250     { 0x00000050, "Invalid destination address TON" },
251     { 0x00000051, "Invalid destination address NPI" },
252     { 0x00000052, "[Reserved]" },
253     { 0x00000053, "Invalid system_type field" },
254     { 0x00000054, "Invalid replace_if_present flag" },
255     { 0x00000055, "Invalid number of messages" },
256     { 0x00000056, "[Reserved]" },
257     { 0x00000057, "[Reserved]" },
258     { 0x00000058, "Throttling error (ESME exceeded allowed message limits)" },
259     { 0x00000059, "[Reserved]" },
260     { 0x00000060, "[Reserved]" },
261     { 0x00000061, "Invalid scheduled delivery time" },
262     { 0x00000062, "Invalid message validity period (expirey time)" },
263     { 0x00000063, "Predefined message invalid or not found" },
264     { 0x00000064, "ESME receiver temporary app error code" },
265     { 0x00000065, "ESME receiver permanent app error code" },
266     { 0x00000066, "ESME receiver reject message error code" },
267     { 0x00000067, "query_sm request failed" },
268     { 0x000000C0, "Error in the optional part of the PDU body" },
269     { 0x000000C1, "Optional parameter not allowed" },
270     { 0x000000C2, "Invalid parameter length" },
271     { 0x000000C3, "Expected optional parameter missing" },
272     { 0x000000C4, "Invalid optional parameter  value" },
273     { 0x000000FE, "Delivery failure (used for data_sm_resp)" },
274     { 0x000000FF, "Unknown error" },
275     { 0, NULL }
276 };
277
278 static const value_string vals_addr_ton[] = {
279     { 0, "Unknown" },
280     { 1, "International" },
281     { 2, "National" },
282     { 3, "Network specific" },
283     { 4, "Subscriber number" },
284     { 5, "Alphanumeric" },
285     { 6, "Abbreviated" },
286     { 0, NULL }
287 };
288
289 static const value_string vals_addr_npi[] = {
290     {  0, "Unknown" },
291     {  1, "ISDN (E163/E164)" },
292     {  3, "Data (X.121)" },
293     {  4, "Telex (F.69)" },
294     {  6, "Land mobile (E.212)" },
295     {  8, "National" },
296     {  9, "Private" },
297     { 10, "ERMES" },
298     { 14, "Internet (IP)" },
299     { 18, "WAP client Id" },
300     {  0, NULL }
301 };
302
303 static const value_string vals_esm_submit_msg_mode[] = {
304     {  0x0, "Default SMSC mode" },
305     {  0x1, "Datagram mode" },
306     {  0x2, "Forward mode" },
307     {  0x3, "Store and forward mode" },
308     {  0, NULL }
309 };
310
311 static const value_string vals_esm_submit_msg_type[] = {
312     {  0x0, "Default message type" },
313     {  0x1, "Short message contains SMSC Delivery Receipt" },
314     {  0x2, "Short message contains (E)SME delivery acknowledgement" },
315     {  0x3, "Reserved" },
316     {  0x4, "Short message contains (E)SME manual/user acknowledgement" },
317     {  0x5, "Reserved" },
318     {  0x6, "Short message contains conversation abort" },
319     {  0x7, "Reserved" },
320     {  0x8, "Short message contains intermediate delivery notification" },
321     {  0, NULL }
322 };
323
324 static const value_string vals_esm_submit_features[] = {
325     {  0x0, "No specific features selected" },
326     {  0x1, "UDHI indicator" },
327     {  0x2, "Reply path" },
328     {  0x3, "UDHI and reply path" },
329     {  0, NULL }
330 };
331
332 static const value_string vals_priority_flag[] = {
333     {  0, "GSM: None      ANSI-136: Bulk         IS-95: Normal" },
334     {  1, "GSM: priority  ANSI-136: Normal       IS-95: Interactive" },
335     {  2, "GSM: priority  ANSI-136: Urgent       IS-95: Urgent" },
336     {  3, "GSM: priority  ANSI-136: Very Urgent  IS-95: Emergency" },
337     {  0, NULL }
338 };
339
340 static const value_string vals_regdel_receipt[] = {
341     {  0x0, "No SMSC delivery receipt requested" },
342     {  0x1, "Delivery receipt requested (for success or failure)" },
343     {  0x2, "Delivery receipt requested (for failure)" },
344     {  0x3, "Reserved" },
345     {  0, NULL }
346 };
347
348 static const value_string vals_regdel_acks[] = {
349     {  0x0, "No recipient SME acknowledgement requested" },
350     {  0x1, "SME delivery acknowledgement requested" },
351     {  0x2, "SME manual/user acknowledgement requested" },
352     {  0x3, "Both delivery and manual/user acknowledgement requested" },
353     {  0, NULL }
354 };
355
356 static const value_string vals_regdel_notif[] = {
357     {  0x0, "No intermediate notification requested" },
358     {  0x1, "Intermediate notification requested" },
359     {  0, NULL }
360 };
361
362 static const value_string vals_replace_if_present_flag[] = {
363     {  0x0, "Don't replace" },
364     {  0x1, "Replace" },
365     {  0, NULL }
366 };
367
368 static const value_string vals_data_coding[] = {
369     {  0, "SMSC default alphabet" },
370     {  1, "IA5 (CCITT T.50/ASCII (ANSI X3.4)" },
371     {  2, "Octet unspecified (8-bit binary)" },
372     {  3, "Latin 1 (ISO-8859-1)" },
373     {  4, "Octet unspecified (8-bit binary)" },
374     {  5, "JIS (X 0208-1990)" },
375     {  6, "Cyrillic (ISO-8859-5)" },
376     {  7, "Latin/Hebrew (ISO-8859-8)" },
377     {  8, "UCS2 (ISO/IEC-10646)" },
378     {  9, "Pictogram encoding" },
379     {  10, "ISO-2022-JP (Music codes)" },
380     {  11, "reserved" },
381     {  12, "reserved" },
382     {  13, "Extended Kanji JIS(X 0212-1990)" },
383     {  14, "KS C 5601" },
384     /*! \todo Rest to be defined (bitmask?) according GSM 03.38 */
385     {  0, NULL }
386 };
387
388 static const value_string vals_message_state[] = {
389     {  1, "ENROUTE" },
390     {  2, "DELIVERED" },
391     {  3, "EXPIRED" },
392     {  4, "DELETED" },
393     {  5, "UNDELIVERABLE" },
394     {  6, "ACCEPTED" },
395     {  7, "UNKNOWN" },
396     {  8, "REJECTED" },
397     {  0, NULL }
398 };
399
400 static const value_string vals_addr_subunit[] = {
401     {  0, "Unknown -default-" },
402     {  1, "MS Display" },
403     {  2, "Mobile equipment" },
404     {  3, "Smart card 1" },
405     {  4, "External unit 1" },
406     {  0, NULL }
407 };
408
409 static const value_string vals_network_type[] = {
410     {  0, "Unknown" },
411     {  1, "GSM" },
412     {  2, "ANSI-136/TDMA" },
413     {  3, "IS-95/CDMA" },
414     {  4, "PDC" },
415     {  5, "PHS" },
416     {  6, "iDEN" },
417     {  7, "AMPS" },
418     {  8, "Paging network" },
419     {  0, NULL }
420 };
421
422 static const value_string vals_bearer_type[] = {
423     {  0, "Unknown" },
424     {  1, "SMS" },
425     {  2, "Circuit Switched Data (CSD)" },
426     {  3, "Packet data" },
427     {  4, "USSD" },
428     {  5, "CDPD" },
429     {  6, "DataTAC" },
430     {  7, "FLEX/ReFLEX" },
431     {  8, "Cell Broadcast" },
432     {  0, NULL }
433 };
434
435 static const value_string vals_payload_type[] = {
436     {  0, "Default" },
437     {  1, "WCMP message" },
438     {  0, NULL }
439 };
440
441 static const value_string vals_privacy_indicator[] = {
442     {  0, "Not restricted -default-" },
443     {  1, "Restricted" },
444     {  2, "Confidential" },
445     {  3, "Secret" },
446     {  0, NULL }
447 };
448
449 static const value_string vals_language_indicator[] = {
450     {  0, "Unspecified -default-" },
451     {  1, "english" },
452     {  2, "french" },
453     {  3, "spanish" },
454     {  4, "german" },
455     {  5, "portuguese" },
456     {  0, NULL }
457 };
458
459 static const value_string vals_display_time[] = {
460     {  0, "Temporary" },
461     {  1, "Default -default-" },
462     {  2, "Invoke" },
463     {  0, NULL }
464 };
465
466 static const value_string vals_ms_validity[] = {
467     {  0, "Store indefinitely -default-" },
468     {  1, "Power down" },
469     {  2, "SID based registration area" },
470     {  3, "Display only" },
471     {  0, NULL }
472 };
473
474 static const value_string vals_dpf_result[] = {
475     {  0, "DPF not set" },
476     {  1, "DPF set" },
477     {  0, NULL }
478 };
479
480 static const value_string vals_set_dpf[] = {
481     {  0, "Not requested (Set DPF for delivery failure)" },
482     {  1, "Requested (Set DPF for delivery failure)" },
483     {  0, NULL }
484 };
485
486 static const value_string vals_ms_availability_status[] = {
487     {  0, "Available -default-" },
488     {  1, "Denied" },
489     {  2, "Unavailable" },
490     {  0, NULL }
491 };
492
493 static const value_string vals_delivery_failure_reason[] = {
494     {  0, "Destination unavailable" },
495     {  1, "Destination address invalid" },
496     {  2, "Permanent network error" },
497     {  3, "Temporary network error" },
498     {  0, NULL }
499 };
500
501 static const value_string vals_more_messages_to_send[] = {
502     {  0, "No more messages" },
503     {  1, "More messages -default-" },
504     {  0, NULL }
505 };
506
507 static const value_string vals_its_reply_type[] = {
508     {  0, "Digit" },
509     {  1, "Number" },
510     {  2, "Telephone no." },
511     {  3, "Password" },
512     {  4, "Character line" },
513     {  5, "Menu" },
514     {  6, "Date" },
515     {  7, "Time" },
516     {  8, "Continue" },
517     {  0, NULL }
518 };
519
520 static const value_string vals_ussd_service_op[] = {
521     {  0, "PSSD indication" },
522     {  1, "PSSR indication" },
523     {  2, "USSR request" },
524     {  3, "USSN request" },
525     { 16, "PSSD response" },
526     { 17, "PSSR response" },
527     { 18, "USSR confirm" },
528     { 19, "USSN confirm" },
529     {  0, NULL }
530 };
531
532 static const value_string vals_msg_wait_ind[] = {
533     {  0, "Set indication inactive" },
534     {  1, "Set indication active" },
535     {  0, NULL }
536 };
537
538 static const value_string vals_msg_wait_type[] = {
539     {  0, "Voicemail message waiting" },
540     {  1, "Fax message waiting" },
541     {  2, "Electronic mail message waiting" },
542     {  3, "Other message waiting" },
543     {  0, NULL }
544 };
545
546 static const value_string vals_callback_num_pres[] = {
547     {  0, "Presentation allowed" },
548     {  1, "Presentation restricted" },
549     {  2, "Number not available" },
550     {  3, "[Reserved]" },
551     {  0, NULL }
552 };
553
554 static const value_string vals_callback_num_scrn[] = {
555     {  0, "User provided, not screened" },
556     {  1, "User provided, verified and passed" },
557     {  2, "User provided, verified and failed" },
558     {  3, "Network provided" },
559     {  0, NULL }
560 };
561
562 static const value_string vals_network_error_type[] = {
563     {  1, "ANSI-136" },
564     {  2, "IS-95" },
565     {  3, "GSM" },
566     {  4, "[Reserved]" },
567     {  0, NULL }
568 };
569
570 static const value_string vals_its_session_ind[] = {
571     {  0, "End of session indicator inactive" },
572     {  1, "End of session indicator active" },
573     {  0, NULL }
574 };
575
576 /*!
577  * SMPP equivalent of mktime() (3). Convert date to standard 'time_t' format
578  *
579  * \param       datestr The SMPP-formatted date to convert
580  * \param       secs    Returns the 'time_t' equivalent
581  * \param       nsecs   Returns the additional nano-seconds
582  *
583  * \return              Whether time is specified relative or absolute
584  * \retval      TRUE    Relative time
585  * \retval      FALSE   Absolute time
586  */
587 static gboolean
588 smpp_mktime(char *datestr, time_t *secs, int *nsecs)
589 {
590     struct tm    r_time;
591     time_t       t_diff;
592     gboolean     relative = FALSE;
593
594     r_time.tm_year = 10 * (datestr[0] - '0') + (datestr[1] - '0');
595     /*
596      * Y2K rollover date as recommended in appendix C
597      */
598     if (r_time.tm_year < 38)
599         r_time.tm_year += 100;
600     r_time.tm_mon  = 10 * (datestr[2] - '0') + (datestr[3] - '0');
601     r_time.tm_mon--;
602     r_time.tm_mday = 10 * (datestr[4] - '0') + (datestr[5] - '0');
603     r_time.tm_hour = 10 * (datestr[6] - '0') + (datestr[7] - '0');
604     r_time.tm_min  = 10 * (datestr[8] - '0') + (datestr[9] - '0');
605     r_time.tm_sec  = 10 * (datestr[10] - '0') + (datestr[11] - '0');
606     r_time.tm_isdst = -1;
607     *secs = mktime(&r_time);
608     *nsecs = (datestr[12] - '0') * 100000000;
609     t_diff = (10 * (datestr[13] - '0') + (datestr[14] - '0')) * 900;
610     if (datestr[15] == '+')
611         *secs += t_diff;
612     else if (datestr[15] == '-')
613         *secs -= t_diff;
614     else                                /* Must be relative ('R')       */
615         relative = TRUE;
616     return relative;
617 }
618
619 /*!
620  * Scanning routines to add standard types (byte, int, string...) to the
621  * protocol tree.
622  *
623  * \param       tree    The protocol tree to add to
624  * \param       tvb     Buffer containing the data
625  * \param       field   Actual field whose value needs displaying
626  * \param       offset  Location of field in buffer, returns location of
627  *                      next field
628  */
629 static void
630 smpp_handle_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
631 {
632     char         strval[BUFSIZ];
633     gint         len;
634
635     len = tvb_get_nstringz(tvb, *offset, BUFSIZ, strval);
636     len++;
637     if (*strval)
638         proto_tree_add_string(tree, field, tvb, *offset, len, strval);
639     (*offset) += len;
640 }
641
642 static void
643 smpp_handle_int1(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
644 {
645     guint8       val;
646
647     val = tvb_get_guint8(tvb, *offset);
648     proto_tree_add_uint(tree, field, tvb, *offset, 1, val);
649     (*offset)++;
650 }
651
652 static void
653 smpp_handle_int2(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
654 {
655     guint        val;
656
657     val = tvb_get_ntohs(tvb, *offset);
658     proto_tree_add_uint(tree, field, tvb, *offset, 2, val);
659     (*offset) += 2;
660 }
661
662 static void
663 smpp_handle_int4(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
664 {
665     guint        val;
666
667     val = tvb_get_ntohl(tvb, *offset);
668     proto_tree_add_uint(tree, field, tvb, *offset, 4, val);
669     (*offset) += 4;
670 }
671
672 static void
673 smpp_handle_time(proto_tree *tree, tvbuff_t *tvb,
674                  int field, int field_R, int *offset)
675 {
676     char         strval[BUFSIZ];
677     gint         len;
678     nstime_t     tmptime;
679
680     len = tvb_get_nstringz(tvb, *offset, BUFSIZ, strval);
681     len++;
682     if (*strval)
683     {
684         if (smpp_mktime(strval, &tmptime.secs, &tmptime.nsecs))
685             proto_tree_add_time(tree, field_R, tvb, *offset, len, &tmptime);
686         else
687             proto_tree_add_time(tree, field, tvb, *offset, len, &tmptime);
688     }
689     *offset += len;
690 }
691
692 /*!
693  * Scanning routine to handle the destination-list of 'submit_multi'
694  *
695  * \param       tree    The protocol tree to add to
696  * \param       tvb     Buffer containing the data
697  * \param       offset  Location of field in buffer, returns location of
698  *                      next field
699  */
700 static void
701 smpp_handle_dlist(proto_tree *tree, tvbuff_t *tvb, int *offset)
702 {
703     guint8       entries;
704     int          tmpoff = *offset;
705     proto_item  *sub_tree = NULL;
706     guint8       dest_flag;
707
708     if ((entries = tvb_get_guint8(tvb, tmpoff++)))
709     {
710         sub_tree = proto_tree_add_item(tree, hf_smpp_dlist,
711                                         tvb, *offset, 1, FALSE);
712         proto_item_add_subtree(sub_tree, ett_dlist);
713     }
714     while (entries--)
715     {
716         dest_flag = tvb_get_guint8(tvb, tmpoff++);
717         if (dest_flag == 1)                     /* SME address  */
718         {
719             smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff);
720             smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff);
721             smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff);
722         }
723         else                                    /* Distribution list    */
724         {
725             smpp_handle_string(sub_tree, tvb, hf_smpp_dl_name, &tmpoff);
726         }
727     }
728     *offset = tmpoff;
729 }
730
731 /*!
732  * Scanning routine to handle the destination result list
733  * of 'submit_multi_resp'
734  *
735  * \param       tree    The protocol tree to add to
736  * \param       tvb     Buffer containing the data
737  * \param       offset  Location of field in buffer, returns location of
738  *                      next field
739  */
740 static void
741 smpp_handle_dlist_resp(proto_tree *tree, tvbuff_t *tvb, int *offset)
742 {
743     guint8       entries;
744     int          tmpoff = *offset;
745     proto_item  *sub_tree = NULL;
746
747     if ((entries = tvb_get_guint8(tvb, tmpoff++)))
748     {
749         sub_tree = proto_tree_add_item(tree, hf_smpp_dlist_resp,
750                                        tvb, *offset, 1, FALSE);
751         proto_item_add_subtree(sub_tree, ett_dlist_resp);
752     }
753     while (entries--)
754     {
755         smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff);
756         smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff);
757         smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff);
758         smpp_handle_int4(sub_tree, tvb, hf_smpp_error_status_code, &tmpoff);
759     }
760     *offset = tmpoff;
761 }
762
763 /*!
764  * Scanning routine to handle all optional parameters of SMPP-operations.
765  * The parameters have the format Tag Length Value (TLV), with a 2-byte tag
766  * and 2-byte length.
767  *
768  * \param       tree    The protocol tree to add to
769  * \param       tvb     Buffer containing the data
770  * \param       offset  Location of field in buffer, returns location of
771  *                      next field
772  */
773 static void
774 smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset)
775 {
776     proto_item  *sub_tree = NULL;
777     guint        tag;
778     guint        length;
779     guint8       field;
780     guint8       major, minor;
781     char         strval[BUFSIZ];
782
783     if (tvb_reported_length_remaining(tvb, *offset) >= 4)
784     {
785         sub_tree = proto_tree_add_item(tree, hf_smpp_opt_param,
786                                        tvb, *offset, 0, FALSE);
787         proto_item_add_subtree(sub_tree, ett_opt_param);
788     }
789
790     while (tvb_reported_length_remaining(tvb, *offset) >= 4)
791     {
792         tag = tvb_get_ntohs(tvb, *offset);
793         *offset += 2;
794         length = tvb_get_ntohs(tvb, *offset);
795         *offset += 2;
796         switch (tag) {
797             case  0x0005:       /* dest_addr_subunit    */
798                 smpp_handle_int1(sub_tree, tvb,
799                                  hf_smpp_dest_addr_subunit, offset);
800                 break;
801             case  0x0006:       /* dest_network_type    */
802                 smpp_handle_int1(sub_tree, tvb,
803                                  hf_smpp_dest_network_type, offset);
804                 break;
805             case  0x0007:       /* dest_bearer_type     */
806                 smpp_handle_int1(sub_tree, tvb,
807                                  hf_smpp_dest_bearer_type, offset);
808                 break;
809             case  0x0008:       /* dest_telematics_id   */
810                 smpp_handle_int2(sub_tree, tvb,
811                                  hf_smpp_dest_telematics_id, offset);
812                 break;
813             case  0x000D:       /* source_addr_subunit  */
814                 smpp_handle_int1(sub_tree, tvb,
815                                  hf_smpp_source_addr_subunit, offset);
816                 break;
817             case  0x000E:       /* source_network_type  */
818                 smpp_handle_int1(sub_tree, tvb,
819                                  hf_smpp_source_network_type, offset);
820                 break;
821             case  0x000F:       /* source_bearer_type   */
822                 smpp_handle_int1(sub_tree, tvb,
823                                  hf_smpp_source_bearer_type, offset);
824                 break;
825             case  0x0010:       /* source_telematics_id */
826                 smpp_handle_int2(sub_tree, tvb,
827                                  hf_smpp_source_telematics_id, offset);
828                 break;
829             case  0x0017:       /* qos_time_to_live     */
830                 smpp_handle_int4(sub_tree, tvb,
831                                  hf_smpp_qos_time_to_live, offset);
832                 break;
833             case  0x0019:       /* payload_type */
834                 smpp_handle_int1(sub_tree, tvb,
835                                  hf_smpp_payload_type, offset);
836                 break;
837             case  0x001D:       /* additional_status_info_text  */
838                 smpp_handle_string(sub_tree, tvb,
839                                    hf_smpp_additional_status_info_text, offset);
840                 break;
841             case  0x001E:       /* receipted_message_id */
842                 smpp_handle_string(sub_tree, tvb,
843                                    hf_smpp_receipted_message_id, offset);
844                 break;
845             case  0x0030:       /* ms_msg_wait_facilities       */
846                 field = tvb_get_guint8(tvb, *offset);
847                 proto_tree_add_item(sub_tree, hf_smpp_msg_wait_ind,
848                                     tvb, *offset, 1, field);
849                 proto_tree_add_item(sub_tree, hf_smpp_msg_wait_type,
850                                     tvb, *offset, 1, field);
851                 (*offset)++;
852                 break;
853             case  0x0201:       /* privacy_indicator    */
854                 smpp_handle_int1(sub_tree, tvb,
855                                  hf_smpp_privacy_indicator, offset);
856                 break;
857             case  0x0202:       /* source_subaddress    */
858                 smpp_handle_string(sub_tree, tvb,
859                                    hf_smpp_source_subaddress, offset);
860                 break;
861             case  0x0203:       /* dest_subaddress      */
862                 smpp_handle_string(sub_tree, tvb,
863                                    hf_smpp_dest_subaddress, offset);
864                 break;
865             case  0x0204:       /* user_message_reference       */
866                 smpp_handle_int2(sub_tree, tvb,
867                                  hf_smpp_user_message_reference, offset);
868                 break;
869             case  0x0205:       /* user_response_code   */
870                 smpp_handle_int1(sub_tree, tvb,
871                                  hf_smpp_user_response_code, offset);
872                 break;
873             case  0x020A:       /* source_port  */
874                 smpp_handle_int2(sub_tree, tvb,
875                                  hf_smpp_source_port, offset);
876                 break;
877             case  0x020B:       /* destination_port     */
878                 smpp_handle_int2(sub_tree, tvb,
879                                  hf_smpp_destination_port, offset);
880                 break;
881             case  0x020C:       /* sar_msg_ref_num      */
882                 smpp_handle_int2(sub_tree, tvb,
883                                  hf_smpp_sar_msg_ref_num, offset);
884                 break;
885             case  0x020D:       /* language_indicator   */
886                 smpp_handle_int1(sub_tree, tvb,
887                                  hf_smpp_language_indicator, offset);
888                 break;
889             case  0x020E:       /* sar_total_segments   */
890                 smpp_handle_int1(sub_tree, tvb,
891                                  hf_smpp_sar_total_segments, offset);
892                 break;
893             case  0x020F:       /* sar_segment_seqnum   */
894                 smpp_handle_int1(sub_tree, tvb,
895                                  hf_smpp_sar_segment_seqnum, offset);
896                 break;
897             case  0x0210:       /* SC_interface_version */
898                 field = tvb_get_guint8(tvb, *offset);
899                 minor = field & 0x0F;
900                 major = (field & 0xF0) >> 4;
901                 sprintf(strval, "%d.%d", major, minor);
902                 proto_tree_add_string(sub_tree, hf_smpp_SC_interface_version,
903                                       tvb, *offset, 1, strval);
904                 (*offset)++;
905                 break;
906             case  0x0302:       /* callback_num_pres_ind        */
907                 field = tvb_get_guint8(tvb, *offset);
908                 proto_tree_add_item(sub_tree, hf_smpp_callback_num_pres,
909                                     tvb, *offset, 1, field);
910                 proto_tree_add_item(sub_tree, hf_smpp_callback_num_scrn,
911                                     tvb, *offset, 1, field);
912                 (*offset)++;
913                 break;
914             case  0x0303:       /* callback_num_atag    */
915                 if (length)
916                     proto_tree_add_item(sub_tree, hf_smpp_callback_num_atag,
917                                         tvb, *offset, length, FALSE);
918                 (*offset) += length;
919                 break;
920             case  0x0304:       /* number_of_messages   */
921                 smpp_handle_int1(sub_tree, tvb,
922                                  hf_smpp_number_of_messages, offset);
923                 break;
924             case  0x0381:       /* callback_num */
925                 if (length)
926                     proto_tree_add_item(sub_tree, hf_smpp_callback_num,
927                                         tvb, *offset, length, FALSE);
928                 (*offset) += length;
929                 break;
930             case  0x0420:       /* dpf_result   */
931                 smpp_handle_int1(sub_tree, tvb,
932                                  hf_smpp_dpf_result, offset);
933                 break;
934             case  0x0421:       /* set_dpf      */
935                 smpp_handle_int1(sub_tree, tvb,
936                                  hf_smpp_set_dpf, offset);
937                 break;
938             case  0x0422:       /* ms_availability_status       */
939                 smpp_handle_int1(sub_tree, tvb,
940                                  hf_smpp_ms_availability_status, offset);
941                 break;
942             case  0x0423:       /* network_error_code   */
943                 smpp_handle_int1(sub_tree, tvb,
944                                  hf_smpp_network_error_type, offset);
945                 smpp_handle_int2(sub_tree, tvb,
946                                  hf_smpp_network_error_code, offset);
947                 (*offset) += length;
948                 break;
949             case  0x0424:       /* message_payload      */
950                 if (length)
951                     proto_tree_add_item(sub_tree, hf_smpp_message_payload,
952                                         tvb, *offset, length, FALSE);
953                 (*offset) += length;
954                 break;
955             case  0x0425:       /* delivery_failure_reason      */
956                 smpp_handle_int1(sub_tree, tvb,
957                                  hf_smpp_delivery_failure_reason, offset);
958                 break;
959             case  0x0426:       /* more_messages_to_send        */
960                 smpp_handle_int1(sub_tree, tvb,
961                                  hf_smpp_more_messages_to_send, offset);
962                 break;
963             case  0x0427:       /* message_state        */
964                 smpp_handle_int1(sub_tree, tvb,
965                                  hf_smpp_message_state, offset);
966                 break;
967             case  0x0501:       /* ussd_service_op      */
968                 smpp_handle_int1(sub_tree, tvb,
969                                  hf_smpp_ussd_service_op, offset);
970                 break;
971             case  0x1201:       /* display_time */
972                 smpp_handle_int1(sub_tree, tvb,
973                                  hf_smpp_display_time, offset);
974                 break;
975             case  0x1203:       /* sms_signal   */
976                 smpp_handle_int2(sub_tree, tvb,
977                                  hf_smpp_sms_signal, offset);
978                 /*! \todo Fill as per TIA/EIA-136-710-A         */
979                 break;
980             case  0x1204:       /* ms_validity  */
981                 smpp_handle_int1(sub_tree, tvb,
982                                  hf_smpp_ms_validity, offset);
983                 break;
984             case  0x130C:       /* alert_on_message_delivery    */
985                 proto_tree_add_item(sub_tree,
986                                     hf_smpp_alert_on_message_delivery,
987                                     tvb, *offset, length, FALSE);
988                 (*offset) += length;
989                 break;
990             case  0x1380:       /* its_reply_type       */
991                 smpp_handle_int1(sub_tree, tvb,
992                                  hf_smpp_its_reply_type, offset);
993                 break;
994             case  0x1383:       /* its_session_info     */
995                 smpp_handle_int1(sub_tree, tvb,
996                                  hf_smpp_its_session_number, offset);
997                 field = tvb_get_guint8(tvb, *offset);
998                 proto_tree_add_item(sub_tree, hf_smpp_its_session_sequence,
999                                     tvb, *offset, 1, field);
1000                 proto_tree_add_item(sub_tree, hf_smpp_its_session_ind,
1001                                     tvb, *offset, 1, field);
1002                 (*offset)++;
1003                 break;
1004             default:
1005                 if ((tag >= 0x1400) && (tag <= 0x3FFF))
1006                     proto_tree_add_item(sub_tree, hf_smpp_vendor_op, tvb,
1007                                         *offset, length, FALSE);
1008                 else
1009                     proto_tree_add_item(sub_tree, hf_smpp_reserved_op, tvb,
1010                                         *offset, length, FALSE);
1011                 (*offset) += length;
1012                 break;
1013         }
1014     }
1015 }
1016
1017 /*!
1018  * The next set of routines handle the different operations, associated
1019  * with SMPP.
1020  */
1021 static void
1022 bind_receiver(proto_tree *tree, tvbuff_t *tvb)
1023 {
1024     int          offset = 0;
1025     guint8       field;
1026     guint8       major, minor;
1027     char         strval[BUFSIZ];
1028
1029     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1030     smpp_handle_string(tree, tvb, hf_smpp_password, &offset);
1031     smpp_handle_string(tree, tvb, hf_smpp_system_type, &offset);
1032     field = tvb_get_guint8(tvb, offset++);
1033     minor = field & 0x0F;
1034     major = (field & 0xF0) >> 4;
1035     sprintf(strval, "%d.%d", major, minor);
1036     proto_tree_add_string(tree, hf_smpp_interface_version, tvb,
1037                           offset - 1, 1, strval);
1038     smpp_handle_int1(tree, tvb, hf_smpp_addr_ton, &offset);
1039     smpp_handle_int1(tree, tvb, hf_smpp_addr_npi, &offset);
1040     smpp_handle_string(tree, tvb, hf_smpp_address_range, &offset);
1041 }
1042
1043 #define bind_transmitter(a, b) bind_receiver(a, b)
1044
1045 static void
1046 query_sm(proto_tree *tree, tvbuff_t *tvb)
1047 {
1048     int          offset = 0;
1049
1050     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1051     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1052     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1053     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1054 }
1055
1056 #define bind_transceiver(a, b) bind_receiver(a, b)
1057
1058 static void
1059 outbind(proto_tree *tree, tvbuff_t *tvb)
1060 {
1061     int          offset = 0;
1062
1063     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1064     smpp_handle_string(tree, tvb, hf_smpp_password, &offset);
1065 }
1066
1067 static void
1068 submit_sm(proto_tree *tree, tvbuff_t *tvb)
1069 {
1070     int          offset = 0;
1071     guint8       flag;
1072     guint8       length;
1073
1074     smpp_handle_string(tree, tvb, hf_smpp_service_type, &offset);
1075     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1076     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1077     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1078     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1079     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1080     smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
1081     flag = tvb_get_guint8(tvb, offset);
1082     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1083                         tvb, offset, 1, flag);
1084     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1085                         tvb, offset, 1, flag);
1086     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1087                         tvb, offset, 1, flag);
1088     offset++;
1089     smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset);
1090     smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset);
1091     smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1092                                 hf_smpp_schedule_delivery_time_r, &offset);
1093     smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1094                                 hf_smpp_validity_period_r, &offset);
1095     flag = tvb_get_guint8(tvb, offset);
1096     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1097     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1098     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1099     offset++;
1100     smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset);
1101     smpp_handle_int1(tree, tvb, hf_smpp_data_coding, &offset);
1102     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1103     length = tvb_get_guint8(tvb, offset);
1104     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1105     if (length)
1106         proto_tree_add_item(tree, hf_smpp_short_message,
1107                             tvb, offset, length, FALSE);
1108     offset += length;
1109     smpp_handle_tlv(tree, tvb, &offset);
1110 }
1111
1112 #define deliver_sm(a, b) submit_sm(a, b)
1113
1114 static void
1115 replace_sm(proto_tree *tree, tvbuff_t *tvb)
1116 {
1117     int          offset = 0;
1118     guint8       flag;
1119     guint8       length;
1120
1121     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1122     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1123     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1124     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1125     smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1126                                 hf_smpp_schedule_delivery_time_r, &offset);
1127     smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1128                                 hf_smpp_validity_period_r, &offset);
1129     flag = tvb_get_guint8(tvb, offset);
1130     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1131     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1132     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1133     offset++;
1134     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1135     length = tvb_get_guint8(tvb, offset);
1136     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1137     if (length)
1138         proto_tree_add_item(tree, hf_smpp_short_message,
1139                             tvb, offset, length, FALSE);
1140     offset += length;
1141 }
1142
1143 static void
1144 cancel_sm(proto_tree *tree, tvbuff_t *tvb)
1145 {
1146     int          offset = 0;
1147
1148     smpp_handle_string(tree, tvb, hf_smpp_service_type, &offset);
1149     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1150     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1151     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1152     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1153     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1154     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1155     smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
1156 }
1157
1158 static void
1159 submit_multi(proto_tree *tree, tvbuff_t *tvb)
1160 {
1161     int          offset = 0;
1162     guint8       flag;
1163     guint8       length;
1164
1165     smpp_handle_string(tree, tvb, hf_smpp_service_type, &offset);
1166     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1167     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1168     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1169
1170     smpp_handle_dlist(tree, tvb, &offset);
1171
1172     flag = tvb_get_guint8(tvb, offset);
1173     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1174                         tvb, offset, 1, flag);
1175     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1176                         tvb, offset, 1, flag);
1177     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1178                         tvb, offset, 1, flag);
1179     offset++;
1180     smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset);
1181     smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset);
1182     smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1183                                 hf_smpp_schedule_delivery_time_r, &offset);
1184     smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1185                                 hf_smpp_validity_period_r, &offset);
1186     flag = tvb_get_guint8(tvb, offset);
1187     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1188     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1189     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1190     offset++;
1191     smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset);
1192     smpp_handle_int1(tree, tvb, hf_smpp_data_coding, &offset);
1193     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1194     length = tvb_get_guint8(tvb, offset);
1195     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1196     if (length)
1197         proto_tree_add_item(tree, hf_smpp_short_message,
1198                             tvb, offset, length, FALSE);
1199     offset += length;
1200     smpp_handle_tlv(tree, tvb, &offset);
1201 }
1202
1203 static void
1204 alert_notification(proto_tree *tree, tvbuff_t *tvb)
1205 {
1206     int          offset = 0;
1207
1208     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1209     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1210     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1211     smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_ton, &offset);
1212     smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_npi, &offset);
1213     smpp_handle_string(tree, tvb, hf_smpp_esme_addr, &offset);
1214     smpp_handle_tlv(tree, tvb, &offset);
1215 }
1216
1217 static void
1218 data_sm(proto_tree *tree, tvbuff_t *tvb)
1219 {
1220     int          offset = 0;
1221     guint8       flag;
1222
1223     smpp_handle_string(tree, tvb, hf_smpp_service_type, &offset);
1224     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1225     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1226     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1227     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1228     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1229     smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
1230     flag = tvb_get_guint8(tvb, offset);
1231     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1232                         tvb, offset, 1, flag);
1233     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1234                         tvb, offset, 1, flag);
1235     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1236                         tvb, offset, 1, flag);
1237     offset++;
1238     flag = tvb_get_guint8(tvb, offset);
1239     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1240     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1241     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1242     offset++;
1243     smpp_handle_int1(tree, tvb, hf_smpp_data_coding, &offset);
1244     smpp_handle_tlv(tree, tvb, &offset);
1245 }
1246
1247 /*!
1248  * The next set of routines handle the different operation-responses,
1249  * associated with SMPP.
1250  */
1251 static void
1252 bind_receiver_resp(proto_tree *tree, tvbuff_t *tvb)
1253 {
1254     int          offset = 0;
1255
1256     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1257     smpp_handle_tlv(tree, tvb, &offset);
1258 }
1259
1260 #define bind_transmitter_resp(a, b) bind_receiver_resp(a, b)
1261
1262 static void
1263 query_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1264 {
1265     int          offset = 0;
1266
1267     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1268     smpp_handle_time(tree, tvb, hf_smpp_final_date,
1269                                 hf_smpp_final_date_r, &offset);
1270     smpp_handle_int1(tree, tvb, hf_smpp_message_state, &offset);
1271     smpp_handle_int1(tree, tvb, hf_smpp_error_code, &offset);
1272 }
1273
1274 #define bind_transceiver_resp(a, b) bind_receiver_resp(a, b)
1275
1276 static void
1277 submit_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1278 {
1279     int          offset = 0;
1280
1281     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1282 }
1283
1284 #define deliver_sm_resp(a, b) submit_sm_resp(a, b)
1285
1286 static void
1287 submit_multi_resp(proto_tree *tree, tvbuff_t *tvb)
1288 {
1289     int          offset = 0;
1290
1291     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1292     smpp_handle_dlist_resp(tree, tvb, &offset);
1293 }
1294
1295 static void
1296 data_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1297 {
1298     int          offset = 0;
1299
1300     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1301     smpp_handle_tlv(tree, tvb, &offset);
1302 }
1303
1304 /*
1305  * A 'heuristic dissector' that attemtps to establish whether we have
1306  * a genuine SMPP PDU here.
1307  * Only works when:
1308  *      at least the fixed header is there
1309  *      it is a 'well-known' operation
1310  *      has a 'well-known' status
1311  */
1312 static gboolean
1313 dissect_smpp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1314 {
1315     guint        command_id;            /* SMPP command         */
1316     guint        command_status;        /* Status code          */
1317
1318     if (tvb_reported_length(tvb) < 4 * 4)       /* Mandatory header     */
1319         return FALSE;
1320     command_id = tvb_get_ntohl(tvb, 4);         /* Only known commands  */
1321     if (match_strval(command_id, vals_command_id) == NULL)
1322         return FALSE;
1323     command_status = tvb_get_ntohl(tvb, 8);     /* ..with known status  */
1324     if (match_strval(command_status, vals_command_status) == NULL)
1325         return FALSE;
1326     dissect_smpp(tvb, pinfo, tree);
1327     return TRUE;
1328 }
1329
1330 /* Code to actually dissect the packets */
1331 static void
1332 dissect_smpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1333 {
1334     int          offset = 0;            /* Offset within tvbuff */
1335     guint        command_length;        /* length of PDU        */
1336     guint        command_id;            /* SMPP command         */
1337     guint        command_status;        /* Status code          */
1338     guint        sequence_number;       /* ...of command        */
1339
1340     /* Set up structures needed to add the protocol subtree and manage it */
1341     proto_item  *ti;
1342     proto_tree  *smpp_tree;
1343     tvbuff_t    *tmp_tvb;
1344
1345     /*
1346      * Safety: don't even try it when the mandatory header isn't present.
1347      */
1348     if (tvb_reported_length(tvb) < 4 * 4)
1349         return;
1350     command_length = tvb_get_ntohl(tvb, offset);
1351     offset += 4;
1352     command_id = tvb_get_ntohl(tvb, offset);
1353     offset += 4;
1354     command_status = tvb_get_ntohl(tvb, offset);
1355     offset +=4;
1356     sequence_number = tvb_get_ntohl(tvb, offset);
1357     offset += 4;
1358     /* Make entries in Protocol column and Info column on summary display */
1359     if (check_col(pinfo->cinfo, COL_PROTOCOL))
1360         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMPP");
1361
1362     if (check_col(pinfo->cinfo, COL_INFO))
1363     {
1364         col_clear(pinfo->cinfo, COL_INFO);
1365         col_add_fstr(pinfo->cinfo, COL_INFO, "SMPP %s",
1366                  val_to_str(command_id,vals_command_id,"unknown operation"));
1367         if (command_id & 0x80000000)
1368             col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"",
1369                             val_to_str(command_status, vals_command_status,
1370                                        "reserved error"));
1371         if (command_length > tvb_reported_length(tvb))
1372             col_append_str(pinfo->cinfo, COL_INFO, " [short packet]");
1373         if (command_length < tvb_reported_length(tvb))
1374             col_append_str(pinfo->cinfo, COL_INFO, " [trailing data]");
1375     }
1376
1377     /* In the interest of speed, if "tree" is NULL, don't do any work not
1378      * necessary to generate protocol tree items.
1379      */
1380     if (tree) {
1381
1382         /* create display subtree for the protocol      */
1383         ti = proto_tree_add_item(tree, proto_smpp, tvb, 0,
1384                                  command_length, FALSE);
1385         smpp_tree = proto_item_add_subtree(ti, ett_smpp);
1386
1387         /* add an item to the subtree                   */
1388         proto_tree_add_uint(smpp_tree, hf_smpp_command_length, tvb,
1389                             0, 4, command_length);
1390         proto_tree_add_uint(smpp_tree, hf_smpp_command_id, tvb,
1391                             4, 4, command_id);
1392         /* Status is only meaningful with responses     */
1393         if (command_id & 0x80000000)
1394             proto_tree_add_uint(smpp_tree, hf_smpp_command_status, tvb,
1395                                 8, 4, command_status);
1396         proto_tree_add_uint(smpp_tree, hf_smpp_sequence_number, tvb,
1397                             12, 4, sequence_number);
1398         /*
1399          * End of header. Don't dissect variable part if it is shortened.
1400          */
1401         if (command_length > tvb_reported_length(tvb))
1402             return;
1403         tmp_tvb = tvb_new_subset(tvb, offset, -1, command_length - offset);
1404         if (command_id & 0x80000000)
1405         {
1406             switch (command_id & 0x7FFFFFFF) {
1407                 /*
1408                  * All of these only have a fixed header
1409                  */
1410                 case 0:                         /* Generic nack */
1411                 case 6:                         /* Unbind resp  */
1412                 case 7:                         /* Replace SM resp      */
1413                 case 8:                         /* Cancel SM resp       */
1414                 case 21:                        /* Enquire link resp    */
1415                     break;
1416                 case 1:
1417                     if (!command_status)
1418                         bind_receiver_resp(smpp_tree, tmp_tvb);
1419                     break;
1420                 case 2:
1421                     if (!command_status)
1422                         bind_transmitter_resp(smpp_tree, tmp_tvb);
1423                     break;
1424                 case 3:
1425                     if (!command_status)
1426                         query_sm_resp(smpp_tree, tmp_tvb);
1427                     break;
1428                 case 4:
1429                     if (!command_status)
1430                         submit_sm_resp(smpp_tree, tmp_tvb);
1431                     break;
1432                 case 5:
1433                     if (!command_status)
1434                         deliver_sm_resp(smpp_tree, tmp_tvb);
1435                     break;
1436                 case 9:
1437                     if (!command_status)
1438                         bind_transceiver_resp(smpp_tree, tmp_tvb);
1439                     break;
1440                 case 33:
1441                     if (!command_status)
1442                         submit_multi_resp(smpp_tree, tmp_tvb);
1443                     break;
1444                 case 259:
1445                     if (!command_status)
1446                         data_sm_resp(smpp_tree, tmp_tvb);
1447                     break;
1448                 default:
1449                     break;
1450             }
1451         }
1452         else
1453         {
1454             switch (command_id) {
1455                 case  1:
1456                     bind_receiver(smpp_tree, tmp_tvb);
1457                     break;
1458                 case  2:
1459                     bind_transmitter(smpp_tree, tmp_tvb);
1460                     break;
1461                 case  3:
1462                     query_sm(smpp_tree, tmp_tvb);
1463                     break;
1464                 case  4:
1465                     submit_sm(smpp_tree, tmp_tvb);
1466                     break;
1467                 case  5:
1468                     deliver_sm(smpp_tree, tmp_tvb);
1469                     break;
1470                 case  6:                        /* Unbind       */
1471                 case 21:                        /* Enquire link */
1472                     break;
1473                 case  7:
1474                     replace_sm(smpp_tree, tmp_tvb);
1475                     break;
1476                 case  8:
1477                     cancel_sm(smpp_tree, tmp_tvb);
1478                     break;
1479                 case  9:
1480                     bind_transceiver(smpp_tree, tmp_tvb);
1481                     break;
1482                 case  11:
1483                     outbind(smpp_tree, tmp_tvb);
1484                     break;
1485                 case  33:
1486                     submit_multi(smpp_tree, tmp_tvb);
1487                     break;
1488                 case  258:
1489                     alert_notification(smpp_tree, tmp_tvb);
1490                     break;
1491                 case  259:
1492                     data_sm(smpp_tree, tmp_tvb);
1493                     break;
1494                 default:
1495                     break;
1496             }
1497         }
1498     }
1499     /* If this protocol has a sub-dissector call it here.       */
1500     return;
1501 }
1502
1503 /* Register the protocol with Ethereal */
1504 void
1505 proto_register_smpp(void)
1506 {
1507
1508     /* Setup list of header fields      */
1509     static hf_register_info hf[] = {
1510         {   &hf_smpp_command_length,
1511             {   "Length    ", "smpp.command_length",
1512                 FT_UINT32, BASE_DEC, NULL, 0x00,
1513                 "Total length of the SMPP PDU.",
1514                 HFILL
1515             }
1516         },
1517         {   &hf_smpp_command_id,
1518             {   "Operation ", "smpp.command_id",
1519                 FT_UINT32, BASE_HEX, VALS(vals_command_id), 0x00,
1520                 "Defines the SMPP PDU.",
1521                 HFILL
1522             }
1523         },
1524         {   &hf_smpp_command_status,
1525             {   "Result    ", "smpp.command_status",
1526                 FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00,
1527                 "Indicates success or failure of the SMPP request.",
1528                 HFILL
1529             }
1530         },
1531         {   &hf_smpp_sequence_number,
1532             {   "Sequence #", "smpp.sequence_number",
1533                 FT_UINT32, BASE_DEC, NULL, 0x00,
1534                 "A number to correlate requests with responses.",
1535                 HFILL
1536             }
1537         },
1538         {   &hf_smpp_system_id,
1539             {   "System ID", "smpp.system_id",
1540                 FT_STRING, BASE_NONE, NULL, 0x00,
1541                 "Identifies a system.",
1542                 HFILL
1543             }
1544         },
1545         {   &hf_smpp_password,
1546             {   "Password", "smpp.password",
1547                 FT_STRING, BASE_NONE, NULL, 0x00,
1548                 "Password used for authentication.",
1549                 HFILL
1550             }
1551         },
1552         {   &hf_smpp_system_type,
1553             {   "System type", "smpp.system_type",
1554                 FT_STRING, BASE_NONE, NULL, 0x00,
1555                 "Categorises the system.",
1556                 HFILL
1557             }
1558         },
1559         {   &hf_smpp_interface_version,
1560             {   "Version (if)", "smpp.interface_version",
1561                 FT_STRING, BASE_NONE, NULL, 0x00,
1562                 "Version of SMPP interface supported.",
1563                 HFILL
1564             }
1565         },
1566         {   &hf_smpp_service_type,
1567             {   "Service type", "smpp.service_type",
1568                 FT_STRING, BASE_NONE, NULL, 0x00,
1569                 "SMS application service associated with the message.",
1570                 HFILL
1571             }
1572         },
1573         {   &hf_smpp_addr_ton,
1574             {   "Type of number", "smpp.addr_ton",
1575                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
1576                 "Indicates the type of number, given in the address.",
1577                 HFILL
1578             }
1579         },
1580         {   &hf_smpp_source_addr_ton,
1581             {   "Type of number (originator)", "smpp.source_addr_ton",
1582                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
1583                 "Indicates originator type of number, given in the address.",
1584                 HFILL
1585             }
1586         },
1587         {   &hf_smpp_dest_addr_ton,
1588             {   "Type of number (recipient)", "smpp.dest_addr_ton",
1589                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
1590                 "Indicates recipient type of number, given in the address.",
1591                 HFILL
1592             }
1593         },
1594         {   &hf_smpp_addr_npi,
1595             {   "Numbering plan indicator", "smpp.addr_npi",
1596                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
1597                 "Gives the numbering plan this address belongs to.",
1598                 HFILL
1599             }
1600         },
1601         {   &hf_smpp_source_addr_npi,
1602             {   "Numbering plan indicator (originator)", "smpp.source_addr_npi",
1603                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
1604                 "Gives originator numbering plan this address belongs to.",
1605                 HFILL
1606             }
1607         },
1608         {   &hf_smpp_dest_addr_npi,
1609             {   "Numbering plan indicator (recipient)", "smpp.dest_addr_npi",
1610                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
1611                 "Gives recipient numbering plan this address belongs to.",
1612                 HFILL
1613             }
1614         },
1615         {   &hf_smpp_address_range,
1616             {   "Address", "smpp.address_range",
1617                 FT_STRING, BASE_NONE, NULL, 0x00,
1618                 "Given address or address range.",
1619                 HFILL
1620             }
1621         },
1622         {   &hf_smpp_source_addr,
1623             {   "Originator address", "smpp.source_addr",
1624                 FT_STRING, BASE_NONE, NULL, 0x00,
1625                 "Address of SME originating this message.",
1626                 HFILL
1627             }
1628         },
1629         {   &hf_smpp_destination_addr,
1630             {   "Recipient address", "smpp.destination_addr",
1631                 FT_STRING, BASE_NONE, NULL, 0x00,
1632                 "Address of SME receiving this message.",
1633                 HFILL
1634             }
1635         },
1636         {   &hf_smpp_esm_submit_msg_mode,
1637             {   "Messaging mode", "smpp.esm.submit.msg_mode",
1638                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_msg_mode), 0x03,
1639                 "Mode attribute for this message.",
1640                 HFILL
1641             }
1642         },
1643         {   &hf_smpp_esm_submit_msg_type,
1644             {   "Message type  ", "smpp.esm.submit.msg_type",
1645                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_msg_type), 0x3C,
1646                 "Type attribute for this message.",
1647                 HFILL
1648             }
1649         },
1650         {   &hf_smpp_esm_submit_features,
1651             {   "GSM features  ", "smpp.esm.submit.features",
1652                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_features), 0xC0,
1653                 "GSM network specific features.",
1654                 HFILL
1655             }
1656         },
1657         /*! \todo Get proper values from GSM-spec.      */
1658         {   &hf_smpp_protocol_id,
1659             {   "Protocol id.", "smpp.protocol_id",
1660                 FT_UINT8, BASE_HEX, NULL, 0x00,
1661                 "Protocol identifier according GSM 03.40.",
1662                 HFILL
1663             }
1664         },
1665         {   &hf_smpp_priority_flag,
1666             {   "Priority level", "smpp.priority_flag",
1667                 FT_UINT8, BASE_HEX, VALS(vals_priority_flag), 0x00,
1668                 "The priority level of the short message.",
1669                 HFILL
1670             }
1671         },
1672         {   &hf_smpp_schedule_delivery_time,
1673             {   "Scheduled delivery time", "smpp.schedule_delivery_time",
1674                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
1675                 "Scheduled time for delivery of short message.",
1676                 HFILL
1677             }
1678         },
1679         {   &hf_smpp_schedule_delivery_time_r,
1680             {   "Scheduled delivery time", "smpp.schedule_delivery_time_r",
1681                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1682                 "Scheduled time for delivery of short message.",
1683                 HFILL
1684             }
1685         },
1686         {   &hf_smpp_validity_period,
1687             {   "Validity period", "smpp.validity_period",
1688                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
1689                 "Validity period of this message.",
1690                 HFILL
1691             }
1692         },
1693         {   &hf_smpp_validity_period_r,
1694             {   "Validity period", "smpp.validity_period_r",
1695                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1696                 "Validity period of this message.",
1697                 HFILL
1698             }
1699         },
1700         {   &hf_smpp_regdel_receipt,
1701             {   "Delivery receipt  ", "smpp.regdel.receipt",
1702                 FT_UINT8, BASE_HEX, VALS(vals_regdel_receipt), 0x03,
1703                 "SMSC delivery receipt request.",
1704                 HFILL
1705             }
1706         },
1707         {   &hf_smpp_regdel_acks,
1708             {   "Message type      ", "smpp.regdel.acks",
1709                 FT_UINT8, BASE_HEX, VALS(vals_regdel_acks), 0x0C,
1710                 "SME acknowledgement request.",
1711                 HFILL
1712             }
1713         },
1714         {   &hf_smpp_regdel_notif,
1715             {   "Intermediate notif", "smpp.regdel.notif",
1716                 FT_UINT8, BASE_HEX, VALS(vals_regdel_notif), 0x10,
1717                 "Intermediate notification request.",
1718                 HFILL
1719             }
1720         },
1721         {   &hf_smpp_replace_if_present_flag,
1722             {   "Replace           ", "smpp.replace_if_present_flag",
1723                 FT_UINT8, BASE_HEX, VALS(vals_replace_if_present_flag), 0x01,
1724                 "Replace the short message with this one or not.",
1725                 HFILL
1726             }
1727         },
1728         {   &hf_smpp_data_coding,
1729             {   "Data coding", "smpp.data_coding",
1730                 FT_UINT8, BASE_HEX, VALS(vals_data_coding), 0x00,
1731                 "Defines the encoding scheme of the message.",
1732                 HFILL
1733             }
1734         },
1735         {   &hf_smpp_sm_default_msg_id,
1736             {   "Predefined message", "smpp.sm_default_msg_id",
1737                 FT_UINT8, BASE_DEC, NULL, 0x00,
1738                 "Index of a predefined ('canned') short message.",
1739                 HFILL
1740             }
1741         },
1742         {   &hf_smpp_sm_length,
1743             {   "Message length", "smpp.sm_length",
1744                 FT_UINT8, BASE_DEC, NULL, 0x00,
1745                 "Length of the message content.",
1746                 HFILL
1747             }
1748         },
1749         {   &hf_smpp_short_message,
1750             {   "Message", "smpp.message",
1751                 FT_NONE, BASE_NONE, NULL, 0x00,
1752                 "The actual message or data.",
1753                 HFILL
1754             }
1755         },
1756         {   &hf_smpp_message_id,
1757             {   "Message id.", "smpp.message_id",
1758                 FT_STRING, BASE_NONE, NULL, 0x00,
1759                 "Identifier of the submitted short message.",
1760                 HFILL
1761             }
1762         },
1763         {   &hf_smpp_dlist,
1764             {   "Destination list", "smpp.dlist",
1765                 FT_NONE, BASE_NONE, NULL, 0x00,
1766                 "The list of destinations for a short message.",
1767                 HFILL
1768             }
1769         },
1770         {   &hf_smpp_dlist_resp,
1771             {   "Unsuccesfull delivery list", "smpp.dlist_resp",
1772                 FT_NONE, BASE_NONE, NULL, 0x00,
1773                 "The list of unsuccesfull deliveries to destinations.",
1774                 HFILL
1775             }
1776         },
1777         {   &hf_smpp_dl_name,
1778             {   "Distr. list name", "smpp.dl_name",
1779                 FT_STRING, BASE_NONE, NULL, 0x00,
1780                 "The name of the distribution list.",
1781                 HFILL
1782             }
1783         },
1784         {   &hf_smpp_final_date,
1785             {   "Final date", "smpp.final_date",
1786                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
1787                 "Date-time when the queried message reached a final state.",
1788                 HFILL
1789             }
1790         },
1791         {   &hf_smpp_final_date_r,
1792             {   "Final date", "smpp.final_date_r",
1793                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1794                 "Date-time when the queried message reached a final state.",
1795                 HFILL
1796             }
1797         },
1798         {   &hf_smpp_message_state,
1799             {   "Message state", "smpp.message_state",
1800                 FT_UINT8, BASE_DEC, VALS(vals_message_state), 0x00,
1801                 "Specifies the status of the queried short message.",
1802                 HFILL
1803             }
1804         },
1805         {   &hf_smpp_error_code,
1806             {   "Error code", "smpp.error_code",
1807                 FT_UINT8, BASE_DEC, NULL, 0x00,
1808                 "Network specific error code defining reason for failure.",
1809                 HFILL
1810             }
1811         },
1812         {   &hf_smpp_error_status_code,
1813             {   "Status", "smpp.error_status_code",
1814                 FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00,
1815                 "Indicates success/failure of request for this address.",
1816                 HFILL
1817             }
1818         },
1819         {   &hf_smpp_esme_addr_ton,
1820             {   "Type of number (ESME)", "smpp.esme_addr_ton",
1821                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
1822                 "Indicates recipient type of number, given in the address.",
1823                 HFILL
1824             }
1825         },
1826         {   &hf_smpp_esme_addr_npi,
1827             {   "Numbering plan indicator (ESME)", "smpp.esme_addr_npi",
1828                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
1829                 "Gives the numbering plan this address belongs to.",
1830                 HFILL
1831             }
1832         },
1833         {   &hf_smpp_esme_addr,
1834             {   "ESME address", "smpp.esme_addr",
1835                 FT_STRING, BASE_NONE, NULL, 0x00,
1836                 "Address of ESME originating this message.",
1837                 HFILL
1838             }
1839         },
1840         {   &hf_smpp_dest_addr_subunit,
1841             {   "Subunit destination", "smpp.dest_addr_subunit",
1842                 FT_UINT8, BASE_HEX, VALS(vals_addr_subunit), 0x00,
1843                 "Subunit address within mobile to route message to.",
1844                 HFILL
1845             }
1846         },
1847         {   &hf_smpp_source_addr_subunit,
1848             {   "Subunit origin", "smpp.source_addr_subunit",
1849                 FT_UINT8, BASE_HEX, VALS(vals_addr_subunit), 0x00,
1850                 "Subunit address within mobile that generated the message.",
1851                 HFILL
1852             }
1853         },
1854         {   &hf_smpp_dest_network_type,
1855             {   "Destination network", "smpp.dest_network_type",
1856                 FT_UINT8, BASE_HEX, VALS(vals_network_type), 0x00,
1857                 "Network associated with the destination address.",
1858                 HFILL
1859             }
1860         },
1861         {   &hf_smpp_source_network_type,
1862             {   "Originator network", "smpp.source_network_type",
1863                 FT_UINT8, BASE_HEX, VALS(vals_network_type), 0x00,
1864                 "Network associated with the originator address.",
1865                 HFILL
1866             }
1867         },
1868         {   &hf_smpp_dest_bearer_type,
1869             {   "Destination bearer", "smpp.dest_bearer_type",
1870                 FT_UINT8, BASE_HEX, VALS(vals_bearer_type), 0x00,
1871                 "Desired bearer for delivery of message.",
1872                 HFILL
1873             }
1874         },
1875         {   &hf_smpp_source_bearer_type,
1876             {   "Originator bearer", "smpp.source_bearer_type",
1877                 FT_UINT8, BASE_HEX, VALS(vals_bearer_type), 0x00,
1878                 "Bearer over which the message originated.",
1879                 HFILL
1880             }
1881         },
1882         {   &hf_smpp_dest_telematics_id,
1883             {   "Telematic interworking (dest)", "smpp.dest_telematics_id",
1884                 FT_UINT16, BASE_HEX, NULL, 0x00,
1885                 "Telematic interworking to be used for message delivery.",
1886                 HFILL
1887             }
1888         },
1889         {   &hf_smpp_source_telematics_id,
1890             {   "Telematic interworking (orig)", "smpp.source_telematics_id",
1891                 FT_UINT16, BASE_HEX, NULL, 0x00,
1892                 "Telematic interworking used for message submission.",
1893                 HFILL
1894             }
1895         },
1896         {   &hf_smpp_qos_time_to_live,
1897             {   "Validity period", "smpp.qos_time_to_live",
1898                 FT_UINT32, BASE_DEC, NULL, 0x00,
1899                 "Number of seconds to retain message before expiry.",
1900                 HFILL
1901             }
1902         },
1903         {   &hf_smpp_payload_type,
1904             {   "Payload", "smpp.payload_type",
1905                 FT_UINT8, BASE_DEC, VALS(vals_payload_type), 0x00,
1906                 "PDU type contained in the message payload.",
1907                 HFILL
1908             }
1909         },
1910         {   &hf_smpp_additional_status_info_text,
1911             {   "Information", "smpp.additional_status_info_text",
1912                 FT_STRING, BASE_NONE, NULL, 0x00,
1913                 "Description of the meaning of a response PDU.",
1914                 HFILL
1915             }
1916         },
1917         {   &hf_smpp_receipted_message_id,
1918             {   "SMSC identifier", "smpp.receipted_message_id",
1919                 FT_STRING, BASE_NONE, NULL, 0x00,
1920                 "SMSC handle of the message being received.",
1921                 HFILL
1922             }
1923         },
1924         {   &hf_smpp_privacy_indicator,
1925             {   "Privacy indicator", "smpp.privacy_indicator",
1926                 FT_UINT8, BASE_DEC, VALS(vals_privacy_indicator), 0x00,
1927                 "Indicates the privacy level of the message.",
1928                 HFILL
1929             }
1930         },
1931         {   &hf_smpp_user_message_reference,
1932             {   "Message reference", "smpp.user_message_reference",
1933                 FT_UINT16, BASE_HEX, NULL, 0x00,
1934                 "Reference to the message, assigned by the user.",
1935                 HFILL
1936             }
1937         },
1938         {   &hf_smpp_user_response_code,
1939             {   "Application response code", "smpp.user_response_code",
1940                 FT_UINT8, BASE_HEX, NULL, 0x00,
1941                 "A response code set by the user.",
1942                 HFILL
1943             }
1944         },
1945         {   &hf_smpp_language_indicator,
1946             {   "Language", "smpp.language_indicator",
1947                 FT_UINT8, BASE_DEC, VALS(vals_language_indicator), 0x00,
1948                 "Indicates the language of the short message.",
1949                 HFILL
1950             }
1951         },
1952         {   &hf_smpp_source_port,
1953             {   "Source port", "smpp.source_port",
1954                 FT_UINT16, BASE_HEX, NULL, 0x00,
1955                 "Application port associated with the source of the message.",
1956                 HFILL
1957             }
1958         },
1959         {   &hf_smpp_destination_port,
1960             {   "Destination port", "smpp.destination_port",
1961                 FT_UINT16, BASE_HEX, NULL, 0x00,
1962                 "Application port associated with the destination of the message.",
1963                 HFILL
1964             }
1965         },
1966         {   &hf_smpp_sar_msg_ref_num,
1967             {   "SAR reference number", "smpp.sar_msg_ref_num",
1968                 FT_UINT16, BASE_DEC, NULL, 0x00,
1969                 "Reference number for a concatenated short message.",
1970                 HFILL
1971             }
1972         },
1973         {   &hf_smpp_sar_total_segments,
1974             {   "SAR size", "smpp.sar_total_segments",
1975                 FT_UINT16, BASE_DEC, NULL, 0x00,
1976                 "Number of segments of a concatenated short message.",
1977                 HFILL
1978             }
1979         },
1980         {   &hf_smpp_sar_segment_seqnum,
1981             {   "SAR sequence number", "smpp.sar_segment_seqnum",
1982                 FT_UINT8, BASE_DEC, NULL, 0x00,
1983                 "Segment number within a concatenated short message.",
1984                 HFILL
1985             }
1986         },
1987         {   &hf_smpp_display_time,
1988             {   "Display time", "smpp.display_time",
1989                 FT_UINT8, BASE_DEC, VALS(vals_display_time), 0x00,
1990                 "Associates a display time with the message on the handset.",
1991                 HFILL
1992             }
1993         },
1994         {   &hf_smpp_ms_validity,
1995             {   "Validity info", "smpp.ms_validity",
1996                 FT_UINT8, BASE_DEC, VALS(vals_ms_validity), 0x00,
1997                 "Associates validity info with the message on the handset.",
1998                 HFILL
1999             }
2000         },
2001         {   &hf_smpp_dpf_result,
2002             {   "Delivery pending set?", "smpp.dpf_result",
2003                 FT_UINT8, BASE_DEC, VALS(vals_dpf_result), 0x00,
2004                 "Indicates whether Delivery Pending Flag was set.",
2005                 HFILL
2006             }
2007         },
2008         {   &hf_smpp_set_dpf,
2009             {   "Request DPF set", "smpp.set_dpf",
2010                 FT_UINT8, BASE_DEC, VALS(vals_set_dpf), 0x00,
2011                 "Request to set the DPF for certain failure scenario's.",
2012                 HFILL
2013             }
2014         },
2015         {   &hf_smpp_ms_availability_status,
2016             {   "Availability status", "smpp.ms_availability_status",
2017                 FT_UINT8, BASE_DEC, VALS(vals_ms_availability_status), 0x00,
2018                 "Indicates the availability state of the handset.",
2019                 HFILL
2020             }
2021         },
2022         {   &hf_smpp_delivery_failure_reason,
2023             {   "Delivery failure reason", "smpp.delivery_failure_reason",
2024                 FT_UINT8, BASE_DEC, VALS(vals_delivery_failure_reason), 0x00,
2025                 "Indicates the reason for a failed delivery attempt.",
2026                 HFILL
2027             }
2028         },
2029         {   &hf_smpp_more_messages_to_send,
2030             {   "More messages?", "smpp.more_messages_to_send",
2031                 FT_UINT8, BASE_DEC, VALS(vals_more_messages_to_send), 0x00,
2032                 "Indicates more messages pending for the same destination.",
2033                 HFILL
2034             }
2035         },
2036         {   &hf_smpp_number_of_messages,
2037             {   "Number of messages", "smpp.number_of_messages",
2038                 FT_UINT8, BASE_DEC, NULL, 0x00,
2039                 "Indicates number of messages stored in a mailbox.",
2040                 HFILL
2041             }
2042         },
2043         {   &hf_smpp_its_reply_type,
2044             {   "Reply method", "smpp.its_reply_type",
2045                 FT_UINT8, BASE_DEC, VALS(vals_its_reply_type), 0x00,
2046                 "Indicates the handset reply method on message receipt.",
2047                 HFILL
2048             }
2049         },
2050         {   &hf_smpp_ussd_service_op,
2051             {   "USSD service operation", "smpp.ussd_service_op",
2052                 FT_UINT8, BASE_DEC, VALS(vals_ussd_service_op), 0x00,
2053                 "Indicates the USSD service operation.",
2054                 HFILL
2055             }
2056         },
2057         {   &hf_smpp_vendor_op,
2058             {   "Optional parameter - Vendor-specific", "smpp.vendor_op",
2059                 FT_NONE, BASE_NONE, NULL, 0x00,
2060                 "A supplied optional parameter specific to an SMSC-vendor.",
2061                 HFILL
2062             }
2063         },
2064         {   &hf_smpp_reserved_op,
2065             {   "Optional parameter - Reserved", "smpp.reserved_op",
2066                 FT_NONE, BASE_NONE, NULL, 0x00,
2067                 "An optional parameter that is reserved in this version.",
2068                 HFILL
2069             }
2070         },
2071         {   &hf_smpp_msg_wait_ind,
2072             {   "Indication", "smpp.msg_wait.ind",
2073                 FT_UINT8, BASE_HEX, VALS(vals_msg_wait_ind), 0x80,
2074                 "Indicates to the handset that a message is waiting.",
2075                 HFILL
2076             }
2077         },
2078         {   &hf_smpp_msg_wait_type,
2079             {   "Type      ", "smpp.msg_wait.type",
2080                 FT_UINT8, BASE_HEX, VALS(vals_msg_wait_type), 0x03,
2081                 "Indicates type of message that is waiting.",
2082                 HFILL
2083             }
2084         },
2085         {   &hf_smpp_SC_interface_version,
2086             {   "SMSC-supported version", "smpp.SC_interface_version",
2087                 FT_STRING, BASE_NONE, NULL, 0x00,
2088                 "Version of SMPP interface supported by the SMSC.",
2089                 HFILL
2090             }
2091         },
2092         {   &hf_smpp_callback_num_pres,
2093             {   "Presentation", "smpp.callback_num.pres",
2094                 FT_UINT8, BASE_HEX, VALS(vals_callback_num_pres), 0x0C,
2095                 "Controls the presentation indication.",
2096                 HFILL
2097             }
2098         },
2099         {   &hf_smpp_callback_num_scrn,
2100             {   "Screening   ", "smpp.callback_num.scrn",
2101                 FT_UINT8, BASE_HEX, VALS(vals_callback_num_scrn), 0x03,
2102                 "Controls screening of the callback-number.",
2103                 HFILL
2104             }
2105         },
2106         {   &hf_smpp_callback_num_atag,
2107             {   "Callback number - alphanumeric display tag",
2108                 "smpp.callback_num_atag",
2109                 FT_NONE, BASE_NONE, NULL, 0x00,
2110                 "Associates an alphanumeric display with call back number.",
2111                 HFILL
2112             }
2113         },
2114         {   &hf_smpp_callback_num,
2115             {   "Callback number", "smpp.callback_num",
2116                 FT_NONE, BASE_NONE, NULL, 0x00,
2117                 "Associates a call back number with the message.",
2118                 HFILL
2119             }
2120         },
2121         {   &hf_smpp_network_error_type,
2122             {   "Error type", "smpp.network_error.type",
2123                 FT_UINT8, BASE_DEC, VALS(vals_network_error_type), 0x00,
2124                 "Indicates the network type.",
2125                 HFILL
2126             }
2127         },
2128         {   &hf_smpp_network_error_code,
2129             {   "Error code", "smpp.network_error.code",
2130                 FT_UINT16, BASE_HEX, NULL, 0x00,
2131                 "Gives the actual network error code.",
2132                 HFILL
2133             }
2134         },
2135         {   &hf_smpp_message_payload,
2136             {   "Payload", "smpp.message_payload",
2137                 FT_NONE, BASE_NONE, NULL, 0x00,
2138                 "Short message user data.",
2139                 HFILL
2140             }
2141         },
2142         {   &hf_smpp_alert_on_message_delivery,
2143             {   "Alert on delivery", "smpp.alert_on_message_delivery",
2144                 FT_NONE, BASE_NONE, NULL, 0x00,
2145                 "Instructs the handset to alert user on message delivery.",
2146                 HFILL
2147             }
2148         },
2149         {   &hf_smpp_its_session_number,
2150             {   "Session number", "smpp.its_session.number",
2151                 FT_UINT8, BASE_DEC, NULL, 0x00,
2152                 "Session number of interactive teleservice.",
2153                 HFILL
2154             }
2155         },
2156         {   &hf_smpp_its_session_sequence,
2157             {   "Sequence number  ", "smpp.its_session.sequence",
2158                 FT_UINT8, BASE_HEX, NULL, 0xFE,
2159                 "Sequence number of the dialogue unit.",
2160                 HFILL
2161             }
2162         },
2163         {   &hf_smpp_its_session_ind,
2164             {   "Session indicator", "smpp.its_session.ind",
2165                 FT_UINT8, BASE_HEX, NULL, 0x01,
2166                 "Indicates whether this message is end of conversation.",
2167                 HFILL
2168             }
2169         },
2170         {   &hf_smpp_opt_param,
2171             {   "Optional parameters", "smpp.opt_param",
2172                 FT_NONE, BASE_NONE, NULL, 0x00,
2173                 "The list of optional parameters in this operation.",
2174                 HFILL
2175             }
2176         },
2177     };
2178     /* Setup protocol subtree array */
2179     static gint *ett[] = {
2180             &ett_smpp,
2181             &ett_dlist,
2182             &ett_dlist_resp,
2183             &ett_opt_param
2184     };
2185     /* Register the protocol name and description */
2186     proto_smpp = proto_register_protocol("Short Message Peer to Peer",
2187                                          "SMPP", "smpp");
2188
2189     /* Required function calls to register header fields and subtrees used */
2190     proto_register_field_array(proto_smpp, hf, array_length(hf));
2191     proto_register_subtree_array(ett, array_length(ett));
2192 }
2193
2194 /*
2195  * If dissector uses sub-dissector registration add a registration routine.
2196  * This format is required because a script is used to find these routines and
2197  * create the code that calls these routines.
2198  */
2199 void
2200 proto_reg_handoff_smpp(void)
2201 {
2202     dissector_handle_t smpp_handle;
2203
2204     /*
2205      * SMPP can be spoken on any port under TCP or X.25
2206      * ...how *do* we do that under X.25?
2207      *
2208      * We can register the heuristic SMPP dissector with X.25, for one
2209      * thing.  We don't currently have any mechanism to allow the user
2210      * to specify that a given X.25 circuit is to be dissected as SMPP,
2211      * however.
2212      */
2213     smpp_handle = create_dissector_handle(dissect_smpp, proto_smpp);
2214     dissector_add_handle("tcp.port", smpp_handle);
2215     heur_dissector_add("tcp", dissect_smpp_heur, proto_smpp);
2216     heur_dissector_add("x.25", dissect_smpp_heur, proto_smpp);
2217 }