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