diff options
-rw-r--r-- | epan/dissectors/packet-smpp.c | 1754 |
1 files changed, 841 insertions, 913 deletions
diff --git a/epan/dissectors/packet-smpp.c b/epan/dissectors/packet-smpp.c index 6591781968..90697c8b18 100644 --- a/epan/dissectors/packet-smpp.c +++ b/epan/dissectors/packet-smpp.c @@ -47,28 +47,12 @@ #include "packet-tcp.h" #include "packet-smpp.h" -/* General-purpose debug logger. - * Requires double parentheses because of variable arguments of printf(). - * - * Enable debug logging for SMPP by defining AM_CFLAGS - * so that it contains "-DDEBUG_smpp" - */ -#ifdef DEBUG_smpp -#define DebugLog(x) \ - g_print("%s:%u: ", __FILE__, __LINE__); \ - g_print x -#else -#define DebugLog(x) ; -#endif - -#define SMPP_MIN_LENGTH 16 +#define SMPP_FIXED_HEADER_LENGTH 16 +#define SMPP_MIN_LENGTH SMPP_FIXED_HEADER_LENGTH /* Forward declarations */ void proto_register_smpp(void); void proto_reg_handoff_smpp(void); -static int dissect_smpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); -static guint get_smpp_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset, void *data); -static int dissect_smpp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_); /* * Initialize the protocol and registered fields @@ -260,6 +244,8 @@ static gint ett_dlist_resp = -1; static gint ett_opt_params = -1; static gint ett_opt_param = -1; static gint ett_dcs = -1; +static gint ett_dcs_gsm_sms = -1; +static gint ett_dcs_gsm_cbs = -1; static dissector_handle_t smpp_handle; @@ -269,141 +255,159 @@ static gboolean reassemble_over_tcp = TRUE; /* Tap */ static int smpp_tap = -1; +#define SMPP_COMMAND_ID_GENERIC_NACK 0x00000000 +#define SMPP_COMMAND_ID_BIND_RECEIVER 0x00000001 +#define SMPP_COMMAND_ID_BIND_TRANSMITTER 0x00000002 +#define SMPP_COMMAND_ID_QUERY_SM 0x00000003 +#define SMPP_COMMAND_ID_SUBMIT_SM 0x00000004 +#define SMPP_COMMAND_ID_DELIVER_SM 0x00000005 +#define SMPP_COMMAND_ID_UNBIND 0x00000006 +#define SMPP_COMMAND_ID_REPLACE_SM 0x00000007 +#define SMPP_COMMAND_ID_CANCEL_SM 0x00000008 +#define SMPP_COMMAND_ID_BIND_TRANSCEIVER 0x00000009 +#define SMPP_COMMAND_ID_OUTBIND 0x0000000B +#define SMPP_COMMAND_ID_ENQUIRE_LINK 0x00000015 +#define SMPP_COMMAND_ID_SUBMIT_MULTI 0x00000021 +#define SMPP_COMMAND_ID_ALERT_NOTIFICATION 0x00000102 +#define SMPP_COMMAND_ID_DATA_SM 0x00000103 +/* Introduced in SMPP 5.0 */ +#define SMPP_COMMAND_ID_BROADCAST_SM 0x00000111 +#define SMPP_COMMAND_ID_QUERY_BROADCAST_SM 0x00000112 +#define SMPP_COMMAND_ID_CANCEL_BROADCAST_SM 0x00000113 +/* Huawei SMPP+ extensions */ +#define SMPP_COMMAND_ID_HUAWEI_AUTH_ACC 0x01000001 +#define SMPP_COMMAND_ID_HUAWEI_SM_RESULT_NOTIFY 0X01000002 + + +#define SMPP_COMMAND_ID_RESPONSE_MASK 0x80000000 + /* * Value-arrays for field-contents */ static const value_string vals_command_id[] = { /* Operation */ - { 0x80000000, "Generic_nack" }, - { 0x00000001, "Bind_receiver" }, - { 0x80000001, "Bind_receiver - resp" }, - { 0x00000002, "Bind_transmitter" }, - { 0x80000002, "Bind_transmitter - resp" }, - { 0x00000003, "Query_sm" }, - { 0x80000003, "Query_sm - resp" }, - { 0x00000004, "Submit_sm" }, - { 0x80000004, "Submit_sm - resp" }, - { 0x00000005, "Deliver_sm" }, - { 0x80000005, "Deliver_sm - resp" }, - { 0x00000006, "Unbind" }, - { 0x80000006, "Unbind - resp" }, - { 0x00000007, "Replace_sm" }, - { 0x80000007, "Replace_sm - resp" }, - { 0x00000008, "Cancel_sm" }, - { 0x80000008, "Cancel_sm - resp" }, - { 0x00000009, "Bind_transceiver" }, - { 0x80000009, "Bind_transceiver - resp" }, - { 0x0000000B, "Outbind" }, - { 0x00000015, "Enquire_link" }, - { 0x80000015, "Enquire_link - resp" }, - { 0x00000021, "Submit_multi" }, - { 0x80000021, "Submit_multi - resp" }, - { 0x00000102, "Alert_notification" }, - { 0x00000103, "Data_sm" }, - { 0x80000103, "Data_sm - resp" }, - /* Introduced in SMPP 5.0 */ - { 0x00000111, "Broadcast_sm" }, - { 0x80000111, "Broadcast_sm - resp" }, - { 0x00000112, "Query_broadcast_sm" }, - { 0x80000112, "Query_broadcast_sm - resp" }, - { 0x00000113, "Cancel_broadcast_sm" }, - { 0x80000113, "Cancel_broadcast_sm - resp" }, - /* Huawei SMPP+ extensions */ - { 0x01000001, "Auth_acc" }, - { 0x81000001, "Auth_acc - resp" }, - { 0X01000002, "Sm_result_notify" }, - { 0X81000002, "Sm_result_notify - resp" }, - { 0, NULL } -}; - -static const value_string vals_command_status[] = { /* Status */ - { 0x00000000, "Ok" }, - { 0x00000001, "Message length is invalid" }, - { 0x00000002, "Command length is invalid" }, - { 0x00000003, "Invalid command ID" }, - { 0x00000004, "Incorrect BIND status for given command" }, - { 0x00000005, "ESME already in bound state" }, - { 0x00000006, "Invalid priority flag" }, - { 0x00000007, "Invalid registered delivery flag" }, - { 0x00000008, "System error" }, - { 0x00000009, "[Reserved]" }, - { 0x0000000A, "Invalid source address" }, - { 0x0000000B, "Invalid destination address" }, - { 0x0000000C, "Message ID is invalid" }, - { 0x0000000D, "Bind failed" }, - { 0x0000000E, "Invalid password" }, - { 0x0000000F, "Invalid system ID" }, - { 0x00000010, "[Reserved]" }, - { 0x00000011, "Cancel SM failed" }, - { 0x00000012, "[Reserved]" }, - { 0x00000013, "Replace SM failed" }, - { 0x00000014, "Message queue full" }, - { 0x00000015, "Invalid service type" }, - { 0x00000033, "Invalid number of destinations" }, - { 0x00000034, "Invalid distribution list name" }, - { 0x00000040, "Destination flag is invalid (submit_multi)" }, - { 0x00000041, "[Reserved]" }, - { 0x00000042, "Invalid 'submit with replace' request" }, - { 0x00000043, "Invalid esm_class field data" }, - { 0x00000044, "Cannot submit to distribution list" }, - { 0x00000045, "submit_sm or submit_multi failed" }, - { 0x00000046, "[Reserved]" }, - { 0x00000047, "[Reserved]" }, - { 0x00000048, "Invalid source address TON" }, - { 0x00000049, "Invalid source address NPI" }, - { 0x00000050, "Invalid destination address TON" }, - { 0x00000051, "Invalid destination address NPI" }, - { 0x00000052, "[Reserved]" }, - { 0x00000053, "Invalid system_type field" }, - { 0x00000054, "Invalid replace_if_present flag" }, - { 0x00000055, "Invalid number of messages" }, - { 0x00000056, "[Reserved]" }, - { 0x00000057, "[Reserved]" }, - { 0x00000058, "Throttling error (ESME exceeded allowed message limits)" }, - { 0x00000059, "[Reserved]" }, - { 0x00000060, "[Reserved]" }, - { 0x00000061, "Invalid scheduled delivery time" }, - { 0x00000062, "Invalid message validity period (expiry time)" }, - { 0x00000063, "Predefined message invalid or not found" }, - { 0x00000064, "ESME receiver temporary app error code" }, - { 0x00000065, "ESME receiver permanent app error code" }, - { 0x00000066, "ESME receiver reject message error code" }, - { 0x00000067, "query_sm request failed" }, - { 0x000000C0, "Error in the optional part of the PDU body" }, - { 0x000000C1, "Optional parameter not allowed" }, - { 0x000000C2, "Invalid parameter length" }, - { 0x000000C3, "Expected optional parameter missing" }, - { 0x000000C4, "Invalid optional parameter value" }, - { 0x000000FE, "(Transaction) Delivery failure (used for data_sm_resp)" }, - { 0x000000FF, "Unknown error" }, - /* Introduced in SMPP 5.0 */ - { 0x00000100, "ESME Not authorised to use specified service_type." }, - { 0x00000101, "ESME Prohibited from using specified operation."}, - { 0x00000102, "Specified service_type is unavailable." }, - { 0x00000103, "Specified service_type is denied." }, - { 0x00000104, "Invalid Data Coding Scheme." }, - { 0x00000105, "Source Address Sub unit is Invalid." }, - { 0x00000106, "Destination Address Sub unit is Invalid." }, - { 0x00000107, "Broadcast Frequency Interval is invalid." }, - { 0x00000108, "Broadcast Alias Name is invalid." }, - { 0x00000109, "Broadcast Area Format is invalid." }, - { 0x0000010A, "Number of Broadcast Areas is invalid." }, - { 0x0000010B, "Broadcast Content Type is invalid." }, - { 0x0000010C, "Broadcast Message Class is invalid." }, - { 0x0000010D, "broadcast_sm operation failed." }, - { 0x0000010E, "query_broadcast_sm operation failed." }, - { 0x0000010F, "cancel_broadcast_sm operation failed." }, - { 0x00000110, "Number of Repeated Broadcasts is invalid." }, - { 0x00000111, "Broadcast Service Group is invalid." }, - { 0x00000112, "Broadcast Channel Indicator is invalid." }, + { SMPP_COMMAND_ID_BIND_RECEIVER, "Bind_receiver" }, + { SMPP_COMMAND_ID_BIND_TRANSMITTER, "Bind_transmitter" }, + { SMPP_COMMAND_ID_QUERY_SM, "Query_sm" }, + { SMPP_COMMAND_ID_SUBMIT_SM, "Submit_sm" }, + { SMPP_COMMAND_ID_DELIVER_SM, "Deliver_sm" }, + { SMPP_COMMAND_ID_UNBIND, "Unbind" }, + { SMPP_COMMAND_ID_REPLACE_SM, "Replace_sm" }, + { SMPP_COMMAND_ID_CANCEL_SM, "Cancel_sm" }, + { SMPP_COMMAND_ID_BIND_TRANSCEIVER, "Bind_transceiver" }, + { SMPP_COMMAND_ID_OUTBIND, "Outbind" }, + { SMPP_COMMAND_ID_ENQUIRE_LINK, "Enquire_link" }, + { SMPP_COMMAND_ID_SUBMIT_MULTI, "Submit_multi" }, + { SMPP_COMMAND_ID_ALERT_NOTIFICATION, "Alert_notification" }, + { SMPP_COMMAND_ID_DATA_SM, "Data_sm" }, + { SMPP_COMMAND_ID_BROADCAST_SM, "Broadcast_sm" }, + { SMPP_COMMAND_ID_QUERY_BROADCAST_SM, "Query_broadcast_sm" }, + { SMPP_COMMAND_ID_CANCEL_BROADCAST_SM, "Cancel_broadcast_sm" }, + { SMPP_COMMAND_ID_HUAWEI_AUTH_ACC, "Auth_acc" }, + { SMPP_COMMAND_ID_HUAWEI_SM_RESULT_NOTIFY, "Sm_result_notify" }, + + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_GENERIC_NACK, "Generic_nack" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_BIND_RECEIVER, "Bind_receiver - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_BIND_TRANSMITTER, "Bind_transmitter - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_QUERY_SM, "Query_sm - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_SUBMIT_SM, "Submit_sm - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_DELIVER_SM, "Deliver_sm - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_UNBIND, "Unbind - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_REPLACE_SM, "Replace_sm - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_CANCEL_SM, "Cancel_sm - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_BIND_TRANSCEIVER, "Bind_transceiver - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_ENQUIRE_LINK, "Enquire_link - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_SUBMIT_MULTI, "Submit_multi - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_DATA_SM, "Data_sm - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_BROADCAST_SM, "Broadcast_sm - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_QUERY_BROADCAST_SM, "Query_broadcast_sm - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_CANCEL_BROADCAST_SM, "Cancel_broadcast_sm - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_HUAWEI_AUTH_ACC, "Auth_acc - resp" }, + { SMPP_COMMAND_ID_RESPONSE_MASK|SMPP_COMMAND_ID_HUAWEI_SM_RESULT_NOTIFY, "Sm_result_notify - resp" }, { 0, NULL } }; -static const range_string reserved_command_status[] = { /* Reserved ranges */ +static const range_string rvals_command_status[] = { /* Status */ + { 0x00000000, 0x00000000, "Ok" }, + { 0x00000001, 0x00000001, "Message length is invalid" }, + { 0x00000002, 0x00000002, "Command length is invalid" }, + { 0x00000003, 0x00000003, "Invalid command ID" }, + { 0x00000004, 0x00000004, "Incorrect BIND status for given command" }, + { 0x00000005, 0x00000005, "ESME already in bound state" }, + { 0x00000006, 0x00000006, "Invalid priority flag" }, + { 0x00000007, 0x00000007, "Invalid registered delivery flag" }, + { 0x00000008, 0x00000008, "System error" }, + { 0x00000009, 0x00000009, "[Reserved]" }, + { 0x0000000A, 0x0000000A, "Invalid source address" }, + { 0x0000000B, 0x0000000B, "Invalid destination address" }, + { 0x0000000C, 0x0000000C, "Message ID is invalid" }, + { 0x0000000D, 0x0000000D, "Bind failed" }, + { 0x0000000E, 0x0000000E, "Invalid password" }, + { 0x0000000F, 0x0000000F, "Invalid system ID" }, + { 0x00000010, 0x00000010, "[Reserved]" }, + { 0x00000011, 0x00000011, "Cancel SM failed" }, + { 0x00000012, 0x00000012, "[Reserved]" }, + { 0x00000013, 0x00000013, "Replace SM failed" }, + { 0x00000014, 0x00000014, "Message queue full" }, + { 0x00000015, 0x00000015, "Invalid service type" }, { 0x00000016, 0x00000032, "[Reserved]" }, + { 0x00000033, 0x00000033, "Invalid number of destinations" }, + { 0x00000034, 0x00000034, "Invalid distribution list name" }, { 0x00000035, 0x0000003F, "[Reserved]" }, + { 0x00000040, 0x00000040, "Destination flag is invalid (submit_multi)" }, + { 0x00000041, 0x00000041, "[Reserved]" }, + { 0x00000042, 0x00000042, "Invalid 'submit with replace' request" }, + { 0x00000043, 0x00000043, "Invalid esm_class field data" }, + { 0x00000044, 0x00000044, "Cannot submit to distribution list" }, + { 0x00000045, 0x00000045, "submit_sm or submit_multi failed" }, + { 0x00000046, 0x00000047, "[Reserved]" }, + { 0x00000048, 0x00000048, "Invalid source address TON" }, + { 0x00000049, 0x00000049, "Invalid source address NPI" }, + { 0x00000050, 0x00000050, "Invalid destination address TON" }, + { 0x00000051, 0x00000051, "Invalid destination address NPI" }, + { 0x00000052, 0x00000052, "[Reserved]" }, + { 0x00000053, 0x00000053, "Invalid system_type field" }, + { 0x00000054, 0x00000054, "Invalid replace_if_present flag" }, + { 0x00000055, 0x00000055, "Invalid number of messages" }, + { 0x00000056, 0x00000057, "[Reserved]" }, + { 0x00000058, 0x00000058, "Throttling error (ESME exceeded allowed message limits)" }, + { 0x00000059, 0x00000060, "[Reserved]" }, + { 0x00000061, 0x00000061, "Invalid scheduled delivery time" }, + { 0x00000062, 0x00000062, "Invalid message validity period (expiry time)" }, + { 0x00000063, 0x00000063, "Predefined message invalid or not found" }, + { 0x00000064, 0x00000064, "ESME receiver temporary app error code" }, + { 0x00000065, 0x00000065, "ESME receiver permanent app error code" }, + { 0x00000066, 0x00000066, "ESME receiver reject message error code" }, + { 0x00000067, 0x00000067, "query_sm request failed" }, { 0x00000068, 0x000000BF, "[Reserved]" }, + { 0x000000C0, 0x000000C0, "Error in the optional part of the PDU body" }, + { 0x000000C1, 0x000000C1, "Optional parameter not allowed" }, + { 0x000000C2, 0x000000C2, "Invalid parameter length" }, + { 0x000000C3, 0x000000C3, "Expected optional parameter missing" }, + { 0x000000C4, 0x000000C4, "Invalid optional parameter value" }, { 0x000000C5, 0x000000FD, "[Reserved]" }, - { 0x00000400, 0x000004FF, "[Message center vendor-specific error code]" }, + { 0x000000FE, 0x000000FE, "(Transaction) Delivery failure (used for data_sm_resp)" }, + { 0x000000FF, 0x000000FF, "Unknown error" }, + /* Introduced in SMPP 5.0 */ + { 0x00000100, 0x00000100, "ESME Not authorised to use specified service_type." }, + { 0x00000101, 0x00000101, "ESME Prohibited from using specified operation."}, + { 0x00000102, 0x00000102, "Specified service_type is unavailable." }, + { 0x00000103, 0x00000103, "Specified service_type is denied." }, + { 0x00000104, 0x00000104, "Invalid Data Coding Scheme." }, + { 0x00000105, 0x00000105, "Source Address Sub unit is Invalid." }, + { 0x00000106, 0x00000106, "Destination Address Sub unit is Invalid." }, + { 0x00000107, 0x00000107, "Broadcast Frequency Interval is invalid." }, + { 0x00000108, 0x00000108, "Broadcast Alias Name is invalid." }, + { 0x00000109, 0x00000109, "Broadcast Area Format is invalid." }, + { 0x0000010A, 0x0000010A, "Number of Broadcast Areas is invalid." }, + { 0x0000010B, 0x0000010B, "Broadcast Content Type is invalid." }, + { 0x0000010C, 0x0000010C, "Broadcast Message Class is invalid." }, + { 0x0000010D, 0x0000010D, "broadcast_sm operation failed." }, + { 0x0000010E, 0x0000010E, "query_broadcast_sm operation failed." }, + { 0x0000010F, 0x0000010F, "cancel_broadcast_sm operation failed." }, + { 0x00000110, 0x00000110, "Number of Repeated Broadcasts is invalid." }, + { 0x00000111, 0x00000111, "Broadcast Service Group is invalid." }, + { 0x00000112, 0x00000112, "Broadcast Channel Indicator is invalid." }, + { 0x00000400, 0x000004FF, "[Vendor-specific Error]" }, { 0x00000500, 0xFFFFFFFF, "[Reserved]" }, { 0, 0, NULL } }; @@ -582,7 +586,8 @@ static const value_string vals_data_coding[] = { { 12, "reserved" }, { 13, "Extended Kanji JIS(X 0212-1990)" }, { 14, "KS C 5601" }, - /*! \TODO Rest to be defined (bitmask?) according GSM 03.38 */ + { 15, "reserved" }, +/*! \TODO Rest to be defined (bitmask?) according GSM 03.38 */ { 0, NULL } }; @@ -1086,6 +1091,20 @@ static const value_string vals_msc_addr_npi [] = { { 0x00, NULL } }; +static const gint *regdel_fields[] = { + &hf_smpp_regdel_receipt, + &hf_smpp_regdel_acks, + &hf_smpp_regdel_notif, + NULL +}; + +static const gint *submit_msg_fields[] = { + &hf_smpp_esm_submit_msg_mode, + &hf_smpp_esm_submit_msg_type, + &hf_smpp_esm_submit_features, + NULL +}; + static dissector_handle_t gsm_sms_handle; /* @@ -1111,13 +1130,13 @@ smpp_stats_tree_per_packet(stats_tree *st, /* st as it was passed to us */ tick_stat_node(st, "SMPP Operations", 0, TRUE); - if ((tap_rec->command_id & 0x80000000) == 0x80000000) /* Response */ + if ((tap_rec->command_id & SMPP_COMMAND_ID_RESPONSE_MASK) == SMPP_COMMAND_ID_RESPONSE_MASK) /* Response */ { tick_stat_node(st, "SMPP Responses", st_smpp_ops, TRUE); tick_stat_node(st, val_to_str(tap_rec->command_id, vals_command_id, "Unknown 0x%08x"), st_smpp_res, FALSE); tick_stat_node(st, "SMPP Response Status", 0, TRUE); - tick_stat_node(st, val_to_str(tap_rec->command_status, vals_command_status, "Unknown 0x%08x"), st_smpp_res_status, FALSE); + tick_stat_node(st, rval_to_str(tap_rec->command_status, rvals_command_status, "Unknown 0x%08x"), st_smpp_res_status, FALSE); } else /* Request */ @@ -1215,15 +1234,11 @@ static const char * smpp_handle_string_return(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int field, int *offset) { gint len; - const char *str; + const char* str = (const char *)tvb_get_stringz_enc(pinfo->pool, tvb, *offset, &len, ENC_ASCII); - len = tvb_strsize(tvb, *offset); - if (len > 1) { - str = (char *)tvb_get_stringz_enc(pinfo->pool, tvb, *offset, &len, ENC_ASCII); + if (len > 0) proto_tree_add_string(tree, field, tvb, *offset, len, str); - } else { - str = ""; - } + (*offset) += len; return str; } @@ -1244,36 +1259,6 @@ smpp_handle_string_z(proto_tree *tree, tvbuff_t *tvb, int field, int *offset, } static void -smpp_handle_int1(proto_tree *tree, tvbuff_t *tvb, int field, int *offset) -{ - guint8 val; - - val = tvb_get_guint8(tvb, *offset); - proto_tree_add_uint(tree, field, tvb, *offset, 1, val); - (*offset)++; -} - -static void -smpp_handle_int2(proto_tree *tree, tvbuff_t *tvb, int field, int *offset) -{ - guint val; - - val = tvb_get_ntohs(tvb, *offset); - proto_tree_add_uint(tree, field, tvb, *offset, 2, val); - (*offset) += 2; -} - -static void -smpp_handle_int4(proto_tree *tree, tvbuff_t *tvb, int field, int *offset) -{ - guint val; - - val = tvb_get_ntohl(tvb, *offset); - proto_tree_add_uint(tree, field, tvb, *offset, 4, val); - (*offset) += 4; -} - -static void smpp_handle_time(proto_tree *tree, tvbuff_t *tvb, int field, int field_R, int *offset) { @@ -1327,8 +1312,10 @@ smpp_handle_dlist(proto_tree *tree, tvbuff_t *tvb, int *offset) dest_flag = tvb_get_guint8(tvb, tmpoff++); if (dest_flag == 1) /* SME address */ { - smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff); - smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff); + proto_tree_add_item(sub_tree, hf_smpp_dest_addr_ton, tvb, tmpoff, 1, ENC_NA); + tmpoff += 1; + proto_tree_add_item(sub_tree, hf_smpp_dest_addr_npi, tvb, tmpoff, 1, ENC_NA); + tmpoff += 1; smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff); } else /* Distribution list */ @@ -1363,10 +1350,13 @@ smpp_handle_dlist_resp(proto_tree *tree, tvbuff_t *tvb, int *offset) } while (entries--) { - smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_ton, &tmpoff); - smpp_handle_int1(sub_tree, tvb, hf_smpp_dest_addr_npi, &tmpoff); + proto_tree_add_item(sub_tree, hf_smpp_dest_addr_ton, tvb, tmpoff, 1, ENC_NA); + tmpoff += 1; + proto_tree_add_item(sub_tree, hf_smpp_dest_addr_npi, tvb, tmpoff, 1, ENC_NA); + tmpoff += 1; smpp_handle_string(sub_tree,tvb,hf_smpp_destination_addr,&tmpoff); - smpp_handle_int4(sub_tree, tvb, hf_smpp_error_status_code, &tmpoff); + proto_tree_add_item(sub_tree, hf_smpp_error_status_code, tvb, tmpoff, 4, ENC_BIG_ENDIAN); + tmpoff += 4; } *offset = tmpoff; } @@ -1399,11 +1389,6 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) guint16 tag; guint16 length; - guint8 field; - guint16 field16; - guint8 major, minor; - char *strval=NULL; - tag = tvb_get_ntohs(tvb, *offset); length = tvb_get_ntohs(tvb, (*offset+2)); @@ -1419,64 +1404,72 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) switch (tag) { case 0x0005: /* dest_addr_subunit */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_dest_addr_subunit, offset); + proto_tree_add_item(sub_tree, hf_smpp_dest_addr_subunit, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0006: /* dest_network_type */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_dest_network_type, offset); + proto_tree_add_item(sub_tree, hf_smpp_dest_network_type, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0007: /* dest_bearer_type */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_dest_bearer_type, offset); + proto_tree_add_item(sub_tree, hf_smpp_dest_bearer_type, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0008: /* dest_telematics_id */ - smpp_handle_int2(sub_tree, tvb, - hf_smpp_dest_telematics_id, offset); + proto_tree_add_item(sub_tree, hf_smpp_dest_telematics_id, tvb, *offset, 2, ENC_BIG_ENDIAN); + (*offset) += 2; break; case 0x000D: /* source_addr_subunit */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_source_addr_subunit, offset); + proto_tree_add_item(sub_tree, hf_smpp_source_addr_subunit, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x000E: /* source_network_type */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_source_network_type, offset); + proto_tree_add_item(sub_tree, hf_smpp_source_network_type, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x000F: /* source_bearer_type */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_source_bearer_type, offset); + proto_tree_add_item(sub_tree, hf_smpp_source_bearer_type, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0010: /* source_telematics_id */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_source_telematics_id, offset); + proto_tree_add_item(sub_tree, hf_smpp_source_telematics_id, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0017: /* qos_time_to_live */ - smpp_handle_int4(sub_tree, tvb, - hf_smpp_qos_time_to_live, offset); + proto_tree_add_item(sub_tree, hf_smpp_qos_time_to_live, tvb, *offset, 4, ENC_BIG_ENDIAN); + (*offset) += 4; break; case 0x0019: /* payload_type */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_payload_type, offset); + proto_tree_add_item(sub_tree, hf_smpp_payload_type, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x001D: /* additional_status_info_text */ - smpp_handle_string(sub_tree, tvb, - hf_smpp_additional_status_info_text, offset); + if (length) + proto_tree_add_item(sub_tree, hf_smpp_additional_status_info_text, + tvb, *offset, length, ENC_NA | ENC_ASCII); + (*offset) += length; break; case 0x001E: /* receipted_message_id */ - smpp_handle_string(sub_tree, tvb, - hf_smpp_receipted_message_id, offset); - break; - case 0x0030: /* ms_msg_wait_facilities */ - field = tvb_get_guint8(tvb, *offset); - proto_tree_add_uint(sub_tree, hf_smpp_msg_wait_ind, - tvb, *offset, 1, field); - proto_tree_add_uint(sub_tree, hf_smpp_msg_wait_type, - tvb, *offset, 1, field); + if (length) + proto_tree_add_item(sub_tree, hf_smpp_receipted_message_id, + tvb, *offset, length, ENC_NA | ENC_ASCII); + (*offset) += length; + break; + case 0x0030: { /* ms_msg_wait_facilities */ + const gint *fields[] = { + &hf_smpp_msg_wait_ind, + &hf_smpp_msg_wait_type, + NULL + }; + + + proto_tree_add_bitmask_list(sub_tree, tvb, *offset, 1, fields, ENC_NA); (*offset)++; + } break; case 0x0201: /* privacy_indicator */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_privacy_indicator, offset); + proto_tree_add_item(sub_tree, hf_smpp_privacy_indicator, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0202: /* source_subaddress */ if (length) { @@ -1493,53 +1486,52 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) } break; case 0x0204: /* user_message_reference */ - smpp_handle_int2(sub_tree, tvb, - hf_smpp_user_message_reference, offset); + proto_tree_add_item(sub_tree, hf_smpp_user_message_reference, tvb, *offset, 2, ENC_BIG_ENDIAN); + (*offset) += 2; break; case 0x0205: /* user_response_code */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_user_response_code, offset); + proto_tree_add_item(sub_tree, hf_smpp_user_response_code, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x020A: /* source_port */ - smpp_handle_int2(sub_tree, tvb, - hf_smpp_source_port, offset); + proto_tree_add_item(sub_tree, hf_smpp_source_port, tvb, *offset, 2, ENC_BIG_ENDIAN); + (*offset) += 2; break; case 0x020B: /* destination_port */ - smpp_handle_int2(sub_tree, tvb, - hf_smpp_destination_port, offset); + proto_tree_add_item(sub_tree, hf_smpp_destination_port, tvb, *offset, 2, ENC_BIG_ENDIAN); + (*offset) += 2; break; case 0x020C: /* sar_msg_ref_num */ - smpp_handle_int2(sub_tree, tvb, - hf_smpp_sar_msg_ref_num, offset); + proto_tree_add_item(sub_tree, hf_smpp_sar_msg_ref_num, tvb, *offset, 2, ENC_BIG_ENDIAN); + (*offset) += 2; break; case 0x020D: /* language_indicator */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_language_indicator, offset); + proto_tree_add_item(sub_tree, hf_smpp_language_indicator, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x020E: /* sar_total_segments */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_sar_total_segments, offset); + proto_tree_add_item(sub_tree, hf_smpp_sar_total_segments, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x020F: /* sar_segment_seqnum */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_sar_segment_seqnum, offset); + proto_tree_add_item(sub_tree, hf_smpp_sar_segment_seqnum, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0210: /* SC_interface_version */ - field = tvb_get_guint8(tvb, *offset); - minor = field & 0x0F; - major = (field & 0xF0) >> 4; - strval=wmem_strdup_printf(wmem_packet_scope(), "%u.%u", major, minor); - proto_tree_add_string(sub_tree, hf_smpp_SC_interface_version, - tvb, *offset, 1, strval); - (*offset)++; + proto_tree_add_item(sub_tree, hf_smpp_SC_interface_version, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; - case 0x0302: /* callback_num_pres_ind */ - field = tvb_get_guint8(tvb, *offset); - proto_tree_add_uint(sub_tree, hf_smpp_callback_num_pres, - tvb, *offset, 1, field); - proto_tree_add_uint(sub_tree, hf_smpp_callback_num_scrn, - tvb, *offset, 1, field); + case 0x0302: { /* callback_num_pres_ind */ + + const gint *fields[] = { + &hf_smpp_callback_num_pres, + &hf_smpp_callback_num_scrn, + NULL + }; + + proto_tree_add_bitmask_list(sub_tree, tvb, *offset, 1, fields, ENC_NA); (*offset)++; + } break; case 0x0303: /* callback_num_atag */ if (length) @@ -1548,8 +1540,8 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) (*offset) += length; break; case 0x0304: /* number_of_messages */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_number_of_messages, offset); + proto_tree_add_item(sub_tree, hf_smpp_number_of_messages, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0381: /* callback_num */ if (length) @@ -1558,22 +1550,22 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) (*offset) += length; break; case 0x0420: /* dpf_result */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_dpf_result, offset); + proto_tree_add_item(sub_tree, hf_smpp_dpf_result, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0421: /* set_dpf */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_set_dpf, offset); + proto_tree_add_item(sub_tree, hf_smpp_set_dpf, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0422: /* ms_availability_status */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_ms_availability_status, offset); + proto_tree_add_item(sub_tree, hf_smpp_ms_availability_status, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0423: /* network_error_code */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_network_error_type, offset); - smpp_handle_int2(sub_tree, tvb, - hf_smpp_network_error_code, offset); + proto_tree_add_item(sub_tree, hf_smpp_network_error_type, tvb, *offset, 1, ENC_NA); + (*offset) += 1; + proto_tree_add_item(sub_tree, hf_smpp_network_error_code, tvb, *offset, 2, ENC_BIG_ENDIAN); + (*offset) += 2; break; case 0x0424: /* message_payload */ if (length) @@ -1582,36 +1574,33 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) (*offset) += length; break; case 0x0425: /* delivery_failure_reason */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_delivery_failure_reason, offset); + proto_tree_add_item(sub_tree, hf_smpp_delivery_failure_reason, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0426: /* more_messages_to_send */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_more_messages_to_send, offset); + proto_tree_add_item(sub_tree, hf_smpp_more_messages_to_send, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0427: /* message_state */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_message_state, offset); + proto_tree_add_item(sub_tree, hf_smpp_message_state, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0428: /* congestion_state */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_congestion_state, offset); - + proto_tree_add_item(sub_tree, hf_smpp_congestion_state, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0501: /* ussd_service_op */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_ussd_service_op, offset); + proto_tree_add_item(sub_tree, hf_smpp_ussd_service_op, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0600: /* broadcast_channel_indicator */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_broadcast_channel_indicator, offset); + proto_tree_add_item(sub_tree, hf_smpp_broadcast_channel_indicator, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0601: /* broadcast_content_type */ - field = tvb_get_guint8(tvb, *offset); - proto_tree_add_uint(sub_tree, hf_smpp_broadcast_content_type_nw, tvb, *offset, 1, field); - (*offset)++; - field16 = tvb_get_ntohs(tvb, *offset); - proto_tree_add_uint(sub_tree, hf_smpp_broadcast_content_type_type, tvb, *offset, 2, field16); + proto_tree_add_item(sub_tree, hf_smpp_broadcast_content_type_nw, tvb, *offset, 1, ENC_NA); + (*offset) += 1; + proto_tree_add_item(sub_tree, hf_smpp_broadcast_content_type_type, tvb, *offset, 2, ENC_BIG_ENDIAN); (*offset) += 2; break; case 0x0602: /* broadcast_content_type_info */ @@ -1621,35 +1610,32 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) (*offset) += length; break; case 0x0603: /* broadcast_message_class */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_broadcast_message_class, offset); + proto_tree_add_item(sub_tree, hf_smpp_broadcast_message_class, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0604: /* broadcast_rep_num */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_broadcast_rep_num, offset); + proto_tree_add_item(sub_tree, hf_smpp_broadcast_rep_num, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0605: /* broadcast_frequency_interval */ - field = tvb_get_guint8(tvb, *offset); - proto_tree_add_uint(sub_tree, hf_smpp_broadcast_frequency_interval_unit, tvb, *offset, 1, field); - (*offset)++; - field16 = tvb_get_ntohs(tvb, *offset); - proto_tree_add_uint(sub_tree, hf_smpp_broadcast_frequency_interval_value, tvb, *offset, 2, field16); + proto_tree_add_item(sub_tree, hf_smpp_broadcast_frequency_interval_unit, tvb, *offset, 1, ENC_NA); + (*offset) += 1; + proto_tree_add_item(sub_tree, hf_smpp_broadcast_frequency_interval_value, tvb, *offset, 2, ENC_BIG_ENDIAN); (*offset) += 2; break; case 0x0606: /* broadcast_area_identifier */ - field = tvb_get_guint8(tvb, *offset); - proto_tree_add_uint(sub_tree, hf_smpp_broadcast_area_identifier_format, tvb, *offset, 1, field); + proto_tree_add_item(sub_tree, hf_smpp_broadcast_area_identifier_format, tvb, *offset, 1, ENC_NA); proto_tree_add_item(sub_tree, hf_smpp_broadcast_area_identifier, tvb, *offset, length, ENC_NA); (*offset) += length; break; case 0x0607: /* broadcast_error_status */ - smpp_handle_int4(sub_tree, tvb, - hf_smpp_broadcast_error_status, offset); + proto_tree_add_item(sub_tree, hf_smpp_broadcast_error_status, tvb, *offset, 4, ENC_BIG_ENDIAN); + (*offset) += 4; break; case 0x0608: /* broadcast_area_success */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_broadcast_area_success, offset); + proto_tree_add_item(sub_tree, hf_smpp_broadcast_area_success, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0609: /* broadcast_end_time */ smpp_handle_time(sub_tree, tvb, hf_smpp_broadcast_end_time, @@ -1669,12 +1655,16 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) break; /* 0x060C is skipped in the specs for some reason :-? */ case 0x060D: /* source_network_id */ - smpp_handle_string_z(sub_tree, tvb, hf_smpp_source_network_id, - offset, "Empty!"); + if (length) + proto_tree_add_item(sub_tree, hf_smpp_source_network_id, + tvb, *offset, length, ENC_NA|ENC_ASCII); + (*offset) += length; break; case 0x060E: /* dest_network_id */ - smpp_handle_string_z(sub_tree, tvb, hf_smpp_dest_network_id, - offset, "Empty!"); + if (length) + proto_tree_add_item(sub_tree, hf_smpp_dest_network_id, + tvb, *offset, length, ENC_NA | ENC_ASCII); + (*offset) += length; break; case 0x060F: /* source_node_id */ if (length) @@ -1689,8 +1679,8 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) (*offset) += length; break; case 0x0611: /* dest_addr_np_resolution */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_dest_addr_np_resolution, offset); + proto_tree_add_item(sub_tree, hf_smpp_dest_addr_np_resolution, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x0612: /* dest_addr_np_information */ if (length) @@ -1706,17 +1696,17 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) (*offset) += length; break; case 0x1201: /* display_time */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_display_time, offset); + proto_tree_add_item(sub_tree, hf_smpp_display_time, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x1203: /* sms_signal */ - smpp_handle_int2(sub_tree, tvb, - hf_smpp_sms_signal, offset); + proto_tree_add_item(sub_tree, hf_smpp_sms_signal, tvb, *offset, 2, ENC_BIG_ENDIAN); + (*offset) += 2; /*! \todo Fill as per TIA/EIA-136-710-A */ break; case 0x1204: /* ms_validity */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_ms_validity, offset); + proto_tree_add_item(sub_tree, hf_smpp_ms_validity, tvb, *offset, 1, ENC_NA); + (*offset) += 1; break; case 0x130C: /* alert_on_message_delivery */ if (length == 0) { @@ -1724,23 +1714,27 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) hf_smpp_alert_on_message_delivery_null, tvb, *offset, length, ENC_NA); } else { - smpp_handle_int1(sub_tree, tvb, - hf_smpp_alert_on_message_delivery_type, offset); + proto_tree_add_item(sub_tree, hf_smpp_alert_on_message_delivery_type, tvb, *offset, 1, ENC_NA); + (*offset) += 1; } break; case 0x1380: /* its_reply_type */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_its_reply_type, offset); - break; - case 0x1383: /* its_session_info */ - smpp_handle_int1(sub_tree, tvb, - hf_smpp_its_session_number, offset); - field = tvb_get_guint8(tvb, *offset); - proto_tree_add_uint(sub_tree, hf_smpp_its_session_sequence, - tvb, *offset, 1, field); - proto_tree_add_uint(sub_tree, hf_smpp_its_session_ind, - tvb, *offset, 1, field); - (*offset)++; + proto_tree_add_item(sub_tree, hf_smpp_its_reply_type, tvb, *offset, 1, ENC_NA); + (*offset) += 1; + break; + case 0x1383: { /* its_session_info */ + + const gint *fields[] = { + &hf_smpp_its_session_sequence, + &hf_smpp_its_session_ind, + NULL + }; + + proto_tree_add_item(sub_tree, hf_smpp_its_session_number, tvb, *offset, 1, ENC_NA); + (*offset) += 1; + proto_tree_add_bitmask_list(sub_tree, tvb, *offset, 1, fields, ENC_NA); + (*offset) += 1; + } break; default: @@ -1754,7 +1748,9 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) *offset, length, ENC_NA); } - proto_item_append_text(sub_tree,": %s", tvb_bytes_to_str(wmem_packet_scope(), tvb,*offset,length)); + if (length > 0) + proto_item_append_text(sub_tree,": %s", tvb_bytes_to_str(wmem_packet_scope(), tvb,*offset,length)); + (*offset) += length; break; } @@ -1764,72 +1760,107 @@ smpp_handle_tlv(proto_tree *tree, tvbuff_t *tvb, int *offset) void smpp_handle_dcs(proto_tree *tree, tvbuff_t *tvb, int *offset) { - guint8 val; + guint32 val; int off = *offset; proto_tree *subtree, *code_tree; proto_item *pi; - val = tvb_get_guint8(tvb, off); - pi = proto_tree_add_uint(tree, hf_smpp_data_coding, tvb, off, 1, val); + pi = proto_tree_add_item_ret_uint(tree, hf_smpp_data_coding, tvb, off, 1, ENC_NA, &val); subtree = proto_item_add_subtree(pi, ett_dcs); /* SMPP Data Coding Scheme */ proto_tree_add_uint(subtree, hf_smpp_dcs, tvb, off, 1, val); - /* GSM SMS Data Coding Scheme */ - code_tree = proto_tree_add_subtree(subtree, tvb, off, 1, ett_dcs, NULL, "GSM SMS Data Coding"); - - proto_tree_add_uint(code_tree, - hf_smpp_dcs_sms_coding_group, tvb, off, 1, val); - if (val>>6 == 2) { /* Reserved */ - ; - } else if (val < 0xF0) { - proto_tree_add_boolean(code_tree, - hf_smpp_dcs_text_compression, tvb, off, 1, val); - proto_tree_add_boolean(code_tree, - hf_smpp_dcs_class_present, tvb, off, 1, val); - proto_tree_add_uint(code_tree, - hf_smpp_dcs_charset, tvb, off, 1, val); - if (val & 0x10) - proto_tree_add_uint(code_tree, - hf_smpp_dcs_class, tvb, off, 1, val); - } else { - proto_tree_add_uint(code_tree, hf_smpp_dcs_reserved, tvb, off, 1, val); - proto_tree_add_uint(code_tree, hf_smpp_dcs_charset, tvb, off, 1, val); - proto_tree_add_uint(code_tree, hf_smpp_dcs_class, tvb, off, 1, val); - } - /* Cell Broadcast Service (CBS) Data Coding Scheme */ - code_tree = proto_tree_add_subtree(subtree, tvb, off, 1, ett_dcs, NULL, - "GSM CBS Data Coding"); - proto_tree_add_uint(code_tree, - hf_smpp_dcs_cbs_coding_group, tvb, off, 1, val); - if (val < 0x40) { /* Language specified */ - proto_tree_add_uint(code_tree, - hf_smpp_dcs_cbs_language, tvb, off, 1, val); - } else if (val>>6 == 1) { /* General Data Coding indication */ - proto_tree_add_boolean(code_tree, - hf_smpp_dcs_text_compression, tvb, off, 1, val); - proto_tree_add_boolean(code_tree, - hf_smpp_dcs_class_present, tvb, off, 1, val); - proto_tree_add_uint(code_tree, - hf_smpp_dcs_charset, tvb, off, 1, val); - if (val & 0x10) - proto_tree_add_uint(code_tree, - hf_smpp_dcs_class, tvb, off, 1, val); - } else if (val>>6 == 2) { /* Message with UDH structure */ - proto_tree_add_uint(code_tree, - hf_smpp_dcs_charset, tvb, off, 1, val); - proto_tree_add_uint(code_tree, - hf_smpp_dcs_class, tvb, off, 1, val); - } else if (val>>4 == 14) { /* WAP Forum */ - proto_tree_add_uint(code_tree, - hf_smpp_dcs_wap_charset, tvb, off, 1, val); - proto_tree_add_uint(code_tree, - hf_smpp_dcs_wap_class, tvb, off, 1, val); - } else if (val>>4 == 15) { /* Data coding / message handling */ - proto_tree_add_uint(code_tree, hf_smpp_dcs_reserved, tvb, off, 1, val); - proto_tree_add_uint(code_tree, hf_smpp_dcs_charset, tvb, off, 1, val); - proto_tree_add_uint(code_tree, hf_smpp_dcs_cbs_class, tvb, off, 1, val); - } + if (val & 0xC0) { + + /* GSM SMS Data Coding Scheme */ + code_tree = proto_tree_add_subtree(subtree, tvb, off, 1, ett_dcs_gsm_sms, NULL, "GSM SMS Data Coding"); + proto_tree_add_uint(code_tree, hf_smpp_dcs_sms_coding_group, tvb, off, 1, val); + + if ((val & 0x80) == 0x80) { + /* Reserved */ + } else if ((val & 0xF0) == 0xF0) { + const gint *gsm_msg_control_fields[] = { + &hf_smpp_dcs_reserved, + &hf_smpp_dcs_charset, + &hf_smpp_dcs_class, + NULL + }; + + proto_tree_add_bitmask_list_value(code_tree, tvb, off, 1, gsm_msg_control_fields, val); + } else if (val & 0x10) { + const gint *gsm_mwi_control_class_fields[] = { + &hf_smpp_dcs_text_compression, + &hf_smpp_dcs_class_present, + &hf_smpp_dcs_charset, + &hf_smpp_dcs_class, + NULL + }; + + proto_tree_add_bitmask_list_value(code_tree, tvb, off, 1, gsm_mwi_control_class_fields, val); + } else { + const gint *gsm_mwi_control_fields[] = { + &hf_smpp_dcs_text_compression, + &hf_smpp_dcs_class_present, + &hf_smpp_dcs_charset, + NULL + }; + + proto_tree_add_bitmask_list_value(code_tree, tvb, off, 1, gsm_mwi_control_fields, val); + } + /* Cell Broadcast Service (CBS) Data Coding Scheme */ + code_tree = proto_tree_add_subtree(subtree, tvb, off, 1, ett_dcs_gsm_cbs, NULL, "GSM CBS Data Coding"); + proto_tree_add_uint(code_tree, hf_smpp_dcs_cbs_coding_group, tvb, off, 1, val); + + if (val < 0x40) { /* Language specified */ + proto_tree_add_uint(code_tree, hf_smpp_dcs_cbs_language, tvb, off, 1, val); + } else if ((val & 0x40) == 0x40) { /* General Data Coding indication */ + if (val & 0x10) { + const gint *gsm_cbs_gen_class_fields[] = { + &hf_smpp_dcs_text_compression, + &hf_smpp_dcs_class_present, + &hf_smpp_dcs_charset, + &hf_smpp_dcs_class, + NULL + }; + proto_tree_add_bitmask_list_value(code_tree, tvb, off, 1, gsm_cbs_gen_class_fields, val); + + } else { + const gint *gsm_cbs_gen_fields[] = { + &hf_smpp_dcs_text_compression, + &hf_smpp_dcs_class_present, + &hf_smpp_dcs_charset, + NULL + }; + + proto_tree_add_bitmask_list_value(code_tree, tvb, off, 1, gsm_cbs_gen_fields, val); + } + } else if ((val & 0x20) == 0x20) { /* Message with UDH structure */ + const gint *gsm_cbs_udh_fields[] = { + &hf_smpp_dcs_charset, + &hf_smpp_dcs_class, + NULL + }; + + proto_tree_add_bitmask_list_value(code_tree, tvb, off, 1, gsm_cbs_udh_fields, val); + } else if ((val & 0xF0) == 0xE0) { /* WAP Forum */ + const gint *gsm_cbs_wap_fields[] = { + &hf_smpp_dcs_wap_charset, + &hf_smpp_dcs_wap_class, + NULL + }; + + proto_tree_add_bitmask_list_value(code_tree, tvb, off, 1, gsm_cbs_wap_fields, val); + } else if ((val & 0xF0) == 0xF0) { /* Data coding / message handling */ + const gint *gsm_cbs_dcs_fields[] = { + &hf_smpp_dcs_reserved, + &hf_smpp_dcs_charset, + &hf_smpp_dcs_cbs_class, + NULL + }; + + proto_tree_add_bitmask_list_value(code_tree, tvb, off, 1, gsm_cbs_dcs_fields, val); + } + } (*offset)++; } @@ -1838,82 +1869,70 @@ smpp_handle_dcs(proto_tree *tree, tvbuff_t *tvb, int *offset) * with SMPP. */ static void -bind_receiver(proto_tree *tree, tvbuff_t *tvb) +bind_receiver(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - guint8 field; - guint8 major, minor; - char *strval; - smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset); smpp_handle_string(tree, tvb, hf_smpp_password, &offset); smpp_handle_string(tree, tvb, hf_smpp_system_type, &offset); - field = tvb_get_guint8(tvb, offset++); - minor = field & 0x0F; - major = (field & 0xF0) >> 4; - strval=wmem_strdup_printf(wmem_packet_scope(), "%u.%u", major, minor); - proto_tree_add_string(tree, hf_smpp_interface_version, tvb, - offset - 1, 1, strval); - smpp_handle_int1(tree, tvb, hf_smpp_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_interface_version, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_address_range, &offset); } -#define bind_transmitter(a, b) bind_receiver(a, b) - static void -query_sm(proto_tree *tree, tvbuff_t *tvb) +query_sm(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_source_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_source_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset); } -#define bind_transceiver(a, b) bind_receiver(a, b) - static void -outbind(proto_tree *tree, tvbuff_t *tvb) +outbind(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset); smpp_handle_string(tree, tvb, hf_smpp_password, &offset); } static void submit_sm(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, - proto_tree *top_tree) + proto_tree *top_tree, int offset) { tvbuff_t *tvb_msg; - int offset = 0; - guint8 flag, udhi; - guint8 length; + guint8 udhi; + guint32 length; const char *src_str = NULL; const char *dst_str = NULL; address save_src, save_dst; nstime_t zero_time = NSTIME_INIT_ZERO; smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)"); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_source_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_source_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; src_str = smpp_handle_string_return(tree, tvb, pinfo, hf_smpp_source_addr, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_dest_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_dest_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; dst_str = smpp_handle_string_return(tree, tvb, pinfo, hf_smpp_destination_addr, &offset); - flag = tvb_get_guint8(tvb, offset); - udhi = flag & 0x40; - proto_tree_add_uint(tree, hf_smpp_esm_submit_msg_mode, - tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_esm_submit_msg_type, - tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_esm_submit_features, - tvb, offset, 1, flag); + + udhi = tvb_get_guint8(tvb, offset) & 0x40; + proto_tree_add_bitmask_list(tree, tvb, offset, 1, submit_msg_fields, ENC_NA); offset++; - smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset); + + proto_tree_add_item(tree, hf_smpp_protocol_id, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_priority_flag, tvb, offset, 1, ENC_NA); + offset += 1; if (tvb_get_guint8(tvb,offset)) { smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time, hf_smpp_schedule_delivery_time_r, &offset); @@ -1926,23 +1945,21 @@ submit_sm(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, } else { /* Time = NULL means SMSC default validity */ proto_tree_add_time_format_value(tree, hf_smpp_validity_period_r, tvb, offset++, 1, &zero_time, "SMSC default validity period"); } - flag = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag); + + proto_tree_add_bitmask_list(tree, tvb, offset, 1, regdel_fields, ENC_NA); offset++; - smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset); - smpp_handle_dcs(tree, tvb, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset); - length = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length); + proto_tree_add_item(tree, hf_smpp_replace_if_present_flag, tvb, offset, 1, ENC_NA); + offset += 1; + smpp_handle_dcs(tree, tvb, &offset); + proto_tree_add_item(tree, hf_smpp_sm_default_msg_id, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item_ret_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, ENC_NA, &length); if (length) { proto_tree_add_item(tree, hf_smpp_short_message, tvb, offset, length, ENC_NA); if (udhi) /* UDHI indicator present */ { - DebugLog(("UDHI present - set addresses\n")); /* Save original addresses */ copy_address_shallow(&save_src, &pinfo->src); copy_address_shallow(&save_dst, &pinfo->dst); @@ -1962,19 +1979,17 @@ submit_sm(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, smpp_handle_tlv(tree, tvb, &offset); } -#define deliver_sm(a, b, c, d) submit_sm(a, b, c, d) - static void -replace_sm(proto_tree *tree, tvbuff_t *tvb) +replace_sm(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - guint8 flag; - guint8 length; + guint32 length; nstime_t zero_time = NSTIME_INIT_ZERO; smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_source_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_source_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset); if (tvb_get_guint8(tvb,offset)) { smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time, @@ -1988,59 +2003,54 @@ replace_sm(proto_tree *tree, tvbuff_t *tvb) } else { /* Time = NULL */ proto_tree_add_time_format_value(tree, hf_smpp_validity_period_r, tvb, offset++, 1,&zero_time, "Keep initial validity period setting"); } - flag = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag); + proto_tree_add_bitmask_list(tree, tvb, offset, 1, regdel_fields, ENC_NA); offset++; - smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset); - length = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length); + proto_tree_add_item(tree, hf_smpp_sm_default_msg_id, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item_ret_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, ENC_NA, &length); if (length) proto_tree_add_item(tree, hf_smpp_short_message, tvb, offset, length, ENC_NA); } static void -cancel_sm(proto_tree *tree, tvbuff_t *tvb) +cancel_sm(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)"); smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_source_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_source_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_dest_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_dest_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset); } static void -submit_multi(proto_tree *tree, tvbuff_t *tvb) +submit_multi(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - guint8 flag; - guint8 length; + guint32 length; nstime_t zero_time = NSTIME_INIT_ZERO; smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)"); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_source_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_source_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset); smpp_handle_dlist(tree, tvb, &offset); - flag = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(tree, hf_smpp_esm_submit_msg_mode, - tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_esm_submit_msg_type, - tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_esm_submit_features, - tvb, offset, 1, flag); + proto_tree_add_bitmask_list(tree, tvb, offset, 1, submit_msg_fields, ENC_NA); offset++; - smpp_handle_int1(tree, tvb, hf_smpp_protocol_id, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset); + proto_tree_add_item(tree, hf_smpp_protocol_id, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_priority_flag, tvb, offset, 1, ENC_NA); + offset += 1; if (tvb_get_guint8(tvb,offset)) { smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time, hf_smpp_schedule_delivery_time_r, &offset); @@ -2052,16 +2062,14 @@ submit_multi(proto_tree *tree, tvbuff_t *tvb) } else { /* Time = NULL means SMSC default validity */ proto_tree_add_time_format_value(tree, hf_smpp_schedule_delivery_time_r, tvb, offset++, 1, &zero_time, "SMSC default validity period"); } - flag = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag); + proto_tree_add_bitmask_list(tree, tvb, offset, 1, regdel_fields, ENC_NA); offset++; - smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset); + proto_tree_add_item(tree, hf_smpp_replace_if_present_flag, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_dcs(tree, tvb, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset); - length = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, length); + proto_tree_add_item(tree, hf_smpp_sm_default_msg_id, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item_ret_uint(tree, hf_smpp_sm_length, tvb, offset++, 1, ENC_NA, &length); if (length) proto_tree_add_item(tree, hf_smpp_short_message, tvb, offset, length, ENC_NA); @@ -2070,46 +2078,40 @@ submit_multi(proto_tree *tree, tvbuff_t *tvb) } static void -alert_notification(proto_tree *tree, tvbuff_t *tvb) +alert_notification(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_source_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_source_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_esme_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_esme_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_esme_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_esme_addr, &offset); smpp_handle_tlv(tree, tvb, &offset); } static void -data_sm(proto_tree *tree, tvbuff_t *tvb) +data_sm(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - guint8 flag; - smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)"); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_source_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_source_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_dest_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_dest_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_dest_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset); - flag = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(tree, hf_smpp_esm_submit_msg_mode, - tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_esm_submit_msg_type, - tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_esm_submit_features, - tvb, offset, 1, flag); + proto_tree_add_bitmask_list(tree, tvb, offset, 1, submit_msg_fields, ENC_NA); offset++; - flag = tvb_get_guint8(tvb, offset); - proto_tree_add_uint(tree, hf_smpp_regdel_receipt, tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_regdel_acks, tvb, offset, 1, flag); - proto_tree_add_uint(tree, hf_smpp_regdel_notif, tvb, offset, 1, flag); + proto_tree_add_bitmask_list(tree, tvb, offset, 1, regdel_fields, ENC_NA); offset++; - smpp_handle_dcs(tree, tvb, &offset); + smpp_handle_dcs(tree, tvb, &offset); smpp_handle_tlv(tree, tvb, &offset); } @@ -2117,17 +2119,19 @@ data_sm(proto_tree *tree, tvbuff_t *tvb) * Request operations introduced in the SMPP 5.0 */ static void -broadcast_sm(proto_tree *tree, tvbuff_t *tvb) +broadcast_sm(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; nstime_t zero_time = NSTIME_INIT_ZERO; smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)"); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_source_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_source_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset); smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_priority_flag, &offset); + proto_tree_add_item(tree, hf_smpp_priority_flag, tvb, offset, 1, ENC_NA); + offset += 1; if (tvb_get_guint8(tvb,offset)) { smpp_handle_time(tree, tvb, hf_smpp_schedule_delivery_time, hf_smpp_schedule_delivery_time_r, &offset); @@ -2139,33 +2143,35 @@ broadcast_sm(proto_tree *tree, tvbuff_t *tvb) } else { /* Time = NULL means SMSC default validity */ proto_tree_add_time_format_value(tree, hf_smpp_validity_period_r, tvb, offset++, 1, &zero_time, "SMSC default validity period"); } - smpp_handle_int1(tree, tvb, hf_smpp_replace_if_present_flag, &offset); + proto_tree_add_item(tree, hf_smpp_replace_if_present_flag, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_dcs(tree, tvb, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_sm_default_msg_id, &offset); + proto_tree_add_item(tree, hf_smpp_sm_default_msg_id, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_tlv(tree, tvb, &offset); } static void -query_broadcast_sm(proto_tree *tree, tvbuff_t *tvb) +query_broadcast_sm(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_source_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_source_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset); smpp_handle_tlv(tree, tvb, &offset); } static void -cancel_broadcast_sm(proto_tree *tree, tvbuff_t *tvb) +cancel_broadcast_sm(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - smpp_handle_string_z(tree, tvb, hf_smpp_service_type, &offset, "(Default)"); smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_ton, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_source_addr_npi, &offset); + proto_tree_add_item(tree, hf_smpp_source_addr_ton, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_source_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset); smpp_handle_tlv(tree, tvb, &offset); } @@ -2175,168 +2181,120 @@ cancel_broadcast_sm(proto_tree *tree, tvbuff_t *tvb) * associated with SMPP. */ static void -bind_receiver_resp(proto_tree *tree, tvbuff_t *tvb) +bind_receiver_resp(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - smpp_handle_string(tree, tvb, hf_smpp_system_id, &offset); smpp_handle_tlv(tree, tvb, &offset); } -#define bind_transmitter_resp(a, b) bind_receiver_resp(a, b) - static void -query_sm_resp(proto_tree *tree, tvbuff_t *tvb) +query_sm_resp(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset); smpp_handle_time(tree, tvb, hf_smpp_final_date, hf_smpp_final_date_r, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_message_state, &offset); - smpp_handle_int1(tree, tvb, hf_smpp_error_code, &offset); + proto_tree_add_item(tree, hf_smpp_message_state, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_smpp_error_code, tvb, offset, 1, ENC_NA); + offset += 1; } -#define bind_transceiver_resp(a, b) bind_receiver_resp(a, b) - static void -submit_sm_resp(proto_tree *tree, tvbuff_t *tvb) +submit_sm_resp(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset); smpp_handle_tlv(tree, tvb, &offset); } -#define deliver_sm_resp(a, b) submit_sm_resp(a, b) - static void -submit_multi_resp(proto_tree *tree, tvbuff_t *tvb) +submit_multi_resp(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset); smpp_handle_dlist_resp(tree, tvb, &offset); smpp_handle_tlv(tree, tvb, &offset); } static void -data_sm_resp(proto_tree *tree, tvbuff_t *tvb) +data_sm_resp(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset); smpp_handle_tlv(tree, tvb, &offset); } -#define broadcast_sm_resp(a, b) submit_sm_resp(a, b) - static void -query_broadcast_sm_resp(proto_tree *tree, tvbuff_t *tvb) +query_broadcast_sm_resp(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - smpp_handle_string(tree, tvb, hf_smpp_message_id, &offset); smpp_handle_tlv(tree, tvb, &offset); } /* Huawei SMPP+ extensions */ static void -huawei_auth_acc(proto_tree *tree, tvbuff_t *tvb) +huawei_auth_acc(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - guint8 version = 0; + guint32 version; - smpp_handle_int1(tree, tvb, hf_huawei_smpp_version, &offset); - version = tvb_get_guint8(tvb, offset); + proto_tree_add_item_ret_uint(tree, hf_smpp_error_code, tvb, offset, 1, ENC_NA, &version); + offset += 1; smpp_handle_string(tree, tvb, hf_huawei_smpp_smsc_addr, &offset); if ( version == '3' ) { - smpp_handle_int1(tree, tvb, hf_huawei_smpp_msc_addr_noa, &offset); - smpp_handle_int1(tree, tvb, hf_huawei_smpp_msc_addr_npi, &offset); + proto_tree_add_item(tree, hf_huawei_smpp_msc_addr_noa, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_huawei_smpp_msc_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_huawei_smpp_msc_addr, &offset); } smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset); smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset); - smpp_handle_int1(tree, tvb, hf_huawei_smpp_mo_mt_flag, &offset); + proto_tree_add_item(tree, hf_huawei_smpp_mo_mt_flag, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_huawei_smpp_sm_id, &offset); - smpp_handle_int4(tree, tvb, hf_huawei_smpp_length_auth, &offset); - smpp_handle_int4(tree, tvb, hf_huawei_smpp_service_id, &offset); + proto_tree_add_item(tree, hf_huawei_smpp_length_auth, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_huawei_smpp_service_id, tvb, offset, 4, ENC_BIG_ENDIAN); } static void -huawei_auth_acc_resp(proto_tree *tree, tvbuff_t *tvb) +huawei_auth_acc_resp(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - - smpp_handle_int4(tree, tvb, hf_huawei_smpp_operation_result, &offset); - smpp_handle_int1(tree, tvb, hf_huawei_smpp_notify_mode, &offset); + proto_tree_add_item(tree, hf_huawei_smpp_operation_result, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_huawei_smpp_notify_mode, tvb, offset, 1, ENC_NA); } static void -huawei_sm_result_notify(proto_tree *tree, tvbuff_t *tvb) +huawei_sm_result_notify(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - guint8 version = 0; + guint32 version; - smpp_handle_int1(tree, tvb, hf_huawei_smpp_version, &offset); - version = tvb_get_guint8(tvb, offset); + proto_tree_add_item_ret_uint(tree, hf_smpp_error_code, tvb, offset, 1, ENC_NA, &version); + offset += 1; smpp_handle_string(tree, tvb, hf_huawei_smpp_smsc_addr, &offset); if ( version == '3' ) { - smpp_handle_int1(tree, tvb, hf_huawei_smpp_msc_addr_noa, &offset); - smpp_handle_int1(tree, tvb, hf_huawei_smpp_msc_addr_npi, &offset); + proto_tree_add_item(tree, hf_huawei_smpp_msc_addr_noa, tvb, offset, 1, ENC_NA); + offset += 1; + proto_tree_add_item(tree, hf_huawei_smpp_msc_addr_npi, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_huawei_smpp_msc_addr, &offset); } smpp_handle_string(tree, tvb, hf_smpp_source_addr, &offset); smpp_handle_string(tree, tvb, hf_smpp_destination_addr, &offset); - smpp_handle_int1(tree, tvb, hf_huawei_smpp_mo_mt_flag, &offset); + proto_tree_add_item(tree, hf_huawei_smpp_mo_mt_flag, tvb, offset, 1, ENC_NA); + offset += 1; smpp_handle_string(tree, tvb, hf_huawei_smpp_sm_id, &offset); - smpp_handle_int4(tree, tvb, hf_huawei_smpp_length_auth, &offset); - smpp_handle_int4(tree, tvb, hf_huawei_smpp_delivery_result, &offset); - smpp_handle_int4(tree, tvb, hf_huawei_smpp_service_id, &offset); + proto_tree_add_item(tree, hf_huawei_smpp_length_auth, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_huawei_smpp_delivery_result, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_huawei_smpp_service_id, tvb, offset, 4, ENC_BIG_ENDIAN); } static void -huawei_sm_result_notify_resp(proto_tree *tree, tvbuff_t *tvb) +huawei_sm_result_notify_resp(proto_tree *tree, tvbuff_t *tvb, int offset) { - int offset = 0; - - smpp_handle_int4(tree, tvb, hf_huawei_smpp_operation_result, &offset); -} - - -/* - * A 'heuristic dissector' that attemtps to establish whether we have - * a genuine SMPP PDU here. - * Only works when: - * at least the fixed header is there - * it has a correct overall PDU length - * it is a 'well-known' operation - * has a 'well-known' or 'reserved' status - */ -static gboolean -dissect_smpp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) -{ - guint32 command_id; /* SMPP command */ - guint32 command_status; /* Status code */ - guint32 command_length; /* length of PDU */ - - if (tvb_reported_length(tvb) < SMPP_MIN_LENGTH || /* Mandatory header */ - tvb_captured_length(tvb) < 12) - return FALSE; - command_length = tvb_get_ntohl(tvb, 0); - if (command_length > 64 * 1024 || command_length < SMPP_MIN_LENGTH) - return FALSE; - command_id = tvb_get_ntohl(tvb, 4); /* Only known commands */ - if (try_val_to_str(command_id, vals_command_id) == NULL) - return FALSE; - command_status = tvb_get_ntohl(tvb, 8); /* ..with known status */ - if (try_val_to_str(command_status, vals_command_status) == NULL && - try_rval_to_str(command_status, reserved_command_status) == NULL) - return FALSE; - dissect_smpp(tvb, pinfo, tree, data); - return TRUE; + proto_tree_add_item(tree, hf_huawei_smpp_delivery_result, tvb, offset, 4, ENC_BIG_ENDIAN); } static guint @@ -2345,51 +2303,6 @@ get_smpp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _ return tvb_get_ntohl(tvb, offset); } -/* - * This global SMPP variable is used to determine whether the PDU to dissect - * is the first SMPP PDU in the packet (or reassembled buffer), requiring - * different column update code than subsequent SMPP PDUs within this packet - * (or reassembled buffer). - * - * FIXME - This approach is NOT dissection multi-thread safe! - */ -static gboolean first = TRUE; - -static int -dissect_smpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) -{ - first = TRUE; - if (pinfo->ptype == PT_TCP) { /* are we running on top of TCP */ - tcp_dissect_pdus(tvb, pinfo, tree, - reassemble_over_tcp, /* Do we try to reassemble */ - 16, /* Length of fixed header */ - get_smpp_pdu_len, /* Function returning PDU len */ - dissect_smpp_pdu, data); /* PDU dissector */ - } else { /* no? probably X.25 */ - guint32 offset = 0; - while (tvb_reported_length_remaining(tvb, offset) > 0) { - guint16 pdu_len = tvb_get_ntohl(tvb, offset); - gint pdu_real_len = tvb_captured_length_remaining(tvb, offset); - tvbuff_t *pdu_tvb; - - if (pdu_len < 1) - return offset; - - if (pdu_real_len <= 0) - return offset; - if (pdu_real_len > pdu_len) - pdu_real_len = pdu_len; - pdu_tvb = tvb_new_subset_length_caplen(tvb, offset, pdu_real_len, pdu_len); - dissect_smpp_pdu(pdu_tvb, pinfo, tree, data); - offset += pdu_len; - first = FALSE; - } - } - - return tvb_captured_length(tvb); -} - - /* Dissect a single SMPP PDU contained within "tvb". */ static int dissect_smpp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) @@ -2419,15 +2332,9 @@ dissect_smpp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data "(Unknown SMPP Operation 0x%08X)"); offset += 4; command_status = tvb_get_ntohl(tvb, offset); - if (command_id & 0x80000000) { + if (command_id & SMPP_COMMAND_ID_RESPONSE_MASK) { /* PDU is a response. */ - command_status_str = try_val_to_str(command_status, vals_command_status); - if (command_status_str == NULL) { - /* Check if the reserved value is in the vendor-specific range. */ - command_status_str = (command_status >= 0x400 && command_status <= 0x4FF ? - wmem_strdup_printf(wmem_packet_scope(), "Vendor-specific Error (0x%08X)", command_status) : - wmem_strdup_printf(wmem_packet_scope(), "(Reserved Error 0x%08X)", command_status)); - } + command_status_str = rval_to_str(command_status, rvals_command_status, "Unknown (0x%08x)"); } offset += 4; sequence_number = tvb_get_ntohl(tvb, offset); @@ -2436,9 +2343,8 @@ dissect_smpp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data /* * Update the protocol column. */ - if (first == TRUE) { - col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMPP"); - } + col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMPP"); + col_clear(pinfo->cinfo, COL_INFO); /* * Create display subtree for the protocol @@ -2447,247 +2353,268 @@ dissect_smpp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data smpp_tree = proto_item_add_subtree (ti, ett_smpp); /* - * Cycle over the encapsulated PDUs + * Make entries in the Info column on the summary display */ - { - tvbuff_t *pdu_tvb; + col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", command_str); - /* - * Make entries in the Info column on the summary display - */ - if (first == TRUE) { - /* - * First PDU - We already computed the fixed header - */ - col_add_fstr(pinfo->cinfo, COL_INFO, "SMPP %s", command_str); - first = FALSE; - } else { - /* - * Subsequent PDUs - */ - col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", command_str); + /* + * Display command status of responses in Info column + */ + if (command_id & SMPP_COMMAND_ID_RESPONSE_MASK) { + col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"", command_status_str); + } + + /* + * Dissect the PDU + */ + + /* + * Create display subtree for the PDU + */ + proto_tree_add_uint(smpp_tree, hf_smpp_command_length, tvb, 0, 4, command_length); + proto_tree_add_uint(smpp_tree, hf_smpp_command_id, tvb, 4, 4, command_id); + proto_item_append_text(ti, ", Command: %s", command_str); + + /* + * Status is only meaningful with responses + */ + if (command_id & SMPP_COMMAND_ID_RESPONSE_MASK) { + proto_tree_add_uint(smpp_tree, hf_smpp_command_status, tvb, 8, 4, command_status); + proto_item_append_text (ti, ", Status: \"%s\"", command_status_str); + } + proto_tree_add_uint(smpp_tree, hf_smpp_sequence_number, tvb, 12, 4, sequence_number); + proto_item_append_text(ti, ", Seq: %u, Len: %u", sequence_number, command_length); + + if (command_length <= tvb_reported_length(tvb)) + { + if (command_id & SMPP_COMMAND_ID_RESPONSE_MASK) + { + switch (command_id & (~SMPP_COMMAND_ID_RESPONSE_MASK)) { + /* + * All of these only have a fixed header + */ + case SMPP_COMMAND_ID_GENERIC_NACK: + case SMPP_COMMAND_ID_UNBIND: + case SMPP_COMMAND_ID_REPLACE_SM: + case SMPP_COMMAND_ID_CANCEL_SM: + case SMPP_COMMAND_ID_ENQUIRE_LINK: + case SMPP_COMMAND_ID_CANCEL_BROADCAST_SM: + break; + /* FIXME: The body of the response PDUs are only + * only dissected if the request was successful. + * However, in SMPP 5.0 some responses might + * contain body to provide additional information + * about the error. This needs to be handled. + */ + case SMPP_COMMAND_ID_BIND_RECEIVER: + case SMPP_COMMAND_ID_BIND_TRANSMITTER: + case SMPP_COMMAND_ID_BIND_TRANSCEIVER: + if (!command_status) + bind_receiver_resp(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_QUERY_SM: + if (!command_status) + query_sm_resp(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_SUBMIT_SM: + case SMPP_COMMAND_ID_DELIVER_SM: + case SMPP_COMMAND_ID_BROADCAST_SM: + if (!command_status) + submit_sm_resp(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_SUBMIT_MULTI: + if (!command_status) + submit_multi_resp(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_DATA_SM: + if (!command_status) + data_sm_resp(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_QUERY_BROADCAST_SM: + if (!command_status) + query_broadcast_sm_resp(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_HUAWEI_AUTH_ACC: + if (!command_status) + huawei_auth_acc_resp(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_HUAWEI_SM_RESULT_NOTIFY: + if (!command_status) + huawei_sm_result_notify_resp(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + default: + break; + } /* switch (command_id & 0x7FFFFFFF) */ } - /* - * Display command status of responses in Info column - */ - if (command_id & 0x80000000) { - col_append_fstr(pinfo->cinfo, COL_INFO, ": \"%s\"", - command_status_str); + else + { + switch (command_id) { + case SMPP_COMMAND_ID_BIND_RECEIVER: + case SMPP_COMMAND_ID_BIND_TRANSMITTER: + case SMPP_COMMAND_ID_BIND_TRANSCEIVER: + bind_receiver(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_QUERY_SM: + query_sm(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_SUBMIT_SM: + case SMPP_COMMAND_ID_DELIVER_SM: + submit_sm(smpp_tree, tvb, pinfo, tree, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_UNBIND: + case SMPP_COMMAND_ID_ENQUIRE_LINK: + break; + case SMPP_COMMAND_ID_REPLACE_SM: + replace_sm(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_CANCEL_SM: + cancel_sm(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_OUTBIND: + outbind(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_SUBMIT_MULTI: + submit_multi(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_ALERT_NOTIFICATION: + alert_notification(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_DATA_SM: + data_sm(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_BROADCAST_SM: + broadcast_sm(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_QUERY_BROADCAST_SM: + query_broadcast_sm(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_CANCEL_BROADCAST_SM: + cancel_broadcast_sm(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_HUAWEI_AUTH_ACC: + huawei_auth_acc(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + case SMPP_COMMAND_ID_HUAWEI_SM_RESULT_NOTIFY: + huawei_sm_result_notify(smpp_tree, tvb, SMPP_FIXED_HEADER_LENGTH); + break; + default: + break; + } /* switch (command_id) */ } - /* - * Create a tvb for the current PDU. - * Physical length: at most command_length - * Reported length: command_length - */ - if (tvb_captured_length_remaining(tvb, offset - 16 + command_length) > 0) { - pdu_tvb = tvb_new_subset_length_caplen(tvb, offset - 16, - command_length, /* Physical length */ - command_length); /* Length reported by the protocol */ - } else { - pdu_tvb = tvb_new_subset_length_caplen(tvb, offset - 16, - tvb_captured_length_remaining(tvb, offset - 16),/* Physical length */ - command_length); /* Length reported by the protocol */ - } + } - /* - * Dissect the PDU - * - * If "tree" is NULL, Wireshark is only interested in creation - * of conversations, reassembly and subdissection but not in - * the detailed protocol tree. - * In the interest of speed, skip the generation of protocol tree - * items when "tree" is NULL. - * - * The only PDU which requires subdissection currently is the - * sm_submit PDU (command ID = 0x00000004). - */ - if (tree || (command_id == 4)) - { - /* - * Create display subtree for the PDU - */ - if (tree) { - proto_tree_add_uint(smpp_tree, hf_smpp_command_length, - pdu_tvb, 0, 4, command_length); - proto_tree_add_uint(smpp_tree, hf_smpp_command_id, - pdu_tvb, 4, 4, command_id); - proto_item_append_text(ti, ", Command: %s", command_str); + /* Queue packet for Tap */ + tap_rec = wmem_new0(wmem_packet_scope(), smpp_tap_rec_t); + tap_rec->command_id = command_id; + tap_rec->command_status = command_status; + tap_queue_packet(smpp_tap, pinfo, tap_rec); - /* - * Status is only meaningful with responses - */ - if (command_id & 0x80000000) { - proto_tree_add_uint(smpp_tree, hf_smpp_command_status, - pdu_tvb, 8, 4, command_status); - proto_item_append_text (ti, ", Status: \"%s\"", - command_status_str); - } - proto_tree_add_uint(smpp_tree, hf_smpp_sequence_number, - pdu_tvb, 12, 4, sequence_number); - proto_item_append_text(ti, ", Seq: %u, Len: %u", - sequence_number, command_length); - } - - /* - * End of fixed header. - * Don't dissect variable part if it is shortened. - * - * FIXME - We then do not report a Short Frame or Malformed Packet - */ - if (command_length <= tvb_reported_length(pdu_tvb)) - { - tvbuff_t *tmp_tvb = tvb_new_subset_length_caplen(pdu_tvb, 16, - -1, command_length - 16); - if (command_id & 0x80000000) - { - switch (command_id & 0x7FFFFFFF) { - /* - * All of these only have a fixed header - */ - case 0: /* Generic nack */ - case 6: /* Unbind resp */ - case 7: /* Replace SM resp */ - case 8: /* Cancel SM resp */ - case 21: /* Enquire link resp */ - case 275: /* Cancel Broadcast SM resp */ - break; - /* FIXME: The body of the response PDUs are only - * only dissected if the request was successful. - * However, in SMPP 5.0 some responses might - * contain body to provide additional information - * about the error. This needs to be handled. - */ - case 1: - if (!command_status) - bind_receiver_resp(smpp_tree, tmp_tvb); - break; - case 2: - if (!command_status) - bind_transmitter_resp(smpp_tree, tmp_tvb); - break; - case 3: - if (!command_status) - query_sm_resp(smpp_tree, tmp_tvb); - break; - case 4: - if (!command_status) - submit_sm_resp(smpp_tree, tmp_tvb); - break; - case 5: - if (!command_status) - deliver_sm_resp(smpp_tree, tmp_tvb); - break; - case 9: - if (!command_status) - bind_transceiver_resp(smpp_tree, tmp_tvb); - break; - case 33: - if (!command_status) - submit_multi_resp(smpp_tree, tmp_tvb); - break; - case 259: - if (!command_status) - data_sm_resp(smpp_tree, tmp_tvb); - break; - case 273: - if (!command_status) - broadcast_sm_resp(smpp_tree, tmp_tvb); - break; - case 274: - if (!command_status) - query_broadcast_sm_resp(smpp_tree, tmp_tvb); - break; - case 16777217: - if (!command_status) - huawei_auth_acc_resp(smpp_tree, tmp_tvb); - break; - case 16777218: - if (!command_status) - huawei_sm_result_notify_resp(smpp_tree, tmp_tvb); - break; - default: - break; - } /* switch (command_id & 0x7FFFFFFF) */ - } - else - { - switch (command_id) { - case 1: - bind_receiver(smpp_tree, tmp_tvb); - break; - case 2: - bind_transmitter(smpp_tree, tmp_tvb); - break; - case 3: - query_sm(smpp_tree, tmp_tvb); - break; - case 4: - submit_sm(smpp_tree, tmp_tvb, pinfo, tree); - break; - case 5: - deliver_sm(smpp_tree, tmp_tvb, pinfo, tree); - break; - case 6: /* Unbind */ - case 21: /* Enquire link */ - break; - case 7: - replace_sm(smpp_tree, tmp_tvb); - break; - case 8: - cancel_sm(smpp_tree, tmp_tvb); - break; - case 9: - bind_transceiver(smpp_tree, tmp_tvb); - break; - case 11: - outbind(smpp_tree, tmp_tvb); - break; - case 33: - submit_multi(smpp_tree, tmp_tvb); - break; - case 258: - alert_notification(smpp_tree, tmp_tvb); - break; - case 259: - data_sm(smpp_tree, tmp_tvb); - break; - case 273: - broadcast_sm(smpp_tree, tmp_tvb); - break; - case 274: - query_broadcast_sm(smpp_tree, tmp_tvb); - break; - case 275: - cancel_broadcast_sm(smpp_tree, tmp_tvb); - break; - case 16777217: - huawei_auth_acc(smpp_tree, tmp_tvb); - break; - case 16777218: - huawei_sm_result_notify(smpp_tree, tmp_tvb); - break; - default: - break; - } /* switch (command_id) */ - } /* if (command_id & 0x80000000) */ - - } /* if (command_length <= tvb_reported_length(pdu_tvb)) */ - /*offset += command_length;*/ - } /* if (tree || (command_id == 4)) */ - - /* Queue packet for Tap */ - tap_rec = wmem_new0(wmem_packet_scope(), smpp_tap_rec_t); - tap_rec->command_id = command_id; - tap_rec->command_status = command_status; - tap_queue_packet(smpp_tap, pinfo, tap_rec); - - first = FALSE; + col_set_fence(pinfo->cinfo, COL_INFO); + + return tvb_captured_length(tvb); +} + +static int +dissect_smpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + if (pinfo->ptype == PT_TCP) { /* are we running on top of TCP */ + tcp_dissect_pdus(tvb, pinfo, tree, + reassemble_over_tcp, /* Do we try to reassemble */ + 16, /* Length of fixed header */ + get_smpp_pdu_len, /* Function returning PDU len */ + dissect_smpp_pdu, data); /* PDU dissector */ + } + else { /* no? probably X.25 */ + guint32 offset = 0; + while (tvb_reported_length_remaining(tvb, offset) > 0) { + guint16 pdu_len = tvb_get_ntohl(tvb, offset); + gint pdu_real_len = tvb_captured_length_remaining(tvb, offset); + tvbuff_t *pdu_tvb; + + if (pdu_len < 1) + return offset; + + if (pdu_real_len <= 0) + return offset; + if (pdu_real_len > pdu_len) + pdu_real_len = pdu_len; + pdu_tvb = tvb_new_subset_length_caplen(tvb, offset, pdu_real_len, pdu_len); + dissect_smpp_pdu(pdu_tvb, pinfo, tree, data); + offset += pdu_len; + } } return tvb_captured_length(tvb); } +/* +* A 'heuristic dissector' that attemtps to establish whether we have +* a genuine SMPP PDU here. +* Only works when: +* at least the fixed header is there +* it has a correct overall PDU length +* it is a 'well-known' operation +* has a 'well-known' or 'reserved' status +*/ +static gboolean +dissect_smpp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +{ + guint32 command_id; /* SMPP command */ + guint32 command_status; /* Status code */ + guint32 command_length; /* length of PDU */ + + if (tvb_reported_length(tvb) < SMPP_MIN_LENGTH || /* Mandatory header */ + tvb_captured_length(tvb) < 12) + return FALSE; + command_length = tvb_get_ntohl(tvb, 0); + if (command_length > 64 * 1024 || command_length < SMPP_MIN_LENGTH) + return FALSE; + command_id = tvb_get_ntohl(tvb, 4); /* Only known commands */ + if (try_val_to_str(command_id, vals_command_id) == NULL) + return FALSE; + command_status = tvb_get_ntohl(tvb, 8); /* ..with known status */ + if (try_rval_to_str(command_status, rvals_command_status) == NULL) + return FALSE; + + //Check for specific values in commands (to avoid false positives) + switch (command_id) + { + case SMPP_COMMAND_ID_ALERT_NOTIFICATION: + { + guint8 ton, npi; + + if (tvb_reported_length(tvb) < 19) + return FALSE; + ton = tvb_get_guint8(tvb, 16); + if (try_val_to_str(ton, vals_addr_ton) == NULL) + return FALSE; + + npi = tvb_get_guint8(tvb, 17); + if (try_val_to_str(npi, vals_addr_npi) == NULL) + return FALSE; + + //address must be NULL-terminated string of up to 65 ascii characters + int end = tvb_find_guint8(tvb, 18, -1, 0); + if ((end <= 0) || (end > 65)) + return FALSE; + + if (!tvb_ascii_isprint(tvb, 18, end - 18)) + return FALSE; + } + break; + } + + + dissect_smpp(tvb, pinfo, tree, data); + return TRUE; +} + +static void +smpp_fmt_version(gchar *result, guint32 revision) +{ + g_snprintf(result, ITEM_LABEL_LENGTH, "%u.%u", (guint8)((revision & 0xF0) >> 4), (guint8)(revision & 0x0F)); +} /* Register the protocol with Wireshark */ void @@ -2713,7 +2640,7 @@ proto_register_smpp(void) }, { &hf_smpp_command_status, { "Result", "smpp.command_status", - FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00, + FT_UINT32, BASE_HEX | BASE_RANGE_STRING, RVALS(rvals_command_status), 0x00, "Indicates success or failure of the SMPP request.", HFILL } @@ -2748,7 +2675,7 @@ proto_register_smpp(void) }, { &hf_smpp_interface_version, { "Version (if)", "smpp.interface_version", - FT_STRING, BASE_NONE, NULL, 0x00, + FT_UINT8, BASE_CUSTOM, CF_FUNC(smpp_fmt_version), 0x00, "Version of SMPP interface supported.", HFILL } @@ -3001,7 +2928,7 @@ proto_register_smpp(void) }, { &hf_smpp_error_status_code, { "Status", "smpp.error_status_code", - FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00, + FT_UINT32, BASE_HEX | BASE_RANGE_STRING, RVALS(rvals_command_status), 0x00, "Indicates success/failure of request for this address.", HFILL } @@ -3267,14 +3194,14 @@ proto_register_smpp(void) }, { &hf_smpp_vendor_op, { "Value", "smpp.vendor_op", - FT_BYTES, BASE_NONE, NULL, 0x00, + FT_BYTES, BASE_NONE|BASE_ALLOW_ZERO, NULL, 0x00, "A supplied optional parameter specific to an SMSC-vendor.", HFILL } }, { &hf_smpp_reserved_op, { "Value", "smpp.reserved_op", - FT_BYTES, BASE_NONE, NULL, 0x00, + FT_BYTES, BASE_NONE|BASE_ALLOW_ZERO, NULL, 0x00, "An optional parameter that is reserved in this version.", HFILL } @@ -3295,7 +3222,7 @@ proto_register_smpp(void) }, { &hf_smpp_SC_interface_version, { "SMSC-supported version", "smpp.SC_interface_version", - FT_STRING, BASE_NONE, NULL, 0x00, + FT_UINT8, BASE_CUSTOM, CF_FUNC(smpp_fmt_version), 0x00, "Version of SMPP interface supported by the SMSC.", HFILL } @@ -3609,7 +3536,7 @@ proto_register_smpp(void) }, { &hf_smpp_broadcast_error_status, { "Broadcast Message - Error Status", "smpp.broadcast_error_status", - FT_UINT32, BASE_HEX, VALS(vals_command_status), 0x00, + FT_UINT32, BASE_HEX | BASE_RANGE_STRING, RVALS(rvals_command_status), 0x00, "Cell Broadcast Message - Error Status", HFILL } }, @@ -3720,8 +3647,10 @@ proto_register_smpp(void) &ett_opt_params, &ett_opt_param, &ett_dcs, + &ett_dcs_gsm_sms, + &ett_dcs_gsm_cbs, }; - DebugLog(("Registering SMPP dissector\n")); + /* Register the protocol name and description */ proto_smpp = proto_register_protocol("Short Message Peer to Peer", "SMPP", "smpp"); @@ -3764,7 +3693,6 @@ proto_reg_handoff_smpp(void) heur_dissector_add("x.25", dissect_smpp_heur, "SMPP over X.25", "smpp_x25", proto_smpp, HEURISTIC_ENABLE); /* Required for call_dissector() */ - DebugLog(("Finding gsm_sms_ud subdissector\n")); gsm_sms_handle = find_dissector_add_dependency("gsm_sms_ud", proto_smpp); DISSECTOR_ASSERT(gsm_sms_handle); |