summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-tns.c
diff options
context:
space:
mode:
Diffstat (limited to 'epan/dissectors/packet-tns.c')
-rw-r--r--epan/dissectors/packet-tns.c563
1 files changed, 367 insertions, 196 deletions
diff --git a/epan/dissectors/packet-tns.c b/epan/dissectors/packet-tns.c
index d25decb0..49ebad7b 100644
--- a/epan/dissectors/packet-tns.c
+++ b/epan/dissectors/packet-tns.c
@@ -16,9 +16,17 @@
#include "packet-tcp.h"
#include <epan/prefs.h>
+#include <epan/expert.h>
+#include <epan/conversation.h>
+#include <epan/proto_data.h>
+#include <epan/unit_strings.h>
+
+#include <wsutil/array.h>
void proto_register_tns(void);
+#define TNS_HDR_LEN 8
+
/* Packet Types */
#define TNS_TYPE_CONNECT 1
#define TNS_TYPE_ACCEPT 2
@@ -32,6 +40,7 @@ void proto_register_tns(void);
#define TNS_TYPE_MARKER 12
#define TNS_TYPE_ATTENTION 13
#define TNS_TYPE_CONTROL 14
+#define TNS_TYPE_DD 15
#define TNS_TYPE_MAX 19
/* Data Packet Functions */
@@ -64,150 +73,157 @@ void proto_register_tns(void);
#define OPI_OAUTH 3
/* desegmentation of TNS over TCP */
-static gboolean tns_desegment = TRUE;
+static bool tns_desegment = true;
static dissector_handle_t tns_handle;
-static int proto_tns = -1;
-static int hf_tns_request = -1;
-static int hf_tns_response = -1;
-static int hf_tns_length = -1;
-static int hf_tns_packet_checksum = -1;
-static int hf_tns_header_checksum = -1;
-static int hf_tns_packet_type = -1;
-static int hf_tns_reserved_byte = -1;
-static int hf_tns_version = -1;
-static int hf_tns_compat_version = -1;
-
-static int hf_tns_service_options = -1;
-static int hf_tns_sopt_flag_bconn = -1;
-static int hf_tns_sopt_flag_pc = -1;
-static int hf_tns_sopt_flag_hc = -1;
-static int hf_tns_sopt_flag_fd = -1;
-static int hf_tns_sopt_flag_hd = -1;
-static int hf_tns_sopt_flag_dc1 = -1;
-static int hf_tns_sopt_flag_dc2 = -1;
-static int hf_tns_sopt_flag_dio = -1;
-static int hf_tns_sopt_flag_ap = -1;
-static int hf_tns_sopt_flag_ra = -1;
-static int hf_tns_sopt_flag_sa = -1;
-
-static int hf_tns_sdu_size = -1;
-static int hf_tns_max_tdu_size = -1;
-
-static int hf_tns_nt_proto_characteristics = -1;
-static int hf_tns_ntp_flag_hangon = -1;
-static int hf_tns_ntp_flag_crel = -1;
-static int hf_tns_ntp_flag_tduio = -1;
-static int hf_tns_ntp_flag_srun = -1;
-static int hf_tns_ntp_flag_dtest = -1;
-static int hf_tns_ntp_flag_cbio = -1;
-static int hf_tns_ntp_flag_asio = -1;
-static int hf_tns_ntp_flag_pio = -1;
-static int hf_tns_ntp_flag_grant = -1;
-static int hf_tns_ntp_flag_handoff = -1;
-static int hf_tns_ntp_flag_sigio = -1;
-static int hf_tns_ntp_flag_sigpipe = -1;
-static int hf_tns_ntp_flag_sigurg = -1;
-static int hf_tns_ntp_flag_urgentio = -1;
-static int hf_tns_ntp_flag_fdio = -1;
-static int hf_tns_ntp_flag_testop = -1;
-
-static int hf_tns_line_turnaround = -1;
-static int hf_tns_value_of_one = -1;
-static int hf_tns_connect_data_length = -1;
-static int hf_tns_connect_data_offset = -1;
-static int hf_tns_connect_data_max = -1;
-
-static int hf_tns_connect_flags0 = -1;
-static int hf_tns_connect_flags1 = -1;
-static int hf_tns_conn_flag_nareq = -1;
-static int hf_tns_conn_flag_nalink = -1;
-static int hf_tns_conn_flag_enablena = -1;
-static int hf_tns_conn_flag_ichg = -1;
-static int hf_tns_conn_flag_wantna = -1;
-
-static int hf_tns_connect_data = -1;
-static int hf_tns_trace_cf1 = -1;
-static int hf_tns_trace_cf2 = -1;
-static int hf_tns_trace_cid = -1;
-
-static int hf_tns_accept_data_length = -1;
-static int hf_tns_accept_data_offset = -1;
-static int hf_tns_accept_data = -1;
-
-static int hf_tns_refuse_reason_user = -1;
-static int hf_tns_refuse_reason_system = -1;
-static int hf_tns_refuse_data_length = -1;
-static int hf_tns_refuse_data = -1;
-
-static int hf_tns_abort_reason_user = -1;
-static int hf_tns_abort_reason_system = -1;
-static int hf_tns_abort_data = -1;
-
-static int hf_tns_marker_type = -1;
-static int hf_tns_marker_data_byte = -1;
-/* static int hf_tns_marker_data = -1; */
-
-static int hf_tns_redirect_data_length = -1;
-static int hf_tns_redirect_data = -1;
-
-static int hf_tns_control_cmd = -1;
-static int hf_tns_control_data = -1;
-
-static int hf_tns_data_flag = -1;
-static int hf_tns_data_flag_send = -1;
-static int hf_tns_data_flag_rc = -1;
-static int hf_tns_data_flag_c = -1;
-static int hf_tns_data_flag_reserved = -1;
-static int hf_tns_data_flag_more = -1;
-static int hf_tns_data_flag_eof = -1;
-static int hf_tns_data_flag_dic = -1;
-static int hf_tns_data_flag_rts = -1;
-static int hf_tns_data_flag_sntt = -1;
-
-static int hf_tns_data_id = -1;
-static int hf_tns_data_length = -1;
-static int hf_tns_data_oci_id = -1;
-static int hf_tns_data_piggyback_id = -1;
-static int hf_tns_data_unused = -1;
-
-static int hf_tns_data_opi_version2_banner_len = -1;
-static int hf_tns_data_opi_version2_banner = -1;
-static int hf_tns_data_opi_version2_vsnum = -1;
-
-static int hf_tns_data_opi_num_of_params = -1;
-static int hf_tns_data_opi_param_length = -1;
-static int hf_tns_data_opi_param_name = -1;
-static int hf_tns_data_opi_param_value = -1;
-
-static int hf_tns_data_setp_acc_version = -1;
-static int hf_tns_data_setp_cli_plat = -1;
-static int hf_tns_data_setp_version = -1;
-static int hf_tns_data_setp_banner = -1;
-
-static int hf_tns_data_sns_cli_vers = -1;
-static int hf_tns_data_sns_srv_vers = -1;
-static int hf_tns_data_sns_srvcnt = -1;
-
-static gint ett_tns = -1;
-static gint ett_tns_connect = -1;
-static gint ett_tns_accept = -1;
-static gint ett_tns_refuse = -1;
-static gint ett_tns_abort = -1;
-static gint ett_tns_redirect = -1;
-static gint ett_tns_marker = -1;
-static gint ett_tns_attention = -1;
-static gint ett_tns_control = -1;
-static gint ett_tns_data = -1;
-static gint ett_tns_data_flag = -1;
-static gint ett_tns_acc_versions = -1;
-static gint ett_tns_opi_params = -1;
-static gint ett_tns_opi_par = -1;
-static gint ett_tns_sopt_flag = -1;
-static gint ett_tns_ntp_flag = -1;
-static gint ett_tns_conn_flag = -1;
-static gint ett_sql = -1;
+static int proto_tns;
+static int hf_tns_request;
+static int hf_tns_response;
+static int hf_tns_length;
+static int hf_tns_packet_checksum;
+static int hf_tns_header_checksum;
+static int hf_tns_packet_type;
+static int hf_tns_reserved_byte;
+static int hf_tns_version;
+static int hf_tns_compat_version;
+
+static int hf_tns_service_options;
+static int hf_tns_sopt_flag_bconn;
+static int hf_tns_sopt_flag_pc;
+static int hf_tns_sopt_flag_hc;
+static int hf_tns_sopt_flag_fd;
+static int hf_tns_sopt_flag_hd;
+static int hf_tns_sopt_flag_dc1;
+static int hf_tns_sopt_flag_dc2;
+static int hf_tns_sopt_flag_dio;
+static int hf_tns_sopt_flag_ap;
+static int hf_tns_sopt_flag_ra;
+static int hf_tns_sopt_flag_sa;
+
+static int hf_tns_sdu_size;
+static int hf_tns_max_tdu_size;
+
+static int hf_tns_nt_proto_characteristics;
+static int hf_tns_ntp_flag_hangon;
+static int hf_tns_ntp_flag_crel;
+static int hf_tns_ntp_flag_tduio;
+static int hf_tns_ntp_flag_srun;
+static int hf_tns_ntp_flag_dtest;
+static int hf_tns_ntp_flag_cbio;
+static int hf_tns_ntp_flag_asio;
+static int hf_tns_ntp_flag_pio;
+static int hf_tns_ntp_flag_grant;
+static int hf_tns_ntp_flag_handoff;
+static int hf_tns_ntp_flag_sigio;
+static int hf_tns_ntp_flag_sigpipe;
+static int hf_tns_ntp_flag_sigurg;
+static int hf_tns_ntp_flag_urgentio;
+static int hf_tns_ntp_flag_fdio;
+static int hf_tns_ntp_flag_testop;
+
+static int hf_tns_line_turnaround;
+static int hf_tns_value_of_one;
+static int hf_tns_connect_data_length;
+static int hf_tns_connect_data_offset;
+static int hf_tns_connect_data_max;
+
+static int hf_tns_connect_flags0;
+static int hf_tns_connect_flags1;
+static int hf_tns_conn_flag_nareq;
+static int hf_tns_conn_flag_nalink;
+static int hf_tns_conn_flag_enablena;
+static int hf_tns_conn_flag_ichg;
+static int hf_tns_conn_flag_wantna;
+
+static int hf_tns_connect_data;
+static int hf_tns_trace_cf1;
+static int hf_tns_trace_cf2;
+static int hf_tns_trace_cid;
+
+static int hf_tns_accept_data_length;
+static int hf_tns_accept_data_offset;
+static int hf_tns_accept_data;
+
+static int hf_tns_refuse_reason_user;
+static int hf_tns_refuse_reason_system;
+static int hf_tns_refuse_data_length;
+static int hf_tns_refuse_data;
+
+static int hf_tns_abort_reason_user;
+static int hf_tns_abort_reason_system;
+static int hf_tns_abort_data;
+
+static int hf_tns_marker_type;
+static int hf_tns_marker_data_byte;
+/* static int hf_tns_marker_data; */
+
+static int hf_tns_redirect_data_length;
+static int hf_tns_redirect_data;
+
+static int hf_tns_control_cmd;
+static int hf_tns_control_data;
+
+static int hf_tns_data_flag;
+static int hf_tns_data_flag_send;
+static int hf_tns_data_flag_rc;
+static int hf_tns_data_flag_c;
+static int hf_tns_data_flag_reserved;
+static int hf_tns_data_flag_more;
+static int hf_tns_data_flag_eof;
+static int hf_tns_data_flag_dic;
+static int hf_tns_data_flag_rts;
+static int hf_tns_data_flag_sntt;
+
+static int hf_tns_data_id;
+static int hf_tns_data_length;
+static int hf_tns_data_oci_id;
+static int hf_tns_data_piggyback_id;
+static int hf_tns_data_unused;
+
+static int hf_tns_data_opi_version2_banner_len;
+static int hf_tns_data_opi_version2_banner;
+static int hf_tns_data_opi_version2_vsnum;
+
+static int hf_tns_data_opi_num_of_params;
+static int hf_tns_data_opi_param_length;
+static int hf_tns_data_opi_param_name;
+static int hf_tns_data_opi_param_value;
+
+static int hf_tns_data_setp_acc_version;
+static int hf_tns_data_setp_cli_plat;
+static int hf_tns_data_setp_version;
+static int hf_tns_data_setp_banner;
+
+static int hf_tns_data_sns_cli_vers;
+static int hf_tns_data_sns_srv_vers;
+static int hf_tns_data_sns_srvcnt;
+
+static int hf_tns_data_descriptor_row_count;
+static int hf_tns_data_descriptor_row_size;
+
+static int ett_tns;
+static int ett_tns_connect;
+static int ett_tns_accept;
+static int ett_tns_refuse;
+static int ett_tns_abort;
+static int ett_tns_redirect;
+static int ett_tns_marker;
+static int ett_tns_attention;
+static int ett_tns_control;
+static int ett_tns_data;
+static int ett_tns_data_flag;
+static int ett_tns_acc_versions;
+static int ett_tns_opi_params;
+static int ett_tns_opi_par;
+static int ett_tns_sopt_flag;
+static int ett_tns_ntp_flag;
+static int ett_tns_conn_flag;
+static int ett_tns_rows;
+static int ett_sql;
+
+static expert_field ei_tns_connect_data_next_packet;
+static expert_field ei_tns_data_descriptor_size_mismatch;
#define TCP_PORT_TNS 1521 /* Not IANA registered */
@@ -248,6 +264,7 @@ static const value_string tns_type_vals[] = {
{TNS_TYPE_MARKER, "Marker"},
{TNS_TYPE_ATTENTION, "Attention"},
{TNS_TYPE_CONTROL, "Control"},
+ {TNS_TYPE_DD, "Data Descriptor"},
{0, NULL}
};
@@ -455,29 +472,46 @@ static const value_string tns_control_cmds[] = {
{0, NULL}
};
+typedef struct _tns_conv_info_t {
+ uint32_t pending_connect_data;
+} tns_conv_info_t;
+
void proto_reg_handoff_tns(void);
static int dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_);
-static guint get_data_func_id(tvbuff_t *tvb, int offset)
+static tns_conv_info_t*
+tns_get_conv_info(packet_info *pinfo)
+{
+ conversation_t *conversation = find_or_create_conversation(pinfo);
+
+ tns_conv_info_t *tns_info = (tns_conv_info_t *)conversation_get_proto_data(conversation, proto_tns);
+ if (!tns_info) {
+ tns_info = wmem_new0(wmem_file_scope(), tns_conv_info_t);
+ conversation_add_proto_data(conversation, proto_tns, tns_info);
+ }
+ return tns_info;
+}
+
+static unsigned get_data_func_id(tvbuff_t *tvb, int offset)
{
/* Determine Data Function id */
- guint8 first_byte;
+ uint8_t first_byte;
first_byte =
- tvb_reported_length_remaining(tvb, offset) > 0 ? tvb_get_guint8(tvb, offset) : 0;
+ tvb_reported_length_remaining(tvb, offset) > 0 ? tvb_get_uint8(tvb, offset) : 0;
if ( tvb_bytes_exist(tvb, offset, 4) && first_byte == 0xDE &&
- tvb_get_guint24(tvb, offset+1, ENC_BIG_ENDIAN) == 0xADBEEF )
+ tvb_get_uint24(tvb, offset+1, ENC_BIG_ENDIAN) == 0xADBEEF )
{
return SQLNET_SNS;
}
else
{
- return (guint)first_byte;
+ return (unsigned)first_byte;
}
}
-static void vsnum_to_vstext_basecustom(gchar *result, guint32 vsnum)
+static void vsnum_to_vstext_basecustom(char *result, uint32_t vsnum)
{
/*
* Translate hex value to human readable version value, described at
@@ -491,11 +525,58 @@ static void vsnum_to_vstext_basecustom(gchar *result, guint32 vsnum)
vsnum & 0xff);
}
+static void dissect_tns_data_descriptor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tns_tree, uint32_t length)
+{
+ /* This is used by Oracle 12c for at least sending LOB/FILE data. */
+ proto_tree *dd_tree, *row_tree;
+ proto_item *ti;
+ uint32_t data_len, row_count, row_size, total_row_size = 0;
+ int orig_offset = offset;
+
+ /* We only get here after tcp_dissect_pdus(), length is guaranteed. */
+ DISSECTOR_ASSERT_CMPINT(length, >=, TNS_HDR_LEN);
+
+ dd_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL, "Data Descriptor");
+
+ /* No idea what this is. Usually 0x0003. */
+ offset += 4;
+ proto_tree_add_item_ret_uint(dd_tree, hf_tns_data_length, tvb,
+ offset, 4, ENC_BIG_ENDIAN, &data_len);
+ offset += 4;
+
+ /* This next parameter looks like: number of big endian shorts that follow,
+ * the sum of the shorts equals the file length above - each short maxes
+ * out at 0x1f7c = 8060, presumably related to the page size / max table
+ * row size in Microsoft SQL Server? Something about how many rows it
+ * would take to store this in-table?
+ */
+ proto_tree_add_item_ret_uint(dd_tree, hf_tns_data_descriptor_row_count, tvb,
+ offset, 4, ENC_BIG_ENDIAN, &row_count);
+ offset += 4;
+ row_tree = proto_tree_add_subtree(dd_tree, tvb, offset, row_count * 2,
+ ett_tns_rows, &ti, "Rows");
+ for (uint32_t i = 0; i < row_count; i++) {
+ proto_tree_add_item_ret_uint(row_tree, hf_tns_data_descriptor_row_size, tvb,
+ offset, 2, ENC_BIG_ENDIAN, &row_size);
+ total_row_size += row_size;
+ offset += 2;
+ }
+ proto_item_append_text(ti, " (%u bytes)", total_row_size);
+ if (total_row_size != data_len) {
+ expert_add_info(pinfo, ti, &ei_tns_data_descriptor_size_mismatch);
+ }
+
+ offset = orig_offset + (length - TNS_HDR_LEN);
+
+ call_data_dissector(tvb_new_subset_length(tvb, offset, data_len), pinfo,
+ dd_tree);
+}
+
static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tns_tree)
{
proto_tree *data_tree;
- guint data_func_id;
- gboolean is_request;
+ unsigned data_func_id;
+ bool is_request;
static int * const flags[] = {
&hf_tns_data_flag_send,
&hf_tns_data_flag_rc,
@@ -517,8 +598,30 @@ static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, prot
data_func_id = get_data_func_id(tvb, offset);
/* Do this only if the Data message have a body. Otherwise, there are only Data flags. */
- if ( tvb_reported_length_remaining(tvb, offset) > 0 )
+ int remaining = tvb_reported_length_remaining(tvb, offset);
+ if ( remaining > 0 )
{
+ if (is_request) {
+ if (!PINFO_FD_VISITED(pinfo)) {
+ tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
+ if ((uint32_t)remaining == tns_info->pending_connect_data) {
+ col_append_str(pinfo->cinfo, COL_INFO, ", Connect Data");
+ proto_tree_add_item(data_tree, hf_tns_connect_data, tvb,
+ offset, -1, ENC_ASCII);
+ p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, 0,
+ GUINT_TO_POINTER(tns_info->pending_connect_data));
+ tns_info->pending_connect_data = 0;
+ return;
+ }
+ } else {
+ if (p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, 0) != NULL) {
+ col_append_str(pinfo->cinfo, COL_INFO, ", Connect Data");
+ proto_tree_add_item(data_tree, hf_tns_connect_data, tvb,
+ offset, -1, ENC_ASCII);
+ return;
+ }
+ }
+ }
col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(data_func_id, tns_data_funcs, "unknown"));
if ( (data_func_id != SQLNET_SNS) && (try_val_to_str(data_func_id, tns_data_funcs) != NULL) )
@@ -545,9 +648,9 @@ static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, prot
* Add each accepted version as a
* separate item.
*/
- guint8 vers;
+ uint8_t vers;
- vers = tvb_get_guint8(tvb, offset);
+ vers = tvb_get_uint8(tvb, offset);
if (vers == 0) {
/*
* A version of 0 terminates
@@ -568,16 +671,16 @@ static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, prot
}
else
{
- gint len;
+ int len;
versions_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_acc_versions, &ti, "Versions");
sep = ':';
for (;;) {
/*
* Add each version as a separate item.
*/
- guint8 vers;
+ uint8_t vers;
- vers = tvb_get_guint8(tvb, offset);
+ vers = tvb_get_uint8(tvb, offset);
if (vers == 0) {
/*
* A version of 0 terminates
@@ -605,7 +708,7 @@ static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, prot
case SQLNET_RETURN_OPI_PARAM:
{
- guint8 skip = 0, opi = 0;
+ uint8_t skip = 0, opi = 0;
if ( tvb_bytes_exist(tvb, offset, 11) )
{
@@ -688,7 +791,7 @@ static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, prot
proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, skip, ENC_NA);
offset += skip;
- guint8 len = tvb_get_guint8(tvb, offset);
+ uint8_t len = tvb_get_uint8(tvb, offset);
proto_tree_add_item(data_tree, hf_tns_data_opi_version2_banner_len, tvb, offset, 1, ENC_BIG_ENDIAN);
offset += 1;
@@ -703,7 +806,7 @@ static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, prot
{
proto_tree *params_tree;
proto_item *params_ti;
- guint par, params;
+ unsigned par, params;
if ( skip == 1 )
{
@@ -731,7 +834,7 @@ static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, prot
{
proto_tree *par_tree;
proto_item *par_ti;
- guint len, offset_prev;
+ unsigned len, offset_prev;
par_tree = proto_tree_add_subtree(params_tree, tvb, offset, -1, ett_tns_opi_par, &par_ti, "Parameter");
proto_item_append_text(par_ti, " %u", par);
@@ -754,11 +857,11 @@ static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, prot
/* Value length */
if ( opi == OPI_OSESSKEY )
{
- len = tvb_get_guint8(tvb, offset);
+ len = tvb_get_uint8(tvb, offset);
}
else /* OPI_OAUTH */
{
- len = tvb_get_guint8(tvb, offset_prev) == 0 ? 0 : tvb_get_guint8(tvb, offset);
+ len = tvb_get_uint8(tvb, offset_prev) == 0 ? 0 : tvb_get_uint8(tvb, offset);
}
/*
@@ -786,8 +889,8 @@ static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, prot
if ( opi == OPI_OSESSKEY )
{
- /* SQL Developer specifix fix */
- offset += tvb_get_guint8(tvb, offset) == 2 ? 5 : 3;
+ /* SQL Developer specific fix */
+ offset += tvb_get_uint8(tvb, offset) == 2 ? 5 : 3;
}
else /* OPI_OAUTH */
{
@@ -848,7 +951,7 @@ static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, prot
static void dissect_tns_connect(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
{
proto_tree *connect_tree;
- guint32 cd_offset, cd_len;
+ uint32_t cd_offset, cd_len;
int tns_offset = offset-8;
static int * const flags[] = {
&hf_tns_ntp_flag_hangon,
@@ -925,7 +1028,7 @@ static void dissect_tns_connect(tvbuff_t *tvb, int offset, packet_info *pinfo _U
* XXX - sometimes it appears that this stuff isn't present
* in the packet.
*/
- if ((guint32)(offset + 16) <= tns_offset+cd_offset)
+ if ((uint32_t)(offset + 16) <= tns_offset+cd_offset)
{
proto_tree_add_item(connect_tree, hf_tns_trace_cf1, tvb,
offset, 4, ENC_BIG_ENDIAN);
@@ -942,15 +1045,26 @@ static void dissect_tns_connect(tvbuff_t *tvb, int offset, packet_info *pinfo _U
if ( cd_len > 0)
{
- proto_tree_add_item(connect_tree, hf_tns_connect_data, tvb,
- tns_offset+cd_offset, -1, ENC_ASCII);
+ /* Long Connect Data (> 221 bytes?) is not in the Connect PDU
+ * but sent in an immediately following Data PDU.
+ */
+ if (tvb_reported_length_remaining(tvb, tns_offset + cd_offset)) {
+ proto_tree_add_item(connect_tree, hf_tns_connect_data, tvb,
+ tns_offset+cd_offset, -1, ENC_ASCII);
+ } else {
+ proto_tree_add_expert(connect_tree, pinfo, &ei_tns_connect_data_next_packet, tvb, 0, 0);
+ if (!PINFO_FD_VISITED(pinfo)) {
+ tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
+ tns_info->pending_connect_data = cd_len;
+ }
+ }
}
}
static void dissect_tns_accept(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
{
proto_tree *accept_tree;
- guint32 accept_offset, accept_len;
+ uint32_t accept_offset, accept_len;
int tns_offset = offset-8;
accept_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
@@ -1105,30 +1219,67 @@ static void dissect_tns_control(tvbuff_t *tvb, int offset, packet_info *pinfo _U
offset, -1, ENC_NA);
}
-static guint
+static unsigned
get_tns_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
{
/*
* Get the 16-bit length of the TNS message, including header
*/
- return tvb_get_ntohs(tvb, offset);
+ unsigned length = tvb_get_ntohs(tvb, offset);
+ offset += 4;
+ uint8_t type = tvb_get_uint8(tvb, offset);
+ /* Type 0xf (data descriptor, LOB/FILE data) has data which follows
+ * immediately (no new PDU header) but is not counted in the PDU
+ * length field either.
+ */
+ if (type == TNS_TYPE_DD) {
+ offset += 8;
+ if (!tvb_bytes_exist(tvb, offset, 4)) {
+ /* return 0 makes tcp_dissect_pdus() report
+ * DESEGMENT_ONE_MORE_SEGMENT to the TCP dissector.
+ */
+ return 0;
+ }
+ unsigned dd_len = tvb_get_ntohl(tvb, offset);
+ return length + dd_len;
+ }
+ return length;
}
-static guint
+static unsigned
get_tns_pdu_len_nochksum(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
{
/*
* Get the 32-bit length of the TNS message, including header
*/
- return tvb_get_ntohl(tvb, offset);
+ unsigned length = tvb_get_ntohl(tvb, offset);
+ offset += 4;
+ uint8_t type = tvb_get_uint8(tvb, offset);
+ /* Type 0xf (data descriptor, LOB/FILE data) has data which follows
+ * immediately (no new PDU header) but is not counted in the PDU
+ * length field either.
+ */
+ if (type == TNS_TYPE_DD) {
+ offset += 8;
+ if (!tvb_bytes_exist(tvb, offset, 4)) {
+ /* return 0 makes tcp_dissect_pdus() report
+ * DESEGMENT_ONE_MORE_SEGMENT to the TCP dissector.
+ */
+ return 0;
+ }
+ unsigned dd_len = tvb_get_ntohl(tvb, offset);
+ return length + dd_len;
+ }
+
+ return length;
}
static int
dissect_tns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
- guint32 length;
- guint16 chksum;
- guint8 type;
+ uint32_t length;
+ uint16_t chksum;
+ uint8_t type;
/*
* First, do a sanity check to make sure what we have
@@ -1139,7 +1290,7 @@ dissect_tns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
* Well, we have the packet type; let's make sure
* it's a known type.
*/
- type = tvb_get_guint8(tvb, 4);
+ type = tvb_get_uint8(tvb, 4);
if (type < TNS_TYPE_CONNECT || type > TNS_TYPE_MAX)
return 0; /* it's not a known type */
}
@@ -1159,7 +1310,7 @@ dissect_tns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
length = (chksum == 0 || chksum == 4) ? 2 : 4;
- tcp_dissect_pdus(tvb, pinfo, tree, tns_desegment, length,
+ tcp_dissect_pdus(tvb, pinfo, tree, tns_desegment, TNS_HDR_LEN,
(length == 2 ? get_tns_pdu_len : get_tns_pdu_len_nochksum),
dissect_tns_pdu, data);
@@ -1172,9 +1323,9 @@ dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
proto_tree *tns_tree, *ti;
proto_item *hidden_item;
int offset = 0;
- guint32 length;
- guint16 chksum;
- guint8 type;
+ uint32_t length;
+ uint16_t chksum;
+ uint8_t type;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "TNS");
@@ -1187,12 +1338,12 @@ dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
if (pinfo->match_uint == pinfo->destport)
{
hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_request,
- tvb, offset, 0, TRUE);
+ tvb, offset, 0, true);
}
else
{
hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_response,
- tvb, offset, 0, TRUE);
+ tvb, offset, 0, true);
}
proto_item_set_hidden(hidden_item);
@@ -1214,7 +1365,7 @@ dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
offset += 4;
}
- type = tvb_get_guint8(tvb, offset);
+ type = tvb_get_uint8(tvb, offset);
proto_tree_add_uint(tns_tree, hf_tns_packet_type, tvb,
offset, 1, type);
offset += 1;
@@ -1258,6 +1409,9 @@ dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data
case TNS_TYPE_DATA:
dissect_tns_data(tvb,offset,pinfo,tns_tree);
break;
+ case TNS_TYPE_DD:
+ dissect_tns_data_descriptor(tvb,offset,pinfo,tns_tree, length);
+ break;
default:
call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo,
tns_tree);
@@ -1272,10 +1426,10 @@ void proto_register_tns(void)
static hf_register_info hf[] = {
{ &hf_tns_response, {
"Response", "tns.response", FT_BOOLEAN, BASE_NONE,
- NULL, 0x0, "TRUE if TNS response", HFILL }},
+ NULL, 0x0, "true if TNS response", HFILL }},
{ &hf_tns_request, {
"Request", "tns.request", FT_BOOLEAN, BASE_NONE,
- NULL, 0x0, "TRUE if TNS request", HFILL }},
+ NULL, 0x0, "true if TNS request", HFILL }},
{ &hf_tns_length, {
"Packet Length", "tns.length", FT_UINT32, BASE_DEC,
NULL, 0x0, "Length of TNS packet", HFILL }},
@@ -1402,8 +1556,8 @@ void proto_register_tns(void)
NULL, 0x0, NULL, HFILL }},
{ &hf_tns_connect_data_length, {
- "Length of Connect Data", "tns.connect_data_length", FT_UINT16, BASE_DEC,
- NULL, 0x0, NULL, HFILL }},
+ "Length of Connect Data", "tns.connect_data_length", FT_UINT16,
+ BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }},
{ &hf_tns_connect_data_offset, {
"Offset to Connect Data", "tns.connect_data_offset", FT_UINT16, BASE_DEC,
NULL, 0x0, NULL, HFILL }},
@@ -1449,8 +1603,8 @@ void proto_register_tns(void)
NULL, 0x0, NULL, HFILL }},
{ &hf_tns_accept_data_length, {
- "Accept Data Length", "tns.accept_data_length", FT_UINT16, BASE_DEC,
- NULL, 0x0, "Length of Accept Data", HFILL }},
+ "Accept Data Length", "tns.accept_data_length", FT_UINT16,
+ BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }},
{ &hf_tns_accept_data, {
"Accept Data", "tns.accept_data", FT_STRING, BASE_NONE,
NULL, 0x0, NULL, HFILL }},
@@ -1465,8 +1619,8 @@ void proto_register_tns(void)
"Refuse Reason (System)", "tns.refuse_reason_system", FT_UINT8, BASE_HEX,
NULL, 0x0, "Refuse Reason from System", HFILL }},
{ &hf_tns_refuse_data_length, {
- "Refuse Data Length", "tns.refuse_data_length", FT_UINT16, BASE_DEC,
- NULL, 0x0, "Length of Refuse Data", HFILL }},
+ "Refuse Data Length", "tns.refuse_data_length", FT_UINT16,
+ BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }},
{ &hf_tns_refuse_data, {
"Refuse Data", "tns.refuse_data", FT_STRING, BASE_NONE,
NULL, 0x0, NULL, HFILL }},
@@ -1501,8 +1655,8 @@ void proto_register_tns(void)
NULL, 0x0, NULL, HFILL }},
{ &hf_tns_redirect_data_length, {
- "Redirect Data Length", "tns.redirect_data_length", FT_UINT16, BASE_DEC,
- NULL, 0x0, "Length of Redirect Data", HFILL }},
+ "Redirect Data Length", "tns.redirect_data_length", FT_UINT16,
+ BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }},
{ &hf_tns_redirect_data, {
"Redirect Data", "tns.redirect_data", FT_STRING, BASE_NONE,
NULL, 0x0, NULL, HFILL }},
@@ -1542,8 +1696,8 @@ void proto_register_tns(void)
"Data ID", "tns.data_id", FT_UINT32, BASE_HEX,
VALS(tns_data_funcs), 0x0, NULL, HFILL }},
{ &hf_tns_data_length, {
- "Data Length", "tns.data_length", FT_UINT16, BASE_DEC,
- NULL, 0x0, NULL, HFILL }},
+ "Data Length", "tns.data_length", FT_UINT32,
+ BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }},
{ &hf_tns_data_oci_id, {
"Call ID", "tns.data_oci.id", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
@@ -1606,6 +1760,13 @@ void proto_register_tns(void)
"Value", "tns.data_opi.param_value", FT_STRING, BASE_NONE,
NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_data_descriptor_row_count, {
+ "Row Count", "tns.data_descriptor.row_count", FT_UINT32, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_data_descriptor_row_size, {
+ "Row Size", "tns.data_descriptor.row_size", FT_UINT32, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+
{ &hf_tns_reserved_byte, {
"Reserved Byte", "tns.reserved_byte", FT_BYTES, BASE_NONE,
NULL, 0x0, NULL, HFILL }},
@@ -1615,7 +1776,7 @@ void proto_register_tns(void)
};
- static gint *ett[] = {
+ static int *ett[] = {
&ett_tns,
&ett_tns_connect,
&ett_tns_accept,
@@ -1633,13 +1794,23 @@ void proto_register_tns(void)
&ett_tns_sopt_flag,
&ett_tns_ntp_flag,
&ett_tns_conn_flag,
+ &ett_tns_rows,
&ett_sql
};
+
+ static ei_register_info ei[] = {
+ { &ei_tns_connect_data_next_packet, { "tns.connect_data.next_packet", PI_REQUEST_CODE, PI_CHAT, "Long Connect Data (> 221 bytes) carried in subsequent Data packet", EXPFILL }},
+ { &ei_tns_data_descriptor_size_mismatch, { "tns.data_descriptor.size_mismatch", PI_PROTOCOL, PI_WARN, "Data size from summing row sizes differs from size in descriptor", EXPFILL }},
+ };
+
module_t *tns_module;
+ expert_module_t* expert_tns;
proto_tns = proto_register_protocol("Transparent Network Substrate Protocol", "TNS", "tns");
proto_register_field_array(proto_tns, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+ expert_tns = expert_register_protocol(proto_tns);
+ expert_register_field_array(expert_tns, ei, array_length(ei));
tns_handle = register_dissector("tns", dissect_tns, proto_tns);
tns_module = prefs_register_protocol(proto_tns, NULL);