summaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-tns.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dissectors/packet-tns.c
parentInitial commit. (diff)
downloadwireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz
wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-tns.c')
-rw-r--r--epan/dissectors/packet-tns.c1670
1 files changed, 1670 insertions, 0 deletions
diff --git a/epan/dissectors/packet-tns.c b/epan/dissectors/packet-tns.c
new file mode 100644
index 0000000..d25decb
--- /dev/null
+++ b/epan/dissectors/packet-tns.c
@@ -0,0 +1,1670 @@
+/* packet-tns.c
+ * Routines for Oracle TNS packet dissection
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * Copied from packet-tftp.c
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "config.h"
+
+#include <epan/packet.h>
+#include "packet-tcp.h"
+
+#include <epan/prefs.h>
+
+void proto_register_tns(void);
+
+/* Packet Types */
+#define TNS_TYPE_CONNECT 1
+#define TNS_TYPE_ACCEPT 2
+#define TNS_TYPE_ACK 3
+#define TNS_TYPE_REFUSE 4
+#define TNS_TYPE_REDIRECT 5
+#define TNS_TYPE_DATA 6
+#define TNS_TYPE_NULL 7
+#define TNS_TYPE_ABORT 9
+#define TNS_TYPE_RESEND 11
+#define TNS_TYPE_MARKER 12
+#define TNS_TYPE_ATTENTION 13
+#define TNS_TYPE_CONTROL 14
+#define TNS_TYPE_MAX 19
+
+/* Data Packet Functions */
+#define SQLNET_SET_PROTOCOL 1
+#define SQLNET_SET_DATATYPES 2
+#define SQLNET_USER_OCI_FUNC 3
+#define SQLNET_RETURN_STATUS 4
+#define SQLNET_ACCESS_USR_ADDR 5
+#define SQLNET_ROW_TRANSF_HDR 6
+#define SQLNET_ROW_TRANSF_DATA 7
+#define SQLNET_RETURN_OPI_PARAM 8
+#define SQLNET_FUNCCOMPLETE 9
+#define SQLNET_NERROR_RET_DEF 10
+#define SQLNET_IOVEC_4FAST_UPI 11
+#define SQLNET_LONG_4FAST_UPI 12
+#define SQLNET_INVOKE_USER_CB 13
+#define SQLNET_LOB_FILE_DF 14
+#define SQLNET_WARNING 15
+#define SQLNET_DESCRIBE_INFO 16
+#define SQLNET_PIGGYBACK_FUNC 17
+#define SQLNET_SIG_4UCS 18
+#define SQLNET_FLUSH_BIND_DATA 19
+#define SQLNET_SNS 0xdeadbeef
+#define SQLNET_XTRN_PROCSERV_R1 32
+#define SQLNET_XTRN_PROCSERV_R2 68
+
+/* Return OPI Parameter's Type */
+#define OPI_VERSION2 1
+#define OPI_OSESSKEY 2
+#define OPI_OAUTH 3
+
+/* desegmentation of TNS over TCP */
+static gboolean 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;
+
+#define TCP_PORT_TNS 1521 /* Not IANA registered */
+
+static int * const tns_connect_flags[] = {
+ &hf_tns_conn_flag_nareq,
+ &hf_tns_conn_flag_nalink,
+ &hf_tns_conn_flag_enablena,
+ &hf_tns_conn_flag_ichg,
+ &hf_tns_conn_flag_wantna,
+ NULL
+};
+
+static int * const tns_service_options[] = {
+ &hf_tns_sopt_flag_bconn,
+ &hf_tns_sopt_flag_pc,
+ &hf_tns_sopt_flag_hc,
+ &hf_tns_sopt_flag_fd,
+ &hf_tns_sopt_flag_hd,
+ &hf_tns_sopt_flag_dc1,
+ &hf_tns_sopt_flag_dc2,
+ &hf_tns_sopt_flag_dio,
+ &hf_tns_sopt_flag_ap,
+ &hf_tns_sopt_flag_ra,
+ &hf_tns_sopt_flag_sa,
+ NULL
+};
+
+static const value_string tns_type_vals[] = {
+ {TNS_TYPE_CONNECT, "Connect" },
+ {TNS_TYPE_ACCEPT, "Accept" },
+ {TNS_TYPE_ACK, "Acknowledge" },
+ {TNS_TYPE_REFUSE, "Refuse" },
+ {TNS_TYPE_REDIRECT, "Redirect" },
+ {TNS_TYPE_DATA, "Data" },
+ {TNS_TYPE_NULL, "Null" },
+ {TNS_TYPE_ABORT, "Abort" },
+ {TNS_TYPE_RESEND, "Resend"},
+ {TNS_TYPE_MARKER, "Marker"},
+ {TNS_TYPE_ATTENTION, "Attention"},
+ {TNS_TYPE_CONTROL, "Control"},
+ {0, NULL}
+};
+
+static const value_string tns_data_funcs[] = {
+ {SQLNET_SET_PROTOCOL, "Set Protocol"},
+ {SQLNET_SET_DATATYPES, "Set Datatypes"},
+ {SQLNET_USER_OCI_FUNC, "User OCI Functions"},
+ {SQLNET_RETURN_STATUS, "Return Status"},
+ {SQLNET_ACCESS_USR_ADDR, "Access User Address Space"},
+ {SQLNET_ROW_TRANSF_HDR, "Row Transfer Header"},
+ {SQLNET_ROW_TRANSF_DATA, "Row Transfer Data"},
+ {SQLNET_RETURN_OPI_PARAM, "Return OPI Parameter"},
+ {SQLNET_FUNCCOMPLETE, "Function Complete"},
+ {SQLNET_NERROR_RET_DEF, "N Error return definitions follow"},
+ {SQLNET_IOVEC_4FAST_UPI, "Sending I/O Vec only for fast UPI"},
+ {SQLNET_LONG_4FAST_UPI, "Sending long for fast UPI"},
+ {SQLNET_INVOKE_USER_CB, "Invoke user callback"},
+ {SQLNET_LOB_FILE_DF, "LOB/FILE data follows"},
+ {SQLNET_WARNING, "Warning messages - may be a set of them"},
+ {SQLNET_DESCRIBE_INFO, "Describe Information"},
+ {SQLNET_PIGGYBACK_FUNC, "Piggy back function follow"},
+ {SQLNET_SIG_4UCS, "Signals special action for untrusted callout support"},
+ {SQLNET_FLUSH_BIND_DATA, "Flush Out Bind data in DML/w RETURN when error"},
+ {SQLNET_XTRN_PROCSERV_R1, "External Procedures and Services Registrations"},
+ {SQLNET_XTRN_PROCSERV_R2, "External Procedures and Services Registrations"},
+ {SQLNET_SNS, "Secure Network Services"},
+ {0, NULL}
+};
+
+static const value_string tns_data_oci_subfuncs[] = {
+ {1, "Logon to Oracle"},
+ {2, "Open Cursor"},
+ {3, "Parse a Row"},
+ {4, "Execute a Row"},
+ {5, "Fetch a Row"},
+ {8, "Close Cursor"},
+ {9, "Logoff of Oracle"},
+ {10, "Describe a select list column"},
+ {11, "Define where the column goes"},
+ {12, "Auto commit on"},
+ {13, "Auto commit off"},
+ {14, "Commit"},
+ {15, "Rollback"},
+ {16, "Set fatal error options"},
+ {17, "Resume current operation"},
+ {18, "Get Oracle version-date string"},
+ {19, "Until we get rid of OASQL"},
+ {20, "Cancel the current operation"},
+ {21, "Get error message"},
+ {22, "Exit Oracle command"},
+ {23, "Special function"},
+ {24, "Abort"},
+ {25, "Dequeue by RowID"},
+ {26, "Fetch a long column value"},
+ {27, "Create Access Module"},
+ {28, "Save Access Module Statement"},
+ {29, "Save Access Module"},
+ {30, "Parse Access Module Statement"},
+ {31, "How many items?"},
+ {32, "Initialize Oracle"},
+ {33, "Change User ID"},
+ {34, "Bind by reference positional"},
+ {35, "Get n'th Bind Variable"},
+ {36, "Get n'th Into Variable"},
+ {37, "Bind by reference"},
+ {38, "Bind by reference numeric"},
+ {39, "Parse and Execute"},
+ {40, "Parse for syntax (only)"},
+ {41, "Parse for syntax and SQL Dictionary lookup"},
+ {42, "Continue serving after EOF"},
+ {43, "Array describe"},
+ {44, "Init sys pars command table"},
+ {45, "Finalize sys pars command table"},
+ {46, "Put sys par in command table"},
+ {47, "Get sys pars from command table"},
+ {48, "Start Oracle (V6)"},
+ {49, "Shutdown Oracle (V6)"},
+ {50, "Run Independent Process (V6)"},
+ {51, "Test RAM (V6)"},
+ {52, "Archive operation (V6)"},
+ {53, "Media Recovery - start (V6)"},
+ {54, "Media Recovery - record tablespace to recover (V6)"},
+ {55, "Media Recovery - get starting log seq # (V6)"},
+ {56, "Media Recovery - recover using offline log (V6)"},
+ {57, "Media Recovery - cancel media recovery (V6)"},
+ {58, "Logon to Oracle (V6)"},
+ {59, "Get Oracle version-date string in new format"},
+ {60, "Initialize Oracle"},
+ {61, "Reserved for MAC; close all cursors"},
+ {62, "Bundled execution call"},
+ {65, "For direct loader: functions"},
+ {66, "For direct loader: buffer transfer"},
+ {67, "Distrib. trans. mgr. RPC"},
+ {68, "Describe indexes for distributed query"},
+ {69, "Session operations"},
+ {70, "Execute using synchronized system commit numbers"},
+ {71, "Fast UPI calls to OPIAL7"},
+ {72, "Long Fetch (V7)"},
+ {73, "Call OPIEXE from OPIALL: no two-task access"},
+ {74, "Parse Call (V7) to deal with various flavours"},
+ {76, "RPC call from PL/SQL"},
+ {77, "Do a KGL operation"},
+ {78, "Execute and Fetch"},
+ {79, "X/Open XA operation"},
+ {80, "New KGL operation call"},
+ {81, "2nd Half of Logon"},
+ {82, "1st Half of Logon"},
+ {83, "Do Streaming Operation"},
+ {84, "Open Session (71 interface)"},
+ {85, "X/Open XA operations (71 interface)"},
+ {86, "Debugging operations"},
+ {87, "Special debugging operations"},
+ {88, "XA Start"},
+ {89, "XA Switch and Commit"},
+ {90, "Direct copy from db buffers to client address"},
+ {91, "OKOD Call (In Oracle <= 7 this used to be Connect"},
+ {93, "RPI Callback with ctxdef"},
+ {94, "Bundled execution call (V7)"},
+ {95, "Do Streaming Operation without begintxn"},
+ {96, "LOB and FILE related calls"},
+ {97, "File Create call"},
+ {98, "Describe query (V8) call"},
+ {99, "Connect (non-blocking attach host)"},
+ {100, "Open a recursive cursor"},
+ {101, "Bundled KPR Execution"},
+ {102, "Bundled PL/SQL execution"},
+ {103, "Transaction start, attach, detach"},
+ {104, "Transaction commit, rollback, recover"},
+ {105, "Cursor close all"},
+ {106, "Failover into piggyback"},
+ {107, "Session switching piggyback (V8)"},
+ {108, "Do Dummy Defines"},
+ {109, "Init sys pars (V8)"},
+ {110, "Finalize sys pars (V8)"},
+ {111, "Put sys par in par space (V8)"},
+ {112, "Terminate sys pars (V8)"},
+ {114, "Init Untrusted Callbacks"},
+ {115, "Generic authentication call"},
+ {116, "FailOver Get Instance call"},
+ {117, "Oracle Transaction service Commit remote sites"},
+ {118, "Get the session key"},
+ {119, "Describe any (V8)"},
+ {120, "Cancel All"},
+ {121, "AQ Enqueue"},
+ {122, "AQ Dequeue"},
+ {123, "Object transfer"},
+ {124, "RFS Call"},
+ {125, "Kernel programmatic notification"},
+ {126, "Listen"},
+ {127, "Oracle Transaction service Commit remote sites (V >= 8.1.3)"},
+ {128, "Dir Path Prepare"},
+ {129, "Dir Path Load Stream"},
+ {130, "Dir Path Misc. Ops"},
+ {131, "Memory Stats"},
+ {132, "AQ Properties Status"},
+ {134, "Remote Fetch Archive Log FAL"},
+ {135, "Client ID propagation"},
+ {136, "DR Server CNX Process"},
+ {138, "SPFILE parameter put"},
+ {139, "KPFC exchange"},
+ {140, "Object Transfer (V8.2)"},
+ {141, "Push Transaction"},
+ {142, "Pop Transaction"},
+ {143, "KFN Operation"},
+ {144, "Dir Path Unload Stream"},
+ {145, "AQ batch enqueue dequeue"},
+ {146, "File Transfer"},
+ {147, "Ping"},
+ {148, "TSM"},
+ {150, "Begin TSM"},
+ {151, "End TSM"},
+ {152, "Set schema"},
+ {153, "Fetch from suspended result set"},
+ {154, "Key/Value pair"},
+ {155, "XS Create session Operation"},
+ {156, "XS Session Roundtrip Operation"},
+ {157, "XS Piggyback Operation"},
+ {158, "KSRPC Execution"},
+ {159, "Streams combined capture apply"},
+ {160, "AQ replay information"},
+ {161, "SSCR"},
+ {162, "Session Get"},
+ {163, "Session RLS"},
+ {165, "Workload replay data"},
+ {166, "Replay statistic data"},
+ {167, "Query Cache Stats"},
+ {168, "Query Cache IDs"},
+ {169, "RPC Test Stream"},
+ {170, "Replay PL/SQL RPC"},
+ {171, "XStream Out"},
+ {172, "Golden Gate RPC"},
+ {0, NULL}
+};
+static value_string_ext tns_data_oci_subfuncs_ext = VALUE_STRING_EXT_INIT(tns_data_oci_subfuncs);
+
+static const value_string tns_marker_types[] = {
+ {0, "Data Marker - 0 Data Bytes"},
+ {1, "Data Marker - 1 Data Bytes"},
+ {2, "Attention Marker"},
+ {0, NULL}
+};
+
+static const value_string tns_control_cmds[] = {
+ {1, "Oracle Trace Command"},
+ {0, NULL}
+};
+
+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)
+{
+ /* Determine Data Function id */
+ guint8 first_byte;
+
+ first_byte =
+ tvb_reported_length_remaining(tvb, offset) > 0 ? tvb_get_guint8(tvb, offset) : 0;
+
+ if ( tvb_bytes_exist(tvb, offset, 4) && first_byte == 0xDE &&
+ tvb_get_guint24(tvb, offset+1, ENC_BIG_ENDIAN) == 0xADBEEF )
+ {
+ return SQLNET_SNS;
+ }
+ else
+ {
+ return (guint)first_byte;
+ }
+}
+
+static void vsnum_to_vstext_basecustom(gchar *result, guint32 vsnum)
+{
+ /*
+ * Translate hex value to human readable version value, described at
+ * http://docs.oracle.com/cd/B28359_01/server.111/b28310/dba004.htm
+ */
+ snprintf(result, ITEM_LABEL_LENGTH, "%d.%d.%d.%d.%d",
+ vsnum >> 24,
+ (vsnum >> 20) & 0xf,
+ (vsnum >> 12) & 0xf,
+ (vsnum >> 8) & 0xf,
+ vsnum & 0xff);
+}
+
+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;
+ static int * const flags[] = {
+ &hf_tns_data_flag_send,
+ &hf_tns_data_flag_rc,
+ &hf_tns_data_flag_c,
+ &hf_tns_data_flag_reserved,
+ &hf_tns_data_flag_more,
+ &hf_tns_data_flag_eof,
+ &hf_tns_data_flag_dic,
+ &hf_tns_data_flag_rts,
+ &hf_tns_data_flag_sntt,
+ NULL
+ };
+
+ is_request = pinfo->match_uint == pinfo->destport;
+ data_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL, "Data");
+
+ proto_tree_add_bitmask(data_tree, tvb, offset, hf_tns_data_flag, ett_tns_data_flag, flags, ENC_BIG_ENDIAN);
+ offset += 2;
+ 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 )
+ {
+ 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) )
+ {
+ proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ }
+ }
+
+ /* Handle data functions that have more than just ID */
+ switch (data_func_id)
+ {
+ case SQLNET_SET_PROTOCOL:
+ {
+ proto_tree *versions_tree;
+ proto_item *ti;
+ char sep;
+ if ( is_request )
+ {
+ versions_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_acc_versions, &ti, "Accepted Versions");
+ sep = ':';
+ for (;;) {
+ /*
+ * Add each accepted version as a
+ * separate item.
+ */
+ guint8 vers;
+
+ vers = tvb_get_guint8(tvb, offset);
+ if (vers == 0) {
+ /*
+ * A version of 0 terminates
+ * the list.
+ */
+ break;
+ }
+ proto_item_append_text(ti, "%c %u", sep, vers);
+ sep = ',';
+ proto_tree_add_uint(versions_tree, hf_tns_data_setp_acc_version, tvb, offset, 1, vers);
+ offset += 1;
+ }
+ offset += 1; /* skip the 0 terminator */
+ proto_item_set_end(ti, tvb, offset);
+ proto_tree_add_item(data_tree, hf_tns_data_setp_cli_plat, tvb, offset, -1, ENC_ASCII);
+
+ return; /* skip call_data_dissector */
+ }
+ else
+ {
+ gint 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;
+
+ vers = tvb_get_guint8(tvb, offset);
+ if (vers == 0) {
+ /*
+ * A version of 0 terminates
+ * the list.
+ */
+ break;
+ }
+ proto_item_append_text(ti, "%c %u", sep, vers);
+ sep = ',';
+ proto_tree_add_uint(versions_tree, hf_tns_data_setp_version, tvb, offset, 1, vers);
+ offset += 1;
+ }
+ offset += 1; /* skip the 0 terminator */
+ proto_item_set_end(ti, tvb, offset);
+ proto_tree_add_item_ret_length(data_tree, hf_tns_data_setp_banner, tvb, offset, -1, ENC_ASCII|ENC_NA, &len);
+ offset += len;
+ }
+ break;
+ }
+
+ case SQLNET_USER_OCI_FUNC:
+ proto_tree_add_item(data_tree, hf_tns_data_oci_id, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ break;
+
+ case SQLNET_RETURN_OPI_PARAM:
+ {
+ guint8 skip = 0, opi = 0;
+
+ if ( tvb_bytes_exist(tvb, offset, 11) )
+ {
+ /*
+ * OPI_VERSION2 response has a following pattern:
+ *
+ * _ banner _ vsnum
+ * / /
+ * ..(.?)(Orac[le.+])(.?)(....).+$
+ * |
+ * \ banner length (if equal to 0 then next byte indicates the length).
+ *
+ * These differences (to skip 1 or 2 bytes) due to differences in the drivers.
+ */
+ /* Orac[le.+] */
+ if ( tvb_get_ntohl(tvb, offset+2) == 0x4f726163 )
+ {
+ opi = OPI_VERSION2;
+ skip = 1;
+ }
+
+ else if ( tvb_get_ntohl(tvb, offset+3) == 0x4f726163 )
+ {
+ opi = OPI_VERSION2;
+ skip = 2;
+ }
+
+ /*
+ * OPI_OSESSKEY response has a following pattern:
+ *
+ * _ pattern (v1|v2)
+ * / _ params
+ * / /
+ * (....)(........)(.+).+$
+ * ||
+ * \ if these two bytes are equal to 0x0c00 then first byte is <Param Counts> (v1),
+ * else next byte indicate it (v2).
+ */
+ /* ....AUTH (v1) */
+ else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0000000c41555448 )
+ {
+ opi = OPI_OSESSKEY;
+ skip = 1;
+ }
+ /* ..AUTH_V (v2) */
+ else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0c0c415554485f53 )
+ {
+ opi = OPI_OSESSKEY;
+ skip = 2;
+ }
+
+ /*
+ * OPI_OAUTH response has a following pattern:
+ *
+ * _ pattern (v1|v2)
+ * / _ params
+ * / /
+ * (....)(........)(.+).+$
+ * ||
+ * \ if these two bytes are equal to 0x1300 then first byte is <Param Counts> (v1),
+ * else next byte indicate it (v2).
+ */
+
+ /* ....AUTH (v1) */
+ else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0000001341555448 )
+ {
+ opi = OPI_OAUTH;
+ skip = 1;
+ }
+ /* ..AUTH_V (v2) */
+ else if ( tvb_get_ntoh64(tvb, offset+3) == 0x1313415554485f56 )
+ {
+ opi = OPI_OAUTH;
+ skip = 2;
+ }
+ }
+
+ if ( opi == OPI_VERSION2 )
+ {
+ proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, skip, ENC_NA);
+ offset += skip;
+
+ guint8 len = tvb_get_guint8(tvb, offset);
+
+ proto_tree_add_item(data_tree, hf_tns_data_opi_version2_banner_len, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(data_tree, hf_tns_data_opi_version2_banner, tvb, offset, len, ENC_ASCII);
+ offset += len + (skip == 1 ? 1 : 0);
+
+ proto_tree_add_item(data_tree, hf_tns_data_opi_version2_vsnum, tvb, offset, 4, (skip == 1) ? ENC_BIG_ENDIAN : ENC_LITTLE_ENDIAN);
+ offset += 4;
+ }
+ else if ( opi == OPI_OSESSKEY || opi == OPI_OAUTH )
+ {
+ proto_tree *params_tree;
+ proto_item *params_ti;
+ guint par, params;
+
+ if ( skip == 1 )
+ {
+ proto_tree_add_item_ret_uint(data_tree, hf_tns_data_opi_num_of_params, tvb, offset, 1, ENC_NA, &params);
+ offset += 1;
+
+ proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 5, ENC_NA);
+ offset += 5;
+ }
+ else
+ {
+ proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 1, ENC_NA);
+ offset += 1;
+
+ proto_tree_add_item_ret_uint(data_tree, hf_tns_data_opi_num_of_params, tvb, offset, 1, ENC_NA, &params);
+ offset += 1;
+
+ proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 2, ENC_NA);
+ offset += 2;
+ }
+
+ params_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_opi_params, &params_ti, "Parameters");
+
+ for ( par = 1; par <= params; par++ )
+ {
+ proto_tree *par_tree;
+ proto_item *par_ti;
+ guint 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);
+
+ /* Name length */
+ proto_tree_add_item_ret_uint(par_tree, hf_tns_data_opi_param_length, tvb, offset, 1, ENC_NA, &len);
+ offset += 1;
+
+ /* Name */
+ if ( !(len == 0 || len == 2) ) /* Not empty (2 - SQLDeveloper specific sign). */
+ {
+ proto_tree_add_item(par_tree, hf_tns_data_opi_param_name, tvb, offset, len, ENC_ASCII);
+ offset += len;
+ }
+
+ /* Value can be NULL. So, save offset to calculate unused data. */
+ offset_prev = offset;
+ offset += skip == 1 ? 4 : 2;
+
+ /* Value length */
+ if ( opi == OPI_OSESSKEY )
+ {
+ len = tvb_get_guint8(tvb, offset);
+ }
+ else /* OPI_OAUTH */
+ {
+ len = tvb_get_guint8(tvb, offset_prev) == 0 ? 0 : tvb_get_guint8(tvb, offset);
+ }
+
+ /*
+ * Value
+ * OPI_OSESSKEY: AUTH_VFR_DATA with length 0, 9, 0x39 comes without data.
+ * OPI_OAUTH: AUTH_VFR_DATA with length 0, 0x39 comes without data.
+ */
+ if ( ((opi == OPI_OSESSKEY) && !(len == 0 || len == 9 || len == 0x39))
+ || ((opi == OPI_OAUTH) && !(len == 0 || len == 0x39)) )
+ {
+ proto_tree_add_item(par_tree, hf_tns_data_unused, tvb, offset_prev, offset - offset_prev, ENC_NA);
+
+ proto_tree_add_item(par_tree, hf_tns_data_opi_param_length, tvb, offset, 1, ENC_NA);
+ offset += 1;
+
+ proto_tree_add_item(par_tree, hf_tns_data_opi_param_value, tvb, offset, len, ENC_ASCII);
+ offset += len;
+
+ offset_prev = offset; /* Save offset to calculate rest of unused data */
+ }
+ else
+ {
+ offset += 1;
+ }
+
+ if ( opi == OPI_OSESSKEY )
+ {
+ /* SQL Developer specifix fix */
+ offset += tvb_get_guint8(tvb, offset) == 2 ? 5 : 3;
+ }
+ else /* OPI_OAUTH */
+ {
+ offset += len == 0 ? 1 : 3;
+ }
+
+ if ( skip == 1 )
+ {
+ offset += 1 + ((len == 0 || len == 0x39) ? 3 : 4);
+
+ if ( opi == OPI_OAUTH )
+ {
+ offset += len == 0 ? 2 : 0;
+ }
+ }
+
+ proto_tree_add_item(par_tree, hf_tns_data_unused, tvb, offset_prev, offset - offset_prev, ENC_NA);
+ proto_item_set_end(par_ti, tvb, offset);
+ }
+ proto_item_set_end(params_ti, tvb, offset);
+ }
+ break;
+ }
+
+ case SQLNET_PIGGYBACK_FUNC:
+ proto_tree_add_item(data_tree, hf_tns_data_piggyback_id, tvb, offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+ break;
+
+ case SQLNET_SNS:
+ {
+ proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+ proto_tree_add_item(data_tree, hf_tns_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ if ( is_request )
+ {
+ proto_tree_add_item(data_tree, hf_tns_data_sns_cli_vers, tvb, offset, 4, ENC_BIG_ENDIAN);
+ }
+ else
+ {
+ proto_tree_add_item(data_tree, hf_tns_data_sns_srv_vers, tvb, offset, 4, ENC_BIG_ENDIAN);
+ }
+ offset += 4;
+
+ proto_tree_add_item(data_tree, hf_tns_data_sns_srvcnt, tvb, offset, 2, ENC_BIG_ENDIAN);
+
+ /* move back, to include data_id into data_dissector */
+ offset -= 10;
+ break;
+ }
+ }
+
+ call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, data_tree);
+}
+
+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;
+ int tns_offset = offset-8;
+ static int * const flags[] = {
+ &hf_tns_ntp_flag_hangon,
+ &hf_tns_ntp_flag_crel,
+ &hf_tns_ntp_flag_tduio,
+ &hf_tns_ntp_flag_srun,
+ &hf_tns_ntp_flag_dtest,
+ &hf_tns_ntp_flag_cbio,
+ &hf_tns_ntp_flag_asio,
+ &hf_tns_ntp_flag_pio,
+ &hf_tns_ntp_flag_grant,
+ &hf_tns_ntp_flag_handoff,
+ &hf_tns_ntp_flag_sigio,
+ &hf_tns_ntp_flag_sigpipe,
+ &hf_tns_ntp_flag_sigurg,
+ &hf_tns_ntp_flag_urgentio,
+ &hf_tns_ntp_flag_fdio,
+ &hf_tns_ntp_flag_testop,
+ NULL
+ };
+
+ connect_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
+ ett_tns_connect, NULL, "Connect");
+
+ proto_tree_add_item(connect_tree, hf_tns_version, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(connect_tree, hf_tns_compat_version, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_service_options, ett_tns_sopt_flag, tns_service_options, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(connect_tree, hf_tns_sdu_size, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(connect_tree, hf_tns_max_tdu_size, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_nt_proto_characteristics, ett_tns_ntp_flag, flags, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(connect_tree, hf_tns_line_turnaround, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(connect_tree, hf_tns_value_of_one, tvb,
+ offset, 2, ENC_NA);
+ offset += 2;
+
+ proto_tree_add_item_ret_uint(connect_tree, hf_tns_connect_data_length, tvb,
+ offset, 2, ENC_BIG_ENDIAN, &cd_len);
+ offset += 2;
+
+ proto_tree_add_item_ret_uint(connect_tree, hf_tns_connect_data_offset, tvb,
+ offset, 2, ENC_BIG_ENDIAN, &cd_offset);
+ offset += 2;
+
+ proto_tree_add_item(connect_tree, hf_tns_connect_data_max, tvb,
+ offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_connect_flags0, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_connect_flags1, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ /*
+ * XXX - sometimes it appears that this stuff isn't present
+ * in the packet.
+ */
+ if ((guint32)(offset + 16) <= tns_offset+cd_offset)
+ {
+ proto_tree_add_item(connect_tree, hf_tns_trace_cf1, tvb,
+ offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(connect_tree, hf_tns_trace_cf2, tvb,
+ offset, 4, ENC_BIG_ENDIAN);
+ offset += 4;
+
+ proto_tree_add_item(connect_tree, hf_tns_trace_cid, tvb,
+ offset, 8, ENC_BIG_ENDIAN);
+ /* offset += 8;*/
+ }
+
+ if ( cd_len > 0)
+ {
+ proto_tree_add_item(connect_tree, hf_tns_connect_data, tvb,
+ tns_offset+cd_offset, -1, ENC_ASCII);
+ }
+}
+
+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;
+ int tns_offset = offset-8;
+
+ accept_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
+ ett_tns_accept, NULL, "Accept");
+
+ proto_tree_add_item(accept_tree, hf_tns_version, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_service_options, ett_tns_sopt_flag, tns_service_options, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(accept_tree, hf_tns_sdu_size, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(accept_tree, hf_tns_max_tdu_size, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(accept_tree, hf_tns_value_of_one, tvb,
+ offset, 2, ENC_NA);
+ offset += 2;
+
+ proto_tree_add_item_ret_uint(accept_tree, hf_tns_accept_data_length, tvb,
+ offset, 2, ENC_BIG_ENDIAN, &accept_len);
+ offset += 2;
+
+ proto_tree_add_item_ret_uint(accept_tree, hf_tns_accept_data_offset, tvb,
+ offset, 2, ENC_BIG_ENDIAN, &accept_offset);
+ offset += 2;
+
+ proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_connect_flags0, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_connect_flags1, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN);
+ /* offset += 1; */
+
+ if ( accept_len > 0)
+ {
+ proto_tree_add_item(accept_tree, hf_tns_accept_data, tvb,
+ tns_offset+accept_offset, -1, ENC_ASCII);
+ }
+ return;
+}
+
+
+static void dissect_tns_refuse(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
+{
+ /* TODO
+ * According to some reverse engineers, the refuse packet is also sent when the login fails.
+ * Byte 54 shows if this is due to invalid ID (0x02) or password (0x03).
+ * At now we do not have pcaps with such messages to check this statement.
+ */
+ proto_tree *refuse_tree;
+
+ refuse_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
+ ett_tns_refuse, NULL, "Refuse");
+
+ proto_tree_add_item(refuse_tree, hf_tns_refuse_reason_user, tvb,
+ offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(refuse_tree, hf_tns_refuse_reason_system, tvb,
+ offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(refuse_tree, hf_tns_refuse_data_length, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(refuse_tree, hf_tns_refuse_data, tvb,
+ offset, -1, ENC_ASCII);
+}
+
+
+static void dissect_tns_abort(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
+{
+ proto_tree *abort_tree;
+
+ abort_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
+ ett_tns_abort, NULL, "Abort");
+
+ proto_tree_add_item(abort_tree, hf_tns_abort_reason_user, tvb,
+ offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(abort_tree, hf_tns_abort_reason_system, tvb,
+ offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(abort_tree, hf_tns_abort_data, tvb,
+ offset, -1, ENC_ASCII);
+}
+
+
+static void dissect_tns_marker(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree, int is_attention)
+{
+ proto_tree *marker_tree;
+
+ if ( is_attention )
+ {
+ marker_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
+ ett_tns_marker, NULL, "Marker");
+ }
+ else
+ {
+ marker_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
+ ett_tns_marker, NULL, "Attention");
+ }
+
+ proto_tree_add_item(marker_tree, hf_tns_marker_type, tvb,
+ offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(marker_tree, hf_tns_marker_data_byte, tvb,
+ offset, 1, ENC_BIG_ENDIAN);
+ offset += 1;
+
+ proto_tree_add_item(marker_tree, hf_tns_marker_data_byte, tvb,
+ offset, 1, ENC_BIG_ENDIAN);
+ /*offset += 1;*/
+}
+
+static void dissect_tns_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
+{
+ proto_tree *redirect_tree;
+
+ redirect_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
+ ett_tns_redirect, NULL, "Redirect");
+
+ proto_tree_add_item(redirect_tree, hf_tns_redirect_data_length, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(redirect_tree, hf_tns_redirect_data, tvb,
+ offset, -1, ENC_ASCII);
+}
+
+static void dissect_tns_control(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
+{
+ proto_tree *control_tree;
+
+ control_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
+ ett_tns_control, NULL, "Control");
+
+ proto_tree_add_item(control_tree, hf_tns_control_cmd, tvb,
+ offset, 2, ENC_BIG_ENDIAN);
+ offset += 2;
+
+ proto_tree_add_item(control_tree, hf_tns_control_data, tvb,
+ offset, -1, ENC_NA);
+}
+
+static guint
+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);
+}
+
+static guint
+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);
+}
+
+static int
+dissect_tns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
+{
+ guint32 length;
+ guint16 chksum;
+ guint8 type;
+
+ /*
+ * First, do a sanity check to make sure what we have
+ * starts with a TNS PDU.
+ */
+ if (tvb_bytes_exist(tvb, 4, 1)) {
+ /*
+ * Well, we have the packet type; let's make sure
+ * it's a known type.
+ */
+ type = tvb_get_guint8(tvb, 4);
+ if (type < TNS_TYPE_CONNECT || type > TNS_TYPE_MAX)
+ return 0; /* it's not a known type */
+ }
+
+ /*
+ * In some messages (observed in Oracle12c) packet length has 4 bytes
+ * instead of 2.
+ *
+ * If packet length has 2 bytes, length and checksum equals two unsigned
+ * 16-bit numbers. Packet checksum is generally unused (equal zero),
+ * but 10g client may set 2nd byte to 4.
+ *
+ * Else, Oracle 12c combine these two 16-bit numbers into one 32-bit.
+ * This number represents the packet length. Checksum is omitted.
+ */
+ chksum = tvb_get_ntohs(tvb, 2);
+
+ length = (chksum == 0 || chksum == 4) ? 2 : 4;
+
+ tcp_dissect_pdus(tvb, pinfo, tree, tns_desegment, length,
+ (length == 2 ? get_tns_pdu_len : get_tns_pdu_len_nochksum),
+ dissect_tns_pdu, data);
+
+ return tvb_captured_length(tvb);
+}
+
+static int
+dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
+{
+ proto_tree *tns_tree, *ti;
+ proto_item *hidden_item;
+ int offset = 0;
+ guint32 length;
+ guint16 chksum;
+ guint8 type;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "TNS");
+
+ col_set_str(pinfo->cinfo, COL_INFO,
+ (pinfo->match_uint == pinfo->destport) ? "Request" : "Response");
+
+ ti = proto_tree_add_item(tree, proto_tns, tvb, 0, -1, ENC_NA);
+ tns_tree = proto_item_add_subtree(ti, ett_tns);
+
+ if (pinfo->match_uint == pinfo->destport)
+ {
+ hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_request,
+ tvb, offset, 0, TRUE);
+ }
+ else
+ {
+ hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_response,
+ tvb, offset, 0, TRUE);
+ }
+ proto_item_set_hidden(hidden_item);
+
+ chksum = tvb_get_ntohs(tvb, offset+2);
+ if (chksum == 0 || chksum == 4)
+ {
+ proto_tree_add_item_ret_uint(tns_tree, hf_tns_length, tvb, offset,
+ 2, ENC_BIG_ENDIAN, &length);
+ offset += 2;
+ proto_tree_add_checksum(tns_tree, tvb, offset, hf_tns_packet_checksum,
+ -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
+ offset += 2;
+ }
+ else
+ {
+ /* Oracle 12c uses checksum bytes as part of the packet length. */
+ proto_tree_add_item_ret_uint(tns_tree, hf_tns_length, tvb, offset,
+ 4, ENC_BIG_ENDIAN, &length);
+ offset += 4;
+ }
+
+ type = tvb_get_guint8(tvb, offset);
+ proto_tree_add_uint(tns_tree, hf_tns_packet_type, tvb,
+ offset, 1, type);
+ offset += 1;
+
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %s (%u)",
+ val_to_str_const(type, tns_type_vals, "Unknown"), type);
+
+ proto_tree_add_item(tns_tree, hf_tns_reserved_byte, tvb,
+ offset, 1, ENC_NA);
+ offset += 1;
+
+ proto_tree_add_checksum(tns_tree, tvb, offset, hf_tns_header_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
+ offset += 2;
+
+ switch (type)
+ {
+ case TNS_TYPE_CONNECT:
+ dissect_tns_connect(tvb,offset,pinfo,tns_tree);
+ break;
+ case TNS_TYPE_ACCEPT:
+ dissect_tns_accept(tvb,offset,pinfo,tns_tree);
+ break;
+ case TNS_TYPE_REFUSE:
+ dissect_tns_refuse(tvb,offset,pinfo,tns_tree);
+ break;
+ case TNS_TYPE_REDIRECT:
+ dissect_tns_redirect(tvb,offset,pinfo,tns_tree);
+ break;
+ case TNS_TYPE_ABORT:
+ dissect_tns_abort(tvb,offset,pinfo,tns_tree);
+ break;
+ case TNS_TYPE_MARKER:
+ dissect_tns_marker(tvb,offset,pinfo,tns_tree, 0);
+ break;
+ case TNS_TYPE_ATTENTION:
+ dissect_tns_marker(tvb,offset,pinfo,tns_tree, 1);
+ break;
+ case TNS_TYPE_CONTROL:
+ dissect_tns_control(tvb,offset,pinfo,tns_tree);
+ break;
+ case TNS_TYPE_DATA:
+ dissect_tns_data(tvb,offset,pinfo,tns_tree);
+ break;
+ default:
+ call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo,
+ tns_tree);
+ break;
+ }
+
+ return tvb_captured_length(tvb);
+}
+
+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 }},
+ { &hf_tns_request, {
+ "Request", "tns.request", FT_BOOLEAN, BASE_NONE,
+ 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 }},
+ { &hf_tns_packet_checksum, {
+ "Packet Checksum", "tns.packet_checksum", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Checksum of Packet Data", HFILL }},
+ { &hf_tns_header_checksum, {
+ "Header Checksum", "tns.header_checksum", FT_UINT16, BASE_HEX,
+ NULL, 0x0, "Checksum of Header Data", HFILL }},
+
+ { &hf_tns_version, {
+ "Version", "tns.version", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_compat_version, {
+ "Version (Compatible)", "tns.compat_version", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_service_options, {
+ "Service Options", "tns.service_options", FT_UINT16, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_sopt_flag_bconn, {
+ "Broken Connect Notify", "tns.so_flag.bconn", FT_BOOLEAN, 16,
+ NULL, 0x2000, NULL, HFILL }},
+ { &hf_tns_sopt_flag_pc, {
+ "Packet Checksum", "tns.so_flag.pc", FT_BOOLEAN, 16,
+ NULL, 0x1000, NULL, HFILL }},
+ { &hf_tns_sopt_flag_hc, {
+ "Header Checksum", "tns.so_flag.hc", FT_BOOLEAN, 16,
+ NULL, 0x0800, NULL, HFILL }},
+ { &hf_tns_sopt_flag_fd, {
+ "Full Duplex", "tns.so_flag.fd", FT_BOOLEAN, 16,
+ NULL, 0x0400, NULL, HFILL }},
+ { &hf_tns_sopt_flag_hd, {
+ "Half Duplex", "tns.so_flag.hd", FT_BOOLEAN, 16,
+ NULL, 0x0200, NULL, HFILL }},
+ { &hf_tns_sopt_flag_dc1, {
+ "Don't Care", "tns.so_flag.dc1", FT_BOOLEAN, 16,
+ NULL, 0x0100, NULL, HFILL }},
+ { &hf_tns_sopt_flag_dc2, {
+ "Don't Care", "tns.so_flag.dc2", FT_BOOLEAN, 16,
+ NULL, 0x0080, NULL, HFILL }},
+ { &hf_tns_sopt_flag_dio, {
+ "Direct IO to Transport", "tns.so_flag.dio", FT_BOOLEAN, 16,
+ NULL, 0x0010, NULL, HFILL }},
+ { &hf_tns_sopt_flag_ap, {
+ "Attention Processing", "tns.so_flag.ap", FT_BOOLEAN, 16,
+ NULL, 0x0008, NULL, HFILL }},
+ { &hf_tns_sopt_flag_ra, {
+ "Can Receive Attention", "tns.so_flag.ra", FT_BOOLEAN, 16,
+ NULL, 0x0004, NULL, HFILL }},
+ { &hf_tns_sopt_flag_sa, {
+ "Can Send Attention", "tns.so_flag.sa", FT_BOOLEAN, 16,
+ NULL, 0x0002, NULL, HFILL }},
+
+
+ { &hf_tns_sdu_size, {
+ "Session Data Unit Size", "tns.sdu_size", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_max_tdu_size, {
+ "Maximum Transmission Data Unit Size", "tns.max_tdu_size", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_nt_proto_characteristics, {
+ "NT Protocol Characteristics", "tns.nt_proto_characteristics", FT_UINT16, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_ntp_flag_hangon, {
+ "Hangon to listener connect", "tns.ntp_flag.hangon", FT_BOOLEAN, 16,
+ NULL, 0x8000, NULL, HFILL }},
+ { &hf_tns_ntp_flag_crel, {
+ "Confirmed release", "tns.ntp_flag.crel", FT_BOOLEAN, 16,
+ NULL, 0x4000, NULL, HFILL }},
+ { &hf_tns_ntp_flag_tduio, {
+ "TDU based IO", "tns.ntp_flag.tduio", FT_BOOLEAN, 16,
+ NULL, 0x2000, NULL, HFILL }},
+ { &hf_tns_ntp_flag_srun, {
+ "Spawner running", "tns.ntp_flag.srun", FT_BOOLEAN, 16,
+ NULL, 0x1000, NULL, HFILL }},
+ { &hf_tns_ntp_flag_dtest, {
+ "Data test", "tns.ntp_flag.dtest", FT_BOOLEAN, 16,
+ NULL, 0x0800, NULL, HFILL }},
+ { &hf_tns_ntp_flag_cbio, {
+ "Callback IO supported", "tns.ntp_flag.cbio", FT_BOOLEAN, 16,
+ NULL, 0x0400, NULL, HFILL }},
+ { &hf_tns_ntp_flag_asio, {
+ "ASync IO Supported", "tns.ntp_flag.asio", FT_BOOLEAN, 16,
+ NULL, 0x0200, NULL, HFILL }},
+ { &hf_tns_ntp_flag_pio, {
+ "Packet oriented IO", "tns.ntp_flag.pio", FT_BOOLEAN, 16,
+ NULL, 0x0100, NULL, HFILL }},
+ { &hf_tns_ntp_flag_grant, {
+ "Can grant connection to another", "tns.ntp_flag.grant", FT_BOOLEAN, 16,
+ NULL, 0x0080, NULL, HFILL }},
+ { &hf_tns_ntp_flag_handoff, {
+ "Can handoff connection to another", "tns.ntp_flag.handoff", FT_BOOLEAN, 16,
+ NULL, 0x0040, NULL, HFILL }},
+ { &hf_tns_ntp_flag_sigio, {
+ "Generate SIGIO signal", "tns.ntp_flag.sigio", FT_BOOLEAN, 16,
+ NULL, 0x0020, NULL, HFILL }},
+ { &hf_tns_ntp_flag_sigpipe, {
+ "Generate SIGPIPE signal", "tns.ntp_flag.sigpipe", FT_BOOLEAN, 16,
+ NULL, 0x0010, NULL, HFILL }},
+ { &hf_tns_ntp_flag_sigurg, {
+ "Generate SIGURG signal", "tns.ntp_flag.sigurg", FT_BOOLEAN, 16,
+ NULL, 0x0008, NULL, HFILL }},
+ { &hf_tns_ntp_flag_urgentio, {
+ "Urgent IO supported", "tns.ntp_flag.urgentio", FT_BOOLEAN, 16,
+ NULL, 0x0004, NULL, HFILL }},
+ { &hf_tns_ntp_flag_fdio, {
+ "Full duplex IO supported", "tns.ntp_flag.dfio", FT_BOOLEAN, 16,
+ NULL, 0x0002, NULL, HFILL }},
+ { &hf_tns_ntp_flag_testop, {
+ "Test operation", "tns.ntp_flag.testop", FT_BOOLEAN, 16,
+ NULL, 0x0001, NULL, HFILL }},
+
+
+
+
+ { &hf_tns_line_turnaround, {
+ "Line Turnaround Value", "tns.line_turnaround", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_value_of_one, {
+ "Value of 1 in Hardware", "tns.value_of_one", FT_BYTES, BASE_NONE,
+ 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 }},
+ { &hf_tns_connect_data_offset, {
+ "Offset to Connect Data", "tns.connect_data_offset", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_connect_data_max, {
+ "Maximum Receivable Connect Data", "tns.connect_data_max", FT_UINT32, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_connect_flags0, {
+ "Connect Flags 0", "tns.connect_flags0", FT_UINT8, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_connect_flags1, {
+ "Connect Flags 1", "tns.connect_flags1", FT_UINT8, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_conn_flag_nareq, {
+ "NA services required", "tns.connect_flags.nareq", FT_BOOLEAN, 8,
+ NULL, 0x10, NULL, HFILL }},
+ { &hf_tns_conn_flag_nalink, {
+ "NA services linked in", "tns.connect_flags.nalink", FT_BOOLEAN, 8,
+ NULL, 0x08, NULL, HFILL }},
+ { &hf_tns_conn_flag_enablena, {
+ "NA services enabled", "tns.connect_flags.enablena", FT_BOOLEAN, 8,
+ NULL, 0x04, NULL, HFILL }},
+ { &hf_tns_conn_flag_ichg, {
+ "Interchange is involved", "tns.connect_flags.ichg", FT_BOOLEAN, 8,
+ NULL, 0x02, NULL, HFILL }},
+ { &hf_tns_conn_flag_wantna, {
+ "NA services wanted", "tns.connect_flags.wantna", FT_BOOLEAN, 8,
+ NULL, 0x01, NULL, HFILL }},
+
+
+ { &hf_tns_trace_cf1, {
+ "Trace Cross Facility Item 1", "tns.trace_cf1", FT_UINT32, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_trace_cf2, {
+ "Trace Cross Facility Item 2", "tns.trace_cf2", FT_UINT32, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_trace_cid, {
+ "Trace Unique Connection ID", "tns.trace_cid", FT_UINT64, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_connect_data, {
+ "Connect Data", "tns.connect_data", FT_STRING, BASE_NONE,
+ 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 }},
+ { &hf_tns_accept_data, {
+ "Accept Data", "tns.accept_data", FT_STRING, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_accept_data_offset, {
+ "Offset to Accept Data", "tns.accept_data_offset", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_refuse_reason_user, {
+ "Refuse Reason (User)", "tns.refuse_reason_user", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Refuse Reason from Application", HFILL }},
+ { &hf_tns_refuse_reason_system, {
+ "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 }},
+ { &hf_tns_refuse_data, {
+ "Refuse Data", "tns.refuse_data", FT_STRING, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_abort_reason_user, {
+ "Abort Reason (User)", "tns.abort_reason_user", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Abort Reason from Application", HFILL }},
+ { &hf_tns_abort_reason_system, {
+ "Abort Reason (User)", "tns.abort_reason_system", FT_UINT8, BASE_HEX,
+ NULL, 0x0, "Abort Reason from System", HFILL }},
+ { &hf_tns_abort_data, {
+ "Abort Data", "tns.abort_data", FT_STRING, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_marker_type, {
+ "Marker Type", "tns.marker.type", FT_UINT8, BASE_HEX,
+ VALS(tns_marker_types), 0x0, NULL, HFILL }},
+ { &hf_tns_marker_data_byte, {
+ "Marker Data Byte", "tns.marker.databyte", FT_UINT8, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+#if 0
+ { &hf_tns_marker_data, {
+ "Marker Data", "tns.marker.data", FT_UINT16, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+#endif
+
+ { &hf_tns_control_cmd, {
+ "Control Command", "tns.control.cmd", FT_UINT16, BASE_HEX,
+ VALS(tns_control_cmds), 0x0, NULL, HFILL }},
+ { &hf_tns_control_data, {
+ "Control Data", "tns.control.data", FT_BYTES, BASE_NONE,
+ 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 }},
+ { &hf_tns_redirect_data, {
+ "Redirect Data", "tns.redirect_data", FT_STRING, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_data_flag, {
+ "Data Flag", "tns.data_flag", FT_UINT16, BASE_HEX,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_data_flag_send, {
+ "Send Token", "tns.data_flag.send", FT_BOOLEAN, 16,
+ NULL, 0x1, NULL, HFILL }},
+ { &hf_tns_data_flag_rc, {
+ "Request Confirmation", "tns.data_flag.rc", FT_BOOLEAN, 16,
+ NULL, 0x2, NULL, HFILL }},
+ { &hf_tns_data_flag_c, {
+ "Confirmation", "tns.data_flag.c", FT_BOOLEAN, 16,
+ NULL, 0x4, NULL, HFILL }},
+ { &hf_tns_data_flag_reserved, {
+ "Reserved", "tns.data_flag.reserved", FT_BOOLEAN, 16,
+ NULL, 0x8, NULL, HFILL }},
+ { &hf_tns_data_flag_more, {
+ "More Data to Come", "tns.data_flag.more", FT_BOOLEAN, 16,
+ NULL, 0x0020, NULL, HFILL }},
+ { &hf_tns_data_flag_eof, {
+ "End of File", "tns.data_flag.eof", FT_BOOLEAN, 16,
+ NULL, 0x0040, NULL, HFILL }},
+ { &hf_tns_data_flag_dic, {
+ "Do Immediate Confirmation", "tns.data_flag.dic", FT_BOOLEAN, 16,
+ NULL, 0x0080, NULL, HFILL }},
+ { &hf_tns_data_flag_rts, {
+ "Request To Send", "tns.data_flag.rts", FT_BOOLEAN, 16,
+ NULL, 0x0100, NULL, HFILL }},
+ { &hf_tns_data_flag_sntt, {
+ "Send NT Trailer", "tns.data_flag.sntt", FT_BOOLEAN, 16,
+ NULL, 0x0200, NULL, HFILL }},
+
+ { &hf_tns_data_id, {
+ "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 }},
+
+ { &hf_tns_data_oci_id, {
+ "Call ID", "tns.data_oci.id", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
+ &tns_data_oci_subfuncs_ext, 0x00, NULL, HFILL }},
+
+ { &hf_tns_data_piggyback_id, {
+ /* Also Call ID.
+ Piggyback is a message what calls a small subset of functions
+ declared in tns_data_oci_subfuncs. */
+ "Call ID", "tns.data_piggyback.id", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
+ &tns_data_oci_subfuncs_ext, 0x00, NULL, HFILL }},
+
+ { &hf_tns_data_unused, {
+ "Unused", "tns.data.unused", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_data_setp_acc_version, {
+ "Accepted Version", "tns.data_setp_req.acc_vers", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_data_setp_cli_plat, {
+ "Client Platform", "tns.data_setp_req.cli_plat", FT_STRINGZ, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_data_setp_version, {
+ "Version", "tns.data_setp_resp.version", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_data_setp_banner, {
+ "Server Banner", "tns.data_setp_resp.banner", FT_STRINGZ, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_data_sns_cli_vers, {
+ "Client Version", "tns.data_sns.cli_vers", FT_UINT32, BASE_CUSTOM,
+ CF_FUNC(vsnum_to_vstext_basecustom), 0x0, NULL, HFILL }},
+ { &hf_tns_data_sns_srv_vers, {
+ "Server Version", "tns.data_sns.srv_vers", FT_UINT32, BASE_CUSTOM,
+ CF_FUNC(vsnum_to_vstext_basecustom), 0x0, NULL, HFILL }},
+ { &hf_tns_data_sns_srvcnt, {
+ "Services", "tns.data_sns.srvcnt", FT_UINT16, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_data_opi_version2_banner_len, {
+ "Banner Length", "tns.data_opi.vers2.banner_len", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_data_opi_version2_banner, {
+ "Banner", "tns.data_opi.vers2.banner", FT_STRING, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_data_opi_version2_vsnum, {
+ "Version", "tns.data_opi.vers2.version", FT_UINT32, BASE_CUSTOM,
+ CF_FUNC(vsnum_to_vstext_basecustom), 0x0, NULL, HFILL }},
+
+ { &hf_tns_data_opi_num_of_params, {
+ "Number of parameters", "tns.data_opi.num_of_params", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_data_opi_param_length, {
+ "Length", "tns.data_opi.param_length", FT_UINT8, BASE_DEC,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_data_opi_param_name, {
+ "Name", "tns.data_opi.param_name", FT_STRING, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_data_opi_param_value, {
+ "Value", "tns.data_opi.param_value", FT_STRING, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+
+ { &hf_tns_reserved_byte, {
+ "Reserved Byte", "tns.reserved_byte", FT_BYTES, BASE_NONE,
+ NULL, 0x0, NULL, HFILL }},
+ { &hf_tns_packet_type, {
+ "Packet Type", "tns.type", FT_UINT8, BASE_DEC,
+ VALS(tns_type_vals), 0x0, "Type of TNS packet", HFILL }}
+
+ };
+
+ static gint *ett[] = {
+ &ett_tns,
+ &ett_tns_connect,
+ &ett_tns_accept,
+ &ett_tns_refuse,
+ &ett_tns_abort,
+ &ett_tns_redirect,
+ &ett_tns_marker,
+ &ett_tns_attention,
+ &ett_tns_control,
+ &ett_tns_data,
+ &ett_tns_data_flag,
+ &ett_tns_acc_versions,
+ &ett_tns_opi_params,
+ &ett_tns_opi_par,
+ &ett_tns_sopt_flag,
+ &ett_tns_ntp_flag,
+ &ett_tns_conn_flag,
+ &ett_sql
+ };
+ module_t *tns_module;
+
+ 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));
+ tns_handle = register_dissector("tns", dissect_tns, proto_tns);
+
+ tns_module = prefs_register_protocol(proto_tns, NULL);
+ prefs_register_bool_preference(tns_module, "desegment_tns_messages",
+ "Reassemble TNS messages spanning multiple TCP segments",
+ "Whether the TNS dissector should reassemble messages spanning multiple TCP segments. "
+ "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
+ &tns_desegment);
+}
+
+void
+proto_reg_handoff_tns(void)
+{
+ dissector_add_uint_with_preference("tcp.port", TCP_PORT_TNS, tns_handle);
+}
+
+/*
+ * Editor modelines - https://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ *
+ * vi: set shiftwidth=8 tabstop=8 noexpandtab:
+ * :indentSize=8:tabSize=8:noTabs=false:
+ */