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