Rename function and variables for dissecting an NT service Account Control
[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.4 2002/01/21 07:36:43 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     *secs = mktime(&r_time);
607     *nsecs = (datestr[12] - '0') * 100000000;
608     t_diff = (10 * (datestr[13] - '0') + (datestr[14] - '0')) * 900;
609     if (datestr[15] == '+')
610         *secs += t_diff;
611     else if (datestr[15] == '-')
612         *secs -= t_diff;
613     else                                /* Must be relative ('R')       */
614         relative = TRUE;
615     return relative;
616 }
617
618 /*!
619  * Scanning routines to add standard types (byte, int, string...) to the
620  * protocol tree.
621  *
622  * \param       tree    The protocol tree to add to
623  * \param       tvb     Buffer containing the data
624  * \param       field   Actual field whose value needs displaying
625  * \param       offset  Location of field in buffer, returns location of
626  *                      next field
627  */
628 static void
629 smpp_handle_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
630 {
631     char         strval[BUFSIZ];
632     gint         len;
633
634     len = tvb_get_nstringz(tvb, *offset, BUFSIZ, strval);
635     len++;
636     if (*strval)
637         proto_tree_add_string(tree, field, tvb, *offset, len, strval);
638     (*offset) += len;
639 }
640
641 static void
642 smpp_handle_int1(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
643 {
644     guint8       val;
645
646     val = tvb_get_guint8(tvb, *offset);
647     proto_tree_add_uint(tree, field, tvb, *offset, 1, val);
648     (*offset)++;
649 }
650
651 static void
652 smpp_handle_int2(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
653 {
654     guint        val;
655
656     val = tvb_get_ntohs(tvb, *offset);
657     proto_tree_add_uint(tree, field, tvb, *offset, 2, val);
658     (*offset) += 2;
659 }
660
661 static void
662 smpp_handle_int4(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
663 {
664     guint        val;
665
666     val = tvb_get_ntohl(tvb, *offset);
667     proto_tree_add_uint(tree, field, tvb, *offset, 4, val);
668     (*offset) += 4;
669 }
670
671 static void
672 smpp_handle_time(proto_tree *tree, tvbuff_t *tvb,
673                  int field, int field_R, int *offset)
674 {
675     char         strval[BUFSIZ];
676     gint         len;
677     nstime_t     tmptime;
678
679     len = tvb_get_nstringz(tvb, *offset, BUFSIZ, strval);
680     len++;
681     if (*strval)
682     {
683         if (smpp_mktime(strval, &tmptime.secs, &tmptime.nsecs))
684             proto_tree_add_time(tree, field_R, tvb, *offset, len, &tmptime);
685         else
686             proto_tree_add_time(tree, field, tvb, *offset, len, &tmptime);
687     }
688     *offset += len;
689 }
690
691 /*!
692  * Scanning routine to handle the destination-list of 'submit_multi'
693  *
694  * \param       tree    The protocol tree to add to
695  * \param       tvb     Buffer containing the data
696  * \param       offset  Location of field in buffer, returns location of
697  *                      next field
698  */
699 static void
700 smpp_handle_dlist(proto_tree *tree, tvbuff_t *tvb, int *offset)
701 {
702     guint8       entries;
703     int          tmpoff = *offset;
704     proto_item  *sub_tree = NULL;
705     guint8       dest_flag;
706
707     if ((entries = tvb_get_guint8(tvb, tmpoff++)))
708     {
709         sub_tree = proto_tree_add_item(tree, hf_smpp_dlist,
710                                         tvb, *offset, 1, FALSE);
711         proto_item_add_subtree(sub_tree, ett_dlist);
712     }
713     while (entries--)
714     {
715         dest_flag = tvb_get_guint8(tvb, tmpoff++);
716         if (dest_flag == 1)                     /* SME address  */
717         {
718             smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff);
719             smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff);
720             smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff);
721         }
722         else                                    /* Distribution list    */
723         {
724             smpp_handle_string(sub_tree, tvb, hf_smpp_dl_name, &tmpoff);
725         }
726     }
727     *offset = tmpoff;
728 }
729
730 /*!
731  * Scanning routine to handle the destination result list
732  * of 'submit_multi_resp'
733  *
734  * \param       tree    The protocol tree to add to
735  * \param       tvb     Buffer containing the data
736  * \param       offset  Location of field in buffer, returns location of
737  *                      next field
738  */
739 static void
740 smpp_handle_dlist_resp(proto_tree *tree, tvbuff_t *tvb, int *offset)
741 {
742     guint8       entries;
743     int          tmpoff = *offset;
744     proto_item  *sub_tree = NULL;
745
746     if ((entries = tvb_get_guint8(tvb, tmpoff++)))
747     {
748         sub_tree = proto_tree_add_item(tree, hf_smpp_dlist_resp,
749                                        tvb, *offset, 1, FALSE);
750         proto_item_add_subtree(sub_tree, ett_dlist_resp);
751     }
752     while (entries--)
753     {
754         smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff);
755         smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff);
756         smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff);
757         smpp_handle_int4(sub_tree, tvb, hf_smpp_error_status_code, &tmpoff);
758     }
759     *offset = tmpoff;
760 }
761
762 /*!
763  * Scanning routine to handle all optional parameters of SMPP-operations.
764  * The parameters have the format Tag Length Value (TLV), with a 2-byte tag
765  * and 2-byte length.
766  *
767  * \param       tree    The protocol tree to add to
768  * \param       tvb     Buffer containing the data
769  * \param       offset  Location of field in buffer, returns location of
770  *                      next field
771  */
772 static void
773 smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset)
774 {
775     proto_item  *sub_tree = NULL;
776     guint        tag;
777     guint        length;
778     guint8       field;
779     guint8       major, minor;
780     char         strval[BUFSIZ];
781
782     if (tvb_reported_length_remaining(tvb, *offset) >= 4)
783     {
784         sub_tree = proto_tree_add_item(tree, hf_smpp_opt_param,
785                                        tvb, *offset, 0, FALSE);
786         proto_item_add_subtree(sub_tree, ett_opt_param);
787     }
788
789     while (tvb_reported_length_remaining(tvb, *offset) >= 4)
790     {
791         tag = tvb_get_ntohs(tvb, *offset);
792         *offset += 2;
793         length = tvb_get_ntohs(tvb, *offset);
794         *offset += 2;
795         switch (tag) {
796             case  0x0005:       /* dest_addr_subunit    */
797                 smpp_handle_int1(sub_tree, tvb,
798                                  hf_smpp_dest_addr_subunit, offset);
799                 break;
800             case  0x0006:       /* dest_network_type    */
801                 smpp_handle_int1(sub_tree, tvb,
802                                  hf_smpp_dest_network_type, offset);
803                 break;
804             case  0x0007:       /* dest_bearer_type     */
805                 smpp_handle_int1(sub_tree, tvb,
806                                  hf_smpp_dest_bearer_type, offset);
807                 break;
808             case  0x0008:       /* dest_telematics_id   */
809                 smpp_handle_int2(sub_tree, tvb,
810                                  hf_smpp_dest_telematics_id, offset);
811                 break;
812             case  0x000D:       /* source_addr_subunit  */
813                 smpp_handle_int1(sub_tree, tvb,
814                                  hf_smpp_source_addr_subunit, offset);
815                 break;
816             case  0x000E:       /* source_network_type  */
817                 smpp_handle_int1(sub_tree, tvb,
818                                  hf_smpp_source_network_type, offset);
819                 break;
820             case  0x000F:       /* source_bearer_type   */
821                 smpp_handle_int1(sub_tree, tvb,
822                                  hf_smpp_source_bearer_type, offset);
823                 break;
824             case  0x0010:       /* source_telematics_id */
825                 smpp_handle_int2(sub_tree, tvb,
826                                  hf_smpp_source_telematics_id, offset);
827                 break;
828             case  0x0017:       /* qos_time_to_live     */
829                 smpp_handle_int4(sub_tree, tvb,
830                                  hf_smpp_qos_time_to_live, offset);
831                 break;
832             case  0x0019:       /* payload_type */
833                 smpp_handle_int1(sub_tree, tvb,
834                                  hf_smpp_payload_type, offset);
835                 break;
836             case  0x001D:       /* additional_status_info_text  */
837                 smpp_handle_string(sub_tree, tvb,
838                                    hf_smpp_additional_status_info_text, offset);
839                 break;
840             case  0x001E:       /* receipted_message_id */
841                 smpp_handle_string(sub_tree, tvb,
842                                    hf_smpp_receipted_message_id, offset);
843                 break;
844             case  0x0030:       /* ms_msg_wait_facilities       */
845                 field = tvb_get_guint8(tvb, *offset);
846                 proto_tree_add_item(sub_tree, hf_smpp_msg_wait_ind,
847                                     tvb, *offset, 1, field);
848                 proto_tree_add_item(sub_tree, hf_smpp_msg_wait_type,
849                                     tvb, *offset, 1, field);
850                 (*offset)++;
851                 break;
852             case  0x0201:       /* privacy_indicator    */
853                 smpp_handle_int1(sub_tree, tvb,
854                                  hf_smpp_privacy_indicator, offset);
855                 break;
856             case  0x0202:       /* source_subaddress    */
857                 smpp_handle_string(sub_tree, tvb,
858                                    hf_smpp_source_subaddress, offset);
859                 break;
860             case  0x0203:       /* dest_subaddress      */
861                 smpp_handle_string(sub_tree, tvb,
862                                    hf_smpp_dest_subaddress, offset);
863                 break;
864             case  0x0204:       /* user_message_reference       */
865                 smpp_handle_int2(sub_tree, tvb,
866                                  hf_smpp_user_message_reference, offset);
867                 break;
868             case  0x0205:       /* user_response_code   */
869                 smpp_handle_int1(sub_tree, tvb,
870                                  hf_smpp_user_response_code, offset);
871                 break;
872             case  0x020A:       /* source_port  */
873                 smpp_handle_int2(sub_tree, tvb,
874                                  hf_smpp_source_port, offset);
875                 break;
876             case  0x020B:       /* destination_port     */
877                 smpp_handle_int2(sub_tree, tvb,
878                                  hf_smpp_destination_port, offset);
879                 break;
880             case  0x020C:       /* sar_msg_ref_num      */
881                 smpp_handle_int2(sub_tree, tvb,
882                                  hf_smpp_sar_msg_ref_num, offset);
883                 break;
884             case  0x020D:       /* language_indicator   */
885                 smpp_handle_int1(sub_tree, tvb,
886                                  hf_smpp_language_indicator, offset);
887                 break;
888             case  0x020E:       /* sar_total_segments   */
889                 smpp_handle_int1(sub_tree, tvb,
890                                  hf_smpp_sar_total_segments, offset);
891                 break;
892             case  0x020F:       /* sar_segment_seqnum   */
893                 smpp_handle_int1(sub_tree, tvb,
894                                  hf_smpp_sar_segment_seqnum, offset);
895                 break;
896             case  0x0210:       /* SC_interface_version */
897                 field = tvb_get_guint8(tvb, *offset);
898                 minor = field & 0x0F;
899                 major = (field & 0xF0) >> 4;
900                 sprintf(strval, "%d.%d", major, minor);
901                 proto_tree_add_string(sub_tree, hf_smpp_SC_interface_version,
902                                       tvb, *offset, 1, strval);
903                 (*offset)++;
904                 break;
905             case  0x0302:       /* callback_num_pres_ind        */
906                 field = tvb_get_guint8(tvb, *offset);
907                 proto_tree_add_item(sub_tree, hf_smpp_callback_num_pres,
908                                     tvb, *offset, 1, field);
909                 proto_tree_add_item(sub_tree, hf_smpp_callback_num_scrn,
910                                     tvb, *offset, 1, field);
911                 (*offset)++;
912                 break;
913             case  0x0303:       /* callback_num_atag    */
914                 if (length)
915                     proto_tree_add_item(sub_tree, hf_smpp_callback_num_atag,
916                                         tvb, *offset, length, FALSE);
917                 (*offset) += length;
918                 break;
919             case  0x0304:       /* number_of_messages   */
920                 smpp_handle_int1(sub_tree, tvb,
921                                  hf_smpp_number_of_messages, offset);
922                 break;
923             case  0x0381:       /* callback_num */
924                 if (length)
925                     proto_tree_add_item(sub_tree, hf_smpp_callback_num,
926                                         tvb, *offset, length, FALSE);
927                 (*offset) += length;
928                 break;
929             case  0x0420:       /* dpf_result   */
930                 smpp_handle_int1(sub_tree, tvb,
931                                  hf_smpp_dpf_result, offset);
932                 break;
933             case  0x0421:       /* set_dpf      */
934                 smpp_handle_int1(sub_tree, tvb,
935                                  hf_smpp_set_dpf, offset);
936                 break;
937             case  0x0422:       /* ms_availability_status       */
938                 smpp_handle_int1(sub_tree, tvb,
939                                  hf_smpp_ms_availability_status, offset);
940                 break;
941             case  0x0423:       /* network_error_code   */
942                 smpp_handle_int1(sub_tree, tvb,
943                                  hf_smpp_network_error_type, offset);
944                 smpp_handle_int2(sub_tree, tvb,
945                                  hf_smpp_network_error_code, offset);
946                 (*offset) += length;
947                 break;
948             case  0x0424:       /* message_payload      */
949                 if (length)
950                     proto_tree_add_item(sub_tree, hf_smpp_message_payload,
951                                         tvb, *offset, length, FALSE);
952                 (*offset) += length;
953                 break;
954             case  0x0425:       /* delivery_failure_reason      */
955                 smpp_handle_int1(sub_tree, tvb,
956                                  hf_smpp_delivery_failure_reason, offset);
957                 break;
958             case  0x0426:       /* more_messages_to_send        */
959                 smpp_handle_int1(sub_tree, tvb,
960                                  hf_smpp_more_messages_to_send, offset);
961                 break;
962             case  0x0427:       /* message_state        */
963                 smpp_handle_int1(sub_tree, tvb,
964                                  hf_smpp_message_state, offset);
965                 break;
966             case  0x0501:       /* ussd_service_op      */
967                 smpp_handle_int1(sub_tree, tvb,
968                                  hf_smpp_ussd_service_op, offset);
969                 break;
970             case  0x1201:       /* display_time */
971                 smpp_handle_int1(sub_tree, tvb,
972                                  hf_smpp_display_time, offset);
973                 break;
974             case  0x1203:       /* sms_signal   */
975                 smpp_handle_int2(sub_tree, tvb,
976                                  hf_smpp_sms_signal, offset);
977                 /*! \todo Fill as per TIA/EIA-136-710-A         */
978                 break;
979             case  0x1204:       /* ms_validity  */
980                 smpp_handle_int1(sub_tree, tvb,
981                                  hf_smpp_ms_validity, offset);
982                 break;
983             case  0x130C:       /* alert_on_message_delivery    */
984                 proto_tree_add_item(sub_tree,
985                                     hf_smpp_alert_on_message_delivery,
986                                     tvb, *offset, length, FALSE);
987                 (*offset) += length;
988                 break;
989             case  0x1380:       /* its_reply_type       */
990                 smpp_handle_int1(sub_tree, tvb,
991                                  hf_smpp_its_reply_type, offset);
992                 break;
993             case  0x1383:       /* its_session_info     */
994                 smpp_handle_int1(sub_tree, tvb,
995                                  hf_smpp_its_session_number, offset);
996                 field = tvb_get_guint8(tvb, *offset);
997                 proto_tree_add_item(sub_tree, hf_smpp_its_session_sequence,
998                                     tvb, *offset, 1, field);
999                 proto_tree_add_item(sub_tree, hf_smpp_its_session_ind,
1000                                     tvb, *offset, 1, field);
1001                 (*offset)++;
1002                 break;
1003             default:
1004                 if ((tag >= 0x1400) && (tag <= 0x3FFF))
1005                     proto_tree_add_item(sub_tree, hf_smpp_vendor_op, tvb,
1006                                         *offset, length, FALSE);
1007                 else
1008                     proto_tree_add_item(sub_tree, hf_smpp_reserved_op, tvb,
1009                                         *offset, length, FALSE);
1010                 (*offset) += length;
1011                 break;
1012         }
1013     }
1014 }
1015
1016 /*!
1017  * The next set of routines handle the different operations, associated
1018  * with SMPP.
1019  */
1020 static void
1021 bind_receiver(proto_tree *tree, tvbuff_t *tvb)
1022 {
1023     int          offset = 0;
1024     guint8       field;
1025     guint8       major, minor;
1026     char         strval[BUFSIZ];
1027
1028     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1029     smpp_handle_string(tree, tvb, hf_smpp_password, &offset);
1030     smpp_handle_string(tree, tvb, hf_smpp_system_type, &offset);
1031     field = tvb_get_guint8(tvb, offset++);
1032     minor = field & 0x0F;
1033     major = (field & 0xF0) >> 4;
1034     sprintf(strval, "%d.%d", major, minor);
1035     proto_tree_add_string(tree, hf_smpp_interface_version, tvb,
1036                           offset - 1, 1, strval);
1037     smpp_handle_int1(tree, tvb, hf_smpp_addr_ton, &offset);
1038     smpp_handle_int1(tree, tvb, hf_smpp_addr_npi, &offset);
1039     smpp_handle_string(tree, tvb, hf_smpp_address_range, &offset);
1040 }
1041
1042 #define bind_transmitter(a, b) bind_receiver(a, b)
1043
1044 static void
1045 query_sm(proto_tree *tree, tvbuff_t *tvb)
1046 {
1047     int          offset = 0;
1048
1049     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1050     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1051     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1052     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1053 }
1054
1055 #define bind_transceiver(a, b) bind_receiver(a, b)
1056
1057 static void
1058 outbind(proto_tree *tree, tvbuff_t *tvb)
1059 {
1060     int          offset = 0;
1061
1062     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1063     smpp_handle_string(tree, tvb, hf_smpp_password, &offset);
1064 }
1065
1066 static void
1067 submit_sm(proto_tree *tree, tvbuff_t *tvb)
1068 {
1069     int          offset = 0;
1070     guint8       flag;
1071     guint8       length;
1072
1073     smpp_handle_string(tree, tvb, hf_smpp_service_type, &offset);
1074     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1075     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1076     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1077     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1078     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1079     smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
1080     flag = tvb_get_guint8(tvb, offset);
1081     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1082                         tvb, offset, 1, flag);
1083     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1084                         tvb, offset, 1, flag);
1085     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1086                         tvb, offset, 1, flag);
1087     offset++;
1088     smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset);
1089     smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset);
1090     smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1091                                 hf_smpp_schedule_delivery_time_r, &offset);
1092     smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1093                                 hf_smpp_validity_period_r, &offset);
1094     flag = tvb_get_guint8(tvb, offset);
1095     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1096     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1097     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1098     offset++;
1099     smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset);
1100     smpp_handle_int1(tree, tvb, hf_smpp_data_coding, &offset);
1101     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1102     length = tvb_get_guint8(tvb, offset);
1103     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1104     if (length)
1105         proto_tree_add_item(tree, hf_smpp_short_message,
1106                             tvb, offset, length, FALSE);
1107     offset += length;
1108     smpp_handle_tlv(tree, tvb, &offset);
1109 }
1110
1111 #define deliver_sm(a, b) submit_sm(a, b)
1112
1113 static void
1114 replace_sm(proto_tree *tree, tvbuff_t *tvb)
1115 {
1116     int          offset = 0;
1117     guint8       flag;
1118     guint8       length;
1119
1120     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1121     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1122     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1123     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1124     smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1125                                 hf_smpp_schedule_delivery_time_r, &offset);
1126     smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1127                                 hf_smpp_validity_period_r, &offset);
1128     flag = tvb_get_guint8(tvb, offset);
1129     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1130     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1131     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1132     offset++;
1133     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1134     length = tvb_get_guint8(tvb, offset);
1135     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1136     if (length)
1137         proto_tree_add_item(tree, hf_smpp_short_message,
1138                             tvb, offset, length, FALSE);
1139     offset += length;
1140 }
1141
1142 static void
1143 cancel_sm(proto_tree *tree, tvbuff_t *tvb)
1144 {
1145     int          offset = 0;
1146
1147     smpp_handle_string(tree, tvb, hf_smpp_service_type, &offset);
1148     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1149     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1150     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1151     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1152     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1153     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1154     smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
1155 }
1156
1157 static void
1158 submit_multi(proto_tree *tree, tvbuff_t *tvb)
1159 {
1160     int          offset = 0;
1161     guint8       flag;
1162     guint8       length;
1163
1164     smpp_handle_string(tree, tvb, hf_smpp_service_type, &offset);
1165     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1166     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1167     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1168
1169     smpp_handle_dlist(tree, tvb, &offset);
1170
1171     flag = tvb_get_guint8(tvb, offset);
1172     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1173                         tvb, offset, 1, flag);
1174     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1175                         tvb, offset, 1, flag);
1176     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1177                         tvb, offset, 1, flag);
1178     offset++;
1179     smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset);
1180     smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset);
1181     smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time,
1182                                 hf_smpp_schedule_delivery_time_r, &offset);
1183     smpp_handle_time(tree, tvb, hf_smpp_validity_period,
1184                                 hf_smpp_validity_period_r, &offset);
1185     flag = tvb_get_guint8(tvb, offset);
1186     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1187     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1188     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1189     offset++;
1190     smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset);
1191     smpp_handle_int1(tree, tvb, hf_smpp_data_coding, &offset);
1192     smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset);
1193     length = tvb_get_guint8(tvb, offset);
1194     proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length);
1195     if (length)
1196         proto_tree_add_item(tree, hf_smpp_short_message,
1197                             tvb, offset, length, FALSE);
1198     offset += length;
1199     smpp_handle_tlv(tree, tvb, &offset);
1200 }
1201
1202 static void
1203 alert_notification(proto_tree *tree, tvbuff_t *tvb)
1204 {
1205     int          offset = 0;
1206
1207     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1208     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1209     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1210     smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_ton, &offset);
1211     smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_npi, &offset);
1212     smpp_handle_string(tree, tvb, hf_smpp_esme_addr, &offset);
1213     smpp_handle_tlv(tree, tvb, &offset);
1214 }
1215
1216 static void
1217 data_sm(proto_tree *tree, tvbuff_t *tvb)
1218 {
1219     int          offset = 0;
1220     guint8       flag;
1221
1222     smpp_handle_string(tree, tvb, hf_smpp_service_type, &offset);
1223     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset);
1224     smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset);
1225     smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset);
1226     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset);
1227     smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset);
1228     smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset);
1229     flag = tvb_get_guint8(tvb, offset);
1230     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_mode,
1231                         tvb, offset, 1, flag);
1232     proto_tree_add_item(tree, hf_smpp_esm_submit_msg_type,
1233                         tvb, offset, 1, flag);
1234     proto_tree_add_item(tree, hf_smpp_esm_submit_features,
1235                         tvb, offset, 1, flag);
1236     offset++;
1237     flag = tvb_get_guint8(tvb, offset);
1238     proto_tree_add_item(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag);
1239     proto_tree_add_item(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag);
1240     proto_tree_add_item(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag);
1241     offset++;
1242     smpp_handle_int1(tree, tvb, hf_smpp_data_coding, &offset);
1243     smpp_handle_tlv(tree, tvb, &offset);
1244 }
1245
1246 /*!
1247  * The next set of routines handle the different operation-responses,
1248  * associated with SMPP.
1249  */
1250 static void
1251 bind_receiver_resp(proto_tree *tree, tvbuff_t *tvb)
1252 {
1253     int          offset = 0;
1254
1255     smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset);
1256     smpp_handle_tlv(tree, tvb, &offset);
1257 }
1258
1259 #define bind_transmitter_resp(a, b) bind_receiver_resp(a, b)
1260
1261 static void
1262 query_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1263 {
1264     int          offset = 0;
1265
1266     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1267     smpp_handle_time(tree, tvb, hf_smpp_final_date,
1268                                 hf_smpp_final_date_r, &offset);
1269     smpp_handle_int1(tree, tvb, hf_smpp_message_state, &offset);
1270     smpp_handle_int1(tree, tvb, hf_smpp_error_code, &offset);
1271 }
1272
1273 #define bind_transceiver_resp(a, b) bind_receiver_resp(a, b)
1274
1275 static void
1276 submit_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1277 {
1278     int          offset = 0;
1279
1280     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1281 }
1282
1283 #define deliver_sm_resp(a, b) submit_sm_resp(a, b)
1284
1285 static void
1286 submit_multi_resp(proto_tree *tree, tvbuff_t *tvb)
1287 {
1288     int          offset = 0;
1289
1290     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1291     smpp_handle_dlist_resp(tree, tvb, &offset);
1292 }
1293
1294 static void
1295 data_sm_resp(proto_tree *tree, tvbuff_t *tvb)
1296 {
1297     int          offset = 0;
1298
1299     smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset);
1300     smpp_handle_tlv(tree, tvb, &offset);
1301 }
1302
1303 /*
1304  * A 'heuristic dissector' that attemtps to establish whether we have
1305  * a genuine SMPP PDU here.
1306  * Only works when:
1307  *      at least the fixed header is there
1308  *      it is a 'well-known' operation
1309  *      has a 'well-known' status
1310  */
1311 static gboolean
1312 dissect_smpp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1313 {
1314     guint        command_id;            /* SMPP command         */
1315     guint        command_status;        /* Status code          */
1316
1317     if (tvb_reported_length(tvb) < 4 * 4)       /* Mandatory header     */
1318         return FALSE;
1319     command_id = tvb_get_ntohl(tvb, 4);         /* Only known commands  */
1320     if (match_strval(command_id, vals_command_id) == NULL)
1321         return FALSE;
1322     command_status = tvb_get_ntohl(tvb, 8);     /* ..with known status  */
1323     if (match_strval(command_status, vals_command_status) == NULL)
1324         return FALSE;
1325     dissect_smpp(tvb, pinfo, tree);
1326     return TRUE;
1327 }
1328
1329 /* Code to actually dissect the packets */
1330 static void
1331 dissect_smpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1332 {
1333     int          offset = 0;            /* Offset within tvbuff */
1334     guint        command_length;        /* length of PDU        */
1335     guint        command_id;            /* SMPP command         */
1336     guint        command_status;        /* Status code          */
1337     guint        sequence_number;       /* ...of command        */
1338
1339     /* Set up structures needed to add the protocol subtree and manage it */
1340     proto_item  *ti;
1341     proto_tree  *smpp_tree;
1342     tvbuff_t    *tmp_tvb;
1343
1344     /*
1345      * Safety: don't even try it when the mandatory header isn't present.
1346      */
1347     if (tvb_reported_length(tvb) < 4 * 4)
1348         return;
1349     command_length = tvb_get_ntohl(tvb, offset);
1350     offset += 4;
1351     command_id = tvb_get_ntohl(tvb, offset);
1352     offset += 4;
1353     command_status = tvb_get_ntohl(tvb, offset);
1354     offset +=4;
1355     sequence_number = tvb_get_ntohl(tvb, offset);
1356     offset += 4;
1357     /* Make entries in Protocol column and Info column on summary display */
1358     if (check_col(pinfo->cinfo, COL_PROTOCOL))
1359         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMPP");
1360
1361     if (check_col(pinfo->cinfo, COL_INFO))
1362     {
1363         col_clear(pinfo->cinfo, COL_INFO);
1364         col_add_fstr(pinfo->cinfo, COL_INFO, "SMPP %s",
1365                  val_to_str(command_id,vals_command_id,"unknown operation"));
1366         if (command_id & 0x80000000)
1367             col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"",
1368                             val_to_str(command_status, vals_command_status,
1369                                        "reserved error"));
1370         if (command_length > tvb_reported_length(tvb))
1371             col_append_str(pinfo->cinfo, COL_INFO, " [short packet]");
1372         if (command_length < tvb_reported_length(tvb))
1373             col_append_str(pinfo->cinfo, COL_INFO, " [trailing data]");
1374     }
1375
1376     /* In the interest of speed, if "tree" is NULL, don't do any work not
1377      * necessary to generate protocol tree items.
1378      */
1379     if (tree) {
1380
1381         /* create display subtree for the protocol      */
1382         ti = proto_tree_add_item(tree, proto_smpp, tvb, 0,
1383                                  command_length, FALSE);
1384         smpp_tree = proto_item_add_subtree(ti, ett_smpp);
1385
1386         /* add an item to the subtree                   */
1387         proto_tree_add_uint(smpp_tree, hf_smpp_command_length, tvb,
1388                             0, 4, command_length);
1389         proto_tree_add_uint(smpp_tree, hf_smpp_command_id, tvb,
1390                             4, 4, command_id);
1391         /* Status is only meaningful with responses     */
1392         if (command_id & 0x80000000)
1393             proto_tree_add_uint(smpp_tree, hf_smpp_command_status, tvb,
1394                                 8, 4, command_status);
1395         proto_tree_add_uint(smpp_tree, hf_smpp_sequence_number, tvb,
1396                             12, 4, sequence_number);
1397         /*
1398          * End of header. Don't dissect variable part if it is shortened.
1399          */
1400         if (command_length > tvb_reported_length(tvb))
1401             return;
1402         tmp_tvb = tvb_new_subset(tvb, offset, -1, command_length - offset);
1403         if (command_id & 0x80000000)
1404         {
1405             switch (command_id & 0x7FFFFFFF) {
1406                 /*
1407                  * All of these only have a fixed header
1408                  */
1409                 case 0:                         /* Generic nack */
1410                 case 6:                         /* Unbind resp  */
1411                 case 7:                         /* Replace SM resp      */
1412                 case 8:                         /* Cancel SM resp       */
1413                 case 21:                        /* Enquire link resp    */
1414                     break;
1415                 case 1:
1416                     if (!command_status)
1417                         bind_receiver_resp(smpp_tree, tmp_tvb);
1418                     break;
1419                 case 2:
1420                     if (!command_status)
1421                         bind_transmitter_resp(smpp_tree, tmp_tvb);
1422                     break;
1423                 case 3:
1424                     if (!command_status)
1425                         query_sm_resp(smpp_tree, tmp_tvb);
1426                     break;
1427                 case 4:
1428                     if (!command_status)
1429                         submit_sm_resp(smpp_tree, tmp_tvb);
1430                     break;
1431                 case 5:
1432                     if (!command_status)
1433                         deliver_sm_resp(smpp_tree, tmp_tvb);
1434                     break;
1435                 case 9:
1436                     if (!command_status)
1437                         bind_transceiver_resp(smpp_tree, tmp_tvb);
1438                     break;
1439                 case 33:
1440                     if (!command_status)
1441                         submit_multi_resp(smpp_tree, tmp_tvb);
1442                     break;
1443                 case 259:
1444                     if (!command_status)
1445                         data_sm_resp(smpp_tree, tmp_tvb);
1446                     break;
1447                 default:
1448                     break;
1449             }
1450         }
1451         else
1452         {
1453             switch (command_id) {
1454                 case  1:
1455                     bind_receiver(smpp_tree, tmp_tvb);
1456                     break;
1457                 case  2:
1458                     bind_transmitter(smpp_tree, tmp_tvb);
1459                     break;
1460                 case  3:
1461                     query_sm(smpp_tree, tmp_tvb);
1462                     break;
1463                 case  4:
1464                     submit_sm(smpp_tree, tmp_tvb);
1465                     break;
1466                 case  5:
1467                     deliver_sm(smpp_tree, tmp_tvb);
1468                     break;
1469                 case  6:                        /* Unbind       */
1470                 case 21:                        /* Enquire link */
1471                     break;
1472                 case  7:
1473                     replace_sm(smpp_tree, tmp_tvb);
1474                     break;
1475                 case  8:
1476                     cancel_sm(smpp_tree, tmp_tvb);
1477                     break;
1478                 case  9:
1479                     bind_transceiver(smpp_tree, tmp_tvb);
1480                     break;
1481                 case  11:
1482                     outbind(smpp_tree, tmp_tvb);
1483                     break;
1484                 case  33:
1485                     submit_multi(smpp_tree, tmp_tvb);
1486                     break;
1487                 case  258:
1488                     alert_notification(smpp_tree, tmp_tvb);
1489                     break;
1490                 case  259:
1491                     data_sm(smpp_tree, tmp_tvb);
1492                     break;
1493                 default:
1494                     break;
1495             }
1496         }
1497     }
1498     /* If this protocol has a sub-dissector call it here.       */
1499     return;
1500 }
1501
1502 /* Register the protocol with Ethereal */
1503 void
1504 proto_register_smpp(void)
1505 {
1506
1507     /* Setup list of header fields      */
1508     static hf_register_info hf[] = {
1509         {   &hf_smpp_command_length,
1510             {   "Length    ", "smpp.command_length",
1511                 FT_UINT32, BASE_DEC, NULL, 0x00,
1512                 "Total length of the SMPP PDU.",
1513                 HFILL
1514             }
1515         },
1516         {   &hf_smpp_command_id,
1517             {   "Operation ", "smpp.command_id",
1518                 FT_UINT32, BASE_HEX, VALS(vals_command_id), 0x00,
1519                 "Defines the SMPP PDU.",
1520                 HFILL
1521             }
1522         },
1523         {   &hf_smpp_command_status,
1524             {   "Result    ", "smpp.command_status",
1525                 FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00,
1526                 "Indicates success or failure of the SMPP request.",
1527                 HFILL
1528             }
1529         },
1530         {   &hf_smpp_sequence_number,
1531             {   "Sequence #", "smpp.sequence_number",
1532                 FT_UINT32, BASE_DEC, NULL, 0x00,
1533                 "A number to correlate requests with responses.",
1534                 HFILL
1535             }
1536         },
1537         {   &hf_smpp_system_id,
1538             {   "System ID", "smpp.system_id",
1539                 FT_STRING, BASE_NONE, NULL, 0x00,
1540                 "Identifies a system.",
1541                 HFILL
1542             }
1543         },
1544         {   &hf_smpp_password,
1545             {   "Password", "smpp.password",
1546                 FT_STRING, BASE_NONE, NULL, 0x00,
1547                 "Password used for authentication.",
1548                 HFILL
1549             }
1550         },
1551         {   &hf_smpp_system_type,
1552             {   "System type", "smpp.system_type",
1553                 FT_STRING, BASE_NONE, NULL, 0x00,
1554                 "Categorises the system.",
1555                 HFILL
1556             }
1557         },
1558         {   &hf_smpp_interface_version,
1559             {   "Version (if)", "smpp.interface_version",
1560                 FT_STRING, BASE_NONE, NULL, 0x00,
1561                 "Version of SMPP interface supported.",
1562                 HFILL
1563             }
1564         },
1565         {   &hf_smpp_service_type,
1566             {   "Service type", "smpp.service_type",
1567                 FT_STRING, BASE_NONE, NULL, 0x00,
1568                 "SMS application service associated with the message.",
1569                 HFILL
1570             }
1571         },
1572         {   &hf_smpp_addr_ton,
1573             {   "Type of number", "smpp.addr_ton",
1574                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
1575                 "Indicates the type of number, given in the address.",
1576                 HFILL
1577             }
1578         },
1579         {   &hf_smpp_source_addr_ton,
1580             {   "Type of number (originator)", "smpp.source_addr_ton",
1581                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
1582                 "Indicates originator type of number, given in the address.",
1583                 HFILL
1584             }
1585         },
1586         {   &hf_smpp_dest_addr_ton,
1587             {   "Type of number (recipient)", "smpp.dest_addr_ton",
1588                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
1589                 "Indicates recipient type of number, given in the address.",
1590                 HFILL
1591             }
1592         },
1593         {   &hf_smpp_addr_npi,
1594             {   "Numbering plan indicator", "smpp.addr_npi",
1595                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
1596                 "Gives the numbering plan this address belongs to.",
1597                 HFILL
1598             }
1599         },
1600         {   &hf_smpp_source_addr_npi,
1601             {   "Numbering plan indicator (originator)", "smpp.source_addr_npi",
1602                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
1603                 "Gives originator numbering plan this address belongs to.",
1604                 HFILL
1605             }
1606         },
1607         {   &hf_smpp_dest_addr_npi,
1608             {   "Numbering plan indicator (recipient)", "smpp.dest_addr_npi",
1609                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
1610                 "Gives recipient numbering plan this address belongs to.",
1611                 HFILL
1612             }
1613         },
1614         {   &hf_smpp_address_range,
1615             {   "Address", "smpp.address_range",
1616                 FT_STRING, BASE_NONE, NULL, 0x00,
1617                 "Given address or address range.",
1618                 HFILL
1619             }
1620         },
1621         {   &hf_smpp_source_addr,
1622             {   "Originator address", "smpp.source_addr",
1623                 FT_STRING, BASE_NONE, NULL, 0x00,
1624                 "Address of SME originating this message.",
1625                 HFILL
1626             }
1627         },
1628         {   &hf_smpp_destination_addr,
1629             {   "Recipient address", "smpp.destination_addr",
1630                 FT_STRING, BASE_NONE, NULL, 0x00,
1631                 "Address of SME receiving this message.",
1632                 HFILL
1633             }
1634         },
1635         {   &hf_smpp_esm_submit_msg_mode,
1636             {   "Messaging mode", "smpp.esm.submit.msg_mode",
1637                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_msg_mode), 0x03,
1638                 "Mode attribute for this message.",
1639                 HFILL
1640             }
1641         },
1642         {   &hf_smpp_esm_submit_msg_type,
1643             {   "Message type  ", "smpp.esm.submit.msg_type",
1644                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_msg_type), 0x3C,
1645                 "Type attribute for this message.",
1646                 HFILL
1647             }
1648         },
1649         {   &hf_smpp_esm_submit_features,
1650             {   "GSM features  ", "smpp.esm.submit.features",
1651                 FT_UINT8, BASE_HEX, VALS(vals_esm_submit_features), 0xC0,
1652                 "GSM network specific features.",
1653                 HFILL
1654             }
1655         },
1656         /*! \todo Get proper values from GSM-spec.      */
1657         {   &hf_smpp_protocol_id,
1658             {   "Protocol id.", "smpp.protocol_id",
1659                 FT_UINT8, BASE_HEX, NULL, 0x00,
1660                 "Protocol identifier according GSM 03.40.",
1661                 HFILL
1662             }
1663         },
1664         {   &hf_smpp_priority_flag,
1665             {   "Priority level", "smpp.priority_flag",
1666                 FT_UINT8, BASE_HEX, VALS(vals_priority_flag), 0x00,
1667                 "The priority level of the short message.",
1668                 HFILL
1669             }
1670         },
1671         {   &hf_smpp_schedule_delivery_time,
1672             {   "Scheduled delivery time", "smpp.schedule_delivery_time",
1673                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
1674                 "Scheduled time for delivery of short message.",
1675                 HFILL
1676             }
1677         },
1678         {   &hf_smpp_schedule_delivery_time_r,
1679             {   "Scheduled delivery time", "smpp.schedule_delivery_time_r",
1680                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1681                 "Scheduled time for delivery of short message.",
1682                 HFILL
1683             }
1684         },
1685         {   &hf_smpp_validity_period,
1686             {   "Validity period", "smpp.validity_period",
1687                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
1688                 "Validity period of this message.",
1689                 HFILL
1690             }
1691         },
1692         {   &hf_smpp_validity_period_r,
1693             {   "Validity period", "smpp.validity_period_r",
1694                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1695                 "Validity period of this message.",
1696                 HFILL
1697             }
1698         },
1699         {   &hf_smpp_regdel_receipt,
1700             {   "Delivery receipt  ", "smpp.regdel.receipt",
1701                 FT_UINT8, BASE_HEX, VALS(vals_regdel_receipt), 0x03,
1702                 "SMSC delivery receipt request.",
1703                 HFILL
1704             }
1705         },
1706         {   &hf_smpp_regdel_acks,
1707             {   "Message type      ", "smpp.regdel.acks",
1708                 FT_UINT8, BASE_HEX, VALS(vals_regdel_acks), 0x0C,
1709                 "SME acknowledgement request.",
1710                 HFILL
1711             }
1712         },
1713         {   &hf_smpp_regdel_notif,
1714             {   "Intermediate notif", "smpp.regdel.notif",
1715                 FT_UINT8, BASE_HEX, VALS(vals_regdel_notif), 0x10,
1716                 "Intermediate notification request.",
1717                 HFILL
1718             }
1719         },
1720         {   &hf_smpp_replace_if_present_flag,
1721             {   "Replace           ", "smpp.replace_if_present_flag",
1722                 FT_UINT8, BASE_HEX, VALS(vals_replace_if_present_flag), 0x01,
1723                 "Replace the short message with this one or not.",
1724                 HFILL
1725             }
1726         },
1727         {   &hf_smpp_data_coding,
1728             {   "Data coding", "smpp.data_coding",
1729                 FT_UINT8, BASE_HEX, VALS(vals_data_coding), 0x00,
1730                 "Defines the encoding scheme of the message.",
1731                 HFILL
1732             }
1733         },
1734         {   &hf_smpp_sm_default_msg_id,
1735             {   "Predefined message", "smpp.sm_default_msg_id",
1736                 FT_UINT8, BASE_DEC, NULL, 0x00,
1737                 "Index of a predefined ('canned') short message.",
1738                 HFILL
1739             }
1740         },
1741         {   &hf_smpp_sm_length,
1742             {   "Message length", "smpp.sm_length",
1743                 FT_UINT8, BASE_DEC, NULL, 0x00,
1744                 "Length of the message content.",
1745                 HFILL
1746             }
1747         },
1748         {   &hf_smpp_short_message,
1749             {   "Message", "smpp.message",
1750                 FT_NONE, BASE_NONE, NULL, 0x00,
1751                 "The actual message or data.",
1752                 HFILL
1753             }
1754         },
1755         {   &hf_smpp_message_id,
1756             {   "Message id.", "smpp.message_id",
1757                 FT_STRING, BASE_NONE, NULL, 0x00,
1758                 "Identifier of the submitted short message.",
1759                 HFILL
1760             }
1761         },
1762         {   &hf_smpp_dlist,
1763             {   "Destination list", "smpp.dlist",
1764                 FT_NONE, BASE_NONE, NULL, 0x00,
1765                 "The list of destinations for a short message.",
1766                 HFILL
1767             }
1768         },
1769         {   &hf_smpp_dlist_resp,
1770             {   "Unsuccesfull delivery list", "smpp.dlist_resp",
1771                 FT_NONE, BASE_NONE, NULL, 0x00,
1772                 "The list of unsuccesfull deliveries to destinations.",
1773                 HFILL
1774             }
1775         },
1776         {   &hf_smpp_dl_name,
1777             {   "Distr. list name", "smpp.dl_name",
1778                 FT_STRING, BASE_NONE, NULL, 0x00,
1779                 "The name of the distribution list.",
1780                 HFILL
1781             }
1782         },
1783         {   &hf_smpp_final_date,
1784             {   "Final date", "smpp.final_date",
1785                 FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
1786                 "Date-time when the queried message reached a final state.",
1787                 HFILL
1788             }
1789         },
1790         {   &hf_smpp_final_date_r,
1791             {   "Final date", "smpp.final_date_r",
1792                 FT_RELATIVE_TIME, BASE_NONE, NULL, 0x00,
1793                 "Date-time when the queried message reached a final state.",
1794                 HFILL
1795             }
1796         },
1797         {   &hf_smpp_message_state,
1798             {   "Message state", "smpp.message_state",
1799                 FT_UINT8, BASE_DEC, VALS(vals_message_state), 0x00,
1800                 "Specifies the status of the queried short message.",
1801                 HFILL
1802             }
1803         },
1804         {   &hf_smpp_error_code,
1805             {   "Error code", "smpp.error_code",
1806                 FT_UINT8, BASE_DEC, NULL, 0x00,
1807                 "Network specific error code defining reason for failure.",
1808                 HFILL
1809             }
1810         },
1811         {   &hf_smpp_error_status_code,
1812             {   "Status", "smpp.error_status_code",
1813                 FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00,
1814                 "Indicates success/failure of request for this address.",
1815                 HFILL
1816             }
1817         },
1818         {   &hf_smpp_esme_addr_ton,
1819             {   "Type of number (ESME)", "smpp.esme_addr_ton",
1820                 FT_UINT8, BASE_HEX, VALS(vals_addr_ton), 0x00,
1821                 "Indicates recipient type of number, given in the address.",
1822                 HFILL
1823             }
1824         },
1825         {   &hf_smpp_esme_addr_npi,
1826             {   "Numbering plan indicator (ESME)", "smpp.esme_addr_npi",
1827                 FT_UINT8, BASE_HEX, VALS(vals_addr_npi), 0x00,
1828                 "Gives the numbering plan this address belongs to.",
1829                 HFILL
1830             }
1831         },
1832         {   &hf_smpp_esme_addr,
1833             {   "ESME address", "smpp.esme_addr",
1834                 FT_STRING, BASE_NONE, NULL, 0x00,
1835                 "Address of ESME originating this message.",
1836                 HFILL
1837             }
1838         },
1839         {   &hf_smpp_dest_addr_subunit,
1840             {   "Subunit destination", "smpp.dest_addr_subunit",
1841                 FT_UINT8, BASE_HEX, VALS(vals_addr_subunit), 0x00,
1842                 "Subunit address within mobile to route message to.",
1843                 HFILL
1844             }
1845         },
1846         {   &hf_smpp_source_addr_subunit,
1847             {   "Subunit origin", "smpp.source_addr_subunit",
1848                 FT_UINT8, BASE_HEX, VALS(vals_addr_subunit), 0x00,
1849                 "Subunit address within mobile that generated the message.",
1850                 HFILL
1851             }
1852         },
1853         {   &hf_smpp_dest_network_type,
1854             {   "Destination network", "smpp.dest_network_type",
1855                 FT_UINT8, BASE_HEX, VALS(vals_network_type), 0x00,
1856                 "Network associated with the destination address.",
1857                 HFILL
1858             }
1859         },
1860         {   &hf_smpp_source_network_type,
1861             {   "Originator network", "smpp.source_network_type",
1862                 FT_UINT8, BASE_HEX, VALS(vals_network_type), 0x00,
1863                 "Network associated with the originator address.",
1864                 HFILL
1865             }
1866         },
1867         {   &hf_smpp_dest_bearer_type,
1868             {   "Destination bearer", "smpp.dest_bearer_type",
1869                 FT_UINT8, BASE_HEX, VALS(vals_bearer_type), 0x00,
1870                 "Desired bearer for delivery of message.",
1871                 HFILL
1872             }
1873         },
1874         {   &hf_smpp_source_bearer_type,
1875             {   "Originator bearer", "smpp.source_bearer_type",
1876                 FT_UINT8, BASE_HEX, VALS(vals_bearer_type), 0x00,
1877                 "Bearer over which the message originated.",
1878                 HFILL
1879             }
1880         },
1881         {   &hf_smpp_dest_telematics_id,
1882             {   "Telematic interworking (dest)", "smpp.dest_telematics_id",
1883                 FT_UINT16, BASE_HEX, NULL, 0x00,
1884                 "Telematic interworking to be used for message delivery.",
1885                 HFILL
1886             }
1887         },
1888         {   &hf_smpp_source_telematics_id,
1889             {   "Telematic interworking (orig)", "smpp.source_telematics_id",
1890                 FT_UINT16, BASE_HEX, NULL, 0x00,
1891                 "Telematic interworking used for message submission.",
1892                 HFILL
1893             }
1894         },
1895         {   &hf_smpp_qos_time_to_live,
1896             {   "Validity period", "smpp.qos_time_to_live",
1897                 FT_UINT32, BASE_DEC, NULL, 0x00,
1898                 "Number of seconds to retain message before expiry.",
1899                 HFILL
1900             }
1901         },
1902         {   &hf_smpp_payload_type,
1903             {   "Payload", "smpp.payload_type",
1904                 FT_UINT8, BASE_DEC, VALS(vals_payload_type), 0x00,
1905                 "PDU type contained in the message payload.",
1906                 HFILL
1907             }
1908         },
1909         {   &hf_smpp_additional_status_info_text,
1910             {   "Information", "smpp.additional_status_info_text",
1911                 FT_STRING, BASE_NONE, NULL, 0x00,
1912                 "Description of the meaning of a response PDU.",
1913                 HFILL
1914             }
1915         },
1916         {   &hf_smpp_receipted_message_id,
1917             {   "SMSC identifier", "smpp.receipted_message_id",
1918                 FT_STRING, BASE_NONE, NULL, 0x00,
1919                 "SMSC handle of the message being received.",
1920                 HFILL
1921             }
1922         },
1923         {   &hf_smpp_privacy_indicator,
1924             {   "Privacy indicator", "smpp.privacy_indicator",
1925                 FT_UINT8, BASE_DEC, VALS(vals_privacy_indicator), 0x00,
1926                 "Indicates the privacy level of the message.",
1927                 HFILL
1928             }
1929         },
1930         {   &hf_smpp_user_message_reference,
1931             {   "Message reference", "smpp.user_message_reference",
1932                 FT_UINT16, BASE_HEX, NULL, 0x00,
1933                 "Reference to the message, assigned by the user.",
1934                 HFILL
1935             }
1936         },
1937         {   &hf_smpp_user_response_code,
1938             {   "Application response code", "smpp.user_response_code",
1939                 FT_UINT8, BASE_HEX, NULL, 0x00,
1940                 "A response code set by the user.",
1941                 HFILL
1942             }
1943         },
1944         {   &hf_smpp_language_indicator,
1945             {   "Language", "smpp.language_indicator",
1946                 FT_UINT8, BASE_DEC, VALS(vals_language_indicator), 0x00,
1947                 "Indicates the language of the short message.",
1948                 HFILL
1949             }
1950         },
1951         {   &hf_smpp_source_port,
1952             {   "Source port", "smpp.source_port",
1953                 FT_UINT16, BASE_HEX, NULL, 0x00,
1954                 "Application port associated with the source of the message.",
1955                 HFILL
1956             }
1957         },
1958         {   &hf_smpp_destination_port,
1959             {   "Destination port", "smpp.destination_port",
1960                 FT_UINT16, BASE_HEX, NULL, 0x00,
1961                 "Application port associated with the destination of the message.",
1962                 HFILL
1963             }
1964         },
1965         {   &hf_smpp_sar_msg_ref_num,
1966             {   "SAR reference number", "smpp.sar_msg_ref_num",
1967                 FT_UINT16, BASE_DEC, NULL, 0x00,
1968                 "Reference number for a concatenated short message.",
1969                 HFILL
1970             }
1971         },
1972         {   &hf_smpp_sar_total_segments,
1973             {   "SAR size", "smpp.sar_total_segments",
1974                 FT_UINT16, BASE_DEC, NULL, 0x00,
1975                 "Number of segments of a concatenated short message.",
1976                 HFILL
1977             }
1978         },
1979         {   &hf_smpp_sar_segment_seqnum,
1980             {   "SAR sequence number", "smpp.sar_segment_seqnum",
1981                 FT_UINT8, BASE_DEC, NULL, 0x00,
1982                 "Segment number within a concatenated short message.",
1983                 HFILL
1984             }
1985         },
1986         {   &hf_smpp_display_time,
1987             {   "Display time", "smpp.display_time",
1988                 FT_UINT8, BASE_DEC, VALS(vals_display_time), 0x00,
1989                 "Associates a display time with the message on the handset.",
1990                 HFILL
1991             }
1992         },
1993         {   &hf_smpp_ms_validity,
1994             {   "Validity info", "smpp.ms_validity",
1995                 FT_UINT8, BASE_DEC, VALS(vals_ms_validity), 0x00,
1996                 "Associates validity info with the message on the handset.",
1997                 HFILL
1998             }
1999         },
2000         {   &hf_smpp_dpf_result,
2001             {   "Delivery pending set?", "smpp.dpf_result",
2002                 FT_UINT8, BASE_DEC, VALS(vals_dpf_result), 0x00,
2003                 "Indicates whether Delivery Pending Flag was set.",
2004                 HFILL
2005             }
2006         },
2007         {   &hf_smpp_set_dpf,
2008             {   "Request DPF set", "smpp.set_dpf",
2009                 FT_UINT8, BASE_DEC, VALS(vals_set_dpf), 0x00,
2010                 "Request to set the DPF for certain failure scenario's.",
2011                 HFILL
2012             }
2013         },
2014         {   &hf_smpp_ms_availability_status,
2015             {   "Availability status", "smpp.ms_availability_status",
2016                 FT_UINT8, BASE_DEC, VALS(vals_ms_availability_status), 0x00,
2017                 "Indicates the availability state of the handset.",
2018                 HFILL
2019             }
2020         },
2021         {   &hf_smpp_delivery_failure_reason,
2022             {   "Delivery failure reason", "smpp.delivery_failure_reason",
2023                 FT_UINT8, BASE_DEC, VALS(vals_delivery_failure_reason), 0x00,
2024                 "Indicates the reason for a failed delivery attempt.",
2025                 HFILL
2026             }
2027         },
2028         {   &hf_smpp_more_messages_to_send,
2029             {   "More messages?", "smpp.more_messages_to_send",
2030                 FT_UINT8, BASE_DEC, VALS(vals_more_messages_to_send), 0x00,
2031                 "Indicates more messages pending for the same destination.",
2032                 HFILL
2033             }
2034         },
2035         {   &hf_smpp_number_of_messages,
2036             {   "Number of messages", "smpp.number_of_messages",
2037                 FT_UINT8, BASE_DEC, NULL, 0x00,
2038                 "Indicates number of messages stored in a mailbox.",
2039                 HFILL
2040             }
2041         },
2042         {   &hf_smpp_its_reply_type,
2043             {   "Reply method", "smpp.its_reply_type",
2044                 FT_UINT8, BASE_DEC, VALS(vals_its_reply_type), 0x00,
2045                 "Indicates the handset reply method on message receipt.",
2046                 HFILL
2047             }
2048         },
2049         {   &hf_smpp_ussd_service_op,
2050             {   "USSD service operation", "smpp.ussd_service_op",
2051                 FT_UINT8, BASE_DEC, VALS(vals_ussd_service_op), 0x00,
2052                 "Indicates the USSD service operation.",
2053                 HFILL
2054             }
2055         },
2056         {   &hf_smpp_vendor_op,
2057             {   "Optional parameter - Vendor-specific", "smpp.vendor_op",
2058                 FT_NONE, BASE_NONE, NULL, 0x00,
2059                 "A supplied optional parameter specific to an SMSC-vendor.",
2060                 HFILL
2061             }
2062         },
2063         {   &hf_smpp_reserved_op,
2064             {   "Optional parameter - Reserved", "smpp.reserved_op",
2065                 FT_NONE, BASE_NONE, NULL, 0x00,
2066                 "An optional parameter that is reserved in this version.",
2067                 HFILL
2068             }
2069         },
2070         {   &hf_smpp_msg_wait_ind,
2071             {   "Indication", "smpp.msg_wait.ind",
2072                 FT_UINT8, BASE_HEX, VALS(vals_msg_wait_ind), 0x80,
2073                 "Indicates to the handset that a message is waiting.",
2074                 HFILL
2075             }
2076         },
2077         {   &hf_smpp_msg_wait_type,
2078             {   "Type      ", "smpp.msg_wait.type",
2079                 FT_UINT8, BASE_HEX, VALS(vals_msg_wait_type), 0x03,
2080                 "Indicates type of message that is waiting.",
2081                 HFILL
2082             }
2083         },
2084         {   &hf_smpp_SC_interface_version,
2085             {   "SMSC-supported version", "smpp.SC_interface_version",
2086                 FT_STRING, BASE_NONE, NULL, 0x00,
2087                 "Version of SMPP interface supported by the SMSC.",
2088                 HFILL
2089             }
2090         },
2091         {   &hf_smpp_callback_num_pres,
2092             {   "Presentation", "smpp.callback_num.pres",
2093                 FT_UINT8, BASE_HEX, VALS(vals_callback_num_pres), 0x0C,
2094                 "Controls the presentation indication.",
2095                 HFILL
2096             }
2097         },
2098         {   &hf_smpp_callback_num_scrn,
2099             {   "Screening   ", "smpp.callback_num.scrn",
2100                 FT_UINT8, BASE_HEX, VALS(vals_callback_num_scrn), 0x03,
2101                 "Controls screening of the callback-number.",
2102                 HFILL
2103             }
2104         },
2105         {   &hf_smpp_callback_num_atag,
2106             {   "Callback number - alphanumeric display tag",
2107                 "smpp.callback_num_atag",
2108                 FT_NONE, BASE_NONE, NULL, 0x00,
2109                 "Associates an alphanumeric display with call back number.",
2110                 HFILL
2111             }
2112         },
2113         {   &hf_smpp_callback_num,
2114             {   "Callback number", "smpp.callback_num",
2115                 FT_NONE, BASE_NONE, NULL, 0x00,
2116                 "Associates a call back number with the message.",
2117                 HFILL
2118             }
2119         },
2120         {   &hf_smpp_network_error_type,
2121             {   "Error type", "smpp.network_error.type",
2122                 FT_UINT8, BASE_DEC, VALS(vals_network_error_type), 0x00,
2123                 "Indicates the network type.",
2124                 HFILL
2125             }
2126         },
2127         {   &hf_smpp_network_error_code,
2128             {   "Error code", "smpp.network_error.code",
2129                 FT_UINT16, BASE_HEX, NULL, 0x00,
2130                 "Gives the actual network error code.",
2131                 HFILL
2132             }
2133         },
2134         {   &hf_smpp_message_payload,
2135             {   "Payload", "smpp.message_payload",
2136                 FT_NONE, BASE_NONE, NULL, 0x00,
2137                 "Short message user data.",
2138                 HFILL
2139             }
2140         },
2141         {   &hf_smpp_alert_on_message_delivery,
2142             {   "Alert on delivery", "smpp.alert_on_message_delivery",
2143                 FT_NONE, BASE_NONE, NULL, 0x00,
2144                 "Instructs the handset to alert user on message delivery.",
2145                 HFILL
2146             }
2147         },
2148         {   &hf_smpp_its_session_number,
2149             {   "Session number", "smpp.its_session.number",
2150                 FT_UINT8, BASE_DEC, NULL, 0x00,
2151                 "Session number of interactive teleservice.",
2152                 HFILL
2153             }
2154         },
2155         {   &hf_smpp_its_session_sequence,
2156             {   "Sequence number  ", "smpp.its_session.sequence",
2157                 FT_UINT8, BASE_HEX, NULL, 0xFE,
2158                 "Sequence number of the dialogue unit.",
2159                 HFILL
2160             }
2161         },
2162         {   &hf_smpp_its_session_ind,
2163             {   "Session indicator", "smpp.its_session.ind",
2164                 FT_UINT8, BASE_HEX, NULL, 0x01,
2165                 "Indicates whether this message is end of conversation.",
2166                 HFILL
2167             }
2168         },
2169         {   &hf_smpp_opt_param,
2170             {   "Optional parameters", "smpp.opt_param",
2171                 FT_NONE, BASE_NONE, NULL, 0x00,
2172                 "The list of optional parameters in this operation.",
2173                 HFILL
2174             }
2175         },
2176     };
2177     /* Setup protocol subtree array */
2178     static gint *ett[] = {
2179             &ett_smpp,
2180             &ett_dlist,
2181             &ett_dlist_resp,
2182             &ett_opt_param
2183     };
2184     /* Register the protocol name and description */
2185     proto_smpp = proto_register_protocol("Short Message Peer to Peer",
2186                                          "SMPP", "smpp");
2187
2188     /* Required function calls to register header fields and subtrees used */
2189     proto_register_field_array(proto_smpp, hf, array_length(hf));
2190     proto_register_subtree_array(ett, array_length(ett));
2191 }
2192
2193 /*
2194  * If dissector uses sub-dissector registration add a registration routine.
2195  * This format is required because a script is used to find these routines and
2196  * create the code that calls these routines.
2197  */
2198 void
2199 proto_reg_handoff_smpp(void)
2200 {
2201     dissector_handle_t smpp_handle;
2202
2203     /*
2204      * SMPP can be spoken on any port under TCP or X.25
2205      * ...how *do* we do that under x.25?
2206      */
2207     smpp_handle = create_dissector_handle(dissect_smpp, proto_smpp);
2208     dissector_add_handle("tcp.port", smpp_handle);
2209     heur_dissector_add("tcp", dissect_smpp_heur, proto_smpp);
2210 }