Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-tns.c
Warning:line 1424, column 3
Value stored to 'len' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-tns.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-22/lib/clang/22 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/epan -D CARES_NO_DEPRECATED -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu17 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /builds/wireshark/wireshark/sbout/2026-10-05-100400-3663-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-tns.c
1/* packet-tns.c
2 * Routines for Oracle TNS packet dissection
3 *
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
7 *
8 * Copied from packet-tftp.c
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13#include "config.h"
14
15#include <epan/packet.h>
16#include "packet-tcp.h"
17
18#include <epan/prefs.h>
19#include <epan/expert.h>
20#include <epan/conversation.h>
21#include <epan/proto_data.h>
22#include <epan/unit_strings.h>
23#include <epan/charsets.h>
24
25#include <wsutil/array.h>
26#include <wsutil/pint.h>
27
28void proto_register_tns(void);
29
30#define TNS_HDR_LEN8 8
31
32/* Packet Types */
33#define TNS_TYPE_CONNECT1 1
34#define TNS_TYPE_ACCEPT2 2
35#define TNS_TYPE_ACK3 3
36#define TNS_TYPE_REFUSE4 4
37#define TNS_TYPE_REDIRECT5 5
38#define TNS_TYPE_DATA6 6
39#define TNS_TYPE_NULL7 7
40#define TNS_TYPE_ABORT9 9
41#define TNS_TYPE_RESEND11 11
42#define TNS_TYPE_MARKER12 12
43#define TNS_TYPE_ATTENTION13 13
44#define TNS_TYPE_CONTROL14 14
45#define TNS_TYPE_DD15 15
46#define TNS_TYPE_MAX19 19
47
48/*
49 * Oracle datatype codes as they appear on the wire and in tns_data_types[].
50 * python-oracledb lists most of these as its ORA_TYPE_NUM_* constants.
51 */
52#define TNS_DATATYPE_VARCHAR1 1
53#define TNS_DATATYPE_NUMBER2 2
54#define TNS_DATATYPE_INTEGER3 3 /* BINARY_INTEGER */
55#define TNS_DATATYPE_FLOAT4 4
56#define TNS_DATATYPE_STRING5 5
57#define TNS_DATATYPE_VARNUM6 6
58#define TNS_DATATYPE_DECIMAL7 7
59#define TNS_DATATYPE_LONG8 8
60#define TNS_DATATYPE_VCS9 9
61#define TNS_DATATYPE_ROWID11 11 /* RID */
62#define TNS_DATATYPE_DATE12 12
63#define TNS_DATATYPE_VBI15 15
64#define TNS_DATATYPE_RAW23 23
65#define TNS_DATATYPE_LONG_RAW24 24
66#define TNS_DATATYPE_CHAR96 96
67#define TNS_DATATYPE_BINARY_FLOAT100 100
68#define TNS_DATATYPE_BINARY_DOUBLE101 101
69#define TNS_DATATYPE_REFCURSOR102 102
70#define TNS_DATATYPE_ROWID_EXT104 104 /* ROWID */
71#define TNS_DATATYPE_ADT109 109 /* object */
72#define TNS_DATATYPE_REF111 111
73#define TNS_DATATYPE_CLOB112 112
74#define TNS_DATATYPE_BLOB113 113
75#define TNS_DATATYPE_BFILE114 114
76#define TNS_DATATYPE_RSET116 116
77#define TNS_DATATYPE_JSON119 119 /* OSON */
78#define TNS_DATATYPE_VECTOR127 127
79#define TNS_DATATYPE_TIMESTAMP180 180
80#define TNS_DATATYPE_TIMESTAMP_TZ181 181
81#define TNS_DATATYPE_INTERVAL_YM182 182
82#define TNS_DATATYPE_INTERVAL_DS183 183
83#define TNS_DATATYPE_UROWID208 208
84#define TNS_DATATYPE_TIMESTAMP_LTZ231 231
85#define TNS_DATATYPE_BOOLEAN252 252
86
87/* DALC length byte marking a slot with no value (see get_dalc_custom). */
88#define TNS_DALC_ABSENT0xFD 0xFD
89
90/* TTC field versions (compile capability 7), as python-oracledb's
91 * TNS_CCAP_FIELD_VERSION_* name them. The wire shape of several messages
92 * depends on the one a connection negotiates. */
93#define TNS_CCAP_FIELD_VERSION7 7
94#define TNS_FV_11_26 6
95#define TNS_FV_12_17 7
96#define TNS_FV_12_28 8
97#define TNS_FV_12_2_EXT19 9
98#define TNS_FV_18_110 10
99#define TNS_FV_18_1_EXT_111 11
100#define TNS_FV_19_112 12
101#define TNS_FV_19_1_EXT_113 13
102#define TNS_FV_20_114 14
103#define TNS_FV_20_1_EXT_115 15
104#define TNS_FV_21_116 16
105#define TNS_FV_23_117 17
106#define TNS_FV_23_1_EXT_118 18
107#define TNS_FV_23_1_EXT_219 19
108#define TNS_FV_23_1_EXT_320 20
109#define TNS_FV_23_1_EXT_421 21
110#define TNS_FV_23_1_EXT_522 22
111#define TNS_FV_23_3_EXT_623 23
112#define TNS_FV_23_424 24
113
114/* Data Packet Functions */
115#define SQLNET_SET_PROTOCOL1 1
116#define SQLNET_SET_DATATYPES2 2
117#define SQLNET_USER_OCI_FUNC3 3
118#define SQLNET_RETURN_STATUS4 4
119#define SQLNET_ACCESS_USR_ADDR5 5
120#define SQLNET_ROW_TRANSF_HDR6 6
121#define SQLNET_ROW_TRANSF_DATA7 7
122#define SQLNET_RETURN_OPI_PARAM8 8
123#define SQLNET_FUNCCOMPLETE9 9
124#define SQLNET_NERROR_RET_DEF10 10
125#define SQLNET_IOVEC_4FAST_UPI11 11
126#define SQLNET_LONG_4FAST_UPI12 12
127#define SQLNET_INVOKE_USER_CB13 13
128#define SQLNET_LOB_FILE_DF14 14
129#define SQLNET_WARNING15 15
130#define SQLNET_DESCRIBE_INFO16 16
131#define SQLNET_PIGGYBACK_FUNC17 17
132#define SQLNET_SIG_4UCS18 18
133#define SQLNET_FLUSH_BIND_DATA19 19
134#define SQLNET_BIT_VECTOR21 21
135#define SQLNET_SERVER_PIGGYBACK23 23
136#define SQLNET_IMPLICIT_RESULTS27 27
137#define SQLNET_END_OF_RESPONSE29 29
138#define SQLNET_TOKEN33 33
139#define SQLNET_SNS0xdeadbeef 0xdeadbeef
140#define SQLNET_XTRN_PROCSERV_R132 32
141#define SQLNET_XTRN_PROCSERV_R268 68
142
143/* Return OPI Parameter's Type */
144#define OPI_VERSION21 1
145#define OPI_OSESSKEY2 2
146#define OPI_OAUTH3 3
147
148/* An OCI client's execute preamble: offsets from the TTI_FUN byte, and
149 * the 8-byte pointer indicator its fixed slots sit between. */
150#define TNS_OCI_INDICATOR0xfeffffffffffffffUL UINT64_C(0xfeffffffffffffff)0xfeffffffffffffffUL
151#define TNS_OCI_ALL8_CURSOR7 7
152#define TNS_OCI_ALL8_IND11 11
153#define TNS_OCI_ALL8_SQLLEN319 19
154#define TNS_OCI_ALL8_IND2_NARROW23 23
155#define TNS_OCI_ALL8_IND2_WIDE27 27
156
157/* An OCI client's object-type describe (TTI_KOD): the opcodes of its
158 * request, where the request's name or REF sits from the TTI_FUN byte,
159 * the kinds of message in its reply, and the last byte of SYS.KOTTD's
160 * id, the type a type descriptor is an instance of. */
161#define TNS_KOD_BY_NAME3 3
162#define TNS_KOD_BY_REF4 4
163#define TNS_KOD_FRAME99 99
164#define TNS_KOD_RECORD1 1
165#define TNS_KOD_HEADER2 2
166#define TNS_KOD_KOTTD1 1
167
168/* OCI function ids (TTI_FUN sub-functions). */
169#define TTI_REEXECUTE4 4
170#define TTI_FETCH5 5
171#define TTI_REEXECUTE_AND_FETCH78 78
172#define TTI_KOD92 92
173#define TTI_ALL894 94
174#define TTI_LOBOPS96 96
175#define TTI_TPC_TXN_SWITCH103 103
176#define TTI_TPC_TXN_CHANGE_STATE104 104
177#define TTI_CLOSE_CURSORS105 105
178#define TTI_SET_END_TO_END_ATTR135 135
179#define TTI_SET_SCHEMA152 152
180#define TTI_SESSION_RELEASE163 163
181#define TTI_SESSION_STATE176 176
182#define TTI_PIPELINE_BEGIN199 199
183#define TTI_PIPELINE_END200 200
184#define TTI_END_USER_SEC_CTX205 205
185
186/* desegmentation of TNS over TCP */
187static bool_Bool tns_desegment = true1;
188
189static dissector_handle_t tns_handle;
190
191static int proto_tns;
192static int hf_tns_request;
193static int hf_tns_response;
194static int hf_tns_length;
195static int hf_tns_packet_checksum;
196static int hf_tns_header_checksum;
197static int hf_tns_packet_type;
198static int hf_tns_reserved_byte;
199static int hf_tns_version;
200static int hf_tns_compat_version;
201
202static int hf_tns_service_options;
203static int hf_tns_sopt_flag_bconn;
204static int hf_tns_sopt_flag_pc;
205static int hf_tns_sopt_flag_hc;
206static int hf_tns_sopt_flag_fd;
207static int hf_tns_sopt_flag_hd;
208static int hf_tns_sopt_flag_dc1;
209static int hf_tns_sopt_flag_dc2;
210static int hf_tns_sopt_flag_dio;
211static int hf_tns_sopt_flag_ap;
212static int hf_tns_sopt_flag_ra;
213static int hf_tns_sopt_flag_sa;
214
215static int hf_tns_sdu_size;
216static int hf_tns_max_tdu_size;
217
218static int hf_tns_nt_proto_characteristics;
219static int hf_tns_ntp_flag_hangon;
220static int hf_tns_ntp_flag_crel;
221static int hf_tns_ntp_flag_tduio;
222static int hf_tns_ntp_flag_srun;
223static int hf_tns_ntp_flag_dtest;
224static int hf_tns_ntp_flag_cbio;
225static int hf_tns_ntp_flag_asio;
226static int hf_tns_ntp_flag_pio;
227static int hf_tns_ntp_flag_grant;
228static int hf_tns_ntp_flag_handoff;
229static int hf_tns_ntp_flag_sigio;
230static int hf_tns_ntp_flag_sigpipe;
231static int hf_tns_ntp_flag_sigurg;
232static int hf_tns_ntp_flag_urgentio;
233static int hf_tns_ntp_flag_fdio;
234static int hf_tns_ntp_flag_testop;
235
236static int hf_tns_line_turnaround;
237static int hf_tns_value_of_one;
238static int hf_tns_connect_data_length;
239static int hf_tns_connect_data_offset;
240static int hf_tns_connect_data_max;
241
242static int hf_tns_connect_flags0;
243static int hf_tns_connect_flags1;
244static int hf_tns_conn_flag_nareq;
245static int hf_tns_conn_flag_nalink;
246static int hf_tns_conn_flag_enablena;
247static int hf_tns_conn_flag_ichg;
248static int hf_tns_conn_flag_wantna;
249
250static int hf_tns_connect_data;
251static int hf_tns_trace_cf1;
252static int hf_tns_trace_cf2;
253static int hf_tns_trace_cid;
254
255static int hf_tns_accept_data_length;
256static int hf_tns_accept_data_offset;
257static int hf_tns_accept_sdu;
258static int hf_tns_accept_flags2;
259static int hf_tns_accept_flags2_check_oob;
260static int hf_tns_accept_flags2_end_of_response;
261static int hf_tns_accept_flags2_fast_auth;
262static int hf_tns_accept_data;
263
264static int hf_tns_refuse_reason_user;
265static int hf_tns_refuse_reason_system;
266static int hf_tns_refuse_data_length;
267static int hf_tns_refuse_data;
268
269static int hf_tns_abort_reason_user;
270static int hf_tns_abort_reason_system;
271static int hf_tns_abort_data;
272
273static int hf_tns_marker_type;
274static int hf_tns_marker_data_byte;
275static int hf_tns_marker_function;
276/* static int hf_tns_marker_data; */
277
278static int hf_tns_redirect_data_length;
279static int hf_tns_redirect_data;
280
281static int hf_tns_control_cmd;
282static int hf_tns_control_data;
283
284static int hf_tns_data_flag;
285static int hf_tns_data_flag_send;
286static int hf_tns_data_flag_rc;
287static int hf_tns_data_flag_c;
288static int hf_tns_data_flag_reserved;
289static int hf_tns_data_flag_more;
290static int hf_tns_data_flag_eof;
291static int hf_tns_data_flag_dic;
292static int hf_tns_data_flag_rts;
293static int hf_tns_data_flag_sntt;
294static int hf_tns_data_flag_end_of_request;
295static int hf_tns_data_flag_begin_pipeline;
296static int hf_tns_data_flag_end_of_response;
297
298static int hf_tns_data_id;
299static int hf_tns_data_length;
300static int hf_tns_data_oci_id;
301static int hf_tns_data_tseq;
302static int hf_tns_data_token;
303static int hf_tns_data_piggyback_id;
304static int hf_tns_data_unused;
305
306static int hf_tns_cursor;
307
308static int hf_tns_data_opi_version2_banner_len;
309static int hf_tns_data_opi_version2_banner;
310static int hf_tns_data_opi_version2_vsnum;
311
312static int hf_tns_data_opi_num_of_params;
313static int hf_tns_data_opi_param_length;
314static int hf_tns_data_opi_param_name;
315static int hf_tns_data_opi_param_value;
316static int hf_tns_data_auth_mode;
317static int hf_tns_data_auth_mode_logon;
318static int hf_tns_data_auth_mode_change_password;
319static int hf_tns_data_auth_mode_sysdba;
320static int hf_tns_data_auth_mode_sysoper;
321static int hf_tns_data_auth_mode_with_password;
322static int hf_tns_data_auth_user;
323
324static int hf_tns_data_setp_acc_version;
325static int hf_tns_data_setp_cli_plat;
326static int hf_tns_data_setp_version;
327static int hf_tns_data_setp_banner;
328static int hf_tns_data_setp_charset;
329static int hf_tns_data_setp_flags;
330static int hf_tns_data_setp_ncharset;
331static int hf_tns_data_setp_compile_caps;
332static int hf_tns_data_setp_runtime_caps;
333static int hf_tns_data_setp_field_version;
334
335static int hf_tns_data_sns_cli_vers;
336static int hf_tns_data_sns_srv_vers;
337static int hf_tns_data_sns_srvcnt;
338static int hf_tns_data_sns_error;
339static int hf_tns_data_sns_service;
340static int hf_tns_data_sns_subpackets;
341static int hf_tns_data_sns_svc_error;
342static int hf_tns_data_sns_sub_type;
343static int hf_tns_data_sns_sub_data;
344static int hf_tns_data_sns_version;
345static int hf_tns_data_sns_encryption;
346static int hf_tns_data_sns_integrity;
347
348static int hf_tns_data_setdt_charset_in;
349static int hf_tns_data_setdt_charset_out;
350static int hf_tns_data_setdt_flag;
351static int hf_tns_data_setdt_caphdr;
352static int hf_tns_data_setdt_caphdr_version;
353static int hf_tns_data_setdt_caphdr_flags;
354static int hf_tns_data_setdt_field_version;
355static int hf_tns_data_field_version;
356static int hf_tns_data_setdt_tblhdr;
357static int hf_tns_data_setdt_idmap;
358static int hf_tns_data_setdt_overrides;
359static int hf_tns_data_setdt_override_client;
360static int hf_tns_data_setdt_override_repr;
361static int hf_tns_data_setdt_override_format;
362
363static int hf_tns_data_oer_call_status;
364static int hf_tns_data_oer_rowcount;
365static int hf_tns_data_oer_err_code;
366static int hf_tns_data_oer_cursor_id;
367static int hf_tns_data_oer_n_batch_errcodes;
368static int hf_tns_data_oer_n_batch_offsets;
369static int hf_tns_data_oer_n_batch_messages;
370static int hf_tns_data_oer_message;
371static int hf_tns_data_oer_warn_flags;
372static int hf_tns_data_oer_warn_compile;
373static int hf_tns_data_oer_err_num_ext;
374static int hf_tns_data_oer_rowcount_ext;
375static int hf_tns_data_oer_sql_type;
376static int hf_tns_data_oer_checksum;
377
378static int hf_tns_data_rpa_num_al8o4;
379static int hf_tns_data_rpa_al8o4;
380static int hf_tns_data_rpa_al8txl;
381static int hf_tns_data_rpa_num_kv;
382static int hf_tns_data_rpa_registration;
383static int hf_tns_data_rpa_num_rowcounts;
384static int hf_tns_data_rpa_dml_rowcount;
385static int hf_tns_data_spb_opcode;
386static int hf_tns_data_spb_ltxid;
387static int hf_tns_data_spb_os_pid;
388static int hf_tns_data_spb_num_kv;
389static int hf_tns_data_spb_flags;
390static int hf_tns_data_spb_session_id;
391static int hf_tns_data_spb_serial_num;
392static int hf_tns_data_kv_text;
393static int hf_tns_data_kv_binary;
394static int hf_tns_data_kv_keyword;
395
396static int hf_tns_data_wrn_code;
397static int hf_tns_data_wrn_length;
398static int hf_tns_data_wrn_flags;
399static int hf_tns_data_wrn_message;
400
401static int hf_tns_data_oci_oer_status;
402static int hf_tns_data_oci_oer_seq;
403static int hf_tns_data_oci_oer_category;
404static int hf_tns_data_oci_oer_error_pos;
405static int hf_tns_data_oci_oer_command;
406static int hf_tns_data_oci_oer_call_seq;
407
408static int hf_tns_data_sta_call_status;
409static int hf_tns_data_sta_seq;
410static int hf_tns_data_call_status_txn;
411static int hf_tns_data_call_status_sess_release;
412
413static int hf_tns_data_iov_num_binds;
414static int hf_tns_data_iov_bind_dir;
415static int hf_tns_data_bind_retcode;
416
417static int hf_tns_data_dcb_num_columns;
418static int hf_tns_data_col_type;
419static int hf_tns_data_col_precision;
420static int hf_tns_data_col_scale;
421static int hf_tns_data_col_max_length;
422static int hf_tns_data_col_charset;
423static int hf_tns_data_col_csform;
424static int hf_tns_data_col_max_size;
425static int hf_tns_data_col_nulls_ok;
426static int hf_tns_data_col_name;
427static int hf_tns_data_col_uds_flags;
428static int hf_tns_data_col_domain_schema;
429static int hf_tns_data_col_domain_name;
430static int hf_tns_data_col_annotation;
431static int hf_tns_data_col_vector_dims;
432static int hf_tns_data_col_vector_format;
433
434static int hf_tns_data_rxh_num_requests;
435static int hf_tns_data_rxh_iter_num;
436static int hf_tns_data_rxh_num_iters;
437static int hf_tns_data_bit_vector;
438static int hf_tns_data_bvc_num_cols_sent;
439static int hf_tns_data_irs_num_results;
440
441static int hf_tns_data_all8_options;
442static int hf_tns_data_all8_opt_parse;
443static int hf_tns_data_all8_opt_bind;
444static int hf_tns_data_all8_opt_define;
445static int hf_tns_data_all8_opt_execute;
446static int hf_tns_data_all8_opt_commit;
447static int hf_tns_data_all8_opt_plsql;
448static int hf_tns_data_all8_opt_fetch;
449static int hf_tns_data_all8_opt_not_plsql;
450static int hf_tns_data_all8_parse_only;
451static int hf_tns_data_all8_opt_describe;
452static int hf_tns_data_all8_opt_batch_errors;
453static int hf_tns_data_all8_iterations;
454static int hf_tns_data_all8_prefetch;
455static int hf_tns_data_all8_is_query;
456static int hf_tns_data_all8_exec_flags;
457static int hf_tns_data_all8_xflag_scrollable;
458static int hf_tns_data_all8_xflag_no_cancel_on_eof;
459static int hf_tns_data_all8_xflag_dml_rowcounts;
460static int hf_tns_data_all8_xflag_implicit_rs;
461static int hf_tns_data_all8_fetch_orientation;
462static int hf_tns_data_all8_fetch_pos;
463static int hf_tns_data_all8_fetch_rows;
464static int hf_tns_data_all8_bind_count;
465static int hf_tns_data_all8_define_count;
466static int hf_tns_data_all8_oci_preamble;
467static int hf_tns_data_all8_sql;
468static int hf_tns_data_bind_value;
469static int hf_tns_data_fetch_rows;
470static int hf_tns_data_kod_opcode;
471static int hf_tns_data_kod_kind;
472static int hf_tns_data_kod_schema;
473static int hf_tns_data_kod_name;
474static int hf_tns_data_kod_oid;
475static int hf_tns_data_kod_type_oid;
476static int hf_tns_data_kod_system_type;
477static int hf_tns_data_kod_image;
478static int hf_tns_data_kod_version;
479static int hf_tns_data_kod_typecode;
480static int hf_tns_data_reexec_iterations;
481static int hf_tns_data_reexec_options2;
482static int hf_tns_data_reexec_opt2_commit;
483static int hf_tns_data_lob_op;
484static int hf_tns_data_lob_offset;
485static int hf_tns_data_lob_locator;
486static int hf_tns_data_lob_directory;
487static int hf_tns_data_lob_file_name;
488static int hf_tns_data_lob_charset;
489static int hf_tns_data_lob_data;
490static int hf_tns_data_lob_amount;
491static int hf_tns_data_lob_flag;
492static int hf_tns_data_tpc_switch_op;
493static int hf_tns_data_release_tag;
494static int hf_tns_data_release_mode;
495static int hf_tns_data_release_mode_deauth;
496static int hf_tns_data_tpc_change_op;
497static int hf_tns_data_tpc_format_id;
498static int hf_tns_data_tpc_gtrid;
499static int hf_tns_data_tpc_bqual;
500static int hf_tns_data_tpc_flags;
501static int hf_tns_data_tpc_timeout;
502static int hf_tns_data_tpc_state;
503static int hf_tns_data_tpc_context;
504static int hf_tns_data_tpc_app_value;
505static int hf_tns_data_tpc_internal_name;
506static int hf_tns_data_tpc_external_name;
507static int hf_tns_data_lob_text;
508static int hf_tns_data_lob_total_size;
509static int hf_tns_data_pgy_schema;
510static int hf_tns_data_pgy_session_state;
511static int hf_tns_data_pgy_e2e_flags;
512static int hf_tns_data_pgy_client_id;
513static int hf_tns_data_pgy_module;
514static int hf_tns_data_pgy_action;
515static int hf_tns_data_pgy_client_info;
516static int hf_tns_data_pgy_dbop;
517static int hf_tns_data_pgy_error_set_id;
518static int hf_tns_data_pgy_error_set_mode;
519static int hf_tns_data_pgy_pipeline_mode;
520static int hf_tns_data_pgy_sec_flags;
521static int hf_tns_data_pgy_sec_key;
522static int hf_tns_data_pgy_sec_value;
523static int hf_tns_data_col_value;
524static int hf_tns_data_lob_size;
525static int hf_tns_data_lob_chunk_size;
526static int hf_tns_data_json_image;
527static int hf_tns_data_vector_image;
528static int hf_tns_data_obj_toid;
529static int hf_tns_data_obj_image;
530
531static int hf_tns_data_descriptor_row_count;
532static int hf_tns_data_descriptor_row_size;
533
534static int ett_tns;
535static int ett_tns_connect;
536static int ett_tns_accept;
537static int ett_tns_refuse;
538static int ett_tns_abort;
539static int ett_tns_redirect;
540static int ett_tns_marker;
541static int ett_tns_attention;
542static int ett_tns_control;
543static int ett_tns_data;
544static int ett_tns_data_flag;
545static int ett_tns_acc_versions;
546static int ett_tns_opi_params;
547static int ett_tns_opi_par;
548static int ett_tns_sopt_flag;
549static int ett_tns_ntp_flag;
550static int ett_tns_conn_flag;
551static int ett_tns_accept_flags2;
552static int ett_tns_rows;
553static int ett_tns_setdt_caphdr;
554static int ett_tns_setdt_overrides;
555static int ett_tns_setdt_override;
556static int ett_tns_oer;
557static int ett_tns_call_status;
558static int ett_tns_warn_flags;
559static int ett_tns_auth_mode;
560static int ett_tns_sns_service;
561static int ett_tns_sns_subpacket;
562static int ett_tns_release_mode;
563static int ett_tns_rpa;
564static int ett_tns_kv;
565static int ett_tns_iov;
566static int ett_tns_dcb_col;
567static int ett_tns_all8_options;
568static int ett_tns_all8_i4;
569static int ett_tns_all8_exec_flags;
570static int ett_tns_binds;
571static int ett_tns_bind;
572static int ett_tns_defines;
573static int ett_tns_reexec_options2;
574static int ett_tns_bind_row;
575static int ett_tns_rxd_row;
576static int ett_tns_value;
577static int ett_tns_irs;
578static int ett_tns_out_binds;
579static int ett_sql;
580static int ett_tns_kod;
581
582static expert_field ei_tns_connect_data_next_packet;
583static expert_field ei_tns_data_descriptor_size_mismatch;
584static expert_field ei_tns_data_piggyback_cursors;
585static expert_field ei_tns_data_count_too_large;
586static expert_field ei_tns_data_encrypted;
587static expert_field ei_tns_data_compilation_error;
588
589#define TCP_PORT_TNS1521 1521 /* Not IANA registered */
590
591/* The ACCEPT's flags2 word, what the server offers from version 318. */
592static int * const tns_accept_flags2[] = {
593 &hf_tns_accept_flags2_check_oob,
594 &hf_tns_accept_flags2_end_of_response,
595 &hf_tns_accept_flags2_fast_auth,
596 NULL((void*)0)
597};
598
599static int * const tns_connect_flags[] = {
600 &hf_tns_conn_flag_nareq,
601 &hf_tns_conn_flag_nalink,
602 &hf_tns_conn_flag_enablena,
603 &hf_tns_conn_flag_ichg,
604 &hf_tns_conn_flag_wantna,
605 NULL((void*)0)
606};
607
608static int * const tns_service_options[] = {
609 &hf_tns_sopt_flag_bconn,
610 &hf_tns_sopt_flag_pc,
611 &hf_tns_sopt_flag_hc,
612 &hf_tns_sopt_flag_fd,
613 &hf_tns_sopt_flag_hd,
614 &hf_tns_sopt_flag_dc1,
615 &hf_tns_sopt_flag_dc2,
616 &hf_tns_sopt_flag_dio,
617 &hf_tns_sopt_flag_ap,
618 &hf_tns_sopt_flag_ra,
619 &hf_tns_sopt_flag_sa,
620 NULL((void*)0)
621};
622
623/* TTI_ALL8 (SQL execute) options bitmask. */
624static int * const tns_all8_options[] = {
625 &hf_tns_data_all8_opt_parse,
626 &hf_tns_data_all8_opt_bind,
627 &hf_tns_data_all8_opt_define,
628 &hf_tns_data_all8_opt_execute,
629 &hf_tns_data_all8_opt_fetch,
630 &hf_tns_data_all8_opt_commit,
631 &hf_tns_data_all8_opt_plsql,
632 &hf_tns_data_all8_opt_not_plsql,
633 &hf_tns_data_all8_opt_describe,
634 &hf_tns_data_all8_opt_batch_errors,
635 NULL((void*)0)
636};
637
638static const value_string tns_type_vals[] = {
639 {TNS_TYPE_CONNECT1, "Connect" },
640 {TNS_TYPE_ACCEPT2, "Accept" },
641 {TNS_TYPE_ACK3, "Acknowledge" },
642 {TNS_TYPE_REFUSE4, "Refuse" },
643 {TNS_TYPE_REDIRECT5, "Redirect" },
644 {TNS_TYPE_DATA6, "Data" },
645 {TNS_TYPE_NULL7, "Null" },
646 {TNS_TYPE_ABORT9, "Abort" },
647 {TNS_TYPE_RESEND11, "Resend"},
648 {TNS_TYPE_MARKER12, "Marker"},
649 {TNS_TYPE_ATTENTION13, "Attention"},
650 {TNS_TYPE_CONTROL14, "Control"},
651 {TNS_TYPE_DD15, "Data Descriptor"},
652 {0, NULL((void*)0)}
653};
654
655static const value_string tns_data_funcs[] = {
656 {SQLNET_SET_PROTOCOL1, "Set Protocol"},
657 {SQLNET_SET_DATATYPES2, "Set Datatypes"},
658 {SQLNET_USER_OCI_FUNC3, "User OCI Functions"},
659 {SQLNET_RETURN_STATUS4, "Return Status"},
660 {SQLNET_ACCESS_USR_ADDR5, "Access User Address Space"},
661 {SQLNET_ROW_TRANSF_HDR6, "Row Transfer Header"},
662 {SQLNET_ROW_TRANSF_DATA7, "Row Transfer Data"},
663 {SQLNET_RETURN_OPI_PARAM8, "Return OPI Parameter"},
664 {SQLNET_FUNCCOMPLETE9, "Function Complete"},
665 {SQLNET_NERROR_RET_DEF10, "N Error return definitions follow"},
666 {SQLNET_IOVEC_4FAST_UPI11, "Sending I/O Vec only for fast UPI"},
667 {SQLNET_LONG_4FAST_UPI12, "Sending long for fast UPI"},
668 {SQLNET_INVOKE_USER_CB13, "Invoke user callback"},
669 {SQLNET_LOB_FILE_DF14, "LOB/FILE data follows"},
670 {SQLNET_WARNING15, "Warning messages - may be a set of them"},
671 {SQLNET_DESCRIBE_INFO16, "Describe Information"},
672 {SQLNET_PIGGYBACK_FUNC17, "Piggy back function follow"},
673 {SQLNET_SIG_4UCS18, "Signals special action for untrusted callout support"},
674 {SQLNET_FLUSH_BIND_DATA19, "Flush Out Bind data in DML/w RETURN when error"},
675 {SQLNET_BIT_VECTOR21, "Bit Vector"},
676 {SQLNET_SERVER_PIGGYBACK23, "Server-side Piggyback"},
677 {SQLNET_IMPLICIT_RESULTS27, "Implicit Result Sets"},
678 {SQLNET_END_OF_RESPONSE29, "End of Response"},
679 {SQLNET_TOKEN33, "Token"},
680 {SQLNET_XTRN_PROCSERV_R132, "External Procedures and Services Registrations"},
681 {SQLNET_XTRN_PROCSERV_R268, "External Procedures and Services Registrations"},
682 {SQLNET_SNS0xdeadbeef, "Secure Network Services"},
683 {0, NULL((void*)0)}
684};
685
686/* The authentication mode of an authentication call. */
687static int * const tns_auth_modes[] = {
688 &hf_tns_data_auth_mode_logon,
689 &hf_tns_data_auth_mode_change_password,
690 &hf_tns_data_auth_mode_sysdba,
691 &hf_tns_data_auth_mode_sysoper,
692 &hf_tns_data_auth_mode_with_password,
693 NULL((void*)0)
694};
695
696/* The mode of a DRCP session release. */
697static int * const tns_release_modes[] = {
698 &hf_tns_data_release_mode_deauth,
699 NULL((void*)0)
700};
701
702/* The second options word of a re-execute. */
703static int * const tns_reexec_options2[] = {
704 &hf_tns_data_reexec_opt2_commit,
705 NULL((void*)0)
706};
707
708/* Execute flags, the al8i4[9] word of a TTI_ALL8 execute. */
709static int * const tns_all8_exec_flags[] = {
710 &hf_tns_data_all8_xflag_scrollable,
711 &hf_tns_data_all8_xflag_no_cancel_on_eof,
712 &hf_tns_data_all8_xflag_dml_rowcounts,
713 &hf_tns_data_all8_xflag_implicit_rs,
714 NULL((void*)0)
715};
716
717/* Scrollable-cursor fetch orientation, al8i4[10] of a TTI_ALL8 execute. */
718static const value_string tns_fetch_orientations[] = {
719 {0x00, "None"},
720 {0x01, "Current"},
721 {0x02, "Next"},
722 {0x04, "First"},
723 {0x08, "Last"},
724 {0x10, "Prior"},
725 {0x20, "Absolute"},
726 {0x40, "Relative"},
727 {0, NULL((void*)0)}
728};
729
730/* Server-side piggyback opcodes (python-oracledb's
731 * TNS_SERVER_PIGGYBACK_*). */
732#define TNS_SPB_QUERY_CACHE_INVALIDATION1 1
733#define TNS_SPB_OS_PID_MTS2 2
734#define TNS_SPB_TRACE_EVENT3 3
735#define TNS_SPB_SESS_RET4 4
736#define TNS_SPB_SYNC5 5
737#define TNS_SPB_LTXID7 7
738#define TNS_SPB_AC_REPLAY_CONTEXT8 8
739#define TNS_SPB_EXT_SYNC9 9
740#define TNS_SPB_SESS_SIGNATURE10 10
741
742static const value_string tns_spb_opcodes[] = {
743 {TNS_SPB_QUERY_CACHE_INVALIDATION1, "Query Cache Invalidation"},
744 {TNS_SPB_OS_PID_MTS2, "OS PID (shared server)"},
745 {TNS_SPB_TRACE_EVENT3, "Trace Event"},
746 {TNS_SPB_SESS_RET4, "Session Return"},
747 {TNS_SPB_SYNC5, "Session State Sync"},
748 {TNS_SPB_LTXID7, "Logical Transaction Id"},
749 {TNS_SPB_AC_REPLAY_CONTEXT8, "Application Continuity Replay Context"},
750 {TNS_SPB_EXT_SYNC9, "Extended Sync"},
751 {TNS_SPB_SESS_SIGNATURE10, "Session Signature"},
752 {0, NULL((void*)0)}
753};
754
755/* Status byte of an OCI client's status block. */
756static const value_string tns_oci_oer_status_vals[] = {
757 {1, "Success"},
758 {5, "Error"},
759 {0, NULL((void*)0)}
760};
761
762/* Statement command types, as V$SQL.COMMAND_TYPE numbers them. */
763static const value_string tns_command_types[] = {
764 {1, "CREATE TABLE"},
765 {2, "INSERT"},
766 {3, "SELECT"},
767 {6, "UPDATE"},
768 {7, "DELETE"},
769 {9, "CREATE INDEX"},
770 {12, "DROP TABLE"},
771 {15, "ALTER TABLE"},
772 {21, "CREATE VIEW"},
773 {22, "DROP VIEW"},
774 {44, "COMMIT"},
775 {45, "ROLLBACK"},
776 {47, "PL/SQL EXECUTE"},
777 {85, "TRUNCATE TABLE"},
778 {0, NULL((void*)0)}
779};
780
781static const value_string tns_field_versions[] = {
782 {TNS_FV_11_26, "11.2"},
783 {TNS_FV_12_17, "12.1"},
784 {TNS_FV_12_28, "12.2"},
785 {TNS_FV_12_2_EXT19, "12.2 ext 1"},
786 {TNS_FV_18_110, "18.1"},
787 {TNS_FV_18_1_EXT_111, "18.1 ext 1"},
788 {TNS_FV_19_112, "19.1"},
789 {TNS_FV_19_1_EXT_113, "19.1 ext 1"},
790 {TNS_FV_20_114, "20.1"},
791 {TNS_FV_20_1_EXT_115, "20.1 ext 1"},
792 {TNS_FV_21_116, "21.1"},
793 {TNS_FV_23_117, "23.1"},
794 {TNS_FV_23_1_EXT_118, "23.1 ext 1"},
795 {TNS_FV_23_1_EXT_219, "23.1 ext 2"},
796 {TNS_FV_23_1_EXT_320, "23.1 ext 3"},
797 {TNS_FV_23_1_EXT_421, "23.1 ext 4"},
798 {TNS_FV_23_1_EXT_522, "23.1 ext 5"},
799 {TNS_FV_23_3_EXT_623, "23.3 ext 6"},
800 {TNS_FV_23_424, "23.4"},
801 {0, NULL((void*)0)}
802};
803
804/* Two-phase commit operations (python-oracledb's TNS_TPC_*). */
805static const value_string tns_tpc_switch_ops[] = {
806 {0x01, "Start"},
807 {0x02, "Detach"},
808 {0x04, "Post-detach"},
809 {0, NULL((void*)0)}
810};
811
812static const value_string tns_tpc_change_ops[] = {
813 {0x01, "Commit"},
814 {0x02, "Abort"},
815 {0x03, "Prepare"},
816 {0x04, "Forget"},
817 {0, NULL((void*)0)}
818};
819
820static const value_string tns_tpc_states[] = {
821 {0, "Prepared"},
822 {1, "Requires commit"},
823 {2, "Committed"},
824 {3, "Aborted"},
825 {4, "Read only"},
826 {5, "Forgotten"},
827 {0, NULL((void*)0)}
828};
829
830/* Native network services (ANO) negotiation: services, sub-packet types
831 * and the encryption and integrity algorithm ids. */
832#define TNS_ANO_AUTHENTICATION1 1
833#define TNS_ANO_ENCRYPTION2 2
834#define TNS_ANO_DATA_INTEGRITY3 3
835#define TNS_ANO_SUPERVISOR4 4
836#define TNS_ANO_SP_BYTES1 1
837#define TNS_ANO_SP_UB12 2
838#define TNS_ANO_SP_VERSION5 5
839
840static const value_string tns_sns_services[] = {
841 {TNS_ANO_AUTHENTICATION1, "Authentication"},
842 {TNS_ANO_ENCRYPTION2, "Encryption"},
843 {TNS_ANO_DATA_INTEGRITY3, "Data Integrity"},
844 {TNS_ANO_SUPERVISOR4, "Supervisor"},
845 {0, NULL((void*)0)}
846};
847
848static const value_string tns_sns_subpacket_types[] = {
849 {0, "String"},
850 {1, "Bytes"},
851 {2, "UB1"},
852 {3, "UB2"},
853 {4, "UB4"},
854 {5, "Version"},
855 {6, "Status"},
856 {0, NULL((void*)0)}
857};
858
859static const value_string tns_sns_encryption_algs[] = {
860 {0, "None"},
861 {1, "RC4_40"},
862 {2, "DES"},
863 {3, "DES40"},
864 {6, "RC4_256"},
865 {8, "RC4_56"},
866 {10, "RC4_128"},
867 {11, "3DES112"},
868 {12, "3DES168"},
869 {15, "AES128"},
870 {16, "AES192"},
871 {17, "AES256"},
872 {0, NULL((void*)0)}
873};
874
875static const value_string tns_sns_integrity_algs[] = {
876 {0, "None"},
877 {1, "MD5"},
878 {3, "SHA1"},
879 {4, "SHA512"},
880 {5, "SHA256"},
881 {6, "SHA384"},
882 {0, NULL((void*)0)}
883};
884
885/* Keyword numbers of the key/value pairs a server reports back, for a
886 * session attribute a statement changed (python-oracledb's
887 * TNS_KEYWORD_NUM_*). */
888static const value_string tns_kv_keywords[] = {
889 {168, "CURRENT_SCHEMA"},
890 {172, "EDITION"},
891 {201, "TRANSACTION_ID"},
892 {0, NULL((void*)0)}
893};
894
895/* Oracle TNS native data-type ids. Used by the Set Datatypes
896 * negotiation to label override entries with human names. */
897static const value_string tns_data_types[] = {
898 {TNS_DATATYPE_VARCHAR1, "VARCHAR"},
899 {TNS_DATATYPE_NUMBER2, "NUMBER"},
900 {TNS_DATATYPE_INTEGER3, "BINARY_INTEGER"},
901 {TNS_DATATYPE_FLOAT4, "FLOAT"},
902 {TNS_DATATYPE_STRING5, "STRING"},
903 {TNS_DATATYPE_VARNUM6, "VARNUM"},
904 {TNS_DATATYPE_DECIMAL7, "DECIMAL"},
905 {TNS_DATATYPE_LONG8, "LONG"},
906 {TNS_DATATYPE_VCS9, "VCS"},
907 {TNS_DATATYPE_ROWID11, "RID"},
908 {TNS_DATATYPE_DATE12, "DATE"},
909 {TNS_DATATYPE_VBI15, "VBI"},
910 {TNS_DATATYPE_RAW23, "RAW"},
911 {TNS_DATATYPE_LONG_RAW24, "LONG RAW"},
912 {TNS_DATATYPE_CHAR96, "CHAR"},
913 {TNS_DATATYPE_BINARY_FLOAT100, "BINARY_FLOAT"},
914 {TNS_DATATYPE_BINARY_DOUBLE101, "BINARY_DOUBLE"},
915 {TNS_DATATYPE_REFCURSOR102, "REFCURSOR"},
916 {TNS_DATATYPE_ROWID_EXT104, "ROWID"},
917 {TNS_DATATYPE_ADT109, "ADT"},
918 {TNS_DATATYPE_REF111, "REF"},
919 {TNS_DATATYPE_CLOB112, "CLOB"},
920 {TNS_DATATYPE_BLOB113, "BLOB"},
921 {TNS_DATATYPE_BFILE114, "BFILE"},
922 {TNS_DATATYPE_RSET116, "RSET"},
923 {TNS_DATATYPE_JSON119, "JSON"},
924 {TNS_DATATYPE_VECTOR127, "VECTOR"},
925 {TNS_DATATYPE_TIMESTAMP180, "TIMESTAMP"},
926 {TNS_DATATYPE_TIMESTAMP_TZ181, "TIMESTAMP WITH TIME ZONE"},
927 {TNS_DATATYPE_INTERVAL_YM182, "INTERVAL YEAR TO MONTH"},
928 {TNS_DATATYPE_INTERVAL_DS183, "INTERVAL DAY TO SECOND"},
929 {TNS_DATATYPE_UROWID208, "UROWID"},
930 {TNS_DATATYPE_TIMESTAMP_LTZ231, "TIMESTAMP WITH LOCAL TIME ZONE"},
931 {TNS_DATATYPE_BOOLEAN252, "BOOLEAN"},
932 {0, NULL((void*)0)}
933};
934
935/* Oracle NLS character-set ids - the well-known subset, enough to name
936 * the charsets seen in a Set Datatypes negotiation. */
937static const value_string tns_charsets[] = {
938 {31, "WE8ISO8859P1"},
939 {32, "EE8ISO8859P2"},
940 {35, "CL8ISO8859P5"},
941 {170, "EE8MSWIN1250"},
942 {171, "CL8MSWIN1251"},
943 {178, "WE8MSWIN1252"},
944 {830, "JA16EUC"},
945 {852, "ZHS16GBK"},
946 {865, "ZHT16BIG5"},
947 {867, "ZHT16MSWIN950"},
948 {871, "US7ASCII"},
949 {873, "AL32UTF8"},
950 {2000, "AL16UTF16"},
951 {0, NULL((void*)0)}
952};
953
954/* A LOB locator's flag bytes, at these offsets in the locator as a
955 * client holds and sends it (python-oracledb's TNS_LOB_LOC_*). Flag 1
956 * says what kind of LOB it is; flags 3 and 4 how a CLOB's characters are
957 * encoded: UTF-16 with the variable-length charset bit, little-endian
958 * with the little-endian bit too, UTF-8 without. An NCLOB is UTF-16. */
959#define TNS_LOB_LOC_FLAG_10x04 0x04
960#define TNS_LOB_LOC_FLAG_30x06 0x06
961#define TNS_LOB_LOC_FLAG_40x07 0x07
962#define TNS_LOB_LOC_FLAGS_BLOB0x01 0x01
963#define TNS_LOB_LOC_FLAGS_CLOB0x02 0x02
964#define TNS_LOB_LOC_FLAGS_NCLOB0x04 0x04
965#define TNS_LOB_LOC_FLAGS_VAR_LENGTH_CHARSET0x80 0x80
966#define TNS_LOB_LOC_FLAGS_LITTLE_ENDIAN0x40 0x40
967
968/* TTI_LOBOPS operation opcodes. */
969#define TNS_LOB_OP_FILE_ISOPEN0x00400 0x00400
970#define TNS_LOB_OP_FILE_EXISTS0x00800 0x00800
971#define TNS_LOB_OP_CREATE_TEMP0x00110 0x00110
972#define TNS_LOB_OP_IS_OPEN0x11000 0x11000
973
974static const value_string tns_lob_ops[] = {
975 {0x00001, "GET_LENGTH"},
976 {0x00002, "READ"},
977 {0x00020, "TRIM"},
978 {0x00040, "WRITE"},
979 {0x00100, "FILE_OPEN"},
980 {0x00110, "CREATE_TEMP"},
981 {0x00111, "FREE_TEMP"},
982 {0x00200, "FILE_CLOSE"},
983 {0x00400, "FILE_ISOPEN"},
984 {0x00800, "FILE_EXISTS"},
985 {0x04000, "GET_CHUNK_SIZE"},
986 {0x08000, "OPEN"},
987 {0x10000, "CLOSE"},
988 {0x11000, "IS_OPEN"},
989 {0x80000, "ARRAY"},
990 {0, NULL((void*)0)}
991};
992
993/* Column character-set form (csfrm) in an OAC descriptor: whether char data
994 * is in the database charset or the national (AL16UTF16) charset. */
995#define TNS_CSFORM_NCHAR2 2
996static const value_string tns_csform_vals[] = {
997 {1, "Database charset"},
998 {2, "National (AL16UTF16)"},
999 {0, NULL((void*)0)}
1000};
1001
1002/* Bind directions reported per bind in a TTI_IOV vector (TNS_BIND_DIR_*),
1003 * cross-referenced with python-oracledb's constants. */
1004#define TNS_BIND_DIR_INPUT32 32
1005static const value_string tns_iov_bind_dirs[] = {
1006 {16, "OUT"},
1007 {32, "IN"},
1008 {48, "IN OUT"},
1009 {0, NULL((void*)0)}
1010};
1011
1012/* What a TTI_KOD call asks for. */
1013static const value_string tns_kod_opcodes[] = {
1014 {TNS_KOD_BY_NAME3, "Describe by name"},
1015 {TNS_KOD_BY_REF4, "Describe by REF"},
1016 {0, NULL((void*)0)}
1017};
1018
1019/* The messages of a TTI_KOD reply. */
1020static const value_string tns_kod_kinds[] = {
1021 {TNS_KOD_RECORD1, "Type record"},
1022 {TNS_KOD_HEADER2, "Name header"},
1023 {0, NULL((void*)0)}
1024};
1025
1026/* The system types, by the last byte of an id whose first 15 are zero. */
1027static const value_string tns_kod_system_types[] = {
1028 {TNS_KOD_KOTTD1, "SYS.KOTTD"},
1029 {0x02, "SYS.KOTTB"},
1030 {0x03, "SYS.KOTAD"},
1031 {0x0f, "SYS.NUMBER"},
1032 {0, NULL((void*)0)}
1033};
1034
1035/* The typecodes a type descriptor names. */
1036static const value_string tns_kod_typecodes[] = {
1037 {108, "Object"},
1038 {122, "Named collection"},
1039 {0, NULL((void*)0)}
1040};
1041
1042static const value_string tns_data_oci_subfuncs[] = {
1043 {1, "Logon to Oracle"},
1044 {2, "Open Cursor"},
1045 {3, "Parse a Row"},
1046 {4, "Execute a Row"},
1047 {5, "Fetch a Row"},
1048 {8, "Close Cursor"},
1049 {9, "Logoff of Oracle"},
1050 {10, "Describe a select list column"},
1051 {11, "Define where the column goes"},
1052 {12, "Auto commit on"},
1053 {13, "Auto commit off"},
1054 {14, "Commit"},
1055 {15, "Rollback"},
1056 {16, "Set fatal error options"},
1057 {17, "Resume current operation"},
1058 {18, "Get Oracle version-date string"},
1059 {19, "Until we get rid of OASQL"},
1060 {20, "Cancel the current operation"},
1061 {21, "Get error message"},
1062 {22, "Exit Oracle command"},
1063 {23, "Special function"},
1064 {24, "Abort"},
1065 {25, "Dequeue by RowID"},
1066 {26, "Fetch a long column value"},
1067 {27, "Create Access Module"},
1068 {28, "Save Access Module Statement"},
1069 {29, "Save Access Module"},
1070 {30, "Parse Access Module Statement"},
1071 {31, "How many items?"},
1072 {32, "Initialize Oracle"},
1073 {33, "Change User ID"},
1074 {34, "Bind by reference positional"},
1075 {35, "Get n'th Bind Variable"},
1076 {36, "Get n'th Into Variable"},
1077 {37, "Bind by reference"},
1078 {38, "Bind by reference numeric"},
1079 {39, "Parse and Execute"},
1080 {40, "Parse for syntax (only)"},
1081 {41, "Parse for syntax and SQL Dictionary lookup"},
1082 {42, "Continue serving after EOF"},
1083 {43, "Array describe"},
1084 {44, "Init sys pars command table"},
1085 {45, "Finalize sys pars command table"},
1086 {46, "Put sys par in command table"},
1087 {47, "Get sys pars from command table"},
1088 {48, "Start Oracle (V6)"},
1089 {49, "Shutdown Oracle (V6)"},
1090 {50, "Run Independent Process (V6)"},
1091 {51, "Test RAM (V6)"},
1092 {52, "Archive operation (V6)"},
1093 {53, "Media Recovery - start (V6)"},
1094 {54, "Media Recovery - record tablespace to recover (V6)"},
1095 {55, "Media Recovery - get starting log seq # (V6)"},
1096 {56, "Media Recovery - recover using offline log (V6)"},
1097 {57, "Media Recovery - cancel media recovery (V6)"},
1098 {58, "Logon to Oracle (V6)"},
1099 {59, "Get Oracle version-date string in new format"},
1100 {60, "Initialize Oracle"},
1101 {61, "Reserved for MAC; close all cursors"},
1102 {62, "Bundled execution call"},
1103 {65, "For direct loader: functions"},
1104 {66, "For direct loader: buffer transfer"},
1105 {67, "Distrib. trans. mgr. RPC"},
1106 {68, "Describe indexes for distributed query"},
1107 {69, "Session operations"},
1108 {70, "Execute using synchronized system commit numbers"},
1109 {71, "Fast UPI calls to OPIAL7"},
1110 {72, "Long Fetch (V7)"},
1111 {73, "Call OPIEXE from OPIALL: no two-task access"},
1112 {74, "Parse Call (V7) to deal with various flavours"},
1113 {76, "RPC call from PL/SQL"},
1114 {77, "Do a KGL operation"},
1115 {78, "Execute and Fetch"},
1116 {79, "X/Open XA operation"},
1117 {80, "New KGL operation call"},
1118 {81, "2nd Half of Logon"},
1119 {82, "1st Half of Logon"},
1120 {83, "Do Streaming Operation"},
1121 {84, "Open Session (71 interface)"},
1122 {85, "X/Open XA operations (71 interface)"},
1123 {86, "Debugging operations"},
1124 {87, "Special debugging operations"},
1125 {88, "XA Start"},
1126 {89, "XA Switch and Commit"},
1127 {90, "Direct copy from db buffers to client address"},
1128 {91, "OKOD Call (In Oracle <= 7 this used to be Connect"},
1129 {92, "Describe an object type (KOD)"},
1130 {93, "RPI Callback with ctxdef"},
1131 {94, "Bundled execution call (V7)"},
1132 {95, "Do Streaming Operation without begintxn"},
1133 {96, "LOB and FILE related calls"},
1134 {97, "File Create call"},
1135 {98, "Describe query (V8) call"},
1136 {99, "Connect (non-blocking attach host)"},
1137 {100, "Open a recursive cursor"},
1138 {101, "Bundled KPR Execution"},
1139 {102, "Bundled PL/SQL execution"},
1140 {103, "Transaction start, attach, detach"},
1141 {104, "Transaction commit, rollback, recover"},
1142 {105, "Cursor close all"},
1143 {106, "Failover into piggyback"},
1144 {107, "Session switching piggyback (V8)"},
1145 {108, "Do Dummy Defines"},
1146 {109, "Init sys pars (V8)"},
1147 {110, "Finalize sys pars (V8)"},
1148 {111, "Put sys par in par space (V8)"},
1149 {112, "Terminate sys pars (V8)"},
1150 {114, "Init Untrusted Callbacks"},
1151 {115, "Generic authentication call"},
1152 {116, "FailOver Get Instance call"},
1153 {117, "Oracle Transaction service Commit remote sites"},
1154 {118, "Get the session key"},
1155 {119, "Describe any (V8)"},
1156 {120, "Cancel All"},
1157 {121, "AQ Enqueue"},
1158 {122, "AQ Dequeue"},
1159 {123, "Object transfer"},
1160 {124, "RFS Call"},
1161 {125, "Kernel programmatic notification"},
1162 {126, "Listen"},
1163 {127, "Oracle Transaction service Commit remote sites (V >= 8.1.3)"},
1164 {128, "Dir Path Prepare"},
1165 {129, "Dir Path Load Stream"},
1166 {130, "Dir Path Misc. Ops"},
1167 {131, "Memory Stats"},
1168 {132, "AQ Properties Status"},
1169 {134, "Remote Fetch Archive Log FAL"},
1170 {135, "Client ID propagation"},
1171 {136, "DR Server CNX Process"},
1172 {138, "SPFILE parameter put"},
1173 {139, "KPFC exchange"},
1174 {140, "Object Transfer (V8.2)"},
1175 {141, "Push Transaction"},
1176 {142, "Pop Transaction"},
1177 {143, "KFN Operation"},
1178 {144, "Dir Path Unload Stream"},
1179 {145, "AQ batch enqueue dequeue"},
1180 {146, "File Transfer"},
1181 {147, "Ping"},
1182 {148, "TSM"},
1183 {150, "Begin TSM"},
1184 {151, "End TSM"},
1185 {152, "Set schema"},
1186 {153, "Fetch from suspended result set"},
1187 {154, "Key/Value pair"},
1188 {155, "XS Create session Operation"},
1189 {156, "XS Session Roundtrip Operation"},
1190 {157, "XS Piggyback Operation"},
1191 {158, "KSRPC Execution"},
1192 {159, "Streams combined capture apply"},
1193 {160, "AQ replay information"},
1194 {161, "SSCR"},
1195 {162, "Session Get"},
1196 {163, "Session RLS"},
1197 {165, "Workload replay data"},
1198 {166, "Replay statistic data"},
1199 {167, "Query Cache Stats"},
1200 {168, "Query Cache IDs"},
1201 {169, "RPC Test Stream"},
1202 {170, "Replay PL/SQL RPC"},
1203 {171, "XStream Out"},
1204 {172, "Golden Gate RPC"},
1205 {176, "Session state"},
1206 {187, "Notify"},
1207 {199, "Pipeline begin"},
1208 {200, "Pipeline end"},
1209 {205, "End-user security context"},
1210 {0, NULL((void*)0)}
1211};
1212static value_string_ext tns_data_oci_subfuncs_ext = VALUE_STRING_EXT_INIT(tns_data_oci_subfuncs){ _try_val_to_str_ext_init, 0, (sizeof (tns_data_oci_subfuncs
) / sizeof ((tns_data_oci_subfuncs)[0]))-1, tns_data_oci_subfuncs
, "tns_data_oci_subfuncs", ((void*)0) }
;
1213
1214/* The final byte of a TNS_MARKER body selects break vs reset:
1215 * 01 00 01 = break, 01 00 02 = reset. */
1216static const value_string tns_marker_functions[] = {
1217 {1, "Break (interrupt call)"},
1218 {2, "Reset (clear line)"},
1219 {0, NULL((void*)0)}
1220};
1221
1222static const value_string tns_marker_types[] = {
1223 {0, "Data Marker - 0 Data Bytes"},
1224 {1, "Data Marker - 1 Data Bytes"},
1225 {2, "Attention Marker"},
1226 {0, NULL((void*)0)}
1227};
1228
1229static const value_string tns_control_cmds[] = {
1230 {1, "Oracle Trace Command"},
1231 {0, NULL((void*)0)}
1232};
1233
1234/* What a value decoder needs to know about one column or bind: its
1235 * datatype, character set form, and the data length (buffer size) the
1236 * describe gave it. */
1237typedef struct _tns_column_t {
1238 uint8_t type;
1239 uint8_t csform; /* character set form: 2 = national */
1240 uint32_t data_len;
1241} tns_column_t;
1242
1243/* Columns from the most recent describe (TTI_DCB), threaded to a later
1244 * TTI_RXD response so its row values can be split per column. */
1245typedef struct _tns_describe_t {
1246 uint32_t num_cols;
1247 tns_column_t *cols;
1248} tns_describe_t;
1249
1250/* The bind types of a cursor, from the execute that opened it. A later
1251 * execute of the same cursor may send its values with no descriptors. */
1252typedef struct _tns_binds_t {
1253 uint32_t count;
1254 uint32_t num_return; /* the last num_return are RETURNING ... INTO binds */
1255 tns_column_t *cols;
1256} tns_binds_t;
1257
1258/* The call a response answers: some response messages can only be read
1259 * knowing what was asked. */
1260typedef struct _tns_call_t {
1261 uint8_t func; /* OCI function id */
1262 uint32_t exec_flags; /* al8i4[9] of a TTI_ALL8 execute */
1263 uint32_t num_binds; /* bind types of an execute */
1264 uint32_t num_return; /* ... of which the last are RETURNING ... INTO binds */
1265 tns_column_t *binds;
1266 uint32_t lob_op; /* TTI_LOBOPS operation */
1267 uint32_t lob_locator_len; /* ... its source locator length */
1268 bool_Bool lob_amount; /* ... whether it sent an amount */
1269 uint8_t lob_flags[4]; /* ... its locator's flag bytes 1 to 4 */
1270 bool_Bool lob_flags_known;
1271} tns_call_t;
1272
1273typedef struct _tns_conv_info_t {
1274 uint32_t pending_connect_data;
1275 /* The most recent call the client made. */
1276 tns_call_t *last_call;
1277 /* The client speaks the OCI dialect: fixed-width little-endian
1278 * integers and 8-byte pointer indicators, where a thin client uses
1279 * variable-length integers and 1-byte pointer flags. */
1280 bool_Bool oci_dialect;
1281 /* ... and at the 12c band, whose status blocks are 144 bytes. */
1282 bool_Bool oci_band_12c;
1283 /* The TTC field version the client and server settled on, from the
1284 * client's TTI_DTY; 0 until seen. */
1285 uint8_t field_version;
1286 /* The TTC field version the server offered in its TTI_PRO reply,
1287 * which can be higher; 0 until seen. */
1288 uint8_t server_field_version;
1289 /* Native network encryption: the server picked an algorithm, and
1290 * the frame of the client's last negotiation packet, after which the
1291 * data packets are encrypted. */
1292 bool_Bool ano_encryption;
1293 uint32_t ano_active_after;
1294 tns_describe_t *last_describe;
1295 /* Bind types of an execute that opened a new cursor, waiting for the
1296 * status that names the cursor id. */
1297 tns_binds_t *pending_binds;
1298 /* Cursor id -> tns_binds_t. */
1299 wmem_map_t *cursor_binds;
1300} tns_conv_info_t;
1301
1302/* p_add_proto_data key for the describe a TTI_RXD response packet uses. */
1303#define TNS_PROTO_DATA_DESCRIBE1 1
1304/* p_add_proto_data key for the remembered binds of a re-execute. */
1305#define TNS_PROTO_DATA_BINDS2 2
1306/* p_add_proto_data key for the call a response packet answers. */
1307#define TNS_PROTO_DATA_CALL3 3
1308/* p_add_proto_data key for whether a packet is in the OCI dialect. */
1309#define TNS_PROTO_DATA_OCI4 4
1310/* p_add_proto_data key for the field version in force for a packet. */
1311#define TNS_PROTO_DATA_FV5 5
1312/* p_add_proto_data key for whether a packet is encrypted. */
1313#define TNS_PROTO_DATA_ENCRYPTED6 6
1314/* p_add_proto_data key for the field version the server offered. */
1315#define TNS_PROTO_DATA_SERVER_FV7 7
1316/* p_add_proto_data key for whether an OCI session is at the 12c band. */
1317#define TNS_PROTO_DATA_OCI_12C8 8
1318
1319/* The execute options that ask the server to do something: run the
1320 * statement, take a set of defines, or return rows. */
1321#define TNS_EXEC_OPTION_DEFINE0x0010 0x0010
1322#define TNS_EXEC_OPTION_EXECUTE0x0020 0x0020
1323#define TNS_EXEC_OPTION_FETCH0x0040 0x0040
1324
1325/* Execute flag asking for the rows each array DML iteration affected. */
1326#define TNS_EXEC_FLAGS_DML_ROWCOUNTS0x4000 0x4000
1327
1328void proto_reg_handoff_tns(void);
1329static int dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)));
1330
1331static tns_conv_info_t*
1332tns_get_conv_info(packet_info *pinfo)
1333{
1334 conversation_t *conversation = find_or_create_conversation(pinfo);
1335
1336 tns_conv_info_t *tns_info = (tns_conv_info_t *)conversation_get_proto_data(conversation, proto_tns);
1337 if (!tns_info) {
1338 tns_info = wmem_new0(wmem_file_scope(), tns_conv_info_t)((tns_conv_info_t*)wmem_alloc0((wmem_file_scope()), sizeof(tns_conv_info_t
)))
;
1339 tns_info->cursor_binds = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
1340 conversation_add_proto_data(conversation, proto_tns, tns_info);
1341 }
1342 return tns_info;
1343}
1344
1345/* The TTC field version negotiated on the packet's connection, or 0 when
1346 * the negotiation was not seen - which the decoders read as the 11g
1347 * shape. Stored per packet on the first pass. */
1348static unsigned tns_field_version(packet_info *pinfo)
1349{
1350 void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_FV5);
1351 if ( stored || PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
1352 return stored ? GPOINTER_TO_UINT(stored)((guint) (gulong) (stored)) - 1 : 0;
1353
1354 unsigned fv = tns_get_conv_info(pinfo)->field_version;
1355 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_FV5, GUINT_TO_POINTER(fv + 1)((gpointer) (gulong) (fv + 1)));
1356 return fv;
1357}
1358
1359/* The TTC field version the server offered on the packet's connection -
1360 * its own release, before the client lowered it - or 0 when the
1361 * negotiation was not seen. Stored per packet on the first pass. */
1362static unsigned tns_server_field_version(packet_info *pinfo)
1363{
1364 void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_SERVER_FV7);
1365 if ( stored || PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
1366 return stored ? GPOINTER_TO_UINT(stored)((guint) (gulong) (stored)) - 1 : 0;
1367
1368 unsigned fv = tns_get_conv_info(pinfo)->server_field_version;
1369 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_SERVER_FV7, GUINT_TO_POINTER(fv + 1)((gpointer) (gulong) (fv + 1)));
1370 return fv;
1371}
1372
1373/* Whether the connection is known to predate 11g (a 10g server): its
1374 * describe lacks the fields 11g added. */
1375static bool_Bool tns_before_11g(packet_info *pinfo)
1376{
1377 unsigned fv = tns_field_version(pinfo);
1378 return fv != 0 && fv < TNS_FV_11_26;
1379}
1380
1381/* Whether a data packet is encrypted by native network encryption.
1382 * Stored per packet on the first pass. */
1383static bool_Bool tns_is_encrypted(packet_info *pinfo)
1384{
1385 void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_ENCRYPTED6);
1386 if ( stored || PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
1387 return GPOINTER_TO_UINT(stored)((guint) (gulong) (stored)) == 2;
1388
1389 tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
1390 bool_Bool encrypted = tns_info->ano_active_after && pinfo->num > tns_info->ano_active_after;
1391 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_ENCRYPTED6, GUINT_TO_POINTER(encrypted ? 2 : 1)((gpointer) (gulong) (encrypted ? 2 : 1)));
1392 return encrypted;
1393}
1394
1395static unsigned get_data_func_id(tvbuff_t *tvb, int offset)
1396{
1397 /* Determine Data Function id */
1398 uint8_t first_byte;
1399
1400 first_byte =
1401 tvb_reported_length_remaining(tvb, offset) > 0 ? tvb_get_uint8(tvb, offset) : 0;
1402
1403 if ( tvb_bytes_exist(tvb, offset, 4) && first_byte == 0xDE &&
1404 tvb_get_uint24(tvb, offset+1, ENC_BIG_ENDIAN0x00000000) == 0xADBEEF )
1405 {
1406 return SQLNET_SNS0xdeadbeef;
1407 }
1408 else
1409 {
1410 return (unsigned)first_byte;
1411 }
1412}
1413
1414static int get_strtype_custom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1415{
1416 int ret = 1; // 1st byte contains 254 or length if smaller than 64
1417 int len = 0;
1418
1419 wmem_strbuf_t *strbuf = wmem_strbuf_new(pinfo->pool, "");
1420
1421 len = tvb_get_uint8(tvb, offset);
1422 if (len == 254) {
1423 int actual_len = 0;
1424 len = 0;
Value stored to 'len' is never read
1425 do { // walk over the chunks
1426 len = tvb_get_uint8(tvb, offset + ret);
1427 ret++; // 1st byte with the chunk size
1428 wmem_strbuf_append(strbuf, (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset + ret, len, ENC_ASCII0x00000000|ENC_NA0x00000000));
1429 ret += len; // length of the string's chunk
1430 actual_len += len;
1431 } while (len == 64);
1432 ret++; // has to be null-terminated
1433 len = actual_len;
1434 }
1435 else {
1436 ret += len;
1437 wmem_strbuf_append(strbuf, (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset + 1, len, ENC_ASCII0x00000000|ENC_NA0x00000000));
1438 }
1439
1440 proto_tree_add_uint(tree, hf_tns_data_opi_param_length, tvb, offset, 1, len);
1441 proto_tree_add_string(tree, hf_tns_data_opi_param_value, tvb, offset+1, ret-1, wmem_strbuf_get_str(strbuf));
1442
1443 return ret;
1444}
1445
1446/* Decode an Oracle variable-length integer (ub4 / sb4):
1447 * a length byte, then that many big-endian magnitude bytes. The low 7 bits
1448 * of the length byte are the magnitude width (0..4); the high bit flags a
1449 * negative value in sign-magnitude form (not two's complement) — so -1 is
1450 * 0x81 0x01 and NUMBER scale -127 is 0x81 0x7f.
1451 * Returns the number of bytes consumed. */
1452static int get_sb4_custom(tvbuff_t *tvb, int offset, int *result)
1453{
1454 uint8_t first_byte = tvb_get_uint8(tvb, offset); // Contains length of a value
1455 bool_Bool negative = (first_byte & 0x80) != 0;
1456 uint8_t width = first_byte & 0x7f;
1457 int magnitude = 0;
1458
1459 switch(width)
1460 {
1461 case 0:
1462 magnitude = 0;
1463 break;
1464 case 1:
1465 magnitude = tvb_get_uint8(tvb, offset+1);
1466 break;
1467 case 2:
1468 magnitude = tvb_get_ntohs(tvb, offset+1);
1469 break;
1470 case 3:
1471 magnitude = tvb_get_ntoh24(tvb, offset+1);
1472 break;
1473 case 4:
1474 magnitude = tvb_get_ntohl(tvb, offset+1);
1475 break;
1476 default:
1477 /* Width 5..0x7f is not a valid 1..4-byte integer. In practice
1478 * only a raw ub2 counter read through this helper reaches here;
1479 * the historic client behaviour is to consume two bytes and
1480 * return the negated second byte, which keeps the stream
1481 * aligned. The value is discarded by such callers. */
1482 if ( tvb_reported_length_remaining(tvb, offset) < 2 )
1483 {
1484 /* Not even that second byte is present. The width came
1485 * off the wire, so this is malformed input rather than
1486 * a bug in the dissector - step over the width alone. */
1487 *result = 0;
1488 return 1;
1489 }
1490 *result = -(int)tvb_get_uint8(tvb, offset+1);
1491 return 2;
1492 }
1493 *result = negative ? -magnitude : magnitude;
1494 return width + 1;
1495}
1496
1497/* Decode an Oracle variable-length ub8: a width byte (0..8), then that
1498 * many big-endian bytes. Returns the number of bytes consumed. */
1499static int get_ub8_custom(tvbuff_t *tvb, int offset, uint64_t *result)
1500{
1501 uint8_t width = tvb_get_uint8(tvb, offset);
1502 uint64_t value = 0;
1503
1504 if ( width > 8 )
1505 {
1506 /* Not a valid width; the value came off the wire, so step over
1507 * the width byte alone rather than claim bytes. */
1508 *result = 0;
1509 return 1;
1510 }
1511 for ( int i = 0; i < width; i++ )
1512 value = (value << 8) | tvb_get_uint8(tvb, offset + 1 + i);
1513 *result = value;
1514 return 1 + width;
1515}
1516
1517/* Walk the chunks of a chunked (0xFE) value, starting after the 0xFE:
1518 * (length, bytes) pairs until a zero length. A length is one byte up to
1519 * field version 12.1 and a variable-length ub4 from 12.2 on. The data is
1520 * appended to strbuf as UTF-8 when strbuf is not NULL. Returns the bytes
1521 * consumed, the terminating zero included. */
1522static int tns_chunks_len(tvbuff_t *tvb, packet_info *pinfo, int offset, wmem_strbuf_t *strbuf)
1523{
1524 bool_Bool ub4_lengths = tns_field_version(pinfo) >= TNS_FV_12_28;
1525 int o = offset;
1526
1527 while ( tvb_reported_length_remaining(tvb, o) > 0 )
1528 {
1529 int chunk_len;
1530 if ( ub4_lengths )
1531 o += get_sb4_custom(tvb, o, &chunk_len);
1532 else
1533 {
1534 chunk_len = tvb_get_uint8(tvb, o);
1535 o += 1;
1536 }
1537 if ( chunk_len <= 0 )
1538 break;
1539 if ( strbuf )
1540 wmem_strbuf_append(strbuf, (const char *)tvb_get_string_enc(pinfo->pool, tvb, o, chunk_len, ENC_UTF_80x00000002|ENC_NA0x00000000));
1541 o += chunk_len;
1542 }
1543 return o - offset;
1544}
1545
1546/* The data of a DALC value at offset, chunks joined, in pinfo->pool;
1547 * *len receives its length. NULL for an empty, NULL or absent value. */
1548static const uint8_t *tns_dalc_bytes(tvbuff_t *tvb, packet_info *pinfo, int offset, int *len)
1549{
1550 uint8_t first = tvb_get_uint8(tvb, offset);
1551 bool_Bool ub4_lengths = tns_field_version(pinfo) >= TNS_FV_12_28;
1552 wmem_array_t *out;
1553 int o;
1554
1555 *len = 0;
1556 if ( first == 0 || first >= TNS_DALC_ABSENT0xFD )
1557 {
1558 if ( first != 0xfe )
1559 return NULL((void*)0);
1560 }
1561 else
1562 {
1563 *len = first;
1564 return tvb_memdup(pinfo->pool, tvb, offset + 1, first);
1565 }
1566
1567 out = wmem_array_new(pinfo->pool, 1);
1568 o = offset + 1;
1569 while ( tvb_reported_length_remaining(tvb, o) > 0 )
1570 {
1571 int chunk_len;
1572 if ( ub4_lengths )
1573 o += get_sb4_custom(tvb, o, &chunk_len);
1574 else
1575 {
1576 chunk_len = tvb_get_uint8(tvb, o);
1577 o += 1;
1578 }
1579 if ( chunk_len <= 0 )
1580 break;
1581 wmem_array_append(out, tvb_get_ptr(tvb, o, chunk_len), chunk_len);
1582 o += chunk_len;
1583 }
1584 *len = (int)wmem_array_get_count(out);
1585 return (const uint8_t *)wmem_array_get_raw(out);
1586}
1587
1588/* Decode a DALC (Data-Length-And-Content) blob. The leading byte is a
1589 * length only in the middle of its range:
1590 *
1591 * 0x00 empty
1592 * 0x01..0xFC that many data bytes follow (252 is the longest)
1593 * 0xFD absent value: the two-byte placeholder FD 01, no data
1594 * 0xFE chunked: (len, bytes) pairs until a 0-length chunk
1595 * 0xFF null - a marker only, no data follows
1596 *
1597 * The top three bytes are markers, not lengths. The null marker consumes
1598 * just itself. The absent-value placeholder fills a bind slot that has no
1599 * inline value - a pure OUT bind, or a NULL of a type with no inline form
1600 * such as BOOLEAN - and consumes itself plus the 0x01 after it. Reading
1601 * either as a length would claim bytes that are not there and misalign
1602 * every field after it, so they have to be spelled out rather than left
1603 * to the default.
1604 *
1605 * The chunk lengths in the 0xFE form are single bytes up to field version
1606 * 12.1, and variable-length ub4s from 12.2 on.
1607 *
1608 * Returns the number of bytes consumed from the tvb and, when content
1609 * is non-empty, a UTF-8 string allocated from pinfo->pool. */
1610static int get_dalc_custom(tvbuff_t *tvb, packet_info *pinfo, int offset, const char **out_str)
1611{
1612 uint8_t first = tvb_get_uint8(tvb, offset);
1613 if ( first == 0 || first == 255 )
1614 {
1615 if ( out_str )
1616 *out_str = NULL((void*)0);
1617 return 1;
1618 }
1619 if ( first == TNS_DALC_ABSENT0xFD )
1620 {
1621 if ( out_str )
1622 *out_str = NULL((void*)0);
1623 return 2;
1624 }
1625 if ( first != 254 )
1626 {
1627 if ( out_str )
1628 *out_str = (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset + 1, first, ENC_UTF_80x00000002|ENC_NA0x00000000);
1629 return 1 + first;
1630 }
1631
1632 /* Chunked form: (len, bytes)+ until a zero-length chunk. */
1633 wmem_strbuf_t *strbuf = wmem_strbuf_new(pinfo->pool, "");
1634 int used = 1 + tns_chunks_len(tvb, pinfo, offset + 1, strbuf);
1635 if ( out_str )
1636 *out_str = wmem_strbuf_get_str(strbuf);
1637 return used;
1638}
1639
1640/* A server's message text carries a trailing newline; a client strips it
1641 * before showing the error. Returns a pinfo->pool string, or NULL. */
1642static const char *tns_trim_message(packet_info *pinfo, const char *msg)
1643{
1644 size_t len;
1645
1646 if ( !msg )
1647 return NULL((void*)0);
1648 len = strlen(msg);
1649 while ( len > 0 && (msg[len - 1] == '\n' || msg[len - 1] == '\r' || msg[len - 1] == ' ') )
1650 len--;
1651 return wmem_strndup(pinfo->pool, msg, len);
1652}
1653
1654/* Decode a bytes_with_length / str_with_length field: a ub4 count, and
1655 * a DALC carrying the value only when that count is non-zero. The count
1656 * is not simply a byte to step over - an empty field is the count
1657 * alone, so reading a DALC anyway consumes whatever follows it.
1658 * Returns bytes consumed; *out_str (when non-NULL) gets the string, or
1659 * NULL when the field is empty. */
1660static int get_field_with_length(tvbuff_t *tvb, packet_info *pinfo, int offset, const char **out_str)
1661{
1662 int count = 0;
1663 int used = get_sb4_custom(tvb, offset, &count);
1664 if ( out_str )
1665 *out_str = NULL((void*)0);
1666 if ( count > 0 )
1667 used += get_dalc_custom(tvb, pinfo, offset + used, out_str);
1668 return used;
1669}
1670
1671/* Render an Oracle NUMBER value as a decimal string.
1672 * Base-100 float: byte 0 is the biased exponent (top bit = sign, inverted
1673 * for negatives); the rest are base-100 mantissa groups, with a trailing
1674 * 0x66 terminator on negatives.
1675 * Returns a pinfo->pool string, or NULL if the value is not renderable. */
1676static const char *tns_format_number(packet_info *pinfo, const uint8_t *data, int len)
1677{
1678 if ( len <= 0 )
1679 return NULL((void*)0);
1680 if ( len == 1 )
1681 return (data[0] == 0x80) ? "0" : NULL((void*)0); /* 0x80 = zero; sentinels skipped */
1682
1683 uint8_t exp_byte = data[0];
1684 bool_Bool is_pos = (exp_byte & 0x80) != 0;
1685 int exponent = is_pos ? (exp_byte & 0x7f) - 65 : ((~exp_byte) & 0x7f) - 65;
1686
1687 int mant_len = len - 1;
1688 if ( !is_pos && mant_len > 0 && data[len - 1] == 0x66 )
1689 mant_len--; /* drop the negative terminator */
1690
1691 /* Build the base-100 digit string (two decimal digits per group). */
1692 wmem_strbuf_t *digits = wmem_strbuf_new(pinfo->pool, "");
1693 for ( int i = 0; i < mant_len; i++ )
1694 {
1695 int pair = is_pos ? (data[1 + i] - 1) : (101 - data[1 + i]);
1696 if ( pair < 0 || pair > 99 )
1697 return NULL((void*)0); /* malformed */
1698 wmem_strbuf_append_printf(digits, "%02d", pair);
1699 }
1700 const char *ds = wmem_strbuf_get_str(digits);
1701 int dlen = (int)wmem_strbuf_get_len(digits);
1702 int int_digits = (exponent + 1) * 2;
1703
1704 wmem_strbuf_t *ip = wmem_strbuf_new(pinfo->pool, "");
1705 wmem_strbuf_t *fp = wmem_strbuf_new(pinfo->pool, "");
1706 if ( int_digits >= dlen )
1707 {
1708 wmem_strbuf_append(ip, ds);
1709 for ( int i = 0; i < int_digits - dlen; i++ )
1710 wmem_strbuf_append_c(ip, '0');
1711 }
1712 else if ( int_digits <= 0 )
1713 {
1714 wmem_strbuf_append_c(ip, '0');
1715 for ( int i = 0; i < -int_digits; i++ )
1716 wmem_strbuf_append_c(fp, '0');
1717 wmem_strbuf_append(fp, ds);
1718 }
1719 else
1720 {
1721 wmem_strbuf_append(ip, wmem_strndup(pinfo->pool, ds, int_digits));
1722 wmem_strbuf_append(fp, ds + int_digits);
1723 }
1724
1725 /* Trim leading zeros on the integer part, trailing zeros on the fraction. */
1726 const char *ips = wmem_strbuf_get_str(ip);
1727 while ( ips[0] == '0' && ips[1] != '\0' )
1728 ips++;
1729 char *fps = wmem_strdup(pinfo->pool, wmem_strbuf_get_str(fp));
1730 int flen = (int)strlen(fps);
1731 while ( flen > 0 && fps[flen - 1] == '0' )
1732 fps[--flen] = '\0';
1733
1734 const char *sign = is_pos ? "" : "-";
1735 if ( flen > 0 )
1736 return wmem_strdup_printf(pinfo->pool, "%s%s.%s", sign, ips, fps);
1737 return wmem_strdup_printf(pinfo->pool, "%s%s", sign, ips);
1738}
1739
1740/* Render an Oracle DATE / TIMESTAMP value as an
1741 * ISO-ish string. 7 bytes: century+100, year+100, month, day, hour+1,
1742 * minute+1, second+1; 11 bytes add 4-byte big-endian nanoseconds.
1743 * Returns a pinfo->pool string, or NULL. */
1744static const char *tns_format_date(packet_info *pinfo, const uint8_t *data, int len)
1745{
1746 if ( len < 7 )
1747 return NULL((void*)0);
1748 int year = (data[0] - 100) * 100 + (data[1] - 100);
1749 int month = data[2], day = data[3];
1750 int hour = data[4] - 1, minute = data[5] - 1, second = data[6] - 1;
1751 if ( month < 1 || month > 12 || day < 1 || day > 31 ||
1752 hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59 )
1753 return NULL((void*)0);
1754 if ( len >= 11 )
1755 {
1756 uint32_t nsec = ((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) |
1757 ((uint32_t)data[9] << 8) | data[10];
1758 if ( nsec > 0 )
1759 return wmem_strdup_printf(pinfo->pool, "%04d-%02d-%02d %02d:%02d:%02d.%09u",
1760 year, month, day, hour, minute, second, nsec);
1761 }
1762 return wmem_strdup_printf(pinfo->pool, "%04d-%02d-%02d %02d:%02d:%02d",
1763 year, month, day, hour, minute, second);
1764}
1765
1766/* Days since 1970-01-01 of a proleptic Gregorian date, and back. */
1767static int64_t tns_days_from_civil(int64_t y, unsigned m, unsigned d)
1768{
1769 y -= m <= 2;
1770 int64_t era = (y >= 0 ? y : y - 399) / 400;
1771 unsigned yoe = (unsigned)(y - era * 400);
1772 unsigned doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
1773 unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
1774 return era * 146097 + (int64_t)doe - 719468;
1775}
1776
1777static void tns_civil_from_days(int64_t z, int64_t *y, unsigned *m, unsigned *d)
1778{
1779 z += 719468;
1780 int64_t era = (z >= 0 ? z : z - 146096) / 146097;
1781 unsigned doe = (unsigned)(z - era * 146097);
1782 unsigned yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
1783 unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
1784 unsigned mp = (5 * doy + 2) / 153;
1785 *d = doy - (153 * mp + 2) / 5 + 1;
1786 *m = mp < 10 ? mp + 3 : mp - 9;
1787 *y = (int64_t)yoe + era * 400 + (*m <= 2);
1788}
1789
1790/* Render an Oracle TIMESTAMP WITH TIME ZONE value: 13 bytes, the
1791 * 11-byte TIMESTAMP form holding the instant in UTC, then two zone
1792 * bytes. With the top bit of the first clear they are an offset, hour
1793 * + 20 and minute + 60, and the value is shown in local time with that
1794 * offset; with it set they hold a named zone's region id,
1795 * ((b0 & 0x7f) << 6) + (b1 >> 2), and the value is shown in UTC.
1796 * Returns a pinfo->pool string, or NULL. */
1797static const char *tns_format_timestamp_tz(packet_info *pinfo, const uint8_t *data, int len)
1798{
1799 const char *utc;
1800 uint32_t nsec;
1801 int64_t minutes, days, year;
1802 unsigned month, day;
1803 int tz_hour, tz_min, minute_of_day;
1804 char sign;
1805
1806 if ( len != 13 )
1807 return tns_format_date(pinfo, data, len);
1808 utc = tns_format_date(pinfo, data, 11);
1809 if ( !utc )
1810 return NULL((void*)0);
1811 if ( data[11] & 0x80 )
1812 return wmem_strdup_printf(pinfo->pool, "%s UTC (time zone region %u)", utc,
1813 ((unsigned)(data[11] & 0x7f) << 6) + (data[12] >> 2));
1814
1815 /* Shift the UTC wall clock by the offset, in whole minutes. */
1816 tz_hour = data[11] - 20;
1817 tz_min = data[12] - 60;
1818 days = tns_days_from_civil((data[0] - 100) * 100 + (data[1] - 100), data[2], data[3]);
1819 minutes = days * 1440 + (data[4] - 1) * 60 + (data[5] - 1) + tz_hour * 60 + tz_min;
1820 days = minutes >= 0 ? minutes / 1440 : -((-minutes + 1439) / 1440);
1821 minute_of_day = (int)(minutes - days * 1440);
1822 tns_civil_from_days(days, &year, &month, &day);
1823
1824 nsec = ((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) | ((uint32_t)data[9] << 8) | data[10];
1825 /* The sign goes on the whole offset: -03:30 is hour -3, minute -30. */
1826 sign = (tz_hour < 0 || tz_min < 0) ? '-' : '+';
1827 if ( nsec )
1828 return wmem_strdup_printf(pinfo->pool, "%04" PRId64"l" "d" "-%02u-%02u %02d:%02d:%02d.%09u %c%02d:%02d",
1829 year, month, day, minute_of_day / 60, minute_of_day % 60, data[6] - 1, nsec,
1830 sign, abs(tz_hour), abs(tz_min));
1831 return wmem_strdup_printf(pinfo->pool, "%04" PRId64"l" "d" "-%02u-%02u %02d:%02d:%02d %c%02d:%02d",
1832 year, month, day, minute_of_day / 60, minute_of_day % 60, data[6] - 1,
1833 sign, abs(tz_hour), abs(tz_min));
1834}
1835
1836/* Render an Oracle INTERVAL YEAR TO MONTH (5 bytes: years as a
1837 * big-endian ub4 biased by 2^31, months biased by 60) or INTERVAL DAY TO
1838 * SECOND (11 bytes: days as a ub4 biased by 2^31, hours, minutes and
1839 * seconds each biased by 60, nanoseconds as a ub4 biased by 2^31). All
1840 * fields carry the interval's sign. Rendered as Oracle writes an
1841 * interval literal: [-]Y-MM, or [-]D HH:MM:SS[.fffffffff].
1842 * Returns a pinfo->pool string, or NULL. */
1843static const char *tns_format_interval(packet_info *pinfo, uint8_t dtype, const uint8_t *data, int len)
1844{
1845 int32_t lead = (int32_t)((((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) |
1846 ((uint32_t)data[2] << 8) | data[3]) - 0x80000000u);
1847
1848 if ( dtype == TNS_DATATYPE_INTERVAL_YM182 && len == 5 )
1849 {
1850 int months = data[4] - 60;
1851 bool_Bool neg = lead < 0 || months < 0;
1852 return wmem_strdup_printf(pinfo->pool, "%s%d-%02d", neg ? "-" : "",
1853 abs(lead), abs(months));
1854 }
1855 if ( dtype == TNS_DATATYPE_INTERVAL_DS183 && len == 11 )
1856 {
1857 int hours = data[4] - 60, minutes = data[5] - 60, seconds = data[6] - 60;
1858 int32_t nsec = (int32_t)((((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) |
1859 ((uint32_t)data[9] << 8) | data[10]) - 0x80000000u);
1860 bool_Bool neg = lead < 0 || hours < 0 || minutes < 0 || seconds < 0 || nsec < 0;
1861 if ( nsec )
1862 return wmem_strdup_printf(pinfo->pool, "%s%d %02d:%02d:%02d.%09d", neg ? "-" : "",
1863 abs(lead), abs(hours), abs(minutes), abs(seconds), abs(nsec));
1864 return wmem_strdup_printf(pinfo->pool, "%s%d %02d:%02d:%02d", neg ? "-" : "",
1865 abs(lead), abs(hours), abs(minutes), abs(seconds));
1866 }
1867 return NULL((void*)0);
1868}
1869
1870/* Render an Oracle BINARY_FLOAT (4 bytes) / BINARY_DOUBLE (8 bytes) value
1871 * Stored in an order-preserving IEEE-754 form: if the
1872 * high bit is set the value was positive (clear it), else it was negative
1873 * (invert all bits); then read as big-endian IEEE-754. Returns a
1874 * pinfo->pool string, or NULL. */
1875static const char *tns_format_binary_float(packet_info *pinfo, const uint8_t *data, int len)
1876{
1877 char buf[G_ASCII_DTOSTR_BUF_SIZE(29 + 10)];
1878
1879 if ( len == 4 )
1880 {
1881 uint32_t u = ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) |
1882 ((uint32_t)data[2] << 8) | data[3];
1883 u = (u & 0x80000000u) ? (u & 0x7fffffffu) : ~u;
1884 float f;
1885 memcpy(&f, &u, 4);
1886 /* Locale-independent '.' decimal separator. */
1887 g_ascii_formatd(buf, sizeof(buf), "%g", (double)f);
1888 return wmem_strdup(pinfo->pool, buf);
1889 }
1890 if ( len == 8 )
1891 {
1892 uint64_t u = 0;
1893 for ( int i = 0; i < 8; i++ )
1894 u = (u << 8) | data[i];
1895 u = (u & UINT64_C(0x8000000000000000)0x8000000000000000UL) ? (u & UINT64_C(0x7fffffffffffffff)0x7fffffffffffffffUL) : ~u;
1896 double d;
1897 memcpy(&d, &u, 8);
1898 g_ascii_formatd(buf, sizeof(buf), "%g", d);
1899 return wmem_strdup(pinfo->pool, buf);
1900 }
1901 return NULL((void*)0);
1902}
1903
1904/* The base-64 alphabet of Oracle's printable rowids. */
1905static const char tns_rowid_alphabet[] =
1906 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1907
1908/* Append value to buf as `digits` base-64 characters, most significant
1909 * first. */
1910static void tns_rowid_append(wmem_strbuf_t *buf, uint32_t value, int digits)
1911{
1912 char chars[6];
1913
1914 for ( int i = digits - 1; i >= 0; i-- )
1915 {
1916 chars[i] = tns_rowid_alphabet[value & 0x3f];
1917 value >>= 6;
1918 }
1919 wmem_strbuf_append_len(buf, chars, digits);
1920}
1921
1922/* Render a physical rowid as the 18-character extended rowid ROWIDTOCHAR
1923 * prints: object, file, block and slot in 6, 3, 6 and 3 base-64 digits.
1924 * Returns a pinfo->pool string. */
1925static const char *tns_format_rowid(packet_info *pinfo, uint32_t rba, uint32_t part, uint32_t block, uint32_t slot)
1926{
1927 wmem_strbuf_t *buf = wmem_strbuf_new(pinfo->pool, "");
1928
1929 tns_rowid_append(buf, rba, 6);
1930 tns_rowid_append(buf, part, 3);
1931 tns_rowid_append(buf, block, 6);
1932 tns_rowid_append(buf, slot, 3);
1933 return wmem_strbuf_get_str(buf);
1934}
1935
1936/* Render a universal rowid. A leading type byte of 1 marks a physical
1937 * rowid, printed as above; anything else is a logical one - an
1938 * index-organized table's, carrying its primary key - printed as "*" and
1939 * the base-64 of the bytes after the type byte, unpadded. Returns a
1940 * pinfo->pool string, or NULL. */
1941static const char *tns_format_urowid(packet_info *pinfo, const uint8_t *data, int len)
1942{
1943 if ( len >= 13 && data[0] == 1 )
1944 return tns_format_rowid(pinfo,
1945 ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 8) | data[4],
1946 ((uint32_t)data[5] << 8) | data[6],
1947 ((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) | ((uint32_t)data[9] << 8) | data[10],
1948 ((uint32_t)data[11] << 8) | data[12]);
1949 if ( len < 2 )
1950 return NULL((void*)0);
1951
1952 wmem_strbuf_t *buf = wmem_strbuf_new(pinfo->pool, "*");
1953 for ( int i = 1; i < len; i += 3 )
1954 {
1955 int n = MIN(3, len - i)(((3) < (len - i)) ? (3) : (len - i));
1956 uint32_t group = (uint32_t)data[i] << 16;
1957 if ( n > 1 )
1958 group |= (uint32_t)data[i + 1] << 8;
1959 if ( n > 2 )
1960 group |= data[i + 2];
1961 /* n bytes give n + 1 characters */
1962 for ( int k = 0; k <= n; k++ )
1963 wmem_strbuf_append_c(buf, tns_rowid_alphabet[(group >> (18 - 6 * k)) & 0x3f]);
1964 }
1965 return wmem_strbuf_get_str(buf);
1966}
1967
1968/* Render a VECTOR image:
1969 * 0xDB | version (ub1) | flags (be16) | format (ub1) | elements (be32) |
1970 * [norm, 8 bytes, with flag 0x02 or 0x10] |
1971 * [sparse (flag 0x20): count (be16), count x be32 index] | values
1972 * FLOAT32 / FLOAT64 values use the order-preserving BINARY_FLOAT /
1973 * BINARY_DOUBLE encoding, INT8 plain bytes, BINARY bits packed eight to a
1974 * byte (the element count is then a bit count). The first few values are
1975 * shown. Returns a pinfo->pool string, or NULL. */
1976static const char *tns_format_vector(packet_info *pinfo, const uint8_t *data, int len)
1977{
1978 static const char *formats[] = { NULL((void*)0), NULL((void*)0), "FLOAT32", "FLOAT64", "INT8", "BINARY" };
1979 const int shown = 16;
1980 uint16_t flags;
1981 uint8_t format;
1982 uint32_t count, dims;
1983 int pos = 9, size;
1984 const uint8_t *indices = NULL((void*)0);
1985 wmem_strbuf_t *buf;
1986
1987 if ( len < 9 || data[0] != 0xdb )
1988 return NULL((void*)0);
1989 flags = (uint16_t)((data[2] << 8) | data[3]);
1990 format = data[4];
1991 dims = count = ((uint32_t)data[5] << 24) | ((uint32_t)data[6] << 16) | ((uint32_t)data[7] << 8) | data[8];
1992 if ( format < 2 || format > 5 )
1993 return NULL((void*)0);
1994 if ( flags & 0x0012 )
1995 pos += 8;
1996 if ( flags & 0x0020 )
1997 {
1998 if ( pos + 2 > len )
1999 return NULL((void*)0);
2000 count = (uint32_t)((data[pos] << 8) | data[pos + 1]);
2001 pos += 2;
2002 indices = data + pos;
2003 if ( (uint64_t)count * 4 > (uint64_t)(len - pos) )
2004 return NULL((void*)0);
2005 pos += count * 4;
2006 }
2007 else if ( format == 5 )
2008 count = (count + 7) / 8;
2009 size = format == 2 ? 4 : format == 3 ? 8 : 1;
2010 if ( (uint64_t)count * size > (uint64_t)(len - pos) )
2011 return NULL((void*)0);
2012
2013 buf = wmem_strbuf_new(pinfo->pool, "");
2014 if ( indices )
2015 wmem_strbuf_append_printf(buf, "sparse %s of %u dimensions: {", formats[format], dims);
2016 else
2017 wmem_strbuf_append_printf(buf, "%s[%u]: [", formats[format], dims);
2018 for ( uint32_t i = 0; i < count && i < (uint32_t)shown; i++ )
2019 {
2020 const uint8_t *e = data + pos + i * size;
2021 if ( i )
2022 wmem_strbuf_append(buf, ", ");
2023 if ( indices )
2024 wmem_strbuf_append_printf(buf, "%u: ", ((uint32_t)indices[4 * i] << 24)
2025 | ((uint32_t)indices[4 * i + 1] << 16) | ((uint32_t)indices[4 * i + 2] << 8) | indices[4 * i + 3]);
2026 if ( size > 1 )
2027 wmem_strbuf_append(buf, tns_format_binary_float(pinfo, e, size));
2028 else if ( format == 4 )
2029 wmem_strbuf_append_printf(buf, "%d", (int8_t)e[0]);
2030 else
2031 wmem_strbuf_append_printf(buf, "%u", e[0]);
2032 }
2033 if ( count > (uint32_t)shown )
2034 wmem_strbuf_append(buf, ", ...");
2035 wmem_strbuf_append_c(buf, indices ? '}' : ']');
2036 return wmem_strbuf_get_str(buf);
2037}
2038
2039#define TNS_OSON_MAX_DEPTH32 32
2040#define TNS_OSON_MAX_NODES4096 4096
2041#define TNS_OSON_MAX_TEXT2048 2048
2042
2043/* A reader over an OSON image; every access is bounds checked, and a
2044 * failed one marks the reader bad instead of throwing. */
2045typedef struct _tns_oson_t {
2046 const uint8_t *data;
2047 uint32_t len;
2048 bool_Bool bad;
2049 uint32_t tree; /* start of the tree segment */
2050 uint8_t field_id_len; /* 1, 2 or 4 */
2051 bool_Bool relative; /* container children count from the container */
2052 uint32_t num_names;
2053 const uint8_t **names;
2054 uint32_t *name_lens;
2055} tns_oson_t;
2056
2057typedef struct _tns_oson_frame_t {
2058 bool_Bool is_object;
2059 uint8_t node_type;
2060 uint32_t count, next;
2061 uint32_t ids_pos, offsets_pos, container;
2062} tns_oson_frame_t;
2063
2064static uint32_t tns_oson_uint(tns_oson_t *o, uint32_t pos, int width)
2065{
2066 uint32_t v = 0;
2067
2068 if ( o->bad || pos > o->len || (uint32_t)width > o->len - pos )
2069 {
2070 o->bad = true1;
2071 return 0;
2072 }
2073 for ( int i = 0; i < width; i++ )
2074 v = (v << 8) | o->data[pos + i];
2075 return v;
2076}
2077
2078/* Read the field names of one segment: a hash array (hash_size bytes a
2079 * name), an offsets array, then the names, each behind a length of
2080 * len_size bytes. */
2081static uint32_t tns_oson_names(tns_oson_t *o, uint32_t pos, uint32_t first, uint32_t num,
2082 int hash_size, int off_size, uint32_t seg_size, int len_size)
2083{
2084 uint32_t offsets = pos + num * hash_size;
2085 uint32_t seg = offsets + num * off_size;
2086
2087 for ( uint32_t i = 0; i < num && !o->bad; i++ )
2088 {
2089 uint32_t at = tns_oson_uint(o, offsets + i * off_size, off_size);
2090 uint32_t n = tns_oson_uint(o, seg + at, len_size);
2091 if ( at + len_size + n > seg_size || seg + at + len_size + n > o->len )
2092 o->bad = true1;
2093 else
2094 {
2095 o->names[first + i] = o->data + seg + at + len_size;
2096 o->name_lens[first + i] = n;
2097 }
2098 }
2099 return seg + seg_size;
2100}
2101
2102static void tns_oson_append_string(wmem_strbuf_t *buf, const uint8_t *s, uint32_t len)
2103{
2104 wmem_strbuf_append_c(buf, '"');
2105 for ( uint32_t i = 0; i < len; i++ )
2106 {
2107 if ( s[i] == '"' || s[i] == '\\' )
2108 wmem_strbuf_append_printf(buf, "\\%c", s[i]);
2109 else if ( s[i] < 0x20 )
2110 wmem_strbuf_append_printf(buf, "\\u%04x", s[i]);
2111 else
2112 wmem_strbuf_append_c(buf, s[i]);
2113 }
2114 wmem_strbuf_append_c(buf, '"');
2115}
2116
2117/* How an OSON scalar's payload is rendered. */
2118typedef enum {
2119 TNS_OSON_STRING,
2120 TNS_OSON_NUMBER,
2121 TNS_OSON_DATETIME,
2122 TNS_OSON_FLOAT,
2123 TNS_OSON_INTERVAL,
2124 TNS_OSON_BYTES
2125} tns_oson_kind_t;
2126
2127/* Render the scalar node at pos; returns false on a malformed or unknown
2128 * node. The tag selects the type and says where its length is: in a byte,
2129 * a be16 or a be32 after the tag, fixed by the type, or in the tag's low
2130 * bits. */
2131static bool_Bool tns_oson_scalar(packet_info *pinfo, tns_oson_t *o, uint32_t pos, wmem_strbuf_t *buf)
2132{
2133 uint8_t t = (uint8_t)tns_oson_uint(o, pos, 1);
2134 uint32_t n = 0, at = pos + 1;
2135 tns_oson_kind_t kind;
2136 const char *text = NULL((void*)0);
2137
2138 if ( o->bad )
2139 return false0;
2140 switch ( t )
2141 {
2142 case 0x30: wmem_strbuf_append(buf, "null"); return true1;
2143 case 0x31: wmem_strbuf_append(buf, "true"); return true1;
2144 case 0x32: wmem_strbuf_append(buf, "false"); return true1;
2145 case 0x33: kind = TNS_OSON_STRING; n = tns_oson_uint(o, at, 1); at += 1; break;
2146 case 0x37: kind = TNS_OSON_STRING; n = tns_oson_uint(o, at, 2); at += 2; break;
2147 case 0x38: kind = TNS_OSON_STRING; n = tns_oson_uint(o, at, 4); at += 4; break;
2148 case 0x34: kind = TNS_OSON_NUMBER; n = tns_oson_uint(o, at, 1); at += 1; break;
2149 case 0x3c: case 0x7d: kind = TNS_OSON_DATETIME; n = 7; break;
2150 case 0x39: kind = TNS_OSON_DATETIME; n = 11; break;
2151 case 0x7c: kind = TNS_OSON_DATETIME; n = 13; break;
2152 case 0x7f: kind = TNS_OSON_FLOAT; n = 4; break;
2153 case 0x36: kind = TNS_OSON_FLOAT; n = 8; break;
2154 case 0x3d: kind = TNS_OSON_INTERVAL; n = 5; break;
2155 case 0x3e: kind = TNS_OSON_INTERVAL; n = 11; break;
2156 case 0x7e: kind = TNS_OSON_BYTES; n = tns_oson_uint(o, at, 1); at += 1; break;
2157 case 0x3a: kind = TNS_OSON_BYTES; n = tns_oson_uint(o, at, 2); at += 2; break;
2158 case 0x3b: kind = TNS_OSON_BYTES; n = tns_oson_uint(o, at, 4); at += 4; break;
2159 case 0x7b:
2160 /* extended type: a vector, with a be32 image length */
2161 if ( tns_oson_uint(o, at, 1) != 0x01 )
2162 return false0;
2163 n = tns_oson_uint(o, at + 1, 4);
2164 at += 5;
2165 if ( o->bad || n > o->len - at )
2166 return false0;
2167 text = tns_format_vector(pinfo, o->data + at, n);
2168 if ( !text )
2169 return false0;
2170 tns_oson_append_string(buf, (const uint8_t *)text, (uint32_t)strlen(text));
2171 return true1;
2172 default:
2173 if ( (t & 0xf0) == 0x20 || (t & 0xf0) == 0x60 )
2174 {
2175 kind = TNS_OSON_NUMBER;
2176 n = (t & 0x0f) + 1u;
2177 }
2178 else if ( (t & 0xf0) == 0x40 || (t & 0xf0) == 0x50 )
2179 {
2180 kind = TNS_OSON_NUMBER;
2181 n = t & 0x0f;
2182 }
2183 else if ( (t & 0xe0) == 0 )
2184 {
2185 kind = TNS_OSON_STRING;
2186 n = t;
2187 }
2188 else
2189 return false0;
2190 break;
2191 }
2192 if ( o->bad || n > o->len - at )
2193 return false0;
2194
2195 switch ( kind )
2196 {
2197 case TNS_OSON_STRING:
2198 tns_oson_append_string(buf, o->data + at, n);
2199 return true1;
2200 case TNS_OSON_BYTES:
2201 wmem_strbuf_append_c(buf, '"');
2202 for ( uint32_t i = 0; i < n; i++ )
2203 wmem_strbuf_append_printf(buf, "%02x", o->data[at + i]);
2204 wmem_strbuf_append_c(buf, '"');
2205 return true1;
2206 case TNS_OSON_NUMBER:
2207 text = n ? tns_format_number(pinfo, o->data + at, (int)n) : "0";
2208 break;
2209 case TNS_OSON_FLOAT:
2210 text = tns_format_binary_float(pinfo, o->data + at, (int)n);
2211 break;
2212 case TNS_OSON_DATETIME:
2213 text = t == 0x7c ? tns_format_timestamp_tz(pinfo, o->data + at, (int)n)
2214 : tns_format_date(pinfo, o->data + at, (int)n);
2215 break;
2216 case TNS_OSON_INTERVAL:
2217 text = tns_format_interval(pinfo, t == 0x3d ? TNS_DATATYPE_INTERVAL_YM182 : TNS_DATATYPE_INTERVAL_DS183,
2218 o->data + at, (int)n);
2219 break;
2220 }
2221 if ( !text )
2222 return false0;
2223 /* numbers stand bare; dates and intervals are strings in JSON */
2224 if ( kind == TNS_OSON_NUMBER || kind == TNS_OSON_FLOAT )
2225 wmem_strbuf_append(buf, text);
2226 else
2227 tns_oson_append_string(buf, (const uint8_t *)text, (uint32_t)strlen(text));
2228 return true1;
2229}
2230
2231/* Open the container node at pos into frame f. A container's tag says
2232 * whether it is an object or an array (0x40), how wide its child count is
2233 * (bits 0x18: one, two or four bytes), and how wide its offsets are
2234 * (0x20). With both count bits set, an object shares another object's
2235 * field ids: the donor's offset - absolute even in relative mode - takes
2236 * the count's place, and the donor supplies the count and ids. */
2237static bool_Bool tns_oson_open(tns_oson_t *o, uint32_t pos, tns_oson_frame_t *f)
2238{
2239 uint8_t t = (uint8_t)tns_oson_uint(o, pos, 1);
2240 int off_size = (t & 0x20) ? 4 : 2;
2241 uint32_t at = pos + 1;
2242
2243 f->node_type = t;
2244 f->is_object = (t & 0x40) == 0;
2245 f->next = 0;
2246 f->container = pos - o->tree;
2247 switch ( t & 0x18 )
2248 {
2249 case 0x00: f->count = tns_oson_uint(o, at, 1); at += 1; break;
2250 case 0x08: f->count = tns_oson_uint(o, at, 2); at += 2; break;
2251 case 0x10: f->count = tns_oson_uint(o, at, 4); at += 4; break;
2252 default:
2253 {
2254 uint32_t donor = o->tree + tns_oson_uint(o, at, off_size);
2255 uint8_t dt = (uint8_t)tns_oson_uint(o, donor, 1);
2256 at += off_size;
2257 f->offsets_pos = at;
2258 switch ( dt & 0x18 )
2259 {
2260 case 0x00: f->count = tns_oson_uint(o, donor + 1, 1); f->ids_pos = donor + 2; break;
2261 case 0x08: f->count = tns_oson_uint(o, donor + 1, 2); f->ids_pos = donor + 3; break;
2262 case 0x10: f->count = tns_oson_uint(o, donor + 1, 4); f->ids_pos = donor + 5; break;
2263 default: return false0;
2264 }
2265 return !o->bad;
2266 }
2267 }
2268 if ( f->is_object )
2269 {
2270 f->ids_pos = at;
2271 f->offsets_pos = at + o->field_id_len * f->count;
2272 }
2273 else
2274 f->offsets_pos = at;
2275 return !o->bad;
2276}
2277
2278/* Render an OSON image as JSON text, or NULL when it is not one this
2279 * decoder understands. Containers are walked with an explicit stack, not
2280 * recursion, and the depth, the nodes visited and the text are bounded:
2281 * the offsets come off the wire and may point anywhere. */
2282static const char *tns_format_oson(packet_info *pinfo, const uint8_t *data, int len)
2283{
2284 tns_oson_t o = { data, (uint32_t)len, false0, 0, 1, false0, 0, NULL((void*)0), NULL((void*)0) };
2285 tns_oson_frame_t stack[TNS_OSON_MAX_DEPTH32];
2286 int depth = 0, nodes = 0;
2287 wmem_strbuf_t *buf;
2288 uint32_t pos, num_short, short_seg, num_long = 0, long_seg = 0;
2289 int short_off = 2, long_off = 4;
2290 uint16_t flags;
2291 uint8_t version;
2292
2293 if ( len < 6 || data[0] != 0xff || data[1] != 0x4a || data[2] != 0x5a )
2294 return NULL((void*)0);
2295 version = data[3];
2296 if ( version != 1 && version != 3 )
2297 return NULL((void*)0);
2298 flags = (uint16_t)tns_oson_uint(&o, 4, 2);
2299 o.relative = (flags & 0x01) != 0;
2300 pos = 6;
2301 buf = wmem_strbuf_new(pinfo->pool, "");
2302
2303 if ( flags & 0x10 )
2304 {
2305 /* a scalar document: the tree segment size, then the value */
2306 pos += (flags & 0x1000) ? 4 : 2;
2307 return tns_oson_scalar(pinfo, &o, pos, buf) ? wmem_strbuf_get_str(buf) : NULL((void*)0);
2308 }
2309
2310 if ( flags & 0x08 )
2311 {
2312 num_short = tns_oson_uint(&o, pos, 4);
2313 pos += 4;
2314 o.field_id_len = 4;
2315 }
2316 else if ( flags & 0x0400 )
2317 {
2318 num_short = tns_oson_uint(&o, pos, 2);
2319 pos += 2;
2320 o.field_id_len = 2;
2321 }
2322 else
2323 {
2324 num_short = tns_oson_uint(&o, pos, 1);
2325 pos += 1;
2326 }
2327 if ( flags & 0x0800 )
2328 {
2329 short_off = 4;
2330 short_seg = tns_oson_uint(&o, pos, 4);
2331 pos += 4;
2332 }
2333 else
2334 {
2335 short_seg = tns_oson_uint(&o, pos, 2);
2336 pos += 2;
2337 }
2338 /* version 3 adds a segment of field names over 255 bytes */
2339 if ( version == 3 )
2340 {
2341 if ( tns_oson_uint(&o, pos, 2) & 0x0100 )
2342 long_off = 2;
2343 num_long = tns_oson_uint(&o, pos + 2, 4);
2344 long_seg = tns_oson_uint(&o, pos + 6, 4);
2345 pos += 10;
2346 }
2347 pos += (flags & 0x1000) ? 4 : 2; /* tree segment size */
2348 pos += 2; /* number of tiny nodes */
2349 if ( o.bad || num_short > o.len || num_long > o.len )
2350 return NULL((void*)0);
2351
2352 o.num_names = num_short + num_long;
2353 o.names = wmem_alloc0_array(pinfo->pool, const uint8_t *, o.num_names + 1)((const uint8_t **)wmem_alloc0((pinfo->pool), (((((o.num_names
+ 1)) <= 0) || ((size_t)sizeof(const uint8_t *) > (9223372036854775807L
/ (size_t)((o.num_names + 1))))) ? 0 : (sizeof(const uint8_t
*) * ((o.num_names + 1))))))
;
2354 o.name_lens = wmem_alloc0_array(pinfo->pool, uint32_t, o.num_names + 1)((uint32_t*)wmem_alloc0((pinfo->pool), (((((o.num_names + 1
)) <= 0) || ((size_t)sizeof(uint32_t) > (9223372036854775807L
/ (size_t)((o.num_names + 1))))) ? 0 : (sizeof(uint32_t) * (
(o.num_names + 1))))))
;
2355 if ( num_short )
2356 pos = tns_oson_names(&o, pos, 0, num_short, 1, short_off, short_seg, 1);
2357 if ( num_long )
2358 pos = tns_oson_names(&o, pos, num_short, num_long, 2, long_off, long_seg, 2);
2359 if ( o.bad )
2360 return NULL((void*)0);
2361 o.tree = pos;
2362
2363 /* the root node */
2364 if ( !(tns_oson_uint(&o, pos, 1) & 0x80) )
2365 return tns_oson_scalar(pinfo, &o, pos, buf) ? wmem_strbuf_get_str(buf) : NULL((void*)0);
2366 if ( !tns_oson_open(&o, pos, &stack[0]) )
2367 return NULL((void*)0);
2368 wmem_strbuf_append_c(buf, stack[0].is_object ? '{' : '[');
2369 depth = 1;
2370
2371 while ( depth > 0 )
2372 {
2373 tns_oson_frame_t *f = &stack[depth - 1];
2374 uint32_t child, off;
2375
2376 if ( f->next == f->count )
2377 {
2378 wmem_strbuf_append_c(buf, f->is_object ? '}' : ']');
2379 depth--;
2380 continue;
2381 }
2382 if ( ++nodes > TNS_OSON_MAX_NODES4096 || wmem_strbuf_get_len(buf) > TNS_OSON_MAX_TEXT2048 )
2383 {
2384 wmem_strbuf_append(buf, "...");
2385 return wmem_strbuf_get_str(buf);
2386 }
2387 if ( f->next > 0 )
2388 wmem_strbuf_append(buf, ", ");
2389 if ( f->is_object )
2390 {
2391 uint32_t id = tns_oson_uint(&o, f->ids_pos + f->next * o.field_id_len, o.field_id_len);
2392 if ( o.bad || id == 0 || id > o.num_names )
2393 return NULL((void*)0);
2394 tns_oson_append_string(buf, o.names[id - 1], o.name_lens[id - 1]);
2395 wmem_strbuf_append(buf, ": ");
2396 }
2397 off = tns_oson_uint(&o, f->offsets_pos + f->next * ((f->node_type & 0x20) ? 4 : 2),
2398 (f->node_type & 0x20) ? 4 : 2);
2399 if ( o.relative )
2400 off += f->container;
2401 child = o.tree + off;
2402 f->next++;
2403 if ( o.bad )
2404 return NULL((void*)0);
2405
2406 if ( tns_oson_uint(&o, child, 1) & 0x80 )
2407 {
2408 if ( depth == TNS_OSON_MAX_DEPTH32 || !tns_oson_open(&o, child, &stack[depth]) )
2409 return NULL((void*)0);
2410 wmem_strbuf_append_c(buf, stack[depth].is_object ? '{' : '[');
2411 depth++;
2412 }
2413 else if ( !tns_oson_scalar(pinfo, &o, child, buf) )
2414 return NULL((void*)0);
2415 }
2416 return wmem_strbuf_get_str(buf);
2417}
2418
2419static void vsnum_to_vstext_basecustom(char *result, uint32_t vsnum)
2420{
2421 /*
2422 * Translate hex value to human readable version value, described at
2423 * http://docs.oracle.com/cd/B28359_01/server.111/b28310/dba004.htm
2424 */
2425 snprintf(result, ITEM_LABEL_LENGTH240, "%d.%d.%d.%d.%d",
2426 vsnum >> 24,
2427 (vsnum >> 20) & 0xf,
2428 (vsnum >> 12) & 0xf,
2429 (vsnum >> 8) & 0xf,
2430 vsnum & 0xff);
2431}
2432
2433/* The warning-flags byte of an error block: a PL/SQL object was created
2434 * with compilation errors, though the call itself succeeded. */
2435#define TNS_WARN_COMPILATION_ERROR0x20 0x20
2436
2437/* End-of-call status flags, carried by both TTI_OER and TTI_STA. */
2438#define TNS_CALL_STATUS_TXN_IN_PROGRESS0x00000002 0x00000002
2439#define TNS_CALL_STATUS_SESS_RELEASE0x00008000 0x00008000
2440
2441/* Show the warning flags of an error block, and say so when the
2442 * compilation-warning bit is set. */
2443static void tns_add_warn_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
2444{
2445 proto_item *ti = proto_tree_add_item(tree, hf_tns_data_oer_warn_flags, tvb, offset, 1, ENC_NA0x00000000);
2446 proto_tree *wt = proto_item_add_subtree(ti, ett_tns_warn_flags);
2447
2448 proto_tree_add_item(wt, hf_tns_data_oer_warn_compile, tvb, offset, 1, ENC_NA0x00000000);
2449 if ( tvb_get_uint8(tvb, offset) & TNS_WARN_COMPILATION_ERROR0x20 )
2450 {
2451 expert_add_info(pinfo, ti, &ei_tns_data_compilation_error);
2452 col_append_str(pinfo->cinfo, COL_INFO, " [created with compilation errors]");
2453 }
2454}
2455
2456/* Break out the flag bits of a call status item. A client reads the
2457 * transaction bit to decide whether closing or releasing the connection
2458 * owes a rollback. */
2459static void tns_add_call_status_flags(proto_item *ti, tvbuff_t *tvb, int start, int len, uint32_t status)
2460{
2461 proto_tree *st = proto_item_add_subtree(ti, ett_tns_call_status);
2462 proto_tree_add_boolean(st, hf_tns_data_call_status_txn, tvb, start, len, status);
2463 proto_tree_add_boolean(st, hf_tns_data_call_status_sess_release, tvb, start, len, status);
2464}
2465
2466/* Decode an OAC (Oracle Access Column) descriptor — the type/format core
2467 * shared by describe columns and bind descriptors. Fields
2468 * use the Oracle variable-length form (get_sb4_custom). From field version
2469 * 12.2 the scale is a single signed byte, where 11g sends a variable-length
2470 * sb4 (NUMBER's default -127 as 0x81 0x7f), and a ub4 oaccolid follows the
2471 * max size.
2472 * When col is not NULL it receives the type and data length.
2473 * Returns the new offset. */
2474static int dissect_tns_oac(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, tns_column_t *col)
2475{
2476 int v = 0, start;
2477 uint64_t u = 0;
2478 bool_Bool fv_12_2 = tns_field_version(pinfo) >= TNS_FV_12_28;
2479
2480 if ( col )
2481 col->type = tvb_get_uint8(tvb, offset);
2482 /* type (ub1) */
2483 proto_tree_add_item(tree, hf_tns_data_col_type, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2484 offset += 1;
2485 /* flag (ub1, skip) */
2486 offset += 1;
2487 /* precision (sb1) */
2488 proto_tree_add_item(tree, hf_tns_data_col_precision, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2489 offset += 1;
2490 /* scale (may be negative — NUMBER default is -127) */
2491 start = offset;
2492 if ( fv_12_2 )
2493 {
2494 v = (int8_t)tvb_get_uint8(tvb, offset);
2495 offset += 1;
2496 }
2497 else
2498 offset += get_sb4_custom(tvb, offset, &v);
2499 proto_tree_add_int(tree, hf_tns_data_col_scale, tvb, start, offset - start, v);
2500 /* max data length / buffer size (ub4) */
2501 start = offset;
2502 offset += get_sb4_custom(tvb, offset, &v);
2503 proto_tree_add_uint(tree, hf_tns_data_col_max_length, tvb, start, offset - start, v);
2504 if ( col )
2505 col->data_len = (uint32_t)v;
2506 /* max array elements (ub4, skip) */
2507 offset += get_sb4_custom(tvb, offset, &v);
2508 /* cont flags (ub8, skip) */
2509 offset += get_ub8_custom(tvb, offset, &u);
2510 /* type OID (bytes_with_length, skip) */
2511 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
2512 /* version (ub4, skip) */
2513 offset += get_sb4_custom(tvb, offset, &v);
2514 /* charset id (ub4) */
2515 start = offset;
2516 offset += get_sb4_custom(tvb, offset, &v);
2517 proto_tree_add_uint(tree, hf_tns_data_col_charset, tvb, start, offset - start, v);
2518 /* charset form (ub1) */
2519 proto_tree_add_item(tree, hf_tns_data_col_csform, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2520 if ( col )
2521 col->csform = tvb_get_uint8(tvb, offset);
2522 offset += 1;
2523 /* max size (ub4) */
2524 start = offset;
2525 offset += get_sb4_custom(tvb, offset, &v);
2526 proto_tree_add_uint(tree, hf_tns_data_col_max_size, tvb, start, offset - start, v);
2527 /* oaccolid (ub4, skip) */
2528 if ( fv_12_2 )
2529 offset += get_sb4_custom(tvb, offset, &v);
2530
2531 return offset;
2532}
2533
2534/* Decode one per-column metadata block of a TTI_DCB describe (11g
2535 * shape): an OAC descriptor plus the nullability and naming fields.
2536 * When col is not NULL it receives what a row decoder needs.
2537 * Returns the new offset. */
2538static int dissect_tns_dcb_column(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int idx, tns_column_t *col)
2539{
2540 unsigned fv = tns_field_version(pinfo);
2541 int start;
2542 proto_tree *col_tree;
2543 proto_item *col_item;
2544 int col_start = offset, v = 0;
2545 uint8_t col_type = tvb_get_uint8(tvb, offset);
2546 const char *name = NULL((void*)0);
2547
2548 col_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
2549 ett_tns_dcb_col, &col_item, "Column %d", idx);
2550
2551 offset = dissect_tns_oac(tvb, pinfo, col_tree, offset, col);
2552
2553 /* nulls allowed (ub1) */
2554 proto_tree_add_item(col_tree, hf_tns_data_col_nulls_ok, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2555 offset += 1;
2556 /* v7 name length (ub1, skip) */
2557 offset += 1;
2558 /* column name (str_with_length) */
2559 int name_start = offset;
2560 offset += get_field_with_length(tvb, pinfo, offset, &name);
2561 if ( name )
2562 proto_tree_add_string(col_tree, hf_tns_data_col_name, tvb, name_start, offset - name_start, name);
2563 /* schema name, type name (str_with_length, skip) */
2564 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
2565 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
2566 /* column position (ub4, skip) */
2567 offset += get_sb4_custom(tvb, offset, &v);
2568 /* uds flags (ub4) — an 11g addition; it marks a JSON column */
2569 if ( !tns_before_11g(pinfo) )
2570 {
2571 start = offset;
2572 offset += get_sb4_custom(tvb, offset, &v);
2573 proto_tree_add_uint(col_tree, hf_tns_data_col_uds_flags, tvb, start, offset - start, v);
2574 }
2575 /* 23ai: the column's SQL domain, its annotations, and a vector
2576 * column's dimensions and format */
2577 if ( fv >= TNS_FV_23_117 )
2578 {
2579 const char *str = NULL((void*)0);
2580 start = offset;
2581 offset += get_field_with_length(tvb, pinfo, offset, &str);
2582 if ( str )
2583 proto_tree_add_string(col_tree, hf_tns_data_col_domain_schema, tvb, start, offset - start, str);
2584 start = offset;
2585 offset += get_field_with_length(tvb, pinfo, offset, &str);
2586 if ( str )
2587 proto_tree_add_string(col_tree, hf_tns_data_col_domain_name, tvb, start, offset - start, str);
2588 }
2589 if ( fv >= TNS_FV_23_1_EXT_320 )
2590 {
2591 int num = 0;
2592 offset += get_sb4_custom(tvb, offset, &num);
2593 if ( num > 0 )
2594 {
2595 offset += 1;
2596 offset += get_sb4_custom(tvb, offset, &num);
2597 offset += 1;
2598 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
2599 {
2600 const char *key = NULL((void*)0), *value = NULL((void*)0);
2601 start = offset;
2602 offset += get_field_with_length(tvb, pinfo, offset, &key);
2603 offset += get_field_with_length(tvb, pinfo, offset, &value);
2604 proto_tree_add_string_format_value(col_tree, hf_tns_data_col_annotation, tvb,
2605 start, offset - start, key ? key : "", "%s = %s",
2606 key ? key : "", value ? value : "");
2607 offset += get_sb4_custom(tvb, offset, &v); /* flags */
2608 }
2609 offset += get_sb4_custom(tvb, offset, &v); /* flags */
2610 }
2611 }
2612 if ( fv >= TNS_FV_23_424 )
2613 {
2614 start = offset;
2615 offset += get_sb4_custom(tvb, offset, &v);
2616 proto_tree_add_uint(col_tree, hf_tns_data_col_vector_dims, tvb, start, offset - start, v);
2617 proto_tree_add_item(col_tree, hf_tns_data_col_vector_format, tvb, offset, 1, ENC_NA0x00000000);
2618 offset += 1;
2619 offset += 1; /* vector flags */
2620 }
2621
2622 if ( name )
2623 proto_item_append_text(col_item, ": %s (%s)", name,
2624 val_to_str_const(col_type, tns_data_types, "unknown"));
2625 proto_item_set_len(col_item, offset - col_start);
2626 return offset;
2627}
2628
2629/* Decode a describe body - the column metadata of a result set - as a
2630 * TTI_DCB carries it after its preamble: a ub4 max row size, a ub4 column
2631 * count, a reserved byte when there are columns, the columns, and a
2632 * trailer. When out is not NULL it receives the columns, allocated in
2633 * file scope. Returns the new offset. */
2634static int dissect_tns_describe_body(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, tns_describe_t **out)
2635{
2636 int v = 0, num_cols = 0, nc_start;
2637 tns_column_t *cols = NULL((void*)0);
2638
2639 /* max row size (ub4, skip) */
2640 offset += get_sb4_custom(tvb, offset, &v);
2641 /* number of columns */
2642 nc_start = offset;
2643 offset += get_sb4_custom(tvb, offset, &num_cols);
2644 proto_tree_add_uint(tree, hf_tns_data_dcb_num_columns, tvb, nc_start, offset - nc_start, num_cols);
2645 /* The count comes off the wire and sizes the allocation below, so a
2646 * count larger than the data left cannot be real - report it and
2647 * decode no columns. */
2648 if ( num_cols < 0 ||
2649 (unsigned)num_cols > tvb_reported_length_remaining(tvb, offset) )
2650 {
2651 proto_tree_add_expert(tree, pinfo, &ei_tns_data_count_too_large,
2652 tvb, nc_start, offset - nc_start);
2653 num_cols = 0;
2654 }
2655 if ( num_cols > 0 )
2656 offset += 1; /* reserved byte */
2657
2658 if ( out && num_cols > 0 )
2659 cols = wmem_alloc0_array(wmem_file_scope(), tns_column_t, num_cols)((tns_column_t*)wmem_alloc0((wmem_file_scope()), (((((num_cols
)) <= 0) || ((size_t)sizeof(tns_column_t) > (9223372036854775807L
/ (size_t)((num_cols))))) ? 0 : (sizeof(tns_column_t) * ((num_cols
))))))
;
2660 for ( int i = 0; i < num_cols && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
2661 offset = dissect_tns_dcb_column(tvb, pinfo, tree, offset, i + 1,
2662 cols ? &cols[i] : NULL((void*)0));
2663 if ( cols )
2664 {
2665 tns_describe_t *desc = wmem_new0(wmem_file_scope(), tns_describe_t)((tns_describe_t*)wmem_alloc0((wmem_file_scope()), sizeof(tns_describe_t
)))
;
2666 desc->num_cols = num_cols;
2667 desc->cols = cols;
2668 *out = desc;
2669 }
2670
2671 /* Trailer: current date (bytes_with_length), four ub4 flags,
2672 * and the query-cache key (bytes_with_length) — all skipped. The key
2673 * came with the 11g result cache: a 10g describe ends after the
2674 * flags. */
2675 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
2676 for ( int i = 0; i < 4; i++ )
2677 offset += get_sb4_custom(tvb, offset, &v);
2678 if ( !tns_before_11g(pinfo) )
2679 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
2680 return offset;
2681}
2682
2683static tns_call_t *tns_answered_call(packet_info *pinfo);
2684
2685/* A BFILE's locator names its file: a big-endian ub2 length and the
2686 * directory object's name, then a ub2 length and the file name, which end
2687 * the locator. They start 16 bytes into the locator as a value carries it,
2688 * behind its own ub2 length, and 14 bytes in in a LOB operation, which
2689 * sends it without that length. Finds the names in the len bytes at
2690 * offset, or returns false. */
2691static bool_Bool tns_bfile_names(tvbuff_t *tvb, int offset, int len,
2692 int *dir_off, int *dir_len, int *file_off, int *file_len)
2693{
2694 static const int bases[] = { 16, 14 };
2695
2696 for ( unsigned i = 0; i < array_length(bases)(sizeof (bases) / sizeof (bases)[0]); i++ )
2697 {
2698 int b = bases[i], dl, fl;
2699
2700 if ( len < b + 4 )
2701 continue;
2702 dl = tvb_get_ntohs(tvb, offset + b);
2703 if ( dl == 0 || b + 2 + dl + 2 > len )
2704 continue;
2705 fl = tvb_get_ntohs(tvb, offset + b + 2 + dl);
2706 if ( fl == 0 || b + 2 + dl + 2 + fl != len )
2707 continue;
2708 if ( !tvb_utf_8_isprint(tvb, offset + b + 2, dl)
2709 || !tvb_utf_8_isprint(tvb, offset + b + 2 + dl + 2, fl) )
2710 continue;
2711 *dir_off = offset + b + 2;
2712 *dir_len = dl;
2713 *file_off = offset + b + 2 + dl + 2;
2714 *file_len = fl;
2715 return true1;
2716 }
2717 return false0;
2718}
2719
2720/* Decode one row/bind value by its data type, and add it as a
2721 * "<prefix> N (TYPE)" item under `hf`. Ordinary values are a
2722 * DALC blob; ROWID / UROWID / LONG / LOB / JSON / VECTOR / object carry
2723 * their own framings. Returns the new offset. */
2724static int dissect_tns_value(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint8_t dtype, uint8_t csform, int idx, int hf, const char *prefix)
2725{
2726 int v_start = offset, disp_start = offset, v = 0;
2727 int is_null = 0, is_absent = 0;
2728 uint8_t first;
2729 const char *rendered = NULL((void*)0);
2730 /* LOB metadata: size and chunk size, with where they sit */
2731 bool_Bool lob_meta = false0;
2732 uint64_t lob_size = 0;
2733 int lob_chunk = 0, size_start = 0, size_len = 0, lchunk_start = 0, lchunk_len = 0;
2734 int image_start = 0, image_len = 0, obj_toid_start = 0, obj_toid_len = 0;
2735 proto_item *ti;
2736
2737 switch ( dtype )
2738 {
2739 case TNS_DATATYPE_REFCURSOR102:
2740 {
2741 /* A cursor - a CURSOR(...) column, or a REF CURSOR OUT
2742 * bind: a ub1 length (a fixed value, ignored), the describe
2743 * of the cursor's result set inline, and the ub2 id the
2744 * client drains it with. The value's length is known only
2745 * once the describe is read, so read it once to size the
2746 * item and again to show it. */
2747 proto_item *ci;
2748 proto_tree *ct;
2749 int end, cursor = 0, start;
2750 const tns_call_t *call = tns_answered_call(pinfo);
2751
2752 /* Rows a TTI_FETCH returns carry a cursor cut short before
2753 * 23ai: the length byte and the id, with no describe. An
2754 * execute's reply, and a fetch-only execute's, carry it
2755 * whole. */
2756 if ( call && call->func == TTI_FETCH5 && tns_field_version(pinfo) < TNS_FV_23_117 )
2757 {
2758 start = offset;
2759 end = offset + 1;
2760 end += get_sb4_custom(tvb, end, &cursor);
2761 ci = proto_tree_add_bytes_format(tree, hf, tvb, start, end - start, NULL((void*)0),
2762 "%s %d (%s): cursor %d", prefix, idx,
2763 val_to_str_const(dtype, tns_data_types, "unknown"), cursor);
2764 ct = proto_item_add_subtree(ci, ett_tns_value);
2765 proto_tree_add_uint(ct, hf_tns_cursor, tvb, offset + 1, end - offset - 1, cursor);
2766 return end;
2767 }
2768
2769 end = dissect_tns_describe_body(tvb, pinfo, NULL((void*)0), offset + 1, NULL((void*)0));
2770 end += get_sb4_custom(tvb, end, &cursor);
2771 ci = proto_tree_add_bytes_format(tree, hf, tvb, offset, end - offset, NULL((void*)0),
2772 "%s %d (%s): cursor %d", prefix, idx,
2773 val_to_str_const(dtype, tns_data_types, "unknown"), cursor);
2774 ct = proto_item_add_subtree(ci, ett_tns_value);
2775 offset = dissect_tns_describe_body(tvb, pinfo, ct, offset + 1, NULL((void*)0));
2776 start = offset;
2777 offset += get_sb4_custom(tvb, offset, &cursor);
2778 proto_tree_add_uint(ct, hf_tns_cursor, tvb, start, offset - start, cursor);
2779 return offset;
2780 }
2781
2782 case TNS_DATATYPE_ADT109:
2783 {
2784 /* An object - or an XMLType, which is an ADT by describe - is
2785 * framed the same way whether it is NULL or not:
2786 * bytes_with_length type OID | bytes_with_length OID |
2787 * bytes_with_length snapshot | ub2 version |
2788 * ub4 image length | ub2 flags | [DALC image]
2789 * A NULL object has an image length of 0 and no image. */
2790 int toid_start = offset, img_len = 0;
2791 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
2792 obj_toid_start = toid_start;
2793 obj_toid_len = offset - toid_start;
2794 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0)); /* OID */
2795 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0)); /* snapshot */
2796 offset += get_sb4_custom(tvb, offset, &v); /* version */
2797 offset += get_sb4_custom(tvb, offset, &img_len);
2798 offset += get_sb4_custom(tvb, offset, &v); /* flags */
2799 if ( img_len > 0 )
2800 {
2801 image_start = offset;
2802 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
2803 image_len = offset - image_start;
2804 rendered = wmem_strdup_printf(pinfo->pool, "object, %d-byte image", img_len);
2805 }
2806 else
2807 rendered = "NULL object";
2808 break;
2809 }
2810
2811 case TNS_DATATYPE_JSON119: /* OSON */
2812 case TNS_DATATYPE_VECTOR127:
2813 /* LOB-class, but the value itself rides in the row: the LOB
2814 * metadata framing with the image spliced in ahead of the
2815 * locator,
2816 * ub4 locator length | ub8 image size | ub4 chunk size |
2817 * DALC image | DALC locator
2818 * The locator is a placeholder. A 0x00 is NULL. A server may
2819 * instead send a bare locator, as for a CLOB, and leave the
2820 * image to a LOB read; that is told apart as for a CLOB. */
2821 first = tvb_get_uint8(tvb, offset);
2822 if ( first == 0 )
2823 {
2824 offset += 1;
2825 is_null = 1;
2826 break;
2827 }
2828 offset += get_sb4_custom(tvb, offset, &v);
2829 if ( v > 8 && tvb_get_uint8(tvb, offset) == v )
2830 {
2831 /* bare locator */
2832 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
2833 rendered = "locator only";
2834 break;
2835 }
2836 lob_meta = true1;
2837 size_start = offset;
2838 offset += get_ub8_custom(tvb, offset, &lob_size);
2839 size_len = offset - size_start;
2840 lchunk_start = offset;
2841 offset += get_sb4_custom(tvb, offset, &lob_chunk);
2842 lchunk_len = offset - lchunk_start;
2843 image_start = offset;
2844 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
2845 image_len = offset - image_start;
2846 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
2847 if ( image_len > 1 )
2848 {
2849 int img_len = 0;
2850 const uint8_t *img = tns_dalc_bytes(tvb, pinfo, image_start, &img_len);
2851 if ( img )
2852 rendered = dtype == TNS_DATATYPE_VECTOR127 ? tns_format_vector(pinfo, img, img_len)
2853 : tns_format_oson(pinfo, img, img_len);
2854 }
2855 if ( !rendered )
2856 rendered = wmem_strdup_printf(pinfo->pool, "%s image, %" PRIu64"l" "u" " bytes",
2857 dtype == TNS_DATATYPE_JSON119 ? "OSON" : "vector", lob_size);
2858 break;
2859
2860 case TNS_DATATYPE_ROWID11:
2861 {
2862 /* a present indicator (0 / 0xff = NULL), then the object id
2863 * (ub4), file number (ub2), an unused byte, block number
2864 * (ub4) and slot number (ub2) */
2865 int rba = 0, part = 0, block = 0, slot = 0;
2866 first = tvb_get_uint8(tvb, offset);
2867 offset += 1;
2868 if ( first == 0 || first == 0xff )
2869 {
2870 is_null = 1;
2871 break;
2872 }
2873 offset += get_sb4_custom(tvb, offset, &rba);
2874 offset += get_sb4_custom(tvb, offset, &part);
2875 offset += 1;
2876 offset += get_sb4_custom(tvb, offset, &block);
2877 offset += get_sb4_custom(tvb, offset, &slot);
2878 rendered = tns_format_rowid(pinfo, (uint32_t)rba, (uint32_t)part, (uint32_t)block, (uint32_t)slot);
2879 break;
2880 }
2881
2882 case TNS_DATATYPE_UROWID208: /* ub4 num_bytes, a length echo byte, then the bytes */
2883 offset += get_sb4_custom(tvb, offset, &v);
2884 if ( v > 0 )
2885 {
2886 offset += 1;
2887 rendered = tns_format_urowid(pinfo, tvb_get_ptr(tvb, offset, v), v);
2888 offset += v;
2889 }
2890 else
2891 is_null = 1;
2892 break;
2893
2894 case TNS_DATATYPE_LONG8:
2895 case TNS_DATATYPE_LONG_RAW24: /* value then two trailing ub4 length indicators */
2896 first = tvb_get_uint8(tvb, offset);
2897 if ( first == 0 )
2898 {
2899 offset += 1;
2900 is_null = 1;
2901 }
2902 else if ( first == 0xfe ) /* chunked */
2903 offset += 1 + tns_chunks_len(tvb, pinfo, offset + 1, NULL((void*)0));
2904 else
2905 offset += 1 + first;
2906 offset += get_sb4_custom(tvb, offset, &v);
2907 offset += get_sb4_custom(tvb, offset, &v);
2908 break;
2909
2910 case TNS_DATATYPE_CLOB112:
2911 case TNS_DATATYPE_BLOB113:
2912 case TNS_DATATYPE_BFILE114:
2913 /* 0x00 NULL, else a ub4 locator length and the locator. A
2914 * server sends CLOB / BLOB in one of two forms: with the LOB's
2915 * size (ub8) and chunk size (ub4) between the two, or bare -
2916 * and which one it picks for a client is not known. They are
2917 * told apart by the byte after the length: the bare form's is
2918 * the locator's own length prefix (or 0xFE when chunked), the
2919 * metadata form's is the size's width, at most 8. A real
2920 * locator is far longer than 8 bytes, so the two cannot meet.
2921 * A BFILE is always bare. */
2922 first = tvb_get_uint8(tvb, offset);
2923 if ( first == 0 )
2924 {
2925 offset += 1;
2926 is_null = 1;
2927 }
2928 else
2929 {
2930 offset += get_sb4_custom(tvb, offset, &v);
2931 if ( dtype != TNS_DATATYPE_BFILE114 && v > 8 )
2932 {
2933 uint8_t next = tvb_get_uint8(tvb, offset);
2934 if ( next <= 8 && next != v )
2935 {
2936 lob_meta = true1;
2937 size_start = offset;
2938 offset += get_ub8_custom(tvb, offset, &lob_size);
2939 size_len = offset - size_start;
2940 lchunk_start = offset;
2941 offset += get_sb4_custom(tvb, offset, &lob_chunk);
2942 lchunk_len = offset - lchunk_start;
2943 rendered = wmem_strdup_printf(pinfo->pool, "locator, size %" PRIu64"l" "u", lob_size);
2944 }
2945 }
2946 int loc_start = offset, dir_off, dir_len, file_off, file_len;
2947 uint8_t loc_len = tvb_get_uint8(tvb, offset);
2948 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
2949 if ( dtype == TNS_DATATYPE_BFILE114 && loc_len <= 0xfc
2950 && tns_bfile_names(tvb, loc_start + 1, loc_len, &dir_off, &dir_len, &file_off, &file_len) )
2951 rendered = wmem_strdup_printf(pinfo->pool, "BFILENAME('%s', '%s')",
2952 tvb_get_string_enc(pinfo->pool, tvb, dir_off, dir_len, ENC_UTF_80x00000002),
2953 tvb_get_string_enc(pinfo->pool, tvb, file_off, file_len, ENC_UTF_80x00000002));
2954 }
2955 break;
2956
2957 default: /* ordinary: a single DALC value */
2958 first = tvb_get_uint8(tvb, offset);
2959 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
2960 if ( first == 0 )
2961 is_null = 1;
2962 else if ( first == TNS_DALC_ABSENT0xFD )
2963 is_absent = 1;
2964 else
2965 {
2966 disp_start = v_start + 1; /* show the value bytes, not the length */
2967 /* Render common scalar types (never chunked): NUMBER as
2968 * decimal, DATE / TIMESTAMP / TIMESTAMP LTZ as a datetime. */
2969 if ( first != 254 && offset > disp_start )
2970 {
2971 const uint8_t *vb = tvb_get_ptr(tvb, disp_start, offset - disp_start);
2972 int vlen = offset - disp_start;
2973 /* A BINARY_INTEGER carries NUMBER bytes, not a native
2974 * integer. */
2975 if ( dtype == TNS_DATATYPE_NUMBER2 || dtype == TNS_DATATYPE_INTEGER3 )
2976 rendered = tns_format_number(pinfo, vb, vlen);
2977 else if ( dtype == TNS_DATATYPE_DATE12 || dtype == TNS_DATATYPE_TIMESTAMP180 || dtype == TNS_DATATYPE_TIMESTAMP_LTZ231 )
2978 rendered = tns_format_date(pinfo, vb, vlen);
2979 else if ( dtype == TNS_DATATYPE_TIMESTAMP_TZ181 )
2980 rendered = tns_format_timestamp_tz(pinfo, vb, vlen);
2981 else if ( (dtype == TNS_DATATYPE_INTERVAL_YM182 || dtype == TNS_DATATYPE_INTERVAL_DS183) && vlen >= 5 )
2982 rendered = tns_format_interval(pinfo, dtype, vb, vlen);
2983 else if ( dtype == TNS_DATATYPE_BOOLEAN252 )
2984 /* an encoded integer: 00 false, 01 01 true */
2985 rendered = vb[0] == 1 ? "TRUE" : "FALSE";
2986 else if ( dtype == TNS_DATATYPE_BINARY_FLOAT100 || dtype == TNS_DATATYPE_BINARY_DOUBLE101 )
2987 rendered = tns_format_binary_float(pinfo, vb, vlen);
2988 else if ( dtype == TNS_DATATYPE_VARCHAR1 || dtype == TNS_DATATYPE_STRING5 || dtype == TNS_DATATYPE_CHAR96 )
2989 /* VARCHAR / STRING / CHAR: character data, in the
2990 * session charset (ordinarily UTF-8), or UTF-16BE
2991 * for the national charset form (NCHAR,
2992 * NVARCHAR2) - in a column and an OUT bind alike. */
2993 rendered = (const char *)tvb_get_string_enc(pinfo->pool,
2994 tvb, disp_start, vlen,
2995 csform == TNS_CSFORM_NCHAR2 ? ENC_UTF_160x00000004|ENC_BIG_ENDIAN0x00000000 : ENC_UTF_80x00000002|ENC_NA0x00000000);
2996 }
2997 }
2998 break;
2999 }
3000
3001 if ( is_null )
3002 proto_tree_add_bytes_format(tree, hf, tvb,
3003 v_start, offset - v_start, NULL((void*)0), "%s %d (%s): NULL", prefix, idx,
3004 val_to_str_const(dtype, tns_data_types, "unknown"));
3005 else if ( is_absent )
3006 proto_tree_add_bytes_format(tree, hf, tvb,
3007 v_start, offset - v_start, NULL((void*)0), "%s %d (%s): no value", prefix, idx,
3008 val_to_str_const(dtype, tns_data_types, "unknown"));
3009 else if ( rendered )
3010 {
3011 ti = proto_tree_add_bytes_format(tree, hf, tvb,
3012 disp_start, offset - disp_start, NULL((void*)0), "%s %d (%s): %s", prefix, idx,
3013 val_to_str_const(dtype, tns_data_types, "unknown"), rendered);
3014 if ( dtype == TNS_DATATYPE_ADT109 )
3015 {
3016 proto_tree *vt = proto_item_add_subtree(ti, ett_tns_value);
3017 /* the type OID, without its ub4 count and DALC length */
3018 if ( obj_toid_len > 2 )
3019 {
3020 int w = 1 + (tvb_get_uint8(tvb, obj_toid_start) & 0x7f);
3021 proto_tree_add_item(vt, hf_tns_data_obj_toid, tvb,
3022 obj_toid_start + w + 1, obj_toid_len - w - 1, ENC_NA0x00000000);
3023 }
3024 if ( image_len > 1 )
3025 {
3026 bool_Bool chunked = tvb_get_uint8(tvb, image_start) == 0xfe;
3027 proto_tree_add_item(vt, hf_tns_data_obj_image, tvb,
3028 chunked ? image_start : image_start + 1, chunked ? image_len : image_len - 1, ENC_NA0x00000000);
3029 }
3030 }
3031 if ( lob_meta )
3032 {
3033 proto_tree *vt = proto_item_add_subtree(ti, ett_tns_value);
3034 proto_tree_add_uint64(vt, hf_tns_data_lob_size, tvb, size_start, size_len, lob_size);
3035 proto_tree_add_uint(vt, hf_tns_data_lob_chunk_size, tvb, lchunk_start, lchunk_len, lob_chunk);
3036 /* the image of a prefetched JSON / VECTOR value, without its
3037 * DALC length byte (chunked images are shown whole) */
3038 if ( image_len > 1 )
3039 {
3040 bool_Bool chunked = tvb_get_uint8(tvb, image_start) == 0xfe;
3041 proto_tree_add_item(vt, dtype == TNS_DATATYPE_JSON119 ? hf_tns_data_json_image : hf_tns_data_vector_image,
3042 tvb, chunked ? image_start : image_start + 1, chunked ? image_len : image_len - 1, ENC_NA0x00000000);
3043 }
3044 }
3045 }
3046 else
3047 proto_tree_add_bytes_format(tree, hf, tvb,
3048 disp_start, offset - disp_start, NULL((void*)0), "%s %d (%s)", prefix, idx,
3049 val_to_str_const(dtype, tns_data_types, "unknown"));
3050 return offset;
3051}
3052
3053/* The describe a row-data message is split by: the conversation's most
3054 * recent one, stored per packet on the first pass so a later pass uses
3055 * the same. */
3056static tns_describe_t *tns_current_describe(packet_info *pinfo)
3057{
3058 tns_describe_t *desc;
3059
3060 if ( PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
3061 return (tns_describe_t *)p_get_proto_data(wmem_file_scope(), pinfo,
3062 proto_tns, TNS_PROTO_DATA_DESCRIBE1);
3063
3064 desc = tns_get_conv_info(pinfo)->last_describe;
3065 if ( desc && !p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_DESCRIBE1) )
3066 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns,
3067 TNS_PROTO_DATA_DESCRIBE1, desc);
3068 return desc;
3069}
3070
3071/* Count the RETURNING ... INTO binds of a statement: the placeholders
3072 * after INTO, in a DML statement that has RETURNING ... INTO. Each
3073 * placeholder is a bind of its own, and those after INTO come last. A
3074 * PL/SQL block is never this form - a RETURNING INTO inside one is its
3075 * own PL/SQL, and its target an ordinary OUT bind. String literals and
3076 * comments are skipped. */
3077static unsigned tns_count_return_binds(const char *sql)
3078{
3079 const char *p = sql;
3080 bool_Bool first_word = true1, returning = false0, into = false0;
3081 unsigned n = 0;
3082
3083 while ( *p )
3084 {
3085 if ( *p == '\'' )
3086 {
3087 for ( p++; *p && *p != '\''; p++ )
3088 ;
3089 if ( *p )
3090 p++;
3091 }
3092 else if ( p[0] == '-' && p[1] == '-' )
3093 {
3094 while ( *p && *p != '\n' )
3095 p++;
3096 }
3097 else if ( p[0] == '/' && p[1] == '*' )
3098 {
3099 const char *end = strstr(p + 2, "*/");
3100 p = end ? end + 2 : p + strlen(p);
3101 }
3102 else if ( g_ascii_isalpha(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_ALPHA) != 0) )
3103 {
3104 const char *w = p;
3105 size_t len;
3106 while ( g_ascii_isalnum(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_ALNUM) != 0) || *p == '_' || *p == '$' || *p == '#' )
3107 p++;
3108 len = p - w;
3109 if ( first_word )
3110 {
3111 first_word = false0;
3112 if ( !((len == 6 && (g_ascii_strncasecmp(w, "INSERT", 6) == 0
3113 || g_ascii_strncasecmp(w, "UPDATE", 6) == 0
3114 || g_ascii_strncasecmp(w, "DELETE", 6) == 0))
3115 || (len == 5 && g_ascii_strncasecmp(w, "MERGE", 5) == 0)) )
3116 return 0;
3117 }
3118 else if ( !returning && len == 9 && g_ascii_strncasecmp(w, "RETURNING", 9) == 0 )
3119 returning = true1;
3120 else if ( returning && !into && len == 4 && g_ascii_strncasecmp(w, "INTO", 4) == 0 )
3121 into = true1;
3122 }
3123 else if ( *p == ':' && into && (g_ascii_isalnum(p[1])((g_ascii_table[(guchar) (p[1])] & G_ASCII_ALNUM) != 0) || p[1] == '_' || p[1] == '"') )
3124 {
3125 n++;
3126 for ( p++; g_ascii_isalnum(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_ALNUM) != 0) || *p == '_' || *p == '"'; p++ )
3127 ;
3128 }
3129 else
3130 p++;
3131 }
3132 return n;
3133}
3134
3135/* Look up the bind types remembered for a cursor, for an execute that
3136 * sends its values without descriptors. Stashed per packet on the first
3137 * pass, so a later pass gets the same answer. */
3138static tns_binds_t *tns_lookup_cursor_binds(packet_info *pinfo, uint32_t cursor)
3139{
3140 if ( PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
3141 return (tns_binds_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_BINDS2);
3142
3143 tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
3144 tns_binds_t *binds = (tns_binds_t *)wmem_map_lookup(tns_info->cursor_binds, GUINT_TO_POINTER(cursor)((gpointer) (gulong) (cursor)));
3145 if ( binds )
3146 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_BINDS2, binds);
3147 return binds;
3148}
3149
3150/* Decode the TTI_RXD value rows of a bind section - one row per
3151 * execution - with each value typed by cols[]. A CLOB / BLOB bind
3152 * carries a temp-LOB locator form not unpacked here, so rows with one are
3153 * left alone. Returns the new offset. */
3154static int dissect_tns_bind_rows(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, const tns_column_t *cols, uint32_t count)
3155{
3156 int rownum = 0;
3157
3158 for ( uint32_t i = 0; i < count; i++ )
3159 if ( cols[i].type == TNS_DATATYPE_CLOB112 || cols[i].type == TNS_DATATYPE_BLOB113 )
3160 return offset;
3161
3162 while ( tvb_reported_length_remaining(tvb, offset) > 0
3163 && tvb_get_uint8(tvb, offset) == SQLNET_ROW_TRANSF_DATA7 )
3164 {
3165 proto_tree *row_tree;
3166 proto_item *row_item;
3167 int r_start = offset;
3168
3169 offset += 1; /* TTI_RXD token */
3170 row_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
3171 ett_tns_bind_row, &row_item, "Row %d", ++rownum);
3172 for ( uint32_t i = 0; i < count
3173 && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3174 offset = dissect_tns_value(tvb, pinfo, row_tree, offset,
3175 cols[i].type, cols[i].csform, i + 1, hf_tns_data_bind_value, "Bind");
3176 proto_item_set_len(row_item, offset - r_start);
3177 }
3178 return offset;
3179}
3180
3181/* Remember the call a request makes, so the response can be read in its
3182 * light. Returns the record to fill in, or NULL on a later pass. */
3183static tns_call_t *tns_remember_call(packet_info *pinfo, uint8_t func)
3184{
3185 if ( PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
3186 return NULL((void*)0);
3187
3188 tns_call_t *call = wmem_new0(wmem_file_scope(), tns_call_t)((tns_call_t*)wmem_alloc0((wmem_file_scope()), sizeof(tns_call_t
)))
;
3189 call->func = func;
3190 tns_get_conv_info(pinfo)->last_call = call;
3191 return call;
3192}
3193
3194/* The call a response packet answers, or NULL if none was seen. */
3195static tns_call_t *tns_answered_call(packet_info *pinfo)
3196{
3197 if ( PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
3198 return (tns_call_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_CALL3);
3199
3200 tns_call_t *call = tns_get_conv_info(pinfo)->last_call;
3201 if ( call )
3202 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_CALL3, call);
3203 return call;
3204}
3205
3206/* Decode num key/value pairs: each a ub2 text length and text, a ub2
3207 * binary length and bytes, and a ub2 keyword number saying which session
3208 * attribute the value is for. Returns the new offset. */
3209static int dissect_tns_kv_pairs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int num)
3210{
3211 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3212 {
3213 proto_tree *kv_tree;
3214 proto_item *kv_item;
3215 const char *text = NULL((void*)0);
3216 int kv_start = offset, len = 0, keyword = 0, start;
3217
3218 kv_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1, ett_tns_kv,
3219 &kv_item, "Key/Value Pair %d", i + 1);
3220 offset += get_sb4_custom(tvb, offset, &len);
3221 if ( len > 0 )
3222 {
3223 start = offset;
3224 offset += get_dalc_custom(tvb, pinfo, offset, &text);
3225 proto_tree_add_string(kv_tree, hf_tns_data_kv_text, tvb, start, offset - start, text);
3226 }
3227 offset += get_sb4_custom(tvb, offset, &len);
3228 if ( len > 0 )
3229 {
3230 start = offset;
3231 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
3232 proto_tree_add_item(kv_tree, hf_tns_data_kv_binary, tvb, start + 1, offset - start - 1, ENC_NA0x00000000);
3233 }
3234 start = offset;
3235 offset += get_sb4_custom(tvb, offset, &keyword);
3236 proto_tree_add_uint(kv_tree, hf_tns_data_kv_keyword, tvb, start, offset - start, keyword);
3237 proto_item_append_text(kv_item, ": %s", val_to_str(pinfo->pool, keyword, tns_kv_keywords, "keyword %u"));
3238 if ( text )
3239 proto_item_append_text(kv_item, " = %s", text);
3240 proto_item_set_len(kv_item, offset - kv_start);
3241 }
3242 return offset;
3243}
3244
3245/* Decode the return-parameters block (TTI_RPA) that answers an execute,
3246 * ahead of its closing status. With DML_ROWCOUNTS requested it ends with
3247 * the rows each iteration of an array DML affected. Returns the new
3248 * offset. */
3249static int dissect_tns_return_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, bool_Bool rowcounts)
3250{
3251 proto_tree *rpa_tree;
3252 proto_item *rpa_item;
3253 int rpa_start = offset, num = 0, len = 0, start;
3254
3255 rpa_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_tns_rpa, &rpa_item, "Return Parameters");
3256
3257 /* al8o4l: a count of ub4 words */
3258 start = offset;
3259 offset += get_sb4_custom(tvb, offset, &num);
3260 proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_num_al8o4, tvb, start, offset - start, num);
3261 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3262 {
3263 int v = 0;
3264 start = offset;
3265 offset += get_sb4_custom(tvb, offset, &v);
3266 proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_al8o4, tvb, start, offset - start, v);
3267 }
3268 /* al8txl: a byte count and the bytes */
3269 offset += get_sb4_custom(tvb, offset, &len);
3270 if ( len > 0 )
3271 {
3272 proto_tree_add_item(rpa_tree, hf_tns_data_rpa_al8txl, tvb, offset, len, ENC_NA0x00000000);
3273 offset += len;
3274 }
3275 /* key/value pairs: a changed session attribute is reported here */
3276 start = offset;
3277 offset += get_sb4_custom(tvb, offset, &num);
3278 proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_num_kv, tvb, start, offset - start, num);
3279 offset = dissect_tns_kv_pairs(tvb, pinfo, rpa_tree, offset, num);
3280 /* registration: a byte count and the bytes */
3281 offset += get_sb4_custom(tvb, offset, &len);
3282 if ( len > 0 )
3283 {
3284 proto_tree_add_item(rpa_tree, hf_tns_data_rpa_registration, tvb, offset, len, ENC_NA0x00000000);
3285 offset += len;
3286 }
3287 /* per-iteration row counts, when the execute asked for them */
3288 if ( rowcounts )
3289 {
3290 start = offset;
3291 offset += get_sb4_custom(tvb, offset, &num);
3292 proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_num_rowcounts, tvb, start, offset - start, num);
3293 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3294 {
3295 uint64_t rows = 0;
3296 start = offset;
3297 offset += get_ub8_custom(tvb, offset, &rows);
3298 proto_tree_add_uint64(rpa_tree, hf_tns_data_rpa_dml_rowcount, tvb, start, offset - start, rows);
3299 }
3300 }
3301 proto_item_set_len(rpa_item, offset - rpa_start);
3302 return offset;
3303}
3304
3305/* From field version 23.1 ext 1 a call or piggyback header carries a ub8
3306 * token after its sequence number, which the reply echoes in a TOKEN
3307 * message. Returns the new offset. */
3308static int dissect_tns_call_token(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
3309{
3310 uint64_t token = 0;
3311 int start = offset;
3312
3313 if ( tns_field_version(pinfo) < TNS_FV_23_1_EXT_118 )
3314 return offset;
3315 offset += get_ub8_custom(tvb, offset, &token);
3316 proto_tree_add_uint64(tree, hf_tns_data_token, tvb, start, offset - start, token);
3317 return offset;
3318}
3319
3320/* Decode a two-phase commit call: a transaction switch (103) - start,
3321 * detach - or a state change (104) - prepare, commit, abort, forget. The
3322 * header gives an operation, the lengths of a transaction context and of
3323 * the XID's parts, and for a switch the names; the context, the XID and
3324 * the rest follow. The XID is padded to 128 bytes. Returns the new
3325 * offset. */
3326static int dissect_tns_tpc_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint32_t func)
3327{
3328 int v = 0, ctx_len = 0, gtrid_len = 0, bqual_len = 0, xid_len = 0;
3329 int int_len = 0, ext_len = 0, start;
3330 uint8_t ctx_ptr, xid_ptr, int_ptr = 0, ext_ptr = 0;
3331
3332 start = offset;
3333 offset += get_sb4_custom(tvb, offset, &v);
3334 proto_tree_add_uint(tree, func == TTI_TPC_TXN_SWITCH103 ? hf_tns_data_tpc_switch_op : hf_tns_data_tpc_change_op,
3335 tvb, start, offset - start, v);
3336 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", val_to_str_const(v,
3337 func == TTI_TPC_TXN_SWITCH103 ? tns_tpc_switch_ops : tns_tpc_change_ops, "unknown"));
3338 ctx_ptr = tvb_get_uint8(tvb, offset);
3339 offset += 1;
3340 offset += get_sb4_custom(tvb, offset, &ctx_len);
3341 start = offset;
3342 offset += get_sb4_custom(tvb, offset, &v);
3343 proto_tree_add_uint(tree, hf_tns_data_tpc_format_id, tvb, start, offset - start, v);
3344 offset += get_sb4_custom(tvb, offset, &gtrid_len);
3345 offset += get_sb4_custom(tvb, offset, &bqual_len);
3346 xid_ptr = tvb_get_uint8(tvb, offset);
3347 offset += 1;
3348 offset += get_sb4_custom(tvb, offset, &xid_len);
3349 if ( func == TTI_TPC_TXN_SWITCH103 )
3350 {
3351 start = offset;
3352 offset += get_sb4_custom(tvb, offset, &v);
3353 proto_tree_add_uint(tree, hf_tns_data_tpc_flags, tvb, start, offset - start, v);
3354 start = offset;
3355 offset += get_sb4_custom(tvb, offset, &v);
3356 proto_tree_add_uint(tree, hf_tns_data_tpc_timeout, tvb, start, offset - start, v);
3357 offset += 3; /* application value, return context and its length pointers */
3358 int_ptr = tvb_get_uint8(tvb, offset);
3359 offset += 1;
3360 offset += get_sb4_custom(tvb, offset, &int_len);
3361 ext_ptr = tvb_get_uint8(tvb, offset);
3362 offset += 1;
3363 offset += get_sb4_custom(tvb, offset, &ext_len);
3364 }
3365 else
3366 {
3367 start = offset;
3368 offset += get_sb4_custom(tvb, offset, &v);
3369 proto_tree_add_uint(tree, hf_tns_data_tpc_timeout, tvb, start, offset - start, v);
3370 start = offset;
3371 offset += get_sb4_custom(tvb, offset, &v);
3372 proto_tree_add_uint(tree, hf_tns_data_tpc_state, tvb, start, offset - start, v);
3373 offset += 1; /* out state pointer */
3374 start = offset;
3375 offset += get_sb4_custom(tvb, offset, &v);
3376 proto_tree_add_uint(tree, hf_tns_data_tpc_flags, tvb, start, offset - start, v);
3377 }
3378 if ( ctx_ptr && ctx_len > 0 )
3379 {
3380 proto_tree_add_item(tree, hf_tns_data_tpc_context, tvb, offset, ctx_len, ENC_NA0x00000000);
3381 offset += ctx_len;
3382 }
3383 if ( xid_ptr && xid_len > 0 )
3384 {
3385 if ( gtrid_len >= 0 && bqual_len >= 0 && gtrid_len + bqual_len <= xid_len )
3386 {
3387 proto_tree_add_item(tree, hf_tns_data_tpc_gtrid, tvb, offset, gtrid_len, ENC_NA0x00000000);
3388 proto_tree_add_item(tree, hf_tns_data_tpc_bqual, tvb, offset + gtrid_len, bqual_len, ENC_NA0x00000000);
3389 }
3390 offset += xid_len;
3391 }
3392 if ( func == TTI_TPC_TXN_SWITCH103 )
3393 {
3394 start = offset;
3395 offset += get_sb4_custom(tvb, offset, &v);
3396 proto_tree_add_uint(tree, hf_tns_data_tpc_app_value, tvb, start, offset - start, v);
3397 if ( int_ptr && int_len > 0 )
3398 {
3399 proto_tree_add_item(tree, hf_tns_data_tpc_internal_name, tvb, offset, int_len, ENC_UTF_80x00000002);
3400 offset += int_len;
3401 }
3402 if ( ext_ptr && ext_len > 0 )
3403 {
3404 proto_tree_add_item(tree, hf_tns_data_tpc_external_name, tvb, offset, ext_len, ENC_UTF_80x00000002);
3405 offset += ext_len;
3406 }
3407 }
3408 return offset;
3409}
3410
3411/* Decode the body of a piggyback other than close-cursors. Layouts
3412 * follow python-oracledb's _write_*_piggyback. Sets *walk when the body
3413 * was understood, so the call behind it can be decoded. Returns the new
3414 * offset. */
3415static int dissect_tns_piggyback_body(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint8_t piggyback_id, bool_Bool *walk)
3416{
3417 int v = 0, start;
3418 uint64_t u = 0;
3419
3420 switch ( piggyback_id )
3421 {
3422 case TTI_LOBOPS96:
3423 {
3424 /* close temporary LOBs: a FREE_TEMP | ARRAY LOB operation
3425 * whose locators, each with its own ub2 length prefix, follow
3426 * back to back - as many bytes as the total says. */
3427 int total = 0, op = 0;
3428 offset += 1; /* pointer */
3429 start = offset;
3430 offset += get_sb4_custom(tvb, offset, &total);
3431 proto_tree_add_uint(tree, hf_tns_data_lob_total_size, tvb, start, offset - start, total);
3432 offset += 1; /* dest locator pointer */
3433 offset += get_sb4_custom(tvb, offset, &v); /* dest locator length */
3434 offset += get_sb4_custom(tvb, offset, &v); /* source locator */
3435 offset += get_sb4_custom(tvb, offset, &v);
3436 offset += 3; /* offsets, charset */
3437 start = offset;
3438 offset += get_sb4_custom(tvb, offset, &op);
3439 proto_tree_add_uint(tree, hf_tns_data_lob_op, tvb, start, offset - start, op);
3440 offset += 1; /* scn */
3441 offset += get_sb4_custom(tvb, offset, &v); /* losbscn */
3442 offset += get_ub8_custom(tvb, offset, &u); /* lobscnl */
3443 offset += get_ub8_custom(tvb, offset, &u);
3444 offset += 1;
3445 for ( int i = 0; i < 3; i++ ) /* array LOB fields */
3446 {
3447 offset += 1;
3448 offset += get_sb4_custom(tvb, offset, &v);
3449 }
3450 if ( total < 0 || (unsigned)total > tvb_reported_length_remaining(tvb, offset) )
3451 {
3452 proto_tree_add_expert(tree, pinfo, &ei_tns_data_count_too_large, tvb, offset, 0);
3453 return offset;
3454 }
3455 for ( int end = offset + total; offset + 2 <= end; )
3456 {
3457 int len = 2 + tvb_get_ntohs(tvb, offset);
3458 if ( offset + len > end )
3459 len = end - offset;
3460 proto_tree_add_item(tree, hf_tns_data_lob_locator, tvb, offset, len, ENC_NA0x00000000);
3461 offset += len;
3462 }
3463 break;
3464 }
3465
3466 case TTI_SET_SCHEMA152:
3467 {
3468 const char *schema = NULL((void*)0);
3469 offset += 1; /* pointer */
3470 start = offset;
3471 offset += get_field_with_length(tvb, pinfo, offset, &schema);
3472 if ( schema )
3473 proto_tree_add_string(tree, hf_tns_data_pgy_schema, tvb, start, offset - start, schema);
3474 break;
3475 }
3476
3477 case TTI_SESSION_STATE176:
3478 start = offset;
3479 offset += get_ub8_custom(tvb, offset, &u);
3480 proto_tree_add_uint64(tree, hf_tns_data_pgy_session_state, tvb, start, offset - start, u);
3481 break;
3482
3483 case TTI_PIPELINE_BEGIN199:
3484 start = offset;
3485 offset += get_sb4_custom(tvb, offset, &v);
3486 proto_tree_add_uint(tree, hf_tns_data_pgy_error_set_id, tvb, start, offset - start, v);
3487 proto_tree_add_item(tree, hf_tns_data_pgy_error_set_mode, tvb, offset, 1, ENC_NA0x00000000);
3488 offset += 1;
3489 proto_tree_add_item(tree, hf_tns_data_pgy_pipeline_mode, tvb, offset, 1, ENC_NA0x00000000);
3490 offset += 1;
3491 break;
3492
3493 case TTI_SET_END_TO_END_ATTR135:
3494 {
3495 /* End-to-end attributes: a flags word saying which changed,
3496 * then a (pointer, length) header for each attribute - some
3497 * never used - and finally the strings of those that have a
3498 * value, in the same order. */
3499 static int * const hfs[] = { &hf_tns_data_pgy_client_id, &hf_tns_data_pgy_module,
3500 &hf_tns_data_pgy_action, NULL((void*)0), &hf_tns_data_pgy_client_info, NULL((void*)0), NULL((void*)0),
3501 &hf_tns_data_pgy_dbop };
3502 int lens[array_length(hfs)(sizeof (hfs) / sizeof (hfs)[0])];
3503
3504 offset += 2; /* cidnam, cidser pointers */
3505 start = offset;
3506 offset += get_sb4_custom(tvb, offset, &v);
3507 proto_tree_add_uint(tree, hf_tns_data_pgy_e2e_flags, tvb, start, offset - start, v);
3508 for ( unsigned i = 0; i < array_length(hfs)(sizeof (hfs) / sizeof (hfs)[0]); i++ )
3509 {
3510 uint8_t ptr = tvb_get_uint8(tvb, offset);
3511 offset += 1;
3512 offset += get_sb4_custom(tvb, offset, &lens[i]);
3513 if ( !ptr || !hfs[i] )
3514 lens[i] = 0;
3515 if ( i == 3 ) /* cideci is followed by cidcct, cidecs */
3516 {
3517 offset += 1;
3518 offset += get_sb4_custom(tvb, offset, &v);
3519 }
3520 }
3521 for ( unsigned i = 0; i < array_length(hfs)(sizeof (hfs) / sizeof (hfs)[0]); i++ )
3522 {
3523 const char *str = NULL((void*)0);
3524 if ( lens[i] <= 0 )
3525 continue;
3526 start = offset;
3527 offset += get_dalc_custom(tvb, pinfo, offset, &str);
3528 if ( str )
3529 proto_tree_add_string(tree, *hfs[i], tvb, start, offset - start, str);
3530 }
3531 break;
3532 }
3533
3534 case TTI_END_USER_SEC_CTX205:
3535 {
3536 /* End-user security context: flags, then key/value pairs, each
3537 * a flags word and a key, a text and a value in the
3538 * bytes_with_length form. */
3539 int num = 0;
3540 start = offset;
3541 offset += get_sb4_custom(tvb, offset, &v);
3542 proto_tree_add_uint(tree, hf_tns_data_pgy_sec_flags, tvb, start, offset - start, v);
3543 offset += 1; /* pointer */
3544 offset += get_sb4_custom(tvb, offset, &num);
3545 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3546 {
3547 const char *key = NULL((void*)0);
3548 offset += get_sb4_custom(tvb, offset, &v); /* flags */
3549 start = offset;
3550 offset += get_field_with_length(tvb, pinfo, offset, &key);
3551 if ( key )
3552 proto_tree_add_string(tree, hf_tns_data_pgy_sec_key, tvb, start, offset - start, key);
3553 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0)); /* text */
3554 start = offset;
3555 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
3556 proto_tree_add_item(tree, hf_tns_data_pgy_sec_value, tvb, start, offset - start, ENC_NA0x00000000);
3557 }
3558 break;
3559 }
3560
3561 default:
3562 /* An unknown body has an unknown length. */
3563 return offset;
3564 }
3565 *walk = true1;
3566 return offset;
3567}
3568
3569static void dissect_tns_data_descriptor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tns_tree, uint32_t length)
3570{
3571 /* This is used by Oracle 12c for at least sending LOB/FILE data. */
3572 proto_tree *dd_tree, *row_tree;
3573 proto_item *ti;
3574 uint32_t data_len, row_count, row_size, total_row_size = 0;
3575 int orig_offset = offset;
3576
3577 /* We only get here after tcp_dissect_pdus(), length is guaranteed. */
3578 DISSECTOR_ASSERT_CMPINT(length, >=, TNS_HDR_LEN)((void) ((length >= 8) ? (void)0 : (proto_report_dissector_bug
("%s:%u: failed assertion " "length" " " ">=" " " "8" " ("
"%" "l" "d" " " ">=" " " "%" "l" "d" ")", "epan/dissectors/packet-tns.c"
, 3578, (int64_t)length, (int64_t)8))))
;
3579
3580 dd_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL((void*)0), "Data Descriptor");
3581
3582 /* No idea what this is. Usually 0x0003. */
3583 offset += 4;
3584 proto_tree_add_item_ret_uint(dd_tree, hf_tns_data_length, tvb,
3585 offset, 4, ENC_BIG_ENDIAN0x00000000, &data_len);
3586 offset += 4;
3587
3588 /* This next parameter looks like: number of big endian shorts that follow,
3589 * the sum of the shorts equals the file length above - each short maxes
3590 * out at 0x1f7c = 8060, presumably related to the page size / max table
3591 * row size in Microsoft SQL Server? Something about how many rows it
3592 * would take to store this in-table?
3593 */
3594 proto_tree_add_item_ret_uint(dd_tree, hf_tns_data_descriptor_row_count, tvb,
3595 offset, 4, ENC_BIG_ENDIAN0x00000000, &row_count);
3596 offset += 4;
3597 row_tree = proto_tree_add_subtree(dd_tree, tvb, offset, row_count * 2,
3598 ett_tns_rows, &ti, "Rows");
3599 for (uint32_t i = 0; i < row_count; i++) {
3600 proto_tree_add_item_ret_uint(row_tree, hf_tns_data_descriptor_row_size, tvb,
3601 offset, 2, ENC_BIG_ENDIAN0x00000000, &row_size);
3602 total_row_size += row_size;
3603 offset += 2;
3604 }
3605 proto_item_append_text(ti, " (%u bytes)", total_row_size);
3606 if (total_row_size != data_len) {
3607 expert_add_info(pinfo, ti, &ei_tns_data_descriptor_size_mismatch);
3608 }
3609
3610 offset = orig_offset + (length - TNS_HDR_LEN8);
3611
3612 call_data_dissector(tvb_new_subset_length(tvb, offset, data_len), pinfo,
3613 dd_tree);
3614}
3615
3616/* State carried from one TTC message to the next within a packet. */
3617typedef struct _tns_msg_ctx_t {
3618 /* The decoder ended exactly on its message's last byte. */
3619 bool_Bool walk;
3620 /* Which columns the next row sends, from a row header or a TTI_BVC:
3621 * a clear bit means the value repeats the previous row's. NULL when
3622 * every column is sent. */
3623 const uint8_t *bit_vector;
3624 unsigned bit_vector_len;
3625 /* After a TTI_IOV: the call it answers and each bind's direction, so
3626 * the TTI_RXD after it can be read as the OUT bind values. */
3627 const tns_call_t *out_call;
3628 const uint8_t *bind_dirs;
3629} tns_msg_ctx_t;
3630
3631static int dissect_tns_message(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *data_tree, bool_Bool is_request, unsigned data_func_id, tns_msg_ctx_t *ctx);
3632
3633static bool_Bool tns_is_oci(packet_info *pinfo);
3634
3635/* Whether a message that follows another in the same packet is one we
3636 * step into. A response is a run of messages back to back - a describe,
3637 * a row header, the rows, a status - and a request may put piggybacks in
3638 * front of its call. */
3639static bool_Bool tns_is_next_message(packet_info *pinfo, unsigned data_func_id, bool_Bool is_request)
3640{
3641 if ( is_request )
3642 return data_func_id == SQLNET_USER_OCI_FUNC3 || data_func_id == SQLNET_PIGGYBACK_FUNC17;
3643
3644 switch ( data_func_id )
3645 {
3646 case SQLNET_RETURN_STATUS4:
3647 case SQLNET_FLUSH_BIND_DATA19:
3648 case SQLNET_FUNCCOMPLETE9:
3649 case SQLNET_WARNING15:
3650 case SQLNET_LOB_FILE_DF14:
3651 case SQLNET_BIT_VECTOR21:
3652 case SQLNET_SERVER_PIGGYBACK23:
3653 case SQLNET_IMPLICIT_RESULTS27:
3654 case SQLNET_TOKEN33:
3655 case SQLNET_END_OF_RESPONSE29:
3656 case SQLNET_ROW_TRANSF_HDR6:
3657 case SQLNET_ROW_TRANSF_DATA7:
3658 case SQLNET_RETURN_OPI_PARAM8:
3659 case SQLNET_IOVEC_4FAST_UPI11:
3660 case SQLNET_DESCRIBE_INFO16:
3661 return true1;
3662 case SQLNET_INVOKE_USER_CB13:
3663 /* a record of an OCI client's TTI_KOD reply */
3664 return tns_is_oci(pinfo);
3665 default:
3666 return false0;
3667 }
3668}
3669
3670static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tns_tree)
3671{
3672 proto_tree *data_tree;
3673 unsigned data_func_id;
3674 bool_Bool is_request;
3675 static int * const flags[] = {
3676 &hf_tns_data_flag_send,
3677 &hf_tns_data_flag_rc,
3678 &hf_tns_data_flag_c,
3679 &hf_tns_data_flag_reserved,
3680 &hf_tns_data_flag_more,
3681 &hf_tns_data_flag_eof,
3682 &hf_tns_data_flag_dic,
3683 &hf_tns_data_flag_rts,
3684 &hf_tns_data_flag_sntt,
3685 &hf_tns_data_flag_end_of_request,
3686 &hf_tns_data_flag_begin_pipeline,
3687 &hf_tns_data_flag_end_of_response,
3688 NULL((void*)0)
3689 };
3690
3691 is_request = pinfo->match_uint == pinfo->destport;
3692 data_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL((void*)0), "Data");
3693
3694 proto_tree_add_bitmask(data_tree, tvb, offset, hf_tns_data_flag, ett_tns_data_flag, flags, ENC_BIG_ENDIAN0x00000000);
3695 offset += 2;
3696 data_func_id = get_data_func_id(tvb, offset);
3697
3698 /* Once native network encryption is on, a data packet is ciphertext
3699 * followed by a padding and a key-fold byte; nothing in it can be
3700 * decoded without the session key. */
3701 if ( tns_is_encrypted(pinfo) && data_func_id != SQLNET_SNS0xdeadbeef )
3702 {
3703 col_append_str(pinfo->cinfo, COL_INFO, ", Encrypted Data");
3704 proto_tree_add_expert(data_tree, pinfo, &ei_tns_data_encrypted, tvb, offset, tvb_reported_length_remaining(tvb, offset));
3705 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, data_tree);
3706 return;
3707 }
3708
3709 /* The field version the connection negotiated decides the shape of
3710 * several messages; show the one in force. */
3711 unsigned fv = tns_field_version(pinfo);
3712 if ( fv )
3713 proto_item_set_generated(proto_tree_add_uint(data_tree, hf_tns_data_field_version, tvb, 0, 0, fv));
3714
3715 /* Do this only if the Data message have a body. Otherwise, there are only Data flags. */
3716 int remaining = tvb_reported_length_remaining(tvb, offset);
3717 if ( remaining > 0 )
3718 {
3719 if (is_request) {
3720 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
3721 tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
3722 if ((uint32_t)remaining == tns_info->pending_connect_data) {
3723 col_append_str(pinfo->cinfo, COL_INFO, ", Connect Data");
3724 proto_tree_add_item(data_tree, hf_tns_connect_data, tvb,
3725 offset, -1, ENC_ASCII0x00000000);
3726 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, 0,
3727 GUINT_TO_POINTER(tns_info->pending_connect_data)((gpointer) (gulong) (tns_info->pending_connect_data)));
3728 tns_info->pending_connect_data = 0;
3729 return;
3730 }
3731 } else {
3732 if (p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, 0) != NULL((void*)0)) {
3733 col_append_str(pinfo->cinfo, COL_INFO, ", Connect Data");
3734 proto_tree_add_item(data_tree, hf_tns_connect_data, tvb,
3735 offset, -1, ENC_ASCII0x00000000);
3736 return;
3737 }
3738 }
3739 }
3740 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(data_func_id, tns_data_funcs, "unknown"));
3741
3742 if ( (data_func_id != SQLNET_SNS0xdeadbeef) && (try_val_to_str(data_func_id, tns_data_funcs) != NULL((void*)0)) )
3743 {
3744 proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
3745 offset += 1;
3746 }
3747 }
3748
3749 /* Decode the first message, then step into each one after it for as
3750 * long as the previous decoder ended exactly on its last byte. */
3751 tns_msg_ctx_t ctx = { 0 };
3752 offset = dissect_tns_message(tvb, offset, pinfo, data_tree, is_request, data_func_id, &ctx);
3753 while ( ctx.walk && tvb_reported_length_remaining(tvb, offset) > 0 )
3754 {
3755 data_func_id = tvb_get_uint8(tvb, offset);
3756 if ( !tns_is_next_message(pinfo, data_func_id, is_request) )
3757 break;
3758 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(data_func_id, tns_data_funcs, "unknown"));
3759 proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
3760 offset += 1;
3761 ctx.walk = false0;
3762 offset = dissect_tns_message(tvb, offset, pinfo, data_tree, is_request, data_func_id, &ctx);
3763 }
3764
3765 if ( tvb_reported_length_remaining(tvb, offset) > 0 )
3766 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, data_tree);
3767}
3768
3769/* Whether the length byte in front of an OCI execute's SQL agrees with
3770 * the SQL length its preamble declares. A client in AL32UTF8, the
3771 * database's own character set, declares the SQL's byte length; one in
3772 * any other set declares three times it, a conversion buffer's worth.
3773 * The length byte is the byte length either way, or 0xFE for chunked
3774 * text. */
3775static bool_Bool tns_oci_sql_length_matches(uint8_t prefix, uint32_t declared)
3776{
3777 return prefix == 0xfe || prefix == declared || (uint32_t)prefix * 3 == declared;
3778}
3779
3780/* Whether a packet belongs to a conversation whose client speaks the OCI
3781 * dialect. Stored per packet on the first pass. */
3782static bool_Bool tns_is_oci(packet_info *pinfo)
3783{
3784 void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_OCI4);
3785 if ( stored || PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
3786 return GPOINTER_TO_UINT(stored)((guint) (gulong) (stored)) == 2;
3787
3788 bool_Bool oci = tns_get_conv_info(pinfo)->oci_dialect;
3789 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_OCI4, GUINT_TO_POINTER(oci ? 2 : 1)((gpointer) (gulong) (oci ? 2 : 1)));
3790 return oci;
3791}
3792
3793/* Whether an OCI client's session has been seen at the 12c band. Stored
3794 * per packet on the first pass. */
3795static bool_Bool tns_is_oci_12c(packet_info *pinfo)
3796{
3797 void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_OCI_12C8);
3798 if ( stored || PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
3799 return GPOINTER_TO_UINT(stored)((guint) (gulong) (stored)) == 2;
3800
3801 bool_Bool band = tns_get_conv_info(pinfo)->oci_band_12c;
3802 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_OCI_12C8, GUINT_TO_POINTER(band ? 2 : 1)((gpointer) (gulong) (band ? 2 : 1)));
3803 return band;
3804}
3805
3806/* A REF in a TTI_KOD message: a ub4 LE length, then the REF itself - a
3807 * ub2 LE length, three flag bytes, the 16-byte object id and 15 bytes
3808 * more. Adds the object id as hf. An id of 15 zero bytes and one more is
3809 * a system type's; *sys_type, when not NULL, gets that last byte, or 0.
3810 * Returns the offset past the REF. */
3811static int dissect_tns_kod_ref(tvbuff_t *tvb, proto_tree *tree, int offset, int hf, int *sys_type)
3812{
3813 uint32_t len = tvb_get_letohl(tvb, offset);
3814
3815 if ( sys_type )
3816 *sys_type = 0;
3817 tvb_ensure_bytes_exist(tvb, offset + 4, (int)MIN(len, INT_MAX)(((len) < (2147483647)) ? (len) : (2147483647)));
3818 if ( len < 21 )
3819 return offset + 4 + len;
3820 proto_tree_add_item(tree, hf, tvb, offset + 9, 16, ENC_NA0x00000000);
3821 if ( sys_type && tvb_skip_uint8(tvb, offset + 9, 15, 0) == (unsigned)(offset + 24) )
3822 {
3823 *sys_type = tvb_get_uint8(tvb, offset + 24);
3824 proto_item_set_generated(proto_tree_add_uint(tree, hf_tns_data_kod_system_type, tvb, offset + 24, 1, *sys_type));
3825 }
3826 return offset + 4 + len;
3827}
3828
3829/* A TEXT in a TTI_KOD reply: a ub4 LE count, then, unless it is zero, a
3830 * length byte and the text. Returns the offset past it. */
3831static int dissect_tns_kod_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int hf, const char **out)
3832{
3833 uint8_t len;
3834
3835 *out = NULL((void*)0);
3836 if ( tvb_get_letohl(tvb, offset) == 0 )
3837 return offset + 4;
3838 len = tvb_get_uint8(tvb, offset + 4);
3839 proto_tree_add_item_ret_string(tree, hf, tvb, offset + 5, len, ENC_UTF_80x00000002, pinfo->pool, (const uint8_t **)out);
3840 return offset + 5 + len;
3841}
3842
3843/* The image of a type descriptor in a TTI_KOD record: a DALC, chunked in
3844 * single-byte lengths when long. The image is a pickled object - 85 01
3845 * fe and a ub4 BE length, then one value per attribute: a length byte,
3846 * fe and a ub4 BE length, or ff for NULL. An instance of SYS.KOTTD
3847 * describes a type, and its attributes 1 to 4 are the type's schema,
3848 * name, version and a ub2 BE typecode. Returns the offset past the
3849 * image. */
3850static int dissect_tns_kod_image(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int sys_type)
3851{
3852 wmem_array_t *buf = wmem_array_new(pinfo->pool, 1);
3853 uint8_t first = tvb_get_uint8(tvb, offset);
3854 const char *schema = NULL((void*)0), *name = NULL((void*)0);
3855 const uint8_t *img;
3856 int start = offset, base = -1, len, pos;
3857
3858 if ( first == 0xfe )
3859 {
3860 offset += 1;
3861 for ( uint8_t n = tvb_get_uint8(tvb, offset++); n > 0; n = tvb_get_uint8(tvb, offset++) )
3862 {
3863 wmem_array_append(buf, tvb_get_ptr(tvb, offset, n), n);
3864 offset += n;
3865 }
3866 }
3867 else if ( first < TNS_DALC_ABSENT0xFD )
3868 {
3869 /* in place: an attribute's bytes can be pointed at */
3870 base = offset + 1;
3871 wmem_array_append(buf, tvb_get_ptr(tvb, base, first), first);
3872 offset = base + first;
3873 }
3874 else
3875 return offset + get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
3876
3877 img = (const uint8_t *)wmem_array_get_raw(buf);
3878 len = (int)wmem_array_get_count(buf);
3879 proto_tree_add_bytes_with_length(tree, hf_tns_data_kod_image, tvb, start, offset - start, img, len);
3880 if ( sys_type != TNS_KOD_KOTTD1 || len < 7 || img[0] != 0x85 || img[2] != 0xfe )
3881 return offset;
3882
3883 pos = 7;
3884 for ( int attr = 0; attr <= 4 && pos < len; attr++ )
3885 {
3886 uint32_t alen = img[pos++];
3887 int item_start = start, item_len = offset - start;
3888
3889 if ( alen == 0xff )
3890 continue;
3891 if ( alen == 0xfe )
3892 {
3893 if ( len - pos < 4 )
3894 break;
3895 alen = pntohu32(img + pos);
3896 pos += 4;
3897 }
3898 if ( alen > (uint32_t)(len - pos) )
3899 break;
3900 if ( base >= 0 )
3901 {
3902 item_start = base + pos;
3903 item_len = (int)alen;
3904 }
3905 switch ( attr )
3906 {
3907 case 1:
3908 schema = (const char *)get_utf_8_string(pinfo->pool, img + pos, (int)alen);
3909 proto_tree_add_string(tree, hf_tns_data_kod_schema, tvb, item_start, item_len, schema);
3910 break;
3911 case 2:
3912 name = (const char *)get_utf_8_string(pinfo->pool, img + pos, (int)alen);
3913 proto_tree_add_string(tree, hf_tns_data_kod_name, tvb, item_start, item_len, name);
3914 break;
3915 case 3:
3916 proto_tree_add_string(tree, hf_tns_data_kod_version, tvb, item_start, item_len,
3917 (const char *)get_utf_8_string(pinfo->pool, img + pos, (int)alen));
3918 break;
3919 case 4:
3920 if ( alen == 2 )
3921 proto_tree_add_uint(tree, hf_tns_data_kod_typecode, tvb, item_start, item_len, pntohu16(img + pos));
3922 break;
3923 default:
3924 break;
3925 }
3926 pos += (int)alen;
3927 }
3928 if ( name )
3929 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s%s%s]", schema ? schema : "", schema ? "." : "", name);
3930 return offset;
3931}
3932
3933/* Read the error text after an OCI status block: a length byte for up to
3934 * 252 bytes, else 0xFE and chunks until a zero length. The chunk lengths
3935 * are single bytes from an 11g server and ub4 LE from an 18c one, and
3936 * which a server sends is not its field version but a capability not yet
3937 * identified. The text holds no zero bytes and a message never runs to
3938 * 64K, so the two zero high bytes of a ub4 LE length tell it from a ub1
3939 * length followed by text. Returns the bytes consumed; *out_str gets the
3940 * text, or NULL. */
3941static int tns_oci_error_text(tvbuff_t *tvb, packet_info *pinfo, int offset, const char **out_str)
3942{
3943 wmem_strbuf_t *strbuf;
3944 bool_Bool ub4_lengths;
3945 int o;
3946
3947 if ( tvb_get_uint8(tvb, offset) != 0xfe )
3948 return get_dalc_custom(tvb, pinfo, offset, out_str);
3949
3950 ub4_lengths = tvb_bytes_exist(tvb, offset + 1, 4) && tvb_get_letohs(tvb, offset + 3) == 0;
3951 strbuf = wmem_strbuf_new(pinfo->pool, "");
3952 o = offset + 1;
3953 while ( tvb_reported_length_remaining(tvb, o) > 0 )
3954 {
3955 int chunk_len;
3956 if ( ub4_lengths )
3957 {
3958 chunk_len = (int)MIN(tvb_get_letohl(tvb, o), INT_MAX)(((tvb_get_letohl(tvb, o)) < (2147483647)) ? (tvb_get_letohl
(tvb, o)) : (2147483647))
;
3959 o += 4;
3960 }
3961 else
3962 {
3963 chunk_len = tvb_get_uint8(tvb, o);
3964 o += 1;
3965 }
3966 if ( chunk_len == 0 )
3967 break;
3968 wmem_strbuf_append(strbuf, (const char *)tvb_get_string_enc(pinfo->pool, tvb, o, chunk_len, ENC_UTF_80x00000002|ENC_NA0x00000000));
3969 o += chunk_len;
3970 }
3971 *out_str = wmem_strbuf_get_str(strbuf);
3972 return o - offset;
3973}
3974
3975/* Decode a server message to an OCI client. Its integers are fixed-width
3976 * little-endian, so only the status messages, whose layout is known, are
3977 * decoded; the rest is left to the data dissector. Returns the new
3978 * offset. */
3979static int dissect_tns_oci_message(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *data_tree, unsigned data_func_id, tns_msg_ctx_t *ctx)
3980{
3981 switch ( data_func_id )
3982 {
3983 case SQLNET_INVOKE_USER_CB13:
3984 {
3985 /* A message of a TTI_KOD reply: a by-name reply's header,
3986 * then a record per type descriptor, then the status. A
3987 * TEXT is a ub4 count, a length byte and the text. The
3988 * header: a ub4 2, the schema (the connected user's, even
3989 * for a SYS type), a ub4 0, the name, a byte, the REF of the
3990 * type and 01 00, with four zero bytes more at the 12c band.
3991 * A record: the REF of the system type the descriptor is an
3992 * instance of, a byte, the REF of the type described, a
3993 * byte, a 24-byte descriptor behind a ub4 length (a bare 35
3994 * bytes at the 12c band), 00 01 00, the image's ub4 length,
3995 * 09 00, and the image. */
3996 tns_call_t *call = tns_answered_call(pinfo);
3997 proto_tree *kod_tree;
3998 proto_item *kod_item;
3999 const char *schema, *name;
4000 int start = offset - 1, sys_type;
4001 uint8_t kind;
4002
4003 if ( !call || call->func != TTI_KOD92 )
4004 return offset;
4005 kind = tvb_get_uint8(tvb, offset);
4006 kod_tree = proto_tree_add_subtree(data_tree, tvb, start, -1, ett_tns_kod, &kod_item,
4007 kind == TNS_KOD_HEADER2 ? "Object Type Header" : "Object Type Record");
4008 proto_tree_add_item(kod_tree, hf_tns_data_kod_kind, tvb, offset, 1, ENC_NA0x00000000);
4009 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str_const(kind, tns_kod_kinds, "unknown"));
4010 offset += 1;
4011 if ( kind == TNS_KOD_HEADER2 )
4012 {
4013 offset += 4;
4014 offset = dissect_tns_kod_text(tvb, pinfo, kod_tree, offset, hf_tns_data_kod_schema, &schema);
4015 offset += 4;
4016 offset = dissect_tns_kod_text(tvb, pinfo, kod_tree, offset, hf_tns_data_kod_name, &name);
4017 offset += 1;
4018 offset = dissect_tns_kod_ref(tvb, kod_tree, offset, hf_tns_data_kod_oid, NULL((void*)0));
4019 offset += tvb_bytes_exist(tvb, offset + 2, 1) && tvb_get_uint8(tvb, offset + 2) == 0 ? 6 : 2;
4020 if ( name )
4021 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s%s%s]", schema ? schema : "", schema ? "." : "", name);
4022 }
4023 else if ( kind == TNS_KOD_RECORD1 )
4024 {
4025 offset = dissect_tns_kod_ref(tvb, kod_tree, offset, hf_tns_data_kod_type_oid, &sys_type);
4026 offset += 1;
4027 offset = dissect_tns_kod_ref(tvb, kod_tree, offset, hf_tns_data_kod_oid, NULL((void*)0));
4028 offset += 1;
4029 offset += tvb_get_letohl(tvb, offset) == 24 ? 4 + 24 : 35;
4030 offset += 3 + 4 + 2;
4031 offset = dissect_tns_kod_image(tvb, pinfo, kod_tree, offset, sys_type);
4032 }
4033 else
4034 return offset;
4035 proto_item_set_len(kod_item, offset - start);
4036 ctx->walk = true1;
4037 return offset;
4038 }
4039
4040 case SQLNET_RETURN_STATUS4:
4041 {
4042 /* The OCI status block: 136 bytes, or a compact 24 for a
4043 * query's execute status, the end of a fetch and a no-row
4044 * status. Offsets count from the message id byte; a field
4045 * this decoder skips is a constant or not understood. The
4046 * error message follows the full form. At the 12c band the
4047 * full form is 144 bytes: the error number again at 132 and
4048 * a ub8 row count, the one sqlplus reports for a DML. */
4049 proto_tree *oer_tree;
4050 proto_item *oer_item;
4051 int base = offset - 1, remaining = tvb_reported_length_remaining(tvb, base);
4052 bool_Bool full = remaining >= 136, wide = false0;
4053 uint32_t err_code;
4054
4055 if ( remaining < 24 )
4056 return offset;
4057 err_code = tvb_get_letohl(tvb, base + 12);
4058 if ( remaining >= 144 )
4059 wide = tns_is_oci_12c(pinfo)
4060 || (err_code != 0 && tvb_get_letohl(tvb, base + 132) == err_code)
4061 || (err_code == 0 && remaining == 144);
4062 oer_tree = proto_tree_add_subtree(data_tree, tvb, base, wide ? 144 : full ? 136 : 24, ett_tns_oer, &oer_item,
4063 wide ? "Oracle Error Return (OCI, 12c band)" : full ? "Oracle Error Return (OCI)"
4064 : "Oracle Error Return (OCI, compact)");
4065 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_status, tvb, base + 1, 1, ENC_NA0x00000000);
4066 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_seq, tvb, base + 5, 2, ENC_LITTLE_ENDIAN0x80000000);
4067 proto_tree_add_int(oer_tree, hf_tns_data_oer_rowcount, tvb, base + 8, 4, (int32_t)tvb_get_letohl(tvb, base + 8));
4068 proto_tree_add_int(oer_tree, hf_tns_data_oer_err_code, tvb, base + 12, 4, (int32_t)err_code);
4069 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_category, tvb, base + 18, 1, ENC_NA0x00000000);
4070 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_error_pos, tvb, base + 20, 1, ENC_NA0x00000000);
4071 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_command, tvb, base + 22, 1, ENC_NA0x00000000);
4072 if ( !full )
4073 return base + 24;
4074 /* the sequence number of the call this answers - the client's
4075 * own, not the counter at offset 5 */
4076 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_call_seq, tvb, base + 49, 2, ENC_LITTLE_ENDIAN0x80000000);
4077 offset = base + 136;
4078 if ( wide )
4079 {
4080 proto_tree_add_item(oer_tree, hf_tns_data_oer_err_num_ext, tvb, base + 132, 4, ENC_LITTLE_ENDIAN0x80000000);
4081 proto_tree_add_item(oer_tree, hf_tns_data_oer_rowcount_ext, tvb, base + 136, 8, ENC_LITTLE_ENDIAN0x80000000);
4082 offset = base + 144;
4083 }
4084 if ( err_code != 0 && tvb_reported_length_remaining(tvb, offset) > 0 )
4085 {
4086 const char *msg = NULL((void*)0);
4087 int msg_start = offset;
4088 offset += tns_oci_error_text(tvb, pinfo, offset, &msg);
4089 msg = tns_trim_message(pinfo, msg);
4090 if ( msg )
4091 {
4092 proto_tree_add_string(oer_tree, hf_tns_data_oer_message, tvb, msg_start, offset - msg_start, msg);
4093 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", msg);
4094 }
4095 proto_item_set_len(oer_item, offset - base);
4096 }
4097 return offset;
4098 }
4099
4100 case SQLNET_FUNCCOMPLETE9:
4101 /* TTI_STA, answering a commit, a rollback or a logoff: a
4102 * ub4 LE call status and a ub2 LE end-to-end sequence */
4103 if ( !tvb_bytes_exist(tvb, offset, 6) )
4104 return offset;
4105 tns_add_call_status_flags(
4106 proto_tree_add_item(data_tree, hf_tns_data_sta_call_status, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000),
4107 tvb, offset, 4, tvb_get_letohl(tvb, offset));
4108 proto_tree_add_item(data_tree, hf_tns_data_sta_seq, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN0x80000000);
4109 return offset + 6;
4110
4111 default:
4112 return offset;
4113 }
4114}
4115
4116/* Decode the body of one TTC message, whose id byte has already been
4117 * consumed. Sets ctx->walk when the decoder ended exactly on the
4118 * message's last byte, so the caller can step into whatever follows it.
4119 * Returns the new offset. */
4120static int dissect_tns_message(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *data_tree, bool_Bool is_request, unsigned data_func_id, tns_msg_ctx_t *ctx)
4121{
4122 /* The thin decoders below would misread the fixed-width integers of
4123 * a server talking to an OCI client. */
4124 if ( !is_request && data_func_id != SQLNET_SNS0xdeadbeef && data_func_id != SQLNET_RETURN_OPI_PARAM8
4125 && tns_is_oci(pinfo) )
4126 return dissect_tns_oci_message(tvb, offset, pinfo, data_tree, data_func_id, ctx);
4127
4128 /* Handle data functions that have more than just ID */
4129 switch (data_func_id)
4130 {
4131 case SQLNET_SET_PROTOCOL1:
4132 {
4133 proto_tree *versions_tree;
4134 proto_item *ti;
4135 char sep;
4136 if ( is_request )
4137 {
4138 versions_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_acc_versions, &ti, "Accepted Versions");
4139 sep = ':';
4140 for (;;) {
4141 /*
4142 * Add each accepted version as a
4143 * separate item.
4144 */
4145 uint8_t vers;
4146
4147 vers = tvb_get_uint8(tvb, offset);
4148 if (vers == 0) {
4149 /*
4150 * A version of 0 terminates
4151 * the list.
4152 */
4153 break;
4154 }
4155 proto_item_append_text(ti, "%c %u", sep, vers);
4156 sep = ',';
4157 proto_tree_add_uint(versions_tree, hf_tns_data_setp_acc_version, tvb, offset, 1, vers);
4158 offset += 1;
4159 }
4160 offset += 1; /* skip the 0 terminator */
4161 proto_item_set_end(ti, tvb, offset);
4162 proto_tree_add_item(data_tree, hf_tns_data_setp_cli_plat, tvb, offset, -1, ENC_ASCII0x00000000);
4163
4164 return tvb_reported_length(tvb); /* skip call_data_dissector */
4165 }
4166 else
4167 {
4168 unsigned len;
4169 versions_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_acc_versions, &ti, "Versions");
4170 sep = ':';
4171 for (;;) {
4172 /*
4173 * Add each version as a separate item.
4174 */
4175 uint8_t vers;
4176
4177 vers = tvb_get_uint8(tvb, offset);
4178 if (vers == 0) {
4179 /*
4180 * A version of 0 terminates
4181 * the list.
4182 */
4183 break;
4184 }
4185 proto_item_append_text(ti, "%c %u", sep, vers);
4186 sep = ',';
4187 proto_tree_add_uint(versions_tree, hf_tns_data_setp_version, tvb, offset, 1, vers);
4188 offset += 1;
4189 }
4190 offset += 1; /* skip the 0 terminator */
4191 proto_item_set_end(ti, tvb, offset);
4192 proto_tree_add_item_ret_length(data_tree, hf_tns_data_setp_banner, tvb, offset, -1, ENC_ASCII0x00000000|ENC_NA0x00000000, &len);
4193 offset += len;
4194
4195 /* After the banner: the server's charset (LE), flags, a
4196 * count of 5-byte elements (LE), the "fdo" block (a BE
4197 * length) whose tail names the national charset, and the
4198 * server's compile and runtime capabilities, each behind a
4199 * length byte. Capability 7 is the highest TTC field
4200 * version the server offers. */
4201 if ( tvb_reported_length_remaining(tvb, offset) < 5 )
4202 break;
4203 proto_tree_add_item(data_tree, hf_tns_data_setp_charset, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000);
4204 offset += 2;
4205 proto_tree_add_item(data_tree, hf_tns_data_setp_flags, tvb, offset, 1, ENC_NA0x00000000);
4206 offset += 1;
4207 unsigned num_elem = tvb_get_letohs(tvb, offset);
4208 offset += 2 + 5 * num_elem;
4209 unsigned fdo_len = tvb_get_ntohs(tvb, offset);
4210 offset += 2;
4211 if ( fdo_len >= 7 )
4212 {
4213 unsigned ix = 6 + tvb_get_uint8(tvb, offset + 5) + tvb_get_uint8(tvb, offset + 6);
4214 if ( ix + 5 <= fdo_len )
4215 proto_tree_add_item(data_tree, hf_tns_data_setp_ncharset, tvb, offset + ix + 3, 2, ENC_BIG_ENDIAN0x00000000);
4216 }
4217 offset += fdo_len;
4218 uint8_t caps_len = tvb_get_uint8(tvb, offset);
4219 proto_tree_add_item(data_tree, hf_tns_data_setp_compile_caps, tvb, offset, 1 + caps_len, ENC_NA0x00000000);
4220 if ( caps_len > TNS_CCAP_FIELD_VERSION7 )
4221 {
4222 proto_tree_add_item(data_tree, hf_tns_data_setp_field_version, tvb,
4223 offset + 1 + TNS_CCAP_FIELD_VERSION7, 1, ENC_NA0x00000000);
4224 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
4225 tns_get_conv_info(pinfo)->server_field_version =
4226 tvb_get_uint8(tvb, offset + 1 + TNS_CCAP_FIELD_VERSION7);
4227 }
4228 offset += 1 + caps_len;
4229 caps_len = tvb_get_uint8(tvb, offset);
4230 proto_tree_add_item(data_tree, hf_tns_data_setp_runtime_caps, tvb, offset, 1 + caps_len, ENC_NA0x00000000);
4231 offset += 1 + caps_len;
4232 }
4233 break;
4234 }
4235
4236 case SQLNET_SET_DATATYPES2:
4237 {
4238 /* TTI_DTY: Data Type Negotiation, sent right after TTI_PRO
4239 * during the TTC handshake. The body is a fixed-shape blob
4240 * the client uses to tell the server which native Oracle
4241 * data types it understands and what wire representation it
4242 * wants for each. Layout cross-referenced with
4243 * python-oracledb.
4244 *
4245 * charset_in 2 bytes LE NLS_LANGUAGE charset id
4246 * charset_out 2 bytes LE NLS_NCHAR charset id
4247 * flag 1 byte capability flag (1 = std)
4248 * capability header 39 bytes version triple + flag bytes
4249 * table header 8 bytes group/sub counts
4250 * identity map 980 bytes 245 x (type, type, 1, 0)
4251 * type overrides var entries, terminated by 0
4252 */
4253 proto_tree *caphdr_tree, *ov_tree;
4254 proto_item *caphdr_item, *ov_item;
4255
4256 if ( !is_request )
4257 break;
4258
4259 proto_tree_add_item(data_tree, hf_tns_data_setdt_charset_in, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000);
4260 offset += 2;
4261 proto_tree_add_item(data_tree, hf_tns_data_setdt_charset_out, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000);
4262 offset += 2;
4263 proto_tree_add_item(data_tree, hf_tns_data_setdt_flag, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4264 offset += 1;
4265
4266 caphdr_item = proto_tree_add_item(data_tree, hf_tns_data_setdt_caphdr, tvb, offset, 39, ENC_NA0x00000000);
4267 caphdr_tree = proto_item_add_subtree(caphdr_item, ett_tns_setdt_caphdr);
4268 proto_tree_add_item(caphdr_tree, hf_tns_data_setdt_caphdr_version, tvb, offset, 3, ENC_BIG_ENDIAN0x00000000);
4269 proto_tree_add_item(caphdr_tree, hf_tns_data_setdt_caphdr_flags, tvb, offset + 3, 36, ENC_NA0x00000000);
4270 /* The header opens with the length of the client's compile
4271 * capabilities, and capability 7 is the TTC field version.
4272 * The client has already lowered it to the server's, so it
4273 * is the one the connection uses. */
4274 if ( tvb_get_uint8(tvb, offset) > TNS_CCAP_FIELD_VERSION7 )
4275 {
4276 uint8_t fv = tvb_get_uint8(tvb, offset + 1 + TNS_CCAP_FIELD_VERSION7);
4277 proto_tree_add_item(caphdr_tree, hf_tns_data_setdt_field_version, tvb,
4278 offset + 1 + TNS_CCAP_FIELD_VERSION7, 1, ENC_NA0x00000000);
4279 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
4280 tns_get_conv_info(pinfo)->field_version = fv;
4281 }
4282 offset += 39;
4283
4284 proto_tree_add_item(data_tree, hf_tns_data_setdt_tblhdr, tvb, offset, 8, ENC_NA0x00000000);
4285 offset += 8;
4286 proto_tree_add_item(data_tree, hf_tns_data_setdt_idmap, tvb, offset, 980, ENC_NA0x00000000);
4287 offset += 980;
4288
4289 /* Walk type-override entries until the 0 terminator. Each
4290 * entry is (client_type, server_repr[, format]); a 0 in the
4291 * server_repr slot marks a short "client knows the id but
4292 * has no override" entry. */
4293 ov_item = proto_tree_add_item(data_tree, hf_tns_data_setdt_overrides, tvb, offset, -1, ENC_NA0x00000000);
4294 ov_tree = proto_item_add_subtree(ov_item, ett_tns_setdt_overrides);
4295 int ov_start = offset;
4296 while ( tvb_reported_length_remaining(tvb, offset) > 0 )
4297 {
4298 uint8_t client_type = tvb_get_uint8(tvb, offset);
4299 if ( client_type == 0 )
4300 {
4301 proto_tree_add_item(ov_tree, hf_tns_data_setdt_override_client, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4302 offset += 1;
4303 break;
4304 }
4305 uint8_t repr = tvb_get_uint8(tvb, offset + 1);
4306 int entry_len = (repr == 0) ? 2 : 4;
4307 proto_tree *e_tree = proto_tree_add_subtree_format(ov_tree, tvb, offset, entry_len,
4308 ett_tns_setdt_override, NULL((void*)0), "Type %u (%s)",
4309 client_type, val_to_str_const(client_type, tns_data_types, "unknown"));
4310 proto_tree_add_item(e_tree, hf_tns_data_setdt_override_client, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4311 if ( entry_len == 4 )
4312 {
4313 proto_tree_add_item(e_tree, hf_tns_data_setdt_override_repr, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
4314 proto_tree_add_item(e_tree, hf_tns_data_setdt_override_format, tvb, offset + 2, 1, ENC_BIG_ENDIAN0x00000000);
4315 }
4316 offset += entry_len;
4317 }
4318 proto_item_set_len(ov_item, offset - ov_start);
4319 break;
4320 }
4321
4322 case SQLNET_RETURN_STATUS4:
4323 {
4324 /* TTI_OER: server-side end-of-call status block. Emitted at
4325 * the end of every response — success or failure. Layout
4326 * cross-referenced with python-oracledb's
4327 * _process_error_info, in the Oracle 11g shape (no extended
4328 * ub4 error number / ub8 rowcount that 12c+ adds).
4329 *
4330 * All multi-byte integers are stored in the ub4 variable-
4331 * length form (see get_sb4_custom): first byte holds the
4332 * value's width (0..4), followed by that many big-endian
4333 * data bytes. */
4334 proto_tree *oer_tree;
4335 proto_item *oer_item;
4336 int oer_start = offset;
4337 int v;
4338
4339 oer_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_oer, &oer_item, "Oracle Error Return");
4340
4341 /* call_status */
4342 offset += get_sb4_custom(tvb, offset, &v);
4343 tns_add_call_status_flags(
4344 proto_tree_add_int(oer_tree, hf_tns_data_oer_call_status, tvb, oer_start, offset - oer_start, v),
4345 tvb, oer_start, offset - oer_start, (uint32_t)v);
4346 /* end-to-end seq# (skipped) */
4347 offset += get_sb4_custom(tvb, offset, &v);
4348 /* rowcount: the rows the call applied, whether it went on
4349 * to fail or not */
4350 int rc_start = offset;
4351 uint64_t rows_done;
4352 offset += get_sb4_custom(tvb, offset, &v);
4353 proto_tree_add_int(oer_tree, hf_tns_data_oer_rowcount, tvb, rc_start, offset - rc_start, v);
4354 rows_done = (uint64_t)(uint32_t)v;
4355 /* err_code (ORA-NNNNN, 0 on success) */
4356 int ec_start = offset;
4357 int err_code = 0;
4358 offset += get_sb4_custom(tvb, offset, &err_code);
4359 proto_tree_add_int(oer_tree, hf_tns_data_oer_err_code, tvb, ec_start, offset - ec_start, err_code);
4360 /* array elem error #1, #2 (skipped) */
4361 offset += get_sb4_custom(tvb, offset, &v);
4362 offset += get_sb4_custom(tvb, offset, &v);
4363 /* cursor_id */
4364 int ci_start = offset;
4365 offset += get_sb4_custom(tvb, offset, &v);
4366 proto_tree_add_int(oer_tree, hf_tns_data_oer_cursor_id, tvb, ci_start, offset - ci_start, v);
4367 /* The status of an execute that opened a new cursor names it:
4368 * its bind types now belong to that cursor id. */
4369 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && v != 0 )
4370 {
4371 tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
4372 if ( tns_info->pending_binds )
4373 {
4374 wmem_map_insert(tns_info->cursor_binds, GUINT_TO_POINTER(v)((gpointer) (gulong) (v)), tns_info->pending_binds);
4375 tns_info->pending_binds = NULL((void*)0);
4376 }
4377 }
4378 /* error position (skipped) */
4379 offset += get_sb4_custom(tvb, offset, &v);
4380 /* 6 single-byte fields: sql_type, fatal, flags,
4381 * user_cursor_opts, upi_param, warn_flags. Five are
4382 * diagnostic; the last is not. Its bit 0x20 says the
4383 * statement created a PL/SQL object that compiled with
4384 * errors - the call succeeded, the error code is 0 and the
4385 * reply is otherwise indistinguishable from a clean one, so
4386 * this bit is the only sign the object is invalid. */
4387 offset += 5;
4388 tns_add_warn_flags(tvb, pinfo, oer_tree, offset);
4389 offset += 1;
4390 /* rowid: ub4 rba, ub2 part_id, 1 byte reserved, ub4 block, ub2 slot */
4391 offset += get_sb4_custom(tvb, offset, &v);
4392 offset += get_sb4_custom(tvb, offset, &v);
4393 offset += 1;
4394 offset += get_sb4_custom(tvb, offset, &v);
4395 offset += get_sb4_custom(tvb, offset, &v);
4396 /* os error (skipped) */
4397 offset += get_sb4_custom(tvb, offset, &v);
4398 /* statement #, call # (1 byte each) */
4399 offset += 2;
4400 /* padding ub2 + successful iterations ub4 */
4401 offset += get_sb4_custom(tvb, offset, &v);
4402 offset += get_sb4_custom(tvb, offset, &v);
4403 /* oerrdd (logical rowid), a bytes_with_length — skipped */
4404 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
4405
4406 /* Batch error arrays (array DML). The code and offset arrays
4407 * are each a ub4 count followed by one DALC packing that many
4408 * ub4 values back to back; the message array is a ub4 count,
4409 * an indicator byte, and then that many str_with_length
4410 * entries each with a 2-byte trailer. All three counts are
4411 * zero for an ordinary statement. */
4412 int n_codes = 0, n_offs = 0, n_msgs = 0;
4413 int nb_start = offset;
4414 offset += get_sb4_custom(tvb, offset, &n_codes);
4415 proto_tree_add_int(oer_tree, hf_tns_data_oer_n_batch_errcodes, tvb, nb_start, offset - nb_start, n_codes);
4416 if ( n_codes > 0 )
4417 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
4418 nb_start = offset;
4419 offset += get_sb4_custom(tvb, offset, &n_offs);
4420 proto_tree_add_int(oer_tree, hf_tns_data_oer_n_batch_offsets, tvb, nb_start, offset - nb_start, n_offs);
4421 if ( n_offs > 0 )
4422 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
4423 nb_start = offset;
4424 offset += get_sb4_custom(tvb, offset, &n_msgs);
4425 proto_tree_add_int(oer_tree, hf_tns_data_oer_n_batch_messages, tvb, nb_start, offset - nb_start, n_msgs);
4426 if ( n_msgs > 0 )
4427 {
4428 offset += 1;
4429 for ( int i = 0; i < n_msgs; i++ )
4430 {
4431 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
4432 offset += 2;
4433 }
4434 }
4435
4436 /* From 12.1 the block goes on with the error number and row
4437 * count at their full widths (a ub4 and a ub8), and from 20.1
4438 * with the SQL type and a server checksum. The extended error
4439 * number is the one that says whether a message follows.
4440 * The first pair follows the negotiated field version, the
4441 * second the server's own release: a 21c or later server
4442 * sends it even to a session that settled on 12.1 or 19c. */
4443 unsigned fv = tns_field_version(pinfo);
4444 unsigned server_fv = tns_server_field_version(pinfo);
4445 if ( fv >= TNS_FV_12_17 )
4446 {
4447 uint64_t rows = 0;
4448 int start = offset;
4449 offset += get_sb4_custom(tvb, offset, &err_code);
4450 proto_tree_add_uint(oer_tree, hf_tns_data_oer_err_num_ext, tvb, start, offset - start, err_code);
4451 start = offset;
4452 offset += get_ub8_custom(tvb, offset, &rows);
4453 proto_tree_add_uint64(oer_tree, hf_tns_data_oer_rowcount_ext, tvb, start, offset - start, rows);
4454 rows_done = rows;
4455 }
4456 if ( fv >= TNS_FV_12_17 && (server_fv ? server_fv : fv) >= TNS_FV_20_114 )
4457 {
4458 int start = offset;
4459 offset += get_sb4_custom(tvb, offset, &v);
4460 proto_tree_add_uint(oer_tree, hf_tns_data_oer_sql_type, tvb, start, offset - start, v);
4461 start = offset;
4462 offset += get_sb4_custom(tvb, offset, &v);
4463 proto_tree_add_uint(oer_tree, hf_tns_data_oer_checksum, tvb, start, offset - start, v);
4464 }
4465
4466 /* Trailing message DALC — present (and meaningful) only when
4467 * err_code is non-zero. */
4468 if ( err_code != 0 && tvb_reported_length_remaining(tvb, offset) > 0 )
4469 {
4470 const char *msg = NULL((void*)0);
4471 int msg_start = offset;
4472 offset += get_dalc_custom(tvb, pinfo, offset, &msg);
4473 msg = tns_trim_message(pinfo, msg);
4474 if ( msg )
4475 {
4476 proto_tree_add_string(oer_tree, hf_tns_data_oer_message, tvb, msg_start, offset - msg_start, msg);
4477 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", msg);
4478 }
4479 }
4480 /* A call that failed part-way through - an array DML whose
4481 * later iteration raised - still applied the rows before the
4482 * one that raised, and this is where it says how many. */
4483 if ( err_code != 0 && rows_done != 0 )
4484 col_append_fstr(pinfo->cinfo, COL_INFO, " [%" PRIu64"l" "u" " rows applied]", rows_done);
4485 proto_item_set_len(oer_item, offset - oer_start);
4486 /* With the field version known the block ends where it
4487 * should, so an end-of-response marker after it can be read. */
4488 ctx->walk = fv != 0;
4489 break;
4490 }
4491
4492 case SQLNET_FUNCCOMPLETE9:
4493 {
4494 /* TTI_STA: a bare status, with no error block. It answers a
4495 * commit, a rollback or a logoff: a ub4 call status and the
4496 * ub2 end-to-end sequence number. */
4497 int v = 0, start;
4498
4499 if ( is_request )
4500 break;
4501
4502 start = offset;
4503 offset += get_sb4_custom(tvb, offset, &v);
4504 tns_add_call_status_flags(
4505 proto_tree_add_uint(data_tree, hf_tns_data_sta_call_status, tvb, start, offset - start, v),
4506 tvb, start, offset - start, (uint32_t)v);
4507 start = offset;
4508 offset += get_sb4_custom(tvb, offset, &v);
4509 proto_tree_add_uint(data_tree, hf_tns_data_sta_seq, tvb, start, offset - start, v);
4510 ctx->walk = true1;
4511 break;
4512 }
4513
4514 case SQLNET_LOB_FILE_DF14:
4515 {
4516 /* LOB content: what a TTI_LOBOPS READ returns, ahead of the
4517 * return parameters. Raw bytes for a BLOB or BFILE, the LOB's
4518 * character set (usually UTF-16BE) for a CLOB. */
4519 int start = offset;
4520
4521 if ( is_request )
4522 break;
4523
4524 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
4525 if ( tvb_get_uint8(tvb, start) == 0xfe ) /* chunked: shown whole */
4526 proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start, offset - start, ENC_NA0x00000000);
4527 else if ( offset - start > 1 )
4528 proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start + 1, offset - start - 1, ENC_NA0x00000000);
4529
4530 /* A CLOB's content is text; the locator the read named says
4531 * how it is encoded. */
4532 const tns_call_t *call = tns_answered_call(pinfo);
4533 if ( call && call->func == TTI_LOBOPS96 && call->lob_flags_known
4534 && (call->lob_flags[0] & (TNS_LOB_LOC_FLAGS_CLOB0x02 | TNS_LOB_LOC_FLAGS_NCLOB0x04)) )
4535 {
4536 int len = 0;
4537 const uint8_t *data = tns_dalc_bytes(tvb, pinfo, start, &len);
4538 const uint8_t *text = NULL((void*)0);
4539
4540 if ( data && (call->lob_flags[0] & TNS_LOB_LOC_FLAGS_NCLOB0x04) )
4541 text = get_utf_16_string(pinfo->pool, data, len, ENC_BIG_ENDIAN0x00000000);
4542 else if ( data && (call->lob_flags[2] & TNS_LOB_LOC_FLAGS_VAR_LENGTH_CHARSET0x80) )
4543 text = get_utf_16_string(pinfo->pool, data, len,
4544 (call->lob_flags[3] & TNS_LOB_LOC_FLAGS_LITTLE_ENDIAN0x40) ? ENC_LITTLE_ENDIAN0x80000000 : ENC_BIG_ENDIAN0x00000000);
4545 else if ( data )
4546 text = get_utf_8_string(pinfo->pool, data, len);
4547 if ( text )
4548 proto_item_set_generated(proto_tree_add_string(data_tree, hf_tns_data_lob_text, tvb,
4549 start, offset - start, (const char *)text));
4550 }
4551 ctx->walk = true1;
4552 break;
4553 }
4554
4555 case SQLNET_WARNING15:
4556 {
4557 /* TTI_WRN: a warning that does not fail the call - PL/SQL
4558 * compiled with errors, say. A ub2 warning number, a ub2
4559 * message length and ub2 flags, then the message itself when
4560 * both are non-zero. */
4561 int code = 0, len = 0, v = 0, start;
4562
4563 if ( is_request )
4564 break;
4565
4566 start = offset;
4567 offset += get_sb4_custom(tvb, offset, &code);
4568 proto_tree_add_uint(data_tree, hf_tns_data_wrn_code, tvb, start, offset - start, code);
4569 start = offset;
4570 offset += get_sb4_custom(tvb, offset, &len);
4571 proto_tree_add_uint(data_tree, hf_tns_data_wrn_length, tvb, start, offset - start, len);
4572 start = offset;
4573 offset += get_sb4_custom(tvb, offset, &v);
4574 proto_tree_add_uint(data_tree, hf_tns_data_wrn_flags, tvb, start, offset - start, v);
4575 if ( code != 0 && len > 0 )
4576 {
4577 const char *msg = NULL((void*)0);
4578 start = offset;
4579 offset += get_dalc_custom(tvb, pinfo, offset, &msg);
4580 msg = tns_trim_message(pinfo, msg);
4581 if ( msg )
4582 {
4583 proto_tree_add_string(data_tree, hf_tns_data_wrn_message, tvb, start, offset - start, msg);
4584 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", msg);
4585 }
4586 }
4587 ctx->walk = true1;
4588 break;
4589 }
4590
4591 case SQLNET_SERVER_PIGGYBACK23:
4592 {
4593 /* A piggyback from the server: state it pushes to the client
4594 * alongside a reply, selected by an opcode. Layouts follow
4595 * python-oracledb's _process_server_side_piggyback. */
4596 int v = 0, num = 0, start;
4597 uint8_t opcode;
4598
4599 if ( is_request )
4600 break;
4601
4602 proto_tree_add_item_ret_uint8(data_tree, hf_tns_data_spb_opcode, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &opcode);
4603 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
4604 val_to_str_const(opcode, tns_spb_opcodes, "unknown"));
4605 offset += 1;
4606 switch ( opcode )
4607 {
4608 case TNS_SPB_QUERY_CACHE_INVALIDATION1:
4609 case TNS_SPB_TRACE_EVENT3:
4610 break;
4611 case TNS_SPB_LTXID7:
4612 offset += get_sb4_custom(tvb, offset, &v);
4613 if ( v > 0 )
4614 {
4615 start = offset;
4616 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
4617 proto_tree_add_item(data_tree, hf_tns_data_spb_ltxid, tvb, start + 1, offset - start - 1, ENC_NA0x00000000);
4618 }
4619 break;
4620 case TNS_SPB_OS_PID_MTS2:
4621 {
4622 const char *pid = NULL((void*)0);
4623 offset += get_sb4_custom(tvb, offset, &v);
4624 start = offset;
4625 offset += get_dalc_custom(tvb, pinfo, offset, &pid);
4626 if ( pid )
4627 proto_tree_add_string(data_tree, hf_tns_data_spb_os_pid, tvb, start, offset - start, pid);
4628 break;
4629 }
4630 case TNS_SPB_SYNC5:
4631 /* Session state the statement changed - a new current
4632 * schema, edition or NLS setting - as key/value pairs. */
4633 offset += get_sb4_custom(tvb, offset, &v); /* number of DTYs */
4634 offset += 1; /* length of DTYs */
4635 start = offset;
4636 offset += get_sb4_custom(tvb, offset, &num);
4637 proto_tree_add_uint(data_tree, hf_tns_data_spb_num_kv, tvb, start, offset - start, num);
4638 offset += 1; /* length */
4639 offset = dissect_tns_kv_pairs(tvb, pinfo, data_tree, offset, num);
4640 start = offset;
4641 offset += get_sb4_custom(tvb, offset, &v);
4642 proto_tree_add_uint(data_tree, hf_tns_data_spb_flags, tvb, start, offset - start, v);
4643 break;
4644 case TNS_SPB_EXT_SYNC9:
4645 offset += get_sb4_custom(tvb, offset, &v); /* number of DTYs */
4646 offset += 1; /* length of DTYs */
4647 break;
4648 case TNS_SPB_AC_REPLAY_CONTEXT8:
4649 offset += get_sb4_custom(tvb, offset, &v); /* number of DTYs */
4650 offset += 1; /* length of DTYs */
4651 offset += get_sb4_custom(tvb, offset, &v); /* flags */
4652 offset += get_sb4_custom(tvb, offset, &v); /* error code */
4653 offset += 1; /* queue */
4654 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0)); /* replay context */
4655 break;
4656 case TNS_SPB_SESS_RET4:
4657 offset += get_sb4_custom(tvb, offset, &v); /* number of DTYs */
4658 offset += 1; /* length of DTYs */
4659 offset += get_sb4_custom(tvb, offset, &num);
4660 if ( num > 0 )
4661 {
4662 offset += 1;
4663 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4664 {
4665 offset += get_sb4_custom(tvb, offset, &v); /* key */
4666 if ( v > 0 )
4667 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
4668 offset += get_sb4_custom(tvb, offset, &v); /* value */
4669 if ( v > 0 )
4670 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
4671 offset += get_sb4_custom(tvb, offset, &v); /* flags */
4672 }
4673 }
4674 start = offset;
4675 offset += get_sb4_custom(tvb, offset, &v);
4676 proto_tree_add_uint(data_tree, hf_tns_data_spb_flags, tvb, start, offset - start, v);
4677 start = offset;
4678 offset += get_sb4_custom(tvb, offset, &v);
4679 proto_tree_add_uint(data_tree, hf_tns_data_spb_session_id, tvb, start, offset - start, v);
4680 start = offset;
4681 offset += get_sb4_custom(tvb, offset, &v);
4682 proto_tree_add_uint(data_tree, hf_tns_data_spb_serial_num, tvb, start, offset - start, v);
4683 break;
4684 case TNS_SPB_SESS_SIGNATURE10:
4685 {
4686 uint64_t u = 0;
4687 offset += get_sb4_custom(tvb, offset, &v); /* number of DTYs */
4688 offset += 1; /* length of DTYs */
4689 offset += get_ub8_custom(tvb, offset, &u); /* signature flags */
4690 offset += get_ub8_custom(tvb, offset, &u); /* client signature */
4691 offset += get_ub8_custom(tvb, offset, &u); /* server signature */
4692 break;
4693 }
4694 default:
4695 /* Unknown opcode: its length is unknown too. */
4696 return offset;
4697 }
4698 ctx->walk = true1;
4699 break;
4700 }
4701
4702 case SQLNET_IMPLICIT_RESULTS27:
4703 {
4704 /* The result sets a PL/SQL block returned with
4705 * DBMS_SQL.RETURN_RESULT: a ub4 count, then per result a
4706 * length-prefixed opaque blob, the describe of its columns,
4707 * and the ub2 cursor id the client fetches it with. */
4708 int num = 0, start;
4709
4710 if ( is_request )
4711 break;
4712
4713 start = offset;
4714 offset += get_sb4_custom(tvb, offset, &num);
4715 proto_tree_add_uint(data_tree, hf_tns_data_irs_num_results, tvb, start, offset - start, num);
4716 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4717 {
4718 proto_tree *rs_tree;
4719 proto_item *rs_item;
4720 int rs_start = offset, cursor = 0;
4721
4722 rs_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, -1,
4723 ett_tns_irs, &rs_item, "Result Set %d", i + 1);
4724 offset += 1 + tvb_get_uint8(tvb, offset);
4725 offset = dissect_tns_describe_body(tvb, pinfo, rs_tree, offset, NULL((void*)0));
4726 start = offset;
4727 offset += get_sb4_custom(tvb, offset, &cursor);
4728 proto_tree_add_uint(rs_tree, hf_tns_cursor, tvb, start, offset - start, cursor);
4729 proto_item_append_text(rs_item, ": cursor %d", cursor);
4730 proto_item_set_len(rs_item, offset - rs_start);
4731 }
4732 ctx->walk = true1;
4733 break;
4734 }
4735
4736 case SQLNET_TOKEN33:
4737 {
4738 /* the token of the call this answers */
4739 uint64_t token = 0;
4740 int start = offset;
4741
4742 if ( is_request )
4743 break;
4744 offset += get_ub8_custom(tvb, offset, &token);
4745 proto_tree_add_uint64(data_tree, hf_tns_data_token, tvb, start, offset - start, token);
4746 ctx->walk = true1;
4747 break;
4748 }
4749
4750 case SQLNET_FLUSH_BIND_DATA19:
4751 /* Sent when a DML with a RETURNING clause fails: the client
4752 * drops the out-bind data it was collecting. There is no
4753 * body, and the error follows. */
4754 if ( !is_request )
4755 ctx->walk = true1;
4756 break;
4757
4758 case SQLNET_END_OF_RESPONSE29:
4759 /* Marks the end of a response for a client that negotiated
4760 * it; there is no body. */
4761 ctx->walk = true1;
4762 break;
4763
4764 case SQLNET_IOVEC_4FAST_UPI11:
4765 {
4766 /* TTI_IOV: the server's I/O vector for an executed anonymous
4767 * PL/SQL block that carried bind variables. It lists each
4768 * bind's direction (IN / OUT / IN OUT); when any bind is
4769 * OUT / IN OUT the returned values follow as a TTI_RXD row.
4770 * Layout cross-referenced with python-oracledb's
4771 * _process_io_vector, and
4772 * verified against XE 11g.
4773 *
4774 * All the leading counters are stored in the ub4 variable-
4775 * length form (see get_sb4_custom). The per-bind directions
4776 * are one raw byte each. The trailing RXD values need each
4777 * bind's declared type to decode, so they are read only when
4778 * the execute this answers was seen. */
4779 int num_requests = 0, num_iters = 0, v = 0, bv_len = 0, rid_len = 0;
4780
4781 if ( !is_request )
4782 {
4783 /* flag (ub1, skip) */
4784 offset += 1;
4785 offset += get_sb4_custom(tvb, offset, &num_requests);
4786 offset += get_sb4_custom(tvb, offset, &num_iters);
4787 int num_binds = num_iters * 256 + num_requests;
4788 proto_tree_add_uint(data_tree, hf_tns_data_iov_num_binds, tvb, offset, 0, num_binds);
4789 /* num iters this time (skip) */
4790 offset += get_sb4_custom(tvb, offset, &v);
4791 /* uac buffer length (skip) */
4792 offset += get_sb4_custom(tvb, offset, &v);
4793 /* fast-fetch bit-vector: length + bytes (skip) */
4794 offset += get_sb4_custom(tvb, offset, &bv_len);
4795 if ( bv_len > 0 )
4796 offset += bv_len;
4797 /* rowid: length + bytes (skip) */
4798 offset += get_sb4_custom(tvb, offset, &rid_len);
4799 if ( rid_len > 0 )
4800 offset += rid_len;
4801
4802 /* Per-bind direction bytes, in bind order. Bound by both
4803 * the reported count and the bytes actually present so a
4804 * malformed vector cannot run away. */
4805 proto_tree *iov_tree;
4806 proto_item *iov_item;
4807 int iov_start = offset;
4808 iov_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_iov, &iov_item, "Bind Directions");
4809 for ( int i = 0; i < num_binds && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4810 {
4811 proto_tree_add_item(iov_tree, hf_tns_data_iov_bind_dir, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4812 offset += 1;
4813 }
4814 proto_item_set_len(iov_item, offset - iov_start);
4815
4816 /* The OUT and IN OUT values follow as a TTI_RXD, typed by
4817 * the binds of the execute this answers - readable only
4818 * when that execute was seen and bound as many. */
4819 const tns_call_t *call = tns_answered_call(pinfo);
4820 if ( call && call->binds && call->num_binds == (uint32_t)num_binds
4821 && offset - iov_start == num_binds )
4822 {
4823 ctx->out_call = call;
4824 ctx->bind_dirs = tvb_memdup(pinfo->pool, tvb, iov_start, num_binds);
4825 ctx->walk = true1;
4826 }
4827 }
4828 break;
4829 }
4830
4831 case SQLNET_DESCRIBE_INFO16:
4832 {
4833 /* TTI_DCB: describe (column metadata) for a SELECT result set,
4834 * in the Oracle 11g shape: a preamble, then the describe body.
4835 * The columns are remembered, once, so a later TTI_RXD can
4836 * split its row values. */
4837 tns_describe_t *desc = NULL((void*)0);
4838
4839 if ( is_request )
4840 break;
4841
4842 /* describe-info preamble (chunked bytes: cursor uuid + date) */
4843 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
4844 offset = dissect_tns_describe_body(tvb, pinfo, data_tree, offset,
4845 PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) ? NULL((void*)0) : &desc);
4846 if ( desc )
4847 tns_get_conv_info(pinfo)->last_describe = desc;
4848 ctx->walk = true1;
4849 break;
4850 }
4851
4852 case SQLNET_ROW_TRANSF_HDR6:
4853 {
4854 /* TTI_RXH: row transfer header, precedes the row data in a
4855 * SELECT response. All numeric fields use the ub4 variable-
4856 * length form. Layout cross-referenced with
4857 * python-oracledb's _process_row_header. */
4858 int v = 0, bv_len = 0, start;
4859
4860 if ( is_request )
4861 break;
4862
4863 /* flag (ub1, skip) */
4864 offset += 1;
4865 /* number of requests */
4866 start = offset;
4867 offset += get_sb4_custom(tvb, offset, &v);
4868 proto_tree_add_uint(data_tree, hf_tns_data_rxh_num_requests, tvb, start, offset - start, v);
4869 /* iteration number */
4870 start = offset;
4871 offset += get_sb4_custom(tvb, offset, &v);
4872 proto_tree_add_uint(data_tree, hf_tns_data_rxh_iter_num, tvb, start, offset - start, v);
4873 /* number of iterations */
4874 start = offset;
4875 offset += get_sb4_custom(tvb, offset, &v);
4876 proto_tree_add_uint(data_tree, hf_tns_data_rxh_num_iters, tvb, start, offset - start, v);
4877 /* buffer length (ub4, skip) */
4878 offset += get_sb4_custom(tvb, offset, &v);
4879 /* bit vector: length + [repeated length byte + vector bytes],
4880 * saying which columns the first row sends */
4881 offset += get_sb4_custom(tvb, offset, &bv_len);
4882 if ( bv_len > 0 )
4883 {
4884 offset += 1; /* repeated length byte */
4885 proto_tree_add_item(data_tree, hf_tns_data_bit_vector, tvb, offset, bv_len, ENC_NA0x00000000);
4886 ctx->bit_vector = tvb_memdup(pinfo->pool, tvb, offset, bv_len);
4887 ctx->bit_vector_len = bv_len;
4888 offset += bv_len; /* bit vector */
4889 }
4890 /* rxhrid (bytes_with_length, skip) */
4891 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
4892 ctx->walk = true1;
4893 break;
4894 }
4895
4896 case SQLNET_BIT_VECTOR21:
4897 {
4898 /* TTI_BVC: which columns the next row sends. A row that
4899 * repeats values from the row before sends only the ones that
4900 * changed, and the clear bits name those it left out. A ub2
4901 * count of columns sent, then one bit per described column. */
4902 tns_describe_t *desc;
4903 int v = 0, start;
4904
4905 if ( is_request )
4906 break;
4907
4908 start = offset;
4909 offset += get_sb4_custom(tvb, offset, &v);
4910 proto_tree_add_uint(data_tree, hf_tns_data_bvc_num_cols_sent, tvb, start, offset - start, v);
4911 desc = tns_current_describe(pinfo);
4912 if ( !desc )
4913 break;
4914 unsigned bv_len = (desc->num_cols + 7) / 8;
4915 proto_tree_add_item(data_tree, hf_tns_data_bit_vector, tvb, offset, bv_len, ENC_NA0x00000000);
4916 ctx->bit_vector = tvb_memdup(pinfo->pool, tvb, offset, bv_len);
4917 ctx->bit_vector_len = bv_len;
4918 offset += bv_len;
4919 ctx->walk = true1;
4920 break;
4921 }
4922
4923 case SQLNET_ROW_TRANSF_DATA7:
4924 {
4925 /* TTI_RXD: row data for a SELECT result set — typically a
4926 * TTI_FETCH continuation, where the describe (TTI_DCB) arrived
4927 * in an earlier packet. Split each row into columns using the
4928 * types remembered from that describe (threaded through
4929 * conversation state); ordinary values are shown raw.
4930 *
4931 * The leading RXD token was already consumed above, so offset
4932 * sits on the first row's first value. A row that follows a
4933 * bit vector sends only the columns whose bit is set. */
4934 tns_describe_t *desc;
4935
4936 if ( is_request )
4937 break;
4938
4939 if ( ctx->bind_dirs )
4940 {
4941 /* The OUT and IN OUT bind values of a PL/SQL execute, in
4942 * bind order, each followed by its sb4 return code. Out of
4943 * a fetch, ROWID and UROWID come as strings and a LONG has
4944 * no trailing indicators. */
4945 proto_tree *ob_tree;
4946 proto_item *ob_item;
4947 int ob_start = offset, rc = 0, start;
4948
4949 ob_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
4950 ett_tns_out_binds, &ob_item, "Out Binds");
4951 for ( uint32_t i = 0; i < ctx->out_call->num_binds
4952 && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4953 {
4954 uint8_t btype = ctx->out_call->binds[i].type;
4955 if ( ctx->bind_dirs[i] == TNS_BIND_DIR_INPUT32 )
4956 continue;
4957 if ( btype == TNS_DATATYPE_ROWID11 || btype == TNS_DATATYPE_UROWID208
4958 || btype == TNS_DATATYPE_LONG8 )
4959 btype = TNS_DATATYPE_VARCHAR1;
4960 else if ( btype == TNS_DATATYPE_LONG_RAW24 )
4961 btype = TNS_DATATYPE_RAW23;
4962 offset = dissect_tns_value(tvb, pinfo, ob_tree, offset, btype,
4963 ctx->out_call->binds[i].csform, i + 1,
4964 hf_tns_data_bind_value, "Bind");
4965 start = offset;
4966 offset += get_sb4_custom(tvb, offset, &rc);
4967 proto_tree_add_int(ob_tree, hf_tns_data_bind_retcode, tvb, start, offset - start, rc);
4968 }
4969 proto_item_set_len(ob_item, offset - ob_start);
4970 ctx->bind_dirs = NULL((void*)0);
4971 ctx->walk = true1;
4972 break;
4973 }
4974
4975 const tns_call_t *rcall = tns_answered_call(pinfo);
4976 if ( rcall && rcall->num_return > 0 && rcall->binds )
4977 {
4978 /* The values a DML RETURNING ... INTO returned: for each
4979 * return bind a ub4 row count - every row the statement
4980 * touched - then that many values, each followed by its
4981 * sb4 return code. */
4982 proto_tree *rv_tree;
4983 proto_item *rv_item;
4984 int rv_start = offset, rc = 0, start;
4985
4986 rv_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
4987 ett_tns_out_binds, &rv_item, "Returned Values");
4988 for ( uint32_t i = rcall->num_binds - rcall->num_return; i < rcall->num_binds
4989 && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4990 {
4991 int rows = 0;
4992 offset += get_sb4_custom(tvb, offset, &rows);
4993 for ( int j = 0; j < rows && tvb_reported_length_remaining(tvb, offset) > 0; j++ )
4994 {
4995 offset = dissect_tns_value(tvb, pinfo, rv_tree, offset, rcall->binds[i].type,
4996 rcall->binds[i].csform, i + 1, hf_tns_data_bind_value, "Bind");
4997 start = offset;
4998 offset += get_sb4_custom(tvb, offset, &rc);
4999 proto_tree_add_int(rv_tree, hf_tns_data_bind_retcode, tvb, start, offset - start, rc);
5000 }
5001 }
5002 proto_item_set_len(rv_item, offset - rv_start);
5003 ctx->walk = true1;
5004 break;
5005 }
5006
5007 desc = tns_current_describe(pinfo);
5008
5009 if ( desc && desc->num_cols > 0 )
5010 {
5011 int rownum = 0, first_row = 1;
5012 while ( tvb_reported_length_remaining(tvb, offset) > 0 )
5013 {
5014 proto_tree *row_tree;
5015 proto_item *row_item;
5016 int r_start;
5017
5018 if ( !first_row )
5019 {
5020 if ( tvb_get_uint8(tvb, offset) != SQLNET_ROW_TRANSF_DATA7 )
5021 break;
5022 offset += 1; /* RXD token for subsequent rows */
5023 }
5024 first_row = 0;
5025
5026 r_start = offset;
5027 row_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, -1,
5028 ett_tns_rxd_row, &row_item, "Row %d", ++rownum);
5029 for ( uint32_t c = 0; c < desc->num_cols
5030 && tvb_reported_length_remaining(tvb, offset) > 0; c++ )
5031 {
5032 const tns_column_t *col = &desc->cols[c];
5033 if ( ctx->bit_vector && c / 8 < ctx->bit_vector_len
5034 && !(ctx->bit_vector[c / 8] & (1 << (c % 8))) )
5035 {
5036 proto_tree_add_bytes_format(row_tree, hf_tns_data_col_value,
5037 tvb, offset, 0, NULL((void*)0), "Column %u (%s): same as previous row",
5038 c + 1, val_to_str_const(col->type, tns_data_types, "unknown"));
5039 continue;
5040 }
5041 /* A column the describe gives no data length is
5042 * NULL by definition (SELECT NULL, SELECT '')
5043 * and sends no bytes at all - not even an empty
5044 * DALC. LONG, LONG RAW and UROWID are the
5045 * exceptions: they always carry their value. */
5046 if ( col->data_len == 0 && col->type != TNS_DATATYPE_LONG8
5047 && col->type != TNS_DATATYPE_LONG_RAW24
5048 && col->type != TNS_DATATYPE_UROWID208 )
5049 {
5050 proto_tree_add_bytes_format(row_tree, hf_tns_data_col_value,
5051 tvb, offset, 0, NULL((void*)0), "Column %u (%s): NULL (no data length)",
5052 c + 1, val_to_str_const(col->type, tns_data_types, "unknown"));
5053 continue;
5054 }
5055 offset = dissect_tns_value(tvb, pinfo, row_tree, offset,
5056 col->type, col->csform, c + 1, hf_tns_data_col_value, "Column");
5057 }
5058 proto_item_set_len(row_item, offset - r_start);
5059 /* A bit vector covers one row only. */
5060 ctx->bit_vector = NULL((void*)0);
5061 }
5062 ctx->walk = true1;
5063 }
5064 break;
5065 }
5066
5067 case SQLNET_USER_OCI_FUNC3:
5068 {
5069 guint32 oci_id = 0;
5070 tns_call_t *call;
5071 int fun_start = offset - 1; /* the TTI_FUN byte */
5072 proto_tree_add_item_ret_uint(data_tree, hf_tns_data_oci_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &oci_id);
5073 offset += 1;
5074 call = is_request ? tns_remember_call(pinfo, (uint8_t)oci_id) : NULL((void*)0);
5075 /* Name the specific OCI call in the Info column — otherwise every
5076 * function call reads only as the generic "User OCI Functions". */
5077 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
5078 val_to_str_ext_const(oci_id, &tns_data_oci_subfuncs_ext, "unknown"));
5079 proto_tree_add_item(data_tree, hf_tns_data_tseq, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
5080 offset += 1;
5081 offset = dissect_tns_call_token(tvb, pinfo, data_tree, offset);
5082 if((oci_id == 115) || (oci_id == 118)){
5083 /* The two authentication calls: the session key request
5084 * (118) and the authentication itself (115). A pointer
5085 * and a ub4 user name length, the ub4 mode, a pointer, the
5086 * ub4 number of key/value pairs, two pointers, the user
5087 * name, and the pairs - each a key and a value with two
5088 * lengths and a ub4 flags word. The first call's pairs
5089 * carry the client's identity (program, machine, terminal,
5090 * process id, OS user), which is what the server records
5091 * for the session; the second's the proof, the driver name
5092 * and the session settings. */
5093 int user_len = 0, mode = 0, num = 0, start;
5094 proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 1, ENC_NA0x00000000);
5095 offset += 1;
5096 offset += get_sb4_custom(tvb, offset, &user_len);
5097 start = offset;
5098 offset += get_sb4_custom(tvb, offset, &mode);
5099 proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_auth_mode,
5100 ett_tns_auth_mode, tns_auth_modes, (uint64_t)(uint32_t)mode);
5101 offset += 1; /* pointer */
5102 start = offset;
5103 offset += get_sb4_custom(tvb, offset, &num);
5104 proto_tree_add_uint(data_tree, hf_tns_data_opi_num_of_params, tvb, start, offset - start, num);
5105 offset += 2; /* pointers */
5106 if ( user_len > 0 )
5107 {
5108 const char *user = NULL((void*)0);
5109 start = offset;
5110 offset += get_dalc_custom(tvb, pinfo, offset, &user);
5111 if ( user )
5112 {
5113 proto_tree_add_string(data_tree, hf_tns_data_auth_user, tvb, start, offset - start, user);
5114 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", user);
5115 }
5116 }
5117 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
5118 {
5119 proto_tree *par_tree;
5120 proto_item *par_ti;
5121 const char *key = NULL((void*)0), *value = NULL((void*)0);
5122 int v = 0, par_start = offset;
5123
5124 par_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, -1,
5125 ett_tns_opi_par, &par_ti, "Parameter %d", i + 1);
5126 start = offset;
5127 offset += get_field_with_length(tvb, pinfo, offset, &key);
5128 if ( key )
5129 proto_tree_add_string(par_tree, hf_tns_data_opi_param_name, tvb, start, offset - start, key);
5130 start = offset;
5131 offset += get_field_with_length(tvb, pinfo, offset, &value);
5132 if ( value )
5133 proto_tree_add_string(par_tree, hf_tns_data_opi_param_value, tvb, start, offset - start, value);
5134 offset += get_sb4_custom(tvb, offset, &v); /* flags */
5135 if ( key )
5136 proto_item_append_text(par_ti, ": %s = %s", key, value ? value : "");
5137 proto_item_set_len(par_ti, offset - par_start);
5138 }
5139 }
5140 else if ( oci_id == TTI_KOD92 && tvb_bytes_exist(tvb, fun_start + TNS_KOD_FRAME99, 4) )
5141 {
5142 /* An object-type describe, sent only by an OCI client: a
5143 * ub4 LE opcode and a frame of zeros, then by name a ub4
5144 * 2, the schema's length, a ub4 0, the name buffer's
5145 * length (three times the name's characters) and the
5146 * name behind a length byte; by REF the REF of the type
5147 * wanted. The bytes after them are not understood. */
5148 uint32_t opcode;
5149 int o = fun_start + TNS_KOD_FRAME99, sys_type;
5150
5151 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
5152 tns_get_conv_info(pinfo)->oci_dialect = true1;
5153 proto_tree_add_item_ret_uint(data_tree, hf_tns_data_kod_opcode, tvb, fun_start + 3, 4, ENC_LITTLE_ENDIAN0x80000000, &opcode);
5154 if ( opcode == TNS_KOD_BY_NAME3 && tvb_bytes_exist(tvb, o, 17) && tvb_get_letohl(tvb, o + 4) == 0 )
5155 {
5156 const char *name;
5157 uint8_t len = tvb_get_uint8(tvb, o + 16);
5158 proto_tree_add_item_ret_string(data_tree, hf_tns_data_kod_name, tvb, o + 17, len, ENC_UTF_80x00000002, pinfo->pool, (const uint8_t **)&name);
5159 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", name);
5160 }
5161 else if ( opcode == TNS_KOD_BY_REF4 )
5162 dissect_tns_kod_ref(tvb, data_tree, o, hf_tns_data_kod_oid, &sys_type);
5163 offset = tvb_reported_length(tvb);
5164 }
5165 else if ( oci_id == TTI_FETCH5 && tns_is_oci(pinfo) && tvb_bytes_exist(tvb, fun_start + 3, 8) )
5166 {
5167 /* An OCI client's fetch: the cursor id and the row count
5168 * as fixed-width little-endian ub4s, right after the
5169 * sequence number. The count is a hard limit - the
5170 * client sizes its fetch buffer to it. */
5171 proto_tree_add_item(data_tree, hf_tns_cursor, tvb, fun_start + 3, 4, ENC_LITTLE_ENDIAN0x80000000);
5172 proto_tree_add_item(data_tree, hf_tns_data_fetch_rows, tvb, fun_start + 7, 4, ENC_LITTLE_ENDIAN0x80000000);
5173 offset = fun_start + 11;
5174 }
5175 else if ( oci_id == TTI_FETCH5 )
5176 {
5177 /* TTI_FETCH: fetch more rows from an open cursor.
5178 * [TTI_FUN, TTI_FETCH, seq] then cursor id and the row
5179 * count, both ub4. */
5180 int v = 0, start;
5181
5182 start = offset;
5183 offset += get_sb4_custom(tvb, offset, &v);
5184 proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, start, offset - start, v);
5185 start = offset;
5186 offset += get_sb4_custom(tvb, offset, &v);
5187 proto_tree_add_uint(data_tree, hf_tns_data_fetch_rows, tvb, start, offset - start, v);
5188 }
5189 else if ( oci_id == TTI_PIPELINE_END200 )
5190 {
5191 /* ends a pipeline begun by the pipeline-begin piggyback: a
5192 * ub4 id, unused */
5193 int v = 0;
5194 offset += get_sb4_custom(tvb, offset, &v);
5195 }
5196 else if ( oci_id == TTI_SESSION_RELEASE163 )
5197 {
5198 /* DRCP: hand the session back to the pool - a tag name
5199 * (a pointer and a length byte) and the release mode */
5200 int v = 0, start;
5201 uint8_t tag_ptr = tvb_get_uint8(tvb, offset);
5202 uint8_t tag_len = tvb_get_uint8(tvb, offset + 1);
5203 offset += 2;
5204 if ( tag_ptr && tag_len > 0 )
5205 {
5206 proto_tree_add_item(data_tree, hf_tns_data_release_tag, tvb, offset, tag_len, ENC_UTF_80x00000002);
5207 offset += tag_len;
5208 }
5209 start = offset;
5210 offset += get_sb4_custom(tvb, offset, &v);
5211 proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_release_mode,
5212 ett_tns_release_mode, tns_release_modes, (uint64_t)(uint32_t)v);
5213 }
5214 else if ( oci_id == TTI_TPC_TXN_SWITCH103 || oci_id == TTI_TPC_TXN_CHANGE_STATE104 )
5215 offset = dissect_tns_tpc_call(tvb, pinfo, data_tree, offset, oci_id);
5216 else if ( oci_id == TTI_REEXECUTE4 || oci_id == TTI_REEXECUTE_AND_FETCH78 )
5217 {
5218 /* Re-execute of a cursor whose statement already ran and
5219 * whose bind types did not change: the cursor id, the
5220 * iteration count (the prefetch size for 78, the number
5221 * of executions for 4) and two options words, then one
5222 * TTI_RXD row of values per iteration with no bind
5223 * descriptors - the values are typed by the execute that
5224 * opened the cursor. */
5225 int v = 0, cursor = 0, start;
5226
5227 start = offset;
5228 offset += get_sb4_custom(tvb, offset, &cursor);
5229 proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, start, offset - start, cursor);
5230 start = offset;
5231 offset += get_sb4_custom(tvb, offset, &v);
5232 proto_tree_add_uint(data_tree, oci_id == TTI_REEXECUTE_AND_FETCH78 ?
5233 hf_tns_data_all8_prefetch : hf_tns_data_reexec_iterations,
5234 tvb, start, offset - start, v);
5235 start = offset;
5236 offset += get_sb4_custom(tvb, offset, &v);
5237 proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_all8_options,
5238 ett_tns_all8_options, tns_all8_options, (uint64_t)(uint32_t)v);
5239 start = offset;
5240 offset += get_sb4_custom(tvb, offset, &v);
5241 proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_reexec_options2,
5242 ett_tns_reexec_options2, tns_reexec_options2, (uint64_t)(uint32_t)v);
5243
5244 tns_binds_t *binds = tns_lookup_cursor_binds(pinfo, cursor);
5245 if ( binds && tvb_reported_length_remaining(tvb, offset) > 0 )
5246 {
5247 proto_item *binds_item;
5248 proto_tree *binds_tree;
5249 int binds_start = offset;
5250
5251 binds_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
5252 ett_tns_binds, &binds_item, "Binds");
5253 /* RETURNING ... INTO binds send no value */
5254 offset = dissect_tns_bind_rows(tvb, pinfo, binds_tree, offset, binds->cols,
5255 binds->count - binds->num_return);
5256 proto_item_set_len(binds_item, offset - binds_start);
5257 }
5258 if ( call && binds )
5259 {
5260 call->num_binds = binds->count;
5261 call->num_return = binds->num_return;
5262 call->binds = binds->cols;
5263 }
5264 }
5265 else if ( oci_id == TTI_ALL894 && tvb_bytes_exist(tvb, fun_start + TNS_OCI_ALL8_IND11, 8)
5266 && tvb_get_ntoh64(tvb, fun_start + TNS_OCI_ALL8_IND11) == TNS_OCI_INDICATOR0xfeffffffffffffffUL )
5267 {
5268 /* An OCI client's execute (sqlplus and other thick
5269 * clients): a fixed preamble of 8-byte pointer indicators
5270 * FE FF FF FF FF FF FF FF with little-endian scalar slots
5271 * between them, and the ub1-length-prefixed SQL at the
5272 * end. Offsets count from the TTI_FUN byte. The scalar
5273 * slots are 8 bytes wide or 4, fixed for a connection;
5274 * the second indicator tells which - it sits at 27 in the
5275 * wide form and 23 in the narrow one, and the two cannot
5276 * both hold. The cursor id and SQL length precede every
5277 * slot and do not move; the bind count and the SQL do.
5278 * A session at the 12c band inserts 64 zero bytes ahead
5279 * of a narrow preamble's SQL, which moves from 176 to
5280 * 240; the byte before the SQL is its length, never
5281 * zero, so which one holds shows. */
5282 int base = fun_start, bind_count_off, sql_off;
5283 uint32_t cursor, sql_len_decl, bind_count;
5284 bool_Bool wide, band_12c = false0;
5285
5286 if ( tvb_bytes_exist(tvb, base + TNS_OCI_ALL8_IND2_WIDE27, 8)
5287 && tvb_get_ntoh64(tvb, base + TNS_OCI_ALL8_IND2_WIDE27) == TNS_OCI_INDICATOR0xfeffffffffffffffUL )
5288 wide = true1;
5289 else if ( tvb_bytes_exist(tvb, base + TNS_OCI_ALL8_IND2_NARROW23, 8)
5290 && tvb_get_ntoh64(tvb, base + TNS_OCI_ALL8_IND2_NARROW23) == TNS_OCI_INDICATOR0xfeffffffffffffffUL )
5291 wide = false0;
5292 else
5293 break;
5294 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
5295 tns_get_conv_info(pinfo)->oci_dialect = true1;
5296
5297 cursor = tvb_get_letohl(tvb, base + TNS_OCI_ALL8_CURSOR7);
5298 /* the SQL length, as the client's character set has it */
5299 sql_len_decl = tvb_get_letohl(tvb, base + TNS_OCI_ALL8_SQLLEN319);
5300 bind_count_off = base + (wide ? 83 : 71);
5301 sql_off = base + (wide ? 196 : 176);
5302 if ( !wide && sql_len_decl > 0 && tvb_bytes_exist(tvb, base + 239, 1)
5303 && tvb_get_uint8(tvb, base + 175) == 0 )
5304 {
5305 uint8_t prefix = tvb_get_uint8(tvb, base + 239);
5306 if ( tns_oci_sql_length_matches(prefix, sql_len_decl) )
5307 {
5308 band_12c = true1;
5309 sql_off = base + 240;
5310 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
5311 tns_get_conv_info(pinfo)->oci_band_12c = true1;
5312 }
5313 }
5314 proto_tree_add_string(data_tree, hf_tns_data_all8_oci_preamble, tvb, base, 0,
5315 wide ? "OCI, wide (8-byte slots)" : band_12c ? "OCI, narrow (4-byte slots), 12c band"
5316 : "OCI, narrow (4-byte slots)");
5317 proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, base + TNS_OCI_ALL8_CURSOR7, 4, cursor);
5318 bind_count = tvb_get_letohl(tvb, bind_count_off);
5319 proto_tree_add_uint(data_tree, hf_tns_data_all8_bind_count, tvb, bind_count_off, 4, bind_count);
5320 if ( sql_len_decl > 0 && tvb_bytes_exist(tvb, sql_off - 1, 1) )
5321 {
5322 const char *sql = NULL((void*)0);
5323 int start = sql_off - 1;
5324 uint8_t prefix = tvb_get_uint8(tvb, start);
5325
5326 if ( tns_oci_sql_length_matches(prefix, sql_len_decl) )
5327 {
5328 offset = start + get_dalc_custom(tvb, pinfo, start, &sql);
5329 if ( sql )
5330 {
5331 /* sqlplus NUL-terminates its own queries; the
5332 * string ends there */
5333 proto_tree_add_string(data_tree, hf_tns_data_all8_sql, tvb, start, offset - start, sql);
5334 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", sql);
5335 }
5336 }
5337 }
5338 }
5339 else if ( oci_id == TTI_ALL894 )
5340 {
5341 /* TTI_ALL8: the generic SQL execute — SELECT, DML and
5342 * PL/SQL all ride this call, in the Oracle 11g shape of a
5343 * thin client, whose integers use the ub4 variable-length
5344 * form. The bind (or define) descriptors and the value
5345 * rows follow the al8 array. */
5346 int v = 0, options = 0, cursor = 0, query_len = 0, all8_len = 0;
5347 int fetch = 0, bind_count = 0, define_count = 0, start;
5348 const uint8_t *sql = NULL((void*)0);
5349 uint8_t query_flag;
5350
5351 /* options (ub4) + flag breakdown */
5352 start = offset;
5353 offset += get_sb4_custom(tvb, offset, &options);
5354 proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_all8_options,
5355 ett_tns_all8_options, tns_all8_options, (uint64_t)(uint32_t)options);
5356 /* An execute that asks for no work is a parse: the client
5357 * wants the statement checked, not run. The PARSE bit does
5358 * not say so - it rides along with EXECUTE on the first
5359 * execute of any statement, and a parse of a statement the
5360 * client already has cached sets no bit at all. */
5361 if ( !(options & (TNS_EXEC_OPTION_EXECUTE0x0020 | TNS_EXEC_OPTION_DEFINE0x0010
5362 | TNS_EXEC_OPTION_FETCH0x0040)) )
5363 {
5364 proto_item_set_generated(proto_tree_add_boolean(data_tree,
5365 hf_tns_data_all8_parse_only, tvb, start, offset - start, true1));
5366 col_append_str(pinfo->cinfo, COL_INFO, " [parse only]");
5367 }
5368 /* cursor id (ub4) */
5369 start = offset;
5370 offset += get_sb4_custom(tvb, offset, &cursor);
5371 proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, start, offset - start, cursor);
5372 /* query present flag (ub1) */
5373 query_flag = tvb_get_uint8(tvb, offset);
5374 offset += 1;
5375 /* query length (ub4) */
5376 offset += get_sb4_custom(tvb, offset, &query_len);
5377 /* all8 present flag (ub1) */
5378 offset += 1;
5379 /* all8 length (ub4) */
5380 offset += get_sb4_custom(tvb, offset, &all8_len);
5381 /* two reserved bytes */
5382 offset += 2;
5383 /* long max value (ub4, skip) */
5384 offset += get_sb4_custom(tvb, offset, &v);
5385 /* fetch rows (ub4) */
5386 start = offset;
5387 offset += get_sb4_custom(tvb, offset, &fetch);
5388 proto_tree_add_uint(data_tree, hf_tns_data_all8_fetch_rows, tvb, start, offset - start, fetch);
5389 /* max value (ub4, skip) */
5390 offset += get_sb4_custom(tvb, offset, &v);
5391 /* bind indicator (ub1) */
5392 offset += 1;
5393 /* bind count (ub4) */
5394 start = offset;
5395 offset += get_sb4_custom(tvb, offset, &bind_count);
5396 proto_tree_add_uint(data_tree, hf_tns_data_all8_bind_count, tvb, start, offset - start, bind_count);
5397 /* The count comes off the wire and sizes an allocation
5398 * further down, so a count larger than the data left
5399 * cannot be real - report it and decode no binds. */
5400 if ( bind_count < 0 ||
5401 (unsigned)bind_count > tvb_reported_length_remaining(tvb, offset) )
5402 {
5403 proto_tree_add_expert(data_tree, pinfo, &ei_tns_data_count_too_large,
5404 tvb, start, offset - start);
5405 bind_count = 0;
5406 }
5407 /* five reserved bytes */
5408 offset += 5;
5409 /* define-columns present flag (ub1) */
5410 offset += 1;
5411 /* define-columns count (ub4) */
5412 start = offset;
5413 offset += get_sb4_custom(tvb, offset, &define_count);
5414 proto_tree_add_uint(data_tree, hf_tns_data_all8_define_count, tvb, start, offset - start, define_count);
5415 if ( define_count < 0 ||
5416 (unsigned)define_count > tvb_reported_length_remaining(tvb, offset) )
5417 {
5418 proto_tree_add_expert(data_tree, pinfo, &ei_tns_data_count_too_large,
5419 tvb, start, offset - start);
5420 define_count = 0;
5421 }
5422 /* registration id (low half), the al8objlist / al8objlen /
5423 * al8blv pointers, al8blvl, the al8dnam pointer, al8dnaml
5424 * and the registration id's high half */
5425 offset += get_sb4_custom(tvb, offset, &v);
5426 offset += 3;
5427 offset += get_sb4_custom(tvb, offset, &v);
5428 offset += 1;
5429 offset += get_sb4_custom(tvb, offset, &v);
5430 offset += get_sb4_custom(tvb, offset, &v);
5431 /* 12.1 adds the per-row DML count block (a pointer, the
5432 * execution count, a pointer), 12.2 the SQL signature and
5433 * SQL id fields, 12.2 ext 1 the chunk ids */
5434 unsigned fv = tns_field_version(pinfo);
5435 if ( fv >= TNS_FV_12_17 )
5436 {
5437 offset += 1;
5438 offset += get_sb4_custom(tvb, offset, &v);
5439 offset += 1;
5440 }
5441 if ( fv >= TNS_FV_12_28 )
5442 {
5443 offset += 1;
5444 offset += get_sb4_custom(tvb, offset, &v);
5445 offset += 1;
5446 offset += get_sb4_custom(tvb, offset, &v);
5447 offset += 1;
5448 }
5449 if ( fv >= TNS_FV_12_2_EXT19 )
5450 {
5451 offset += 1;
5452 offset += get_sb4_custom(tvb, offset, &v);
5453 }
5454 /* SQL text: a flat run of query_len bytes on 11g, length
5455 * prefixed (and chunked when long) from 12.1 */
5456 if ( query_flag && query_len > 0 && fv >= TNS_FV_12_17 )
5457 {
5458 const char *text = NULL((void*)0);
5459 start = offset;
5460 offset += get_dalc_custom(tvb, pinfo, offset, &text);
5461 if ( text )
5462 {
5463 sql = (const uint8_t *)text;
5464 proto_tree_add_string(data_tree, hf_tns_data_all8_sql, tvb, start, offset - start, text);
5465 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", text);
5466 }
5467 }
5468 else if ( query_flag && query_len > 0 )
5469 {
5470 proto_tree_add_item_ret_string(data_tree, hf_tns_data_all8_sql, tvb,
5471 offset, query_len, ENC_UTF_80x00000002|ENC_NA0x00000000, pinfo->pool, &sql);
5472 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", sql);
5473 offset += query_len;
5474 }
5475 /* al8i4 option array: all8_len ub4 elements. Slot 1 is
5476 * the execution count for DML but the number of rows to
5477 * prefetch for a query, and slot 7 says which - so read
5478 * the array before showing any of it. */
5479 {
5480 int al8i4[13] = {0}, al8i4_start[13] = {0}, al8i4_len[13] = {0};
5481 int i4_start = offset;
5482 proto_tree *i4_tree;
5483 proto_item *i4_item;
5484
5485 for ( int i = 0; i < all8_len && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
5486 {
5487 start = offset;
5488 offset += get_sb4_custom(tvb, offset, &v);
5489 if ( i < (int)array_length(al8i4)(sizeof (al8i4) / sizeof (al8i4)[0]) )
5490 {
5491 al8i4[i] = v;
5492 al8i4_start[i] = start;
5493 al8i4_len[i] = offset - start;
5494 }
5495 }
5496 if ( all8_len >= (int)array_length(al8i4)(sizeof (al8i4) / sizeof (al8i4)[0]) )
5497 {
5498 i4_tree = proto_tree_add_subtree(data_tree, tvb, i4_start, offset - i4_start,
5499 ett_tns_all8_i4, &i4_item, "Execute Arguments (al8i4)");
5500 proto_tree_add_uint(i4_tree, al8i4[7] ? hf_tns_data_all8_prefetch : hf_tns_data_all8_iterations,
5501 tvb, al8i4_start[1], al8i4_len[1], al8i4[1]);
5502 proto_tree_add_boolean(i4_tree, hf_tns_data_all8_is_query,
5503 tvb, al8i4_start[7], al8i4_len[7], al8i4[7]);
5504 proto_tree_add_bitmask_value(i4_tree, tvb, al8i4_start[9], hf_tns_data_all8_exec_flags,
5505 ett_tns_all8_exec_flags, tns_all8_exec_flags, (uint64_t)(uint32_t)al8i4[9]);
5506 proto_tree_add_uint(i4_tree, hf_tns_data_all8_fetch_orientation,
5507 tvb, al8i4_start[10], al8i4_len[10], al8i4[10]);
5508 proto_tree_add_uint(i4_tree, hf_tns_data_all8_fetch_pos,
5509 tvb, al8i4_start[11], al8i4_len[11], al8i4[11]);
5510 if ( call )
5511 call->exec_flags = (uint32_t)al8i4[9];
5512 }
5513 }
5514
5515 /* Bind section: one bare OAC descriptor per bind column,
5516 * then one TTI_RXD row of values per iteration. A cached
5517 * re-execute may leave the descriptors out and rely on
5518 * the ones the cursor was opened with. Whether they are
5519 * there is decided by the wire, not by the SQL text: an
5520 * execute with no SQL often still carries them (every
5521 * executemany after the first), and they are absent
5522 * exactly when the bind area starts on a TTI_RXD, in
5523 * which case the types remembered for the cursor apply.
5524 *
5525 * An execute that opens a new cursor (cursor id 0) learns
5526 * its id only from the status that answers it, so its
5527 * bind types wait for that. */
5528 tns_conv_info_t *tns_info = NULL((void*)0);
5529 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
5530 {
5531 tns_info = tns_get_conv_info(pinfo);
5532 if ( cursor == 0 )
5533 tns_info->pending_binds = NULL((void*)0);
5534 }
5535 if ( bind_count > 0 && tvb_reported_length_remaining(tvb, offset) > 0
5536 && tvb_get_uint8(tvb, offset) == SQLNET_ROW_TRANSF_DATA7 )
5537 {
5538 tns_binds_t *binds = cursor ? tns_lookup_cursor_binds(pinfo, cursor) : NULL((void*)0);
5539 if ( binds && binds->count == (uint32_t)bind_count )
5540 {
5541 if ( call )
5542 {
5543 call->num_binds = binds->count;
5544 call->num_return = binds->num_return;
5545 call->binds = binds->cols;
5546 }
5547 proto_item *binds_item;
5548 proto_tree *binds_tree;
5549 int binds_start = offset;
5550
5551 binds_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
5552 ett_tns_binds, &binds_item, "Binds");
5553 offset = dissect_tns_bind_rows(tvb, pinfo, binds_tree, offset, binds->cols,
5554 binds->count - binds->num_return);
5555 proto_item_set_len(binds_item, offset - binds_start);
5556 }
5557 }
5558 else if ( bind_count > 0 && tvb_reported_length_remaining(tvb, offset) > 0 )
5559 {
5560 proto_tree *binds_tree, *bind_tree;
5561 proto_item *binds_item, *bind_item;
5562 int binds_start = offset;
5563 tns_column_t *bcols;
5564
5565 bcols = wmem_alloc0_array(tns_info ? wmem_file_scope() : pinfo->pool, tns_column_t, bind_count)((tns_column_t*)wmem_alloc0((tns_info ? wmem_file_scope() : pinfo
->pool), (((((bind_count)) <= 0) || ((size_t)sizeof(tns_column_t
) > (9223372036854775807L / (size_t)((bind_count))))) ? 0 :
(sizeof(tns_column_t) * ((bind_count))))))
;
5566 binds_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
5567 ett_tns_binds, &binds_item, "Binds");
5568
5569 for ( int i = 0; i < bind_count && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
5570 {
5571 int b_start = offset;
5572 uint8_t btype = tvb_get_uint8(tvb, offset);
5573 bind_tree = proto_tree_add_subtree_format(binds_tree, tvb, offset, -1,
5574 ett_tns_bind, &bind_item, "Bind %d: %s", i + 1,
5575 val_to_str_const(btype, tns_data_types, "unknown"));
5576 offset = dissect_tns_oac(tvb, pinfo, bind_tree, offset, &bcols[i]);
5577 /* Below 12.2 a CLOB/BLOB bind OAC still carries a
5578 * trailing oaccolid byte; from 12.2 every OAC does,
5579 * and the OAC decoder reads it. */
5580 if ( (btype == TNS_DATATYPE_CLOB112 || btype == TNS_DATATYPE_BLOB113)
5581 && tns_field_version(pinfo) < TNS_FV_12_28 )
5582 offset += 1;
5583 proto_item_set_len(bind_item, offset - b_start);
5584 }
5585
5586 /* A DML RETURNING ... INTO statement sends no values for
5587 * its return binds, the last ones. */
5588 unsigned num_return = sql ? tns_count_return_binds((const char *)sql) : 0;
5589 if ( num_return > (unsigned)bind_count )
5590 num_return = 0;
5591
5592 if ( call )
5593 {
5594 call->num_binds = bind_count;
5595 call->num_return = num_return;
5596 call->binds = bcols;
5597 }
5598
5599 /* Remember the types for later executes of the cursor
5600 * that leave the descriptors out. */
5601 if ( tns_info )
5602 {
5603 tns_binds_t *binds = wmem_new0(wmem_file_scope(), tns_binds_t)((tns_binds_t*)wmem_alloc0((wmem_file_scope()), sizeof(tns_binds_t
)))
;
5604 binds->count = bind_count;
5605 binds->num_return = num_return;
5606 binds->cols = bcols;
5607 if ( cursor != 0 )
5608 wmem_map_insert(tns_info->cursor_binds, GUINT_TO_POINTER(cursor)((gpointer) (gulong) (cursor)), binds);
5609 else
5610 tns_info->pending_binds = binds;
5611 }
5612
5613 /* Value rows: a TTI_RXD token then one DALC value per bind
5614 * column (an ordinary execute sends one row, executemany
5615 * sends N), decoded and rendered by the bind's type. */
5616 offset = dissect_tns_bind_rows(tvb, pinfo, binds_tree, offset, bcols, bind_count - num_return);
5617 proto_item_set_len(binds_item, offset - binds_start);
5618 }
5619
5620 /* Define section: a client that wants a column in some
5621 * other form than the describe gave - a CLOB as a string,
5622 * say - re-executes the cursor with the DEFINE option and
5623 * one OAC per column, in the bind OAC layout. It carries
5624 * no binds. */
5625 if ( define_count > 0 )
5626 {
5627 proto_tree *defs_tree, *def_tree;
5628 proto_item *defs_item, *def_item;
5629 int defs_start = offset;
5630 tns_column_t *dcols = NULL((void*)0);
5631
5632 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
5633 dcols = wmem_alloc0_array(pinfo->pool, tns_column_t, define_count)((tns_column_t*)wmem_alloc0((pinfo->pool), (((((define_count
)) <= 0) || ((size_t)sizeof(tns_column_t) > (9223372036854775807L
/ (size_t)((define_count))))) ? 0 : (sizeof(tns_column_t) * (
(define_count))))))
;
5634 defs_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
5635 ett_tns_defines, &defs_item, "Defines");
5636 for ( int i = 0; i < define_count && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
5637 {
5638 int d_start = offset;
5639 uint8_t dtype = tvb_get_uint8(tvb, offset);
5640 def_tree = proto_tree_add_subtree_format(defs_tree, tvb, offset, -1,
5641 ett_tns_bind, &def_item, "Define %d: %s", i + 1,
5642 val_to_str_const(dtype, tns_data_types, "unknown"));
5643 offset = dissect_tns_oac(tvb, pinfo, def_tree, offset, dcols ? &dcols[i] : NULL((void*)0));
5644 proto_item_set_len(def_item, offset - d_start);
5645 }
5646 proto_item_set_len(defs_item, offset - defs_start);
5647
5648 /* The rows that answer a define come framed the way
5649 * it asked - a CLOB defined as LONG arrives inline,
5650 * with no locator - and so do the rows of every later
5651 * execute of the cursor. Rows are still split by the
5652 * describe's columns, so replace each column's type
5653 * with the one its define gives. */
5654 if ( tns_info && dcols && tns_info->last_describe
5655 && tns_info->last_describe->num_cols == (uint32_t)define_count )
5656 {
5657 tns_describe_t *desc = wmem_new0(wmem_file_scope(), tns_describe_t)((tns_describe_t*)wmem_alloc0((wmem_file_scope()), sizeof(tns_describe_t
)))
;
5658 desc->num_cols = define_count;
5659 desc->cols = (tns_column_t *)wmem_memdup(wmem_file_scope(),
5660 tns_info->last_describe->cols, define_count * sizeof(tns_column_t));
5661 for ( int i = 0; i < define_count; i++ )
5662 {
5663 desc->cols[i].type = dcols[i].type;
5664 desc->cols[i].csform = dcols[i].csform;
5665 }
5666 tns_info->last_describe = desc;
5667 }
5668 }
5669 }
5670 else if ( oci_id == TTI_LOBOPS96 )
5671 {
5672 /* TTI_LOBOPS: the LOB operation family (read, write, get
5673 * length, create/free temp, open/close, BFILE ops). One
5674 * common request layout selects behaviour by the operation
5675 * opcode:
5676 * ub1 source pointer | ub4 source locator length |
5677 * ub1 dest pointer | ub4 dest length |
5678 * ub4 short source offset | ub4 short dest offset |
5679 * ub1 charset pointer | ub1 short amount pointer |
5680 * ub1 null-LOB pointer | ub4 operation |
5681 * ub1 SCN array pointer | ub1 SCN array length |
5682 * ub8 source offset | ub8 dest offset |
5683 * ub1 amount pointer | 3 x ub2 array-LOB slots (fixed) |
5684 * [locator] | [ub4 charset, CREATE_TEMP] |
5685 * [0x0E and the data, WRITE] | [ub8 amount]
5686 * The locator is as long as the source locator length says;
5687 * a temporary LOB's carries its own ub2 length prefix, which
5688 * that length counts. */
5689 int v = 0, op = 0, loc_len = 0, start;
5690 uint8_t src_ptr, charset_ptr, amount_ptr;
5691 uint64_t u = 0;
5692
5693 src_ptr = tvb_get_uint8(tvb, offset);
5694 offset += 1; /* source pointer flag */
5695 offset += get_sb4_custom(tvb, offset, &loc_len); /* source locator length */
5696 offset += 1; /* dest pointer flag */
5697 offset += get_sb4_custom(tvb, offset, &v); /* dest length */
5698 offset += get_sb4_custom(tvb, offset, &v); /* short source offset */
5699 offset += get_sb4_custom(tvb, offset, &v); /* short dest offset */
5700 charset_ptr = tvb_get_uint8(tvb, offset);
5701 offset += 3; /* charset / amount / null-lob flags */
5702 /* operation opcode */
5703 start = offset;
5704 offset += get_sb4_custom(tvb, offset, &op);
5705 proto_tree_add_uint(data_tree, hf_tns_data_lob_op, tvb, start, offset - start, op);
5706 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]",
5707 val_to_str_const(op, tns_lob_ops, "unknown"));
5708 /* scn-array pointer flag + length */
5709 offset += 2;
5710 /* source offset (ub8, 1-based into the LOB) */
5711 start = offset;
5712 offset += get_ub8_custom(tvb, offset, &u);
5713 proto_tree_add_uint64(data_tree, hf_tns_data_lob_offset, tvb, start, offset - start, u);
5714 /* dest offset (ub8, skip) */
5715 offset += get_ub8_custom(tvb, offset, &u);
5716 amount_ptr = tvb_get_uint8(tvb, offset);
5717 offset += 1; /* amount pointer flag */
5718 offset += 6; /* array-LOB slots */
5719 int locator_start = offset;
5720 if ( src_ptr && loc_len > 0 )
5721 {
5722 int dir_off, dir_len, file_off, file_len;
5723
5724 proto_tree_add_item(data_tree, hf_tns_data_lob_locator, tvb, offset, loc_len, ENC_NA0x00000000);
5725 if ( tns_bfile_names(tvb, offset, loc_len, &dir_off, &dir_len, &file_off, &file_len) )
5726 {
5727 const char *dir, *file;
5728 proto_tree_add_item_ret_string(data_tree, hf_tns_data_lob_directory, tvb,
5729 dir_off, dir_len, ENC_UTF_80x00000002, pinfo->pool, (const uint8_t **)&dir);
5730 proto_tree_add_item_ret_string(data_tree, hf_tns_data_lob_file_name, tvb,
5731 file_off, file_len, ENC_UTF_80x00000002, pinfo->pool, (const uint8_t **)&file);
5732 col_append_fstr(pinfo->cinfo, COL_INFO, " [BFILENAME('%s', '%s')]", dir, file);
5733 }
5734 offset += loc_len;
5735 }
5736 if ( charset_ptr )
5737 {
5738 start = offset;
5739 offset += get_sb4_custom(tvb, offset, &v);
5740 proto_tree_add_uint(data_tree, hf_tns_data_lob_charset, tvb, start, offset - start, v);
5741 }
5742 if ( tvb_reported_length_remaining(tvb, offset) > 0
5743 && tvb_get_uint8(tvb, offset) == SQLNET_LOB_FILE_DF14 )
5744 {
5745 /* WRITE: a LOB_DATA marker, then the data */
5746 offset += 1;
5747 start = offset;
5748 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
5749 if ( tvb_get_uint8(tvb, start) == 0xfe ) /* chunked: shown whole */
5750 proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start, offset - start, ENC_NA0x00000000);
5751 else if ( offset - start > 1 )
5752 proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start + 1, offset - start - 1, ENC_NA0x00000000);
5753 }
5754 if ( amount_ptr )
5755 {
5756 start = offset;
5757 offset += get_ub8_custom(tvb, offset, &u);
5758 proto_tree_add_uint64(data_tree, hf_tns_data_lob_amount, tvb, start, offset - start, u);
5759 }
5760 if ( call )
5761 {
5762 call->lob_op = (uint32_t)op;
5763 call->lob_locator_len = src_ptr ? (uint32_t)loc_len : 0;
5764 call->lob_amount = amount_ptr != 0;
5765 if ( src_ptr && loc_len >= TNS_LOB_LOC_FLAG_40x07 + 1 )
5766 {
5767 tvb_memcpy(tvb, call->lob_flags, locator_start + TNS_LOB_LOC_FLAG_10x04, 4);
5768 call->lob_flags_known = true1;
5769 }
5770 }
5771 }
5772 break;
5773 }
5774 case SQLNET_RETURN_OPI_PARAM8:
5775 {
5776 uint8_t skip = 0, opi = 0;
5777
5778 if ( tvb_bytes_exist(tvb, offset, 11) )
5779 {
5780 /*
5781 * OPI_VERSION2 response has a following pattern:
5782 *
5783 * _ banner _ vsnum
5784 * / /
5785 * ..(.?)(Orac[le.+])(.?)(....).+$
5786 * |
5787 * \ banner length (if equal to 0 then next byte indicates the length).
5788 *
5789 * These differences (to skip 1 or 2 bytes) due to differences in the drivers.
5790 */
5791 /* Orac[le.+] */
5792 if ( tvb_get_ntohl(tvb, offset+2) == 0x4f726163 )
5793 {
5794 opi = OPI_VERSION21;
5795 skip = 1;
5796 }
5797
5798 else if ( tvb_get_ntohl(tvb, offset+3) == 0x4f726163 )
5799 {
5800 opi = OPI_VERSION21;
5801 skip = 2;
5802 }
5803
5804 /*
5805 * OPI_OSESSKEY response has a following pattern:
5806 *
5807 * _ pattern (v1|v2)
5808 * / _ params
5809 * / /
5810 * (....)(........)(.+).+$
5811 * ||
5812 * \ if these two bytes are equal to 0x0c00 then first byte is <Param Counts> (v1),
5813 * else next byte indicate it (v2).
5814 */
5815 /* ....AUTH (v1) */
5816 else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0000000c41555448 )
5817 {
5818 opi = OPI_OSESSKEY2;
5819 skip = 1;
5820 }
5821 /* ..AUTH_V (v2) */
5822 else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0c0c415554485f53 )
5823 {
5824 opi = OPI_OSESSKEY2;
5825 skip = 2;
5826 }
5827
5828 /*
5829 * OPI_OAUTH response has a following pattern:
5830 *
5831 * _ pattern (v1|v2)
5832 * / _ params
5833 * / /
5834 * (....)(........)(.+).+$
5835 * ||
5836 * \ if these two bytes are equal to 0x1300 then first byte is <Param Counts> (v1),
5837 * else next byte indicate it (v2).
5838 */
5839
5840 /* ....AUTH (v1) */
5841 else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0000001341555448 )
5842 {
5843 opi = OPI_OAUTH3;
5844 skip = 1;
5845 }
5846 /* ..AUTH_V (v2) */
5847 else if ( tvb_get_ntoh64(tvb, offset+3) == 0x1313415554485f56 )
5848 {
5849 opi = OPI_OAUTH3;
5850 skip = 2;
5851 }
5852 }
5853
5854 if ( opi == OPI_VERSION21 )
5855 {
5856 proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, skip, ENC_NA0x00000000);
5857 offset += skip;
5858
5859 uint8_t len = tvb_get_uint8(tvb, offset);
5860
5861 proto_tree_add_item(data_tree, hf_tns_data_opi_version2_banner_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
5862 offset += 1;
5863
5864 proto_tree_add_item(data_tree, hf_tns_data_opi_version2_banner, tvb, offset, len, ENC_ASCII0x00000000);
5865 offset += len + (skip == 1 ? 1 : 0);
5866
5867 proto_tree_add_item(data_tree, hf_tns_data_opi_version2_vsnum, tvb, offset, 4, (skip == 1) ? ENC_BIG_ENDIAN0x00000000 : ENC_LITTLE_ENDIAN0x80000000);
5868 offset += 4;
5869 }
5870 else if ( opi == OPI_OSESSKEY2 || opi == OPI_OAUTH3 )
5871 {
5872 proto_tree *params_tree;
5873 proto_item *params_ti;
5874 unsigned par, params;
5875
5876 if ( skip == 1 )
5877 {
5878 proto_tree_add_item_ret_uint(data_tree, hf_tns_data_opi_num_of_params, tvb, offset, 1, ENC_NA0x00000000, &params);
5879 offset += 1;
5880
5881 proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 5, ENC_NA0x00000000);
5882 offset += 5;
5883 }
5884 else
5885 {
5886 proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 1, ENC_NA0x00000000);
5887 offset += 1;
5888
5889 proto_tree_add_item_ret_uint(data_tree, hf_tns_data_opi_num_of_params, tvb, offset, 1, ENC_NA0x00000000, &params);
5890 offset += 1;
5891
5892 proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 2, ENC_NA0x00000000);
5893 offset += 2;
5894 }
5895
5896 params_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_opi_params, &params_ti, "Parameters");
5897
5898 for ( par = 1; par <= params; par++ )
5899 {
5900 proto_tree *par_tree;
5901 proto_item *par_ti;
5902 unsigned len, offset_prev;
5903
5904 par_tree = proto_tree_add_subtree(params_tree, tvb, offset, -1, ett_tns_opi_par, &par_ti, "Parameter");
5905 proto_item_append_text(par_ti, " %u", par);
5906
5907 /* Name length */
5908 proto_tree_add_item_ret_uint(par_tree, hf_tns_data_opi_param_length, tvb, offset, 1, ENC_NA0x00000000, &len);
5909 offset += 1;
5910
5911 /* Name */
5912 if ( !(len == 0 || len == 2) ) /* Not empty (2 - SQLDeveloper specific sign). */
5913 {
5914 proto_tree_add_item(par_tree, hf_tns_data_opi_param_name, tvb, offset, len, ENC_ASCII0x00000000);
5915 offset += len;
5916 }
5917
5918 /* Value can be NULL. So, save offset to calculate unused data. */
5919 offset_prev = offset;
5920 offset += skip == 1 ? 4 : 2;
5921
5922 /* Value length */
5923 if ( opi == OPI_OSESSKEY2 )
5924 {
5925 len = get_strtype_custom(tvb, pinfo, par_tree, offset);
5926 }
5927 else /* OPI_OAUTH */
5928 {
5929 len = tvb_get_uint8(tvb, offset_prev) == 0 ? 0 : get_strtype_custom(tvb, pinfo, par_tree, offset);
5930 }
5931
5932 /*
5933 * Value
5934 * OPI_OSESSKEY: AUTH_VFR_DATA with length 0, 9, 0x39 comes without data.
5935 * OPI_OAUTH: AUTH_VFR_DATA with length 0, 0x39 comes without data.
5936 */
5937 if ( ((opi == OPI_OSESSKEY2) && !(len == 0 || len == 9 || len == 0x39))
5938 || ((opi == OPI_OAUTH3) && !(len == 0 || len == 0x39)) )
5939 {
5940 proto_tree_add_item(par_tree, hf_tns_data_unused, tvb, offset_prev, offset - offset_prev, ENC_NA0x00000000);
5941 offset += len;
5942
5943 offset_prev = offset; /* Save offset to calculate rest of unused data */
5944 }
5945 else
5946 {
5947 offset += 1;
5948 }
5949
5950 if ( opi == OPI_OSESSKEY2 )
5951 {
5952 /* SQL Developer specific fix */
5953 offset += tvb_get_uint8(tvb, offset) == 2 ? 5 : 3;
5954 }
5955 else /* OPI_OAUTH */
5956 {
5957 offset += len == 0 ? 1 : 3;
5958 }
5959
5960 if ( skip == 1 )
5961 {
5962 offset += 1 + ((len == 0 || len == 0x39) ? 3 : 4);
5963
5964 if ( opi == OPI_OAUTH3 )
5965 {
5966 offset += len == 0 ? 2 : 0;
5967 }
5968 }
5969
5970 proto_tree_add_item(par_tree, hf_tns_data_unused, tvb, offset_prev, offset - offset_prev, ENC_NA0x00000000);
5971 proto_item_set_end(par_ti, tvb, offset);
5972 }
5973 proto_item_set_end(params_ti, tvb, offset);
5974 }
5975 else if ( !is_request )
5976 {
5977 /* Not an authentication reply: an execute answers with
5978 * its return parameters. */
5979 tns_call_t *call = tns_answered_call(pinfo);
5980 if ( call && (call->func == TTI_ALL894 || call->func == TTI_REEXECUTE4
5981 || call->func == TTI_REEXECUTE_AND_FETCH78) )
5982 {
5983 offset = dissect_tns_return_params(tvb, pinfo, data_tree, offset,
5984 (call->exec_flags & TNS_EXEC_FLAGS_DML_ROWCOUNTS0x4000) != 0);
5985 ctx->walk = true1;
5986 }
5987 else if ( call && call->func == TTI_TPC_TXN_SWITCH103 )
5988 {
5989 /* the application value and the transaction context
5990 * (a ub2 length and the bytes) */
5991 int v = 0, len = 0, start = offset;
5992 offset += get_sb4_custom(tvb, offset, &v);
5993 proto_tree_add_uint(data_tree, hf_tns_data_tpc_app_value, tvb, start, offset - start, v);
5994 offset += get_sb4_custom(tvb, offset, &len);
5995 if ( len > 0 )
5996 {
5997 proto_tree_add_item(data_tree, hf_tns_data_tpc_context, tvb, offset, len, ENC_NA0x00000000);
5998 offset += len;
5999 }
6000 ctx->walk = true1;
6001 }
6002 else if ( call && call->func == TTI_TPC_TXN_CHANGE_STATE104 )
6003 {
6004 int v = 0, start = offset;
6005 offset += get_sb4_custom(tvb, offset, &v);
6006 proto_tree_add_uint(data_tree, hf_tns_data_tpc_state, tvb, start, offset - start, v);
6007 ctx->walk = true1;
6008 }
6009 else if ( call && call->func == TTI_LOBOPS96 )
6010 {
6011 /* A LOB operation's reply: the locator as the server
6012 * now sees it - as long as the one sent, and changed
6013 * by a mutating call - then per operation the new
6014 * temporary LOB's charset, the amount, or a boolean. */
6015 uint64_t u = 0;
6016 int start;
6017
6018 if ( call->lob_locator_len > 0 )
6019 {
6020 proto_tree_add_item(data_tree, hf_tns_data_lob_locator, tvb, offset,
6021 call->lob_locator_len, ENC_NA0x00000000);
6022 offset += call->lob_locator_len;
6023 }
6024 if ( call->lob_op == TNS_LOB_OP_CREATE_TEMP0x00110 )
6025 {
6026 int v = 0;
6027 start = offset;
6028 offset += get_sb4_custom(tvb, offset, &v);
6029 proto_tree_add_uint(data_tree, hf_tns_data_lob_charset, tvb, start, offset - start, v);
6030 offset += 1; /* trailing flags */
6031 }
6032 else if ( call->lob_amount )
6033 {
6034 start = offset;
6035 offset += get_ub8_custom(tvb, offset, &u);
6036 proto_tree_add_uint64(data_tree, hf_tns_data_lob_amount, tvb, start, offset - start, u);
6037 }
6038 if ( call->lob_op == TNS_LOB_OP_IS_OPEN0x11000 || call->lob_op == TNS_LOB_OP_FILE_EXISTS0x00800
6039 || call->lob_op == TNS_LOB_OP_FILE_ISOPEN0x00400 )
6040 {
6041 proto_tree_add_item(data_tree, hf_tns_data_lob_flag, tvb, offset, 1, ENC_NA0x00000000);
6042 offset += 1;
6043 }
6044 ctx->walk = true1;
6045 }
6046 }
6047 break;
6048 }
6049
6050 case SQLNET_PIGGYBACK_FUNC17:
6051 {
6052 int cursors_len = 0;
6053 int cursors_start;
6054 uint8_t piggyback_id = tvb_get_uint8(tvb, offset);
6055 proto_tree_add_item(data_tree, hf_tns_data_piggyback_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
6056 offset += 1;
6057 proto_tree_add_item(data_tree, hf_tns_data_tseq, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
6058 offset += 1;
6059 offset = dissect_tns_call_token(tvb, pinfo, data_tree, offset);
6060 /* Only the close-cursors piggyback carries a cursor list:
6061 * a pointer byte, a ub4 count, then that many ub4 cursor
6062 * ids. The other piggybacks have bodies of their own. */
6063 if ( piggyback_id != TTI_CLOSE_CURSORS105 )
6064 {
6065 offset = dissect_tns_piggyback_body(tvb, pinfo, data_tree, offset, piggyback_id, &ctx->walk);
6066 break;
6067 }
6068 offset += 1; /* pointer */
6069 cursors_start = offset;
6070 offset += get_sb4_custom(tvb, offset, &cursors_len);
6071 /* The count comes off the wire and every cursor takes at
6072 * least one byte, so a count larger than the data left
6073 * cannot be real. Say so and stop, rather than looping on
6074 * a number somebody else chose. */
6075 if ( cursors_len < 0 ||
6076 (unsigned)cursors_len > tvb_reported_length_remaining(tvb, offset) )
6077 {
6078 proto_tree_add_expert(data_tree, pinfo, &ei_tns_data_piggyback_cursors,
6079 tvb, cursors_start, offset - cursors_start);
6080 break;
6081 }
6082 for(int i = 0; i < cursors_len; i++) {
6083 int cursor = 0;
6084 int len = get_sb4_custom(tvb, offset, &cursor);
6085 proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, offset, len, cursor);
6086 offset += len;
6087 }
6088 /* The call this piggyback rides in front of follows it. */
6089 ctx->walk = true1;
6090 break;
6091 }
6092 case SQLNET_SNS0xdeadbeef:
6093 {
6094 proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
6095 offset += 4;
6096 proto_tree_add_item(data_tree, hf_tns_data_length, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
6097 offset += 2;
6098
6099 if ( is_request )
6100 {
6101 proto_tree_add_item(data_tree, hf_tns_data_sns_cli_vers, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
6102 }
6103 else
6104 {
6105 proto_tree_add_item(data_tree, hf_tns_data_sns_srv_vers, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
6106 }
6107 offset += 4;
6108
6109 uint16_t num_services = tvb_get_ntohs(tvb, offset);
6110 proto_tree_add_item(data_tree, hf_tns_data_sns_srvcnt, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
6111 /* With encryption picked, the client's next negotiation packet
6112 * - its Diffie-Hellman public key - is the last in the clear. */
6113 if ( is_request && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
6114 {
6115 tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
6116 if ( tns_info->ano_encryption && !tns_info->ano_active_after )
6117 tns_info->ano_active_after = pinfo->num;
6118 }
6119 offset += 2;
6120 proto_tree_add_item(data_tree, hf_tns_data_sns_error, tvb, offset, 1, ENC_NA0x00000000);
6121 offset += 1;
6122
6123 /* Each service: a type, a sub-packet count and an error, then
6124 * the sub-packets, each a length, a type and that many bytes
6125 * of payload - all big-endian. A service opens with its
6126 * version; in the encryption and integrity services the
6127 * sub-packet after it lists the algorithms a client offers,
6128 * or holds the one the server picked. */
6129 for ( unsigned i = 0; i < num_services && tvb_bytes_exist(tvb, offset, 8); i++ )
6130 {
6131 proto_tree *svc_tree;
6132 proto_item *svc_item;
6133 int svc_start = offset;
6134 uint16_t svc_type = tvb_get_ntohs(tvb, offset);
6135 uint16_t num_sub = tvb_get_ntohs(tvb, offset + 2);
6136
6137 svc_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, -1, ett_tns_sns_service,
6138 &svc_item, "Service: %s", val_to_str_const(svc_type, tns_sns_services, "unknown"));
6139 proto_tree_add_item(svc_tree, hf_tns_data_sns_service, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
6140 proto_tree_add_item(svc_tree, hf_tns_data_sns_subpackets, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000);
6141 proto_tree_add_item(svc_tree, hf_tns_data_sns_svc_error, tvb, offset + 4, 4, ENC_BIG_ENDIAN0x00000000);
6142 offset += 8;
6143 for ( unsigned j = 0; j < num_sub && tvb_bytes_exist(tvb, offset, 4); j++ )
6144 {
6145 uint16_t len = tvb_get_ntohs(tvb, offset);
6146 uint16_t sub_type = tvb_get_ntohs(tvb, offset + 2);
6147 proto_tree *sub_tree = proto_tree_add_subtree_format(svc_tree, tvb, offset, 4 + len,
6148 ett_tns_sns_subpacket, NULL((void*)0), "Sub-packet %u: %s, %u bytes", j + 1,
6149 val_to_str_const(sub_type, tns_sns_subpacket_types, "unknown"), len);
6150 proto_tree_add_item(sub_tree, hf_tns_data_sns_sub_type, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000);
6151 offset += 4;
6152 bool_Bool algs = j == 1 && (sub_type == TNS_ANO_SP_BYTES1 || sub_type == TNS_ANO_SP_UB12);
6153 if ( sub_type == TNS_ANO_SP_VERSION5 && len == 4 )
6154 proto_tree_add_item(sub_tree, hf_tns_data_sns_version, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
6155 else if ( algs && svc_type == TNS_ANO_ENCRYPTION2 )
6156 {
6157 for ( unsigned k = 0; k < len; k++ )
6158 proto_tree_add_item(sub_tree, hf_tns_data_sns_encryption, tvb, offset + k, 1, ENC_NA0x00000000);
6159 /* the server's pick: anything but none turns
6160 * encryption on once the client has answered */
6161 if ( !is_request && !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && len == 1 && tvb_get_uint8(tvb, offset) != 0 )
6162 tns_get_conv_info(pinfo)->ano_encryption = true1;
6163 }
6164 else if ( algs && svc_type == TNS_ANO_DATA_INTEGRITY3 )
6165 for ( unsigned k = 0; k < len; k++ )
6166 proto_tree_add_item(sub_tree, hf_tns_data_sns_integrity, tvb, offset + k, 1, ENC_NA0x00000000);
6167 else if ( len > 0 )
6168 proto_tree_add_item(sub_tree, hf_tns_data_sns_sub_data, tvb, offset, len, ENC_NA0x00000000);
6169 offset += len;
6170 }
6171 proto_item_set_len(svc_item, offset - svc_start);
6172 }
6173 break;
6174 }
6175 }
6176
6177 return offset;
6178}
6179
6180static void dissect_tns_connect(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
6181{
6182 proto_tree *connect_tree;
6183 uint32_t cd_offset, cd_len;
6184 int tns_offset = offset-8;
6185 static int * const flags[] = {
6186 &hf_tns_ntp_flag_hangon,
6187 &hf_tns_ntp_flag_crel,
6188 &hf_tns_ntp_flag_tduio,
6189 &hf_tns_ntp_flag_srun,
6190 &hf_tns_ntp_flag_dtest,
6191 &hf_tns_ntp_flag_cbio,
6192 &hf_tns_ntp_flag_asio,
6193 &hf_tns_ntp_flag_pio,
6194 &hf_tns_ntp_flag_grant,
6195 &hf_tns_ntp_flag_handoff,
6196 &hf_tns_ntp_flag_sigio,
6197 &hf_tns_ntp_flag_sigpipe,
6198 &hf_tns_ntp_flag_sigurg,
6199 &hf_tns_ntp_flag_urgentio,
6200 &hf_tns_ntp_flag_fdio,
6201 &hf_tns_ntp_flag_testop,
6202 NULL((void*)0)
6203 };
6204
6205 connect_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
6206 ett_tns_connect, NULL((void*)0), "Connect");
6207
6208 proto_tree_add_item(connect_tree, hf_tns_version, tvb,
6209 offset, 2, ENC_BIG_ENDIAN0x00000000);
6210 offset += 2;
6211
6212 proto_tree_add_item(connect_tree, hf_tns_compat_version, tvb,
6213 offset, 2, ENC_BIG_ENDIAN0x00000000);
6214 offset += 2;
6215
6216 proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_service_options, ett_tns_sopt_flag, tns_service_options, ENC_BIG_ENDIAN0x00000000);
6217 offset += 2;
6218
6219 proto_tree_add_item(connect_tree, hf_tns_sdu_size, tvb,
6220 offset, 2, ENC_BIG_ENDIAN0x00000000);
6221 offset += 2;
6222
6223 proto_tree_add_item(connect_tree, hf_tns_max_tdu_size, tvb,
6224 offset, 2, ENC_BIG_ENDIAN0x00000000);
6225 offset += 2;
6226
6227 proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_nt_proto_characteristics, ett_tns_ntp_flag, flags, ENC_BIG_ENDIAN0x00000000);
6228 offset += 2;
6229
6230 proto_tree_add_item(connect_tree, hf_tns_line_turnaround, tvb,
6231 offset, 2, ENC_BIG_ENDIAN0x00000000);
6232 offset += 2;
6233
6234 proto_tree_add_item(connect_tree, hf_tns_value_of_one, tvb,
6235 offset, 2, ENC_NA0x00000000);
6236 offset += 2;
6237
6238 proto_tree_add_item_ret_uint(connect_tree, hf_tns_connect_data_length, tvb,
6239 offset, 2, ENC_BIG_ENDIAN0x00000000, &cd_len);
6240 offset += 2;
6241
6242 proto_tree_add_item_ret_uint(connect_tree, hf_tns_connect_data_offset, tvb,
6243 offset, 2, ENC_BIG_ENDIAN0x00000000, &cd_offset);
6244 offset += 2;
6245
6246 proto_tree_add_item(connect_tree, hf_tns_connect_data_max, tvb,
6247 offset, 4, ENC_BIG_ENDIAN0x00000000);
6248 offset += 4;
6249
6250 proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_connect_flags0, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN0x00000000);
6251 offset += 1;
6252
6253 proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_connect_flags1, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN0x00000000);
6254 offset += 1;
6255
6256 /*
6257 * XXX - sometimes it appears that this stuff isn't present
6258 * in the packet.
6259 */
6260 if ((uint32_t)(offset + 16) <= tns_offset+cd_offset)
6261 {
6262 proto_tree_add_item(connect_tree, hf_tns_trace_cf1, tvb,
6263 offset, 4, ENC_BIG_ENDIAN0x00000000);
6264 offset += 4;
6265
6266 proto_tree_add_item(connect_tree, hf_tns_trace_cf2, tvb,
6267 offset, 4, ENC_BIG_ENDIAN0x00000000);
6268 offset += 4;
6269
6270 proto_tree_add_item(connect_tree, hf_tns_trace_cid, tvb,
6271 offset, 8, ENC_BIG_ENDIAN0x00000000);
6272 /* offset += 8;*/
6273 }
6274
6275 if ( cd_len > 0)
6276 {
6277 /* Long Connect Data (> 221 bytes?) is not in the Connect PDU
6278 * but sent in an immediately following Data PDU.
6279 */
6280 if (tvb_reported_length_remaining(tvb, tns_offset + cd_offset)) {
6281 proto_tree_add_item(connect_tree, hf_tns_connect_data, tvb,
6282 tns_offset+cd_offset, -1, ENC_ASCII0x00000000);
6283 } else {
6284 proto_tree_add_expert(connect_tree, pinfo, &ei_tns_connect_data_next_packet, tvb, 0, 0);
6285 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
6286 tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
6287 tns_info->pending_connect_data = cd_len;
6288 }
6289 }
6290 }
6291}
6292
6293static void dissect_tns_accept(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
6294{
6295 proto_tree *accept_tree;
6296 uint32_t accept_offset, accept_len;
6297 uint16_t version;
6298 int tns_offset = offset-8;
6299
6300 accept_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
6301 ett_tns_accept, NULL((void*)0), "Accept");
6302
6303 proto_tree_add_item(accept_tree, hf_tns_version, tvb,
6304 offset, 2, ENC_BIG_ENDIAN0x00000000);
6305 offset += 2;
6306
6307 proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_service_options, ett_tns_sopt_flag, tns_service_options, ENC_BIG_ENDIAN0x00000000);
6308 offset += 2;
6309
6310 proto_tree_add_item(accept_tree, hf_tns_sdu_size, tvb,
6311 offset, 2, ENC_BIG_ENDIAN0x00000000);
6312 offset += 2;
6313
6314 proto_tree_add_item(accept_tree, hf_tns_max_tdu_size, tvb,
6315 offset, 2, ENC_BIG_ENDIAN0x00000000);
6316 offset += 2;
6317
6318 proto_tree_add_item(accept_tree, hf_tns_value_of_one, tvb,
6319 offset, 2, ENC_NA0x00000000);
6320 offset += 2;
6321
6322 proto_tree_add_item_ret_uint(accept_tree, hf_tns_accept_data_length, tvb,
6323 offset, 2, ENC_BIG_ENDIAN0x00000000, &accept_len);
6324 offset += 2;
6325
6326 proto_tree_add_item_ret_uint(accept_tree, hf_tns_accept_data_offset, tvb,
6327 offset, 2, ENC_BIG_ENDIAN0x00000000, &accept_offset);
6328 offset += 2;
6329
6330 proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_connect_flags0, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN0x00000000);
6331 offset += 1;
6332
6333 proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_connect_flags1, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN0x00000000);
6334
6335 /* From version 315 the session data unit is offered again as 32
6336 * bits, 24 bytes into the ACCEPT, and from 318 a flags2 word follows
6337 * at 33 - both ahead of any connect data. */
6338 version = tvb_get_ntohs(tvb, tns_offset + 8);
6339 if ( version >= 315 && accept_offset >= 8 + 24 + 4 && tvb_bytes_exist(tvb, tns_offset + 8 + 24, 4) )
6340 proto_tree_add_item(accept_tree, hf_tns_accept_sdu, tvb, tns_offset + 8 + 24, 4, ENC_BIG_ENDIAN0x00000000);
6341 if ( version >= 318 && accept_offset >= 8 + 33 + 4 && tvb_bytes_exist(tvb, tns_offset + 8 + 33, 4) )
6342 proto_tree_add_bitmask(accept_tree, tvb, tns_offset + 8 + 33, hf_tns_accept_flags2,
6343 ett_tns_accept_flags2, tns_accept_flags2, ENC_BIG_ENDIAN0x00000000);
6344
6345 if ( accept_len > 0)
6346 {
6347 proto_tree_add_item(accept_tree, hf_tns_accept_data, tvb,
6348 tns_offset+accept_offset, -1, ENC_ASCII0x00000000);
6349 }
6350 return;
6351}
6352
6353
6354static void dissect_tns_refuse(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
6355{
6356 /* TODO
6357 * According to some reverse engineers, the refuse packet is also sent when the login fails.
6358 * Byte 54 shows if this is due to invalid ID (0x02) or password (0x03).
6359 * At now we do not have pcaps with such messages to check this statement.
6360 */
6361 proto_tree *refuse_tree;
6362
6363 refuse_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
6364 ett_tns_refuse, NULL((void*)0), "Refuse");
6365
6366 proto_tree_add_item(refuse_tree, hf_tns_refuse_reason_user, tvb,
6367 offset, 1, ENC_BIG_ENDIAN0x00000000);
6368 offset += 1;
6369
6370 proto_tree_add_item(refuse_tree, hf_tns_refuse_reason_system, tvb,
6371 offset, 1, ENC_BIG_ENDIAN0x00000000);
6372 offset += 1;
6373
6374 proto_tree_add_item(refuse_tree, hf_tns_refuse_data_length, tvb,
6375 offset, 2, ENC_BIG_ENDIAN0x00000000);
6376 offset += 2;
6377
6378 proto_tree_add_item(refuse_tree, hf_tns_refuse_data, tvb,
6379 offset, -1, ENC_ASCII0x00000000);
6380}
6381
6382
6383static void dissect_tns_abort(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
6384{
6385 proto_tree *abort_tree;
6386
6387 abort_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
6388 ett_tns_abort, NULL((void*)0), "Abort");
6389
6390 proto_tree_add_item(abort_tree, hf_tns_abort_reason_user, tvb,
6391 offset, 1, ENC_BIG_ENDIAN0x00000000);
6392 offset += 1;
6393
6394 proto_tree_add_item(abort_tree, hf_tns_abort_reason_system, tvb,
6395 offset, 1, ENC_BIG_ENDIAN0x00000000);
6396 offset += 1;
6397
6398 proto_tree_add_item(abort_tree, hf_tns_abort_data, tvb,
6399 offset, -1, ENC_ASCII0x00000000);
6400}
6401
6402
6403static void dissect_tns_marker(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tns_tree, int is_attention)
6404{
6405 proto_tree *marker_tree;
6406
6407 marker_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
6408 ett_tns_marker, NULL((void*)0), is_attention ? "Attention" : "Marker");
6409
6410 proto_tree_add_item(marker_tree, hf_tns_marker_type, tvb,
6411 offset, 1, ENC_BIG_ENDIAN0x00000000);
6412 offset += 1;
6413
6414 proto_tree_add_item(marker_tree, hf_tns_marker_data_byte, tvb,
6415 offset, 1, ENC_BIG_ENDIAN0x00000000);
6416 offset += 1;
6417
6418 /* The last byte selects break vs reset for a data marker. */
6419 if ( tvb_reported_length_remaining(tvb, offset) > 0 )
6420 {
6421 uint32_t func = tvb_get_uint8(tvb, offset);
6422 proto_tree_add_item(marker_tree, hf_tns_marker_function, tvb,
6423 offset, 1, ENC_BIG_ENDIAN0x00000000);
6424 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
6425 val_to_str_const(func, tns_marker_functions, "Unknown"));
6426 }
6427}
6428
6429static void dissect_tns_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
6430{
6431 proto_tree *redirect_tree;
6432
6433 redirect_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
6434 ett_tns_redirect, NULL((void*)0), "Redirect");
6435
6436 proto_tree_add_item(redirect_tree, hf_tns_redirect_data_length, tvb,
6437 offset, 2, ENC_BIG_ENDIAN0x00000000);
6438 offset += 2;
6439
6440 proto_tree_add_item(redirect_tree, hf_tns_redirect_data, tvb,
6441 offset, -1, ENC_ASCII0x00000000);
6442}
6443
6444static void dissect_tns_control(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
6445{
6446 proto_tree *control_tree;
6447
6448 control_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
6449 ett_tns_control, NULL((void*)0), "Control");
6450
6451 proto_tree_add_item(control_tree, hf_tns_control_cmd, tvb,
6452 offset, 2, ENC_BIG_ENDIAN0x00000000);
6453 offset += 2;
6454
6455 proto_tree_add_item(control_tree, hf_tns_control_data, tvb,
6456 offset, -1, ENC_NA0x00000000);
6457}
6458
6459static unsigned
6460get_tns_pdu_len(packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, void *data _U___attribute__((unused)))
6461{
6462 /*
6463 * Get the 16-bit length of the TNS message, including header
6464 */
6465 unsigned length = tvb_get_ntohs(tvb, offset);
6466 offset += 4;
6467 uint8_t type = tvb_get_uint8(tvb, offset);
6468 /* Type 0xf (data descriptor, LOB/FILE data) has data which follows
6469 * immediately (no new PDU header) but is not counted in the PDU
6470 * length field either.
6471 */
6472 if (type == TNS_TYPE_DD15) {
6473 offset += 8;
6474 if (!tvb_bytes_exist(tvb, offset, 4)) {
6475 /* return 0 makes tcp_dissect_pdus() report
6476 * DESEGMENT_ONE_MORE_SEGMENT to the TCP dissector.
6477 */
6478 return 0;
6479 }
6480 unsigned dd_len = tvb_get_ntohl(tvb, offset);
6481 return length + dd_len;
6482 }
6483 return length;
6484}
6485
6486static unsigned
6487get_tns_pdu_len_nochksum(packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, void *data _U___attribute__((unused)))
6488{
6489 /*
6490 * Get the 32-bit length of the TNS message, including header
6491 */
6492 unsigned length = tvb_get_ntohl(tvb, offset);
6493 offset += 4;
6494 uint8_t type = tvb_get_uint8(tvb, offset);
6495 /* Type 0xf (data descriptor, LOB/FILE data) has data which follows
6496 * immediately (no new PDU header) but is not counted in the PDU
6497 * length field either.
6498 */
6499 if (type == TNS_TYPE_DD15) {
6500 offset += 8;
6501 if (!tvb_bytes_exist(tvb, offset, 4)) {
6502 /* return 0 makes tcp_dissect_pdus() report
6503 * DESEGMENT_ONE_MORE_SEGMENT to the TCP dissector.
6504 */
6505 return 0;
6506 }
6507 unsigned dd_len = tvb_get_ntohl(tvb, offset);
6508 return length + dd_len;
6509 }
6510
6511 return length;
6512}
6513
6514static int
6515dissect_tns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
6516{
6517 uint32_t length;
6518 uint16_t chksum;
6519 uint8_t type;
6520
6521 /*
6522 * First, do a sanity check to make sure what we have
6523 * starts with a TNS PDU.
6524 */
6525 if (tvb_bytes_exist(tvb, 4, 1)) {
6526 /*
6527 * Well, we have the packet type; let's make sure
6528 * it's a known type.
6529 */
6530 type = tvb_get_uint8(tvb, 4);
6531 if (type < TNS_TYPE_CONNECT1 || type > TNS_TYPE_MAX19)
6532 return 0; /* it's not a known type */
6533 }
6534
6535 /*
6536 * In some messages (observed in Oracle12c) packet length has 4 bytes
6537 * instead of 2.
6538 *
6539 * If packet length has 2 bytes, length and checksum equals two unsigned
6540 * 16-bit numbers. Packet checksum is generally unused (equal zero),
6541 * but 10g client may set 2nd byte to 4.
6542 *
6543 * Else, Oracle 12c combine these two 16-bit numbers into one 32-bit.
6544 * This number represents the packet length. Checksum is omitted.
6545 */
6546 chksum = tvb_get_ntohs(tvb, 2);
6547
6548 length = (chksum == 0 || chksum == 4) ? 2 : 4;
6549
6550 tcp_dissect_pdus(tvb, pinfo, tree, tns_desegment, TNS_HDR_LEN8,
6551 (length == 2 ? get_tns_pdu_len : get_tns_pdu_len_nochksum),
6552 dissect_tns_pdu, data);
6553
6554 return tvb_captured_length(tvb);
6555}
6556
6557static int
6558dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))
6559{
6560 proto_tree *tns_tree, *ti;
6561 proto_item *hidden_item;
6562 unsigned offset = 0;
6563 uint32_t length;
6564 uint16_t chksum;
6565 uint8_t type;
6566
6567 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TNS");
6568
6569 col_set_str(pinfo->cinfo, COL_INFO,
6570 (pinfo->match_uint == pinfo->destport) ? "Request" : "Response");
6571
6572 ti = proto_tree_add_item(tree, proto_tns, tvb, 0, -1, ENC_NA0x00000000);
6573 tns_tree = proto_item_add_subtree(ti, ett_tns);
6574
6575 if (pinfo->match_uint == pinfo->destport)
6576 {
6577 hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_request,
6578 tvb, offset, 0, true1);
6579 }
6580 else
6581 {
6582 hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_response,
6583 tvb, offset, 0, true1);
6584 }
6585 proto_item_set_hidden(hidden_item);
6586
6587 chksum = tvb_get_ntohs(tvb, offset+2);
6588 if (chksum == 0 || chksum == 4)
6589 {
6590 proto_tree_add_item_ret_uint(tns_tree, hf_tns_length, tvb, offset,
6591 2, ENC_BIG_ENDIAN0x00000000, &length);
6592 offset += 2;
6593 proto_tree_add_checksum(tns_tree, tvb, offset, hf_tns_packet_checksum,
6594 -1, NULL((void*)0), pinfo, 0, ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_NO_FLAGS0x00);
6595 offset += 2;
6596 }
6597 else
6598 {
6599 /* Oracle 12c uses checksum bytes as part of the packet length. */
6600 proto_tree_add_item_ret_uint(tns_tree, hf_tns_length, tvb, offset,
6601 4, ENC_BIG_ENDIAN0x00000000, &length);
6602 offset += 4;
6603 }
6604
6605 type = tvb_get_uint8(tvb, offset);
6606 proto_tree_add_uint(tns_tree, hf_tns_packet_type, tvb,
6607 offset, 1, type);
6608 offset += 1;
6609
6610 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s (%u)",
6611 val_to_str_const(type, tns_type_vals, "Unknown"), type);
6612
6613 proto_tree_add_item(tns_tree, hf_tns_reserved_byte, tvb,
6614 offset, 1, ENC_NA0x00000000);
6615 offset += 1;
6616
6617 proto_tree_add_checksum(tns_tree, tvb, offset, hf_tns_header_checksum, -1, NULL((void*)0), pinfo, 0, ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_NO_FLAGS0x00);
6618 offset += 2;
6619
6620 switch (type)
6621 {
6622 case TNS_TYPE_CONNECT1:
6623 dissect_tns_connect(tvb,offset,pinfo,tns_tree);
6624 break;
6625 case TNS_TYPE_ACCEPT2:
6626 dissect_tns_accept(tvb,offset,pinfo,tns_tree);
6627 break;
6628 case TNS_TYPE_REFUSE4:
6629 dissect_tns_refuse(tvb,offset,pinfo,tns_tree);
6630 break;
6631 case TNS_TYPE_REDIRECT5:
6632 dissect_tns_redirect(tvb,offset,pinfo,tns_tree);
6633 break;
6634 case TNS_TYPE_ABORT9:
6635 dissect_tns_abort(tvb,offset,pinfo,tns_tree);
6636 break;
6637 case TNS_TYPE_MARKER12:
6638 dissect_tns_marker(tvb,offset,pinfo,tns_tree, 0);
6639 break;
6640 case TNS_TYPE_ATTENTION13:
6641 dissect_tns_marker(tvb,offset,pinfo,tns_tree, 1);
6642 break;
6643 case TNS_TYPE_CONTROL14:
6644 dissect_tns_control(tvb,offset,pinfo,tns_tree);
6645 break;
6646 case TNS_TYPE_DATA6:
6647 dissect_tns_data(tvb,offset,pinfo,tns_tree);
6648 break;
6649 case TNS_TYPE_DD15:
6650 dissect_tns_data_descriptor(tvb,offset,pinfo,tns_tree, length);
6651 break;
6652 default:
6653 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo,
6654 tns_tree);
6655 break;
6656 }
6657
6658 return tvb_captured_length(tvb);
6659}
6660
6661void proto_register_tns(void)
6662{
6663 static hf_register_info hf[] = {
6664 { &hf_tns_response, {
6665 "Response", "tns.response", FT_BOOLEAN, BASE_NONE,
6666 NULL((void*)0), 0x0, "true if TNS response", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6667 { &hf_tns_request, {
6668 "Request", "tns.request", FT_BOOLEAN, BASE_NONE,
6669 NULL((void*)0), 0x0, "true if TNS request", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6670 { &hf_tns_length, {
6671 "Packet Length", "tns.length", FT_UINT32, BASE_DEC,
6672 NULL((void*)0), 0x0, "Length of TNS packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6673 { &hf_tns_packet_checksum, {
6674 "Packet Checksum", "tns.packet_checksum", FT_UINT16, BASE_HEX,
6675 NULL((void*)0), 0x0, "Checksum of Packet Data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6676 { &hf_tns_header_checksum, {
6677 "Header Checksum", "tns.header_checksum", FT_UINT16, BASE_HEX,
6678 NULL((void*)0), 0x0, "Checksum of Header Data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6679
6680 { &hf_tns_version, {
6681 "Version", "tns.version", FT_UINT16, BASE_DEC,
6682 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6683 { &hf_tns_compat_version, {
6684 "Version (Compatible)", "tns.compat_version", FT_UINT16, BASE_DEC,
6685 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6686
6687 { &hf_tns_service_options, {
6688 "Service Options", "tns.service_options", FT_UINT16, BASE_HEX,
6689 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6690
6691 { &hf_tns_sopt_flag_bconn, {
6692 "Broken Connect Notify", "tns.so_flag.bconn", FT_BOOLEAN, 16,
6693 NULL((void*)0), 0x2000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6694 { &hf_tns_sopt_flag_pc, {
6695 "Packet Checksum", "tns.so_flag.pc", FT_BOOLEAN, 16,
6696 NULL((void*)0), 0x1000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6697 { &hf_tns_sopt_flag_hc, {
6698 "Header Checksum", "tns.so_flag.hc", FT_BOOLEAN, 16,
6699 NULL((void*)0), 0x0800, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6700 { &hf_tns_sopt_flag_fd, {
6701 "Full Duplex", "tns.so_flag.fd", FT_BOOLEAN, 16,
6702 NULL((void*)0), 0x0400, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6703 { &hf_tns_sopt_flag_hd, {
6704 "Half Duplex", "tns.so_flag.hd", FT_BOOLEAN, 16,
6705 NULL((void*)0), 0x0200, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6706 { &hf_tns_sopt_flag_dc1, {
6707 "Don't Care", "tns.so_flag.dc1", FT_BOOLEAN, 16,
6708 NULL((void*)0), 0x0100, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6709 { &hf_tns_sopt_flag_dc2, {
6710 "Don't Care", "tns.so_flag.dc2", FT_BOOLEAN, 16,
6711 NULL((void*)0), 0x0080, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6712 { &hf_tns_sopt_flag_dio, {
6713 "Direct IO to Transport", "tns.so_flag.dio", FT_BOOLEAN, 16,
6714 NULL((void*)0), 0x0010, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6715 { &hf_tns_sopt_flag_ap, {
6716 "Attention Processing", "tns.so_flag.ap", FT_BOOLEAN, 16,
6717 NULL((void*)0), 0x0008, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6718 { &hf_tns_sopt_flag_ra, {
6719 "Can Receive Attention", "tns.so_flag.ra", FT_BOOLEAN, 16,
6720 NULL((void*)0), 0x0004, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6721 { &hf_tns_sopt_flag_sa, {
6722 "Can Send Attention", "tns.so_flag.sa", FT_BOOLEAN, 16,
6723 NULL((void*)0), 0x0002, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6724
6725
6726 { &hf_tns_sdu_size, {
6727 "Session Data Unit Size", "tns.sdu_size", FT_UINT16, BASE_DEC,
6728 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6729 { &hf_tns_max_tdu_size, {
6730 "Maximum Transmission Data Unit Size", "tns.max_tdu_size", FT_UINT16, BASE_DEC,
6731 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6732
6733 { &hf_tns_nt_proto_characteristics, {
6734 "NT Protocol Characteristics", "tns.nt_proto_characteristics", FT_UINT16, BASE_HEX,
6735 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6736 { &hf_tns_ntp_flag_hangon, {
6737 "Hangon to listener connect", "tns.ntp_flag.hangon", FT_BOOLEAN, 16,
6738 NULL((void*)0), 0x8000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6739 { &hf_tns_ntp_flag_crel, {
6740 "Confirmed release", "tns.ntp_flag.crel", FT_BOOLEAN, 16,
6741 NULL((void*)0), 0x4000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6742 { &hf_tns_ntp_flag_tduio, {
6743 "TDU based IO", "tns.ntp_flag.tduio", FT_BOOLEAN, 16,
6744 NULL((void*)0), 0x2000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6745 { &hf_tns_ntp_flag_srun, {
6746 "Spawner running", "tns.ntp_flag.srun", FT_BOOLEAN, 16,
6747 NULL((void*)0), 0x1000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6748 { &hf_tns_ntp_flag_dtest, {
6749 "Data test", "tns.ntp_flag.dtest", FT_BOOLEAN, 16,
6750 NULL((void*)0), 0x0800, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6751 { &hf_tns_ntp_flag_cbio, {
6752 "Callback IO supported", "tns.ntp_flag.cbio", FT_BOOLEAN, 16,
6753 NULL((void*)0), 0x0400, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6754 { &hf_tns_ntp_flag_asio, {
6755 "ASync IO Supported", "tns.ntp_flag.asio", FT_BOOLEAN, 16,
6756 NULL((void*)0), 0x0200, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6757 { &hf_tns_ntp_flag_pio, {
6758 "Packet oriented IO", "tns.ntp_flag.pio", FT_BOOLEAN, 16,
6759 NULL((void*)0), 0x0100, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6760 { &hf_tns_ntp_flag_grant, {
6761 "Can grant connection to another", "tns.ntp_flag.grant", FT_BOOLEAN, 16,
6762 NULL((void*)0), 0x0080, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6763 { &hf_tns_ntp_flag_handoff, {
6764 "Can handoff connection to another", "tns.ntp_flag.handoff", FT_BOOLEAN, 16,
6765 NULL((void*)0), 0x0040, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6766 { &hf_tns_ntp_flag_sigio, {
6767 "Generate SIGIO signal", "tns.ntp_flag.sigio", FT_BOOLEAN, 16,
6768 NULL((void*)0), 0x0020, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6769 { &hf_tns_ntp_flag_sigpipe, {
6770 "Generate SIGPIPE signal", "tns.ntp_flag.sigpipe", FT_BOOLEAN, 16,
6771 NULL((void*)0), 0x0010, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6772 { &hf_tns_ntp_flag_sigurg, {
6773 "Generate SIGURG signal", "tns.ntp_flag.sigurg", FT_BOOLEAN, 16,
6774 NULL((void*)0), 0x0008, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6775 { &hf_tns_ntp_flag_urgentio, {
6776 "Urgent IO supported", "tns.ntp_flag.urgentio", FT_BOOLEAN, 16,
6777 NULL((void*)0), 0x0004, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6778 { &hf_tns_ntp_flag_fdio, {
6779 "Full duplex IO supported", "tns.ntp_flag.dfio", FT_BOOLEAN, 16,
6780 NULL((void*)0), 0x0002, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6781 { &hf_tns_ntp_flag_testop, {
6782 "Test operation", "tns.ntp_flag.testop", FT_BOOLEAN, 16,
6783 NULL((void*)0), 0x0001, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6784
6785
6786
6787
6788 { &hf_tns_line_turnaround, {
6789 "Line Turnaround Value", "tns.line_turnaround", FT_UINT16, BASE_DEC,
6790 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6791 { &hf_tns_value_of_one, {
6792 "Value of 1 in Hardware", "tns.value_of_one", FT_BYTES, BASE_NONE,
6793 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6794
6795 { &hf_tns_connect_data_length, {
6796 "Length of Connect Data", "tns.connect_data_length", FT_UINT16,
6797 BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_byte_bytes)((0 ? (const struct unit_name_string*)0 : ((&units_byte_bytes
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6798 { &hf_tns_connect_data_offset, {
6799 "Offset to Connect Data", "tns.connect_data_offset", FT_UINT16, BASE_DEC,
6800 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6801 { &hf_tns_connect_data_max, {
6802 "Maximum Receivable Connect Data", "tns.connect_data_max", FT_UINT32, BASE_DEC,
6803 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6804
6805 { &hf_tns_connect_flags0, {
6806 "Connect Flags 0", "tns.connect_flags0", FT_UINT8, BASE_HEX,
6807 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6808 { &hf_tns_connect_flags1, {
6809 "Connect Flags 1", "tns.connect_flags1", FT_UINT8, BASE_HEX,
6810 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6811
6812 { &hf_tns_conn_flag_nareq, {
6813 "NA services required", "tns.connect_flags.nareq", FT_BOOLEAN, 8,
6814 NULL((void*)0), 0x10, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6815 { &hf_tns_conn_flag_nalink, {
6816 "NA services linked in", "tns.connect_flags.nalink", FT_BOOLEAN, 8,
6817 NULL((void*)0), 0x08, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6818 { &hf_tns_conn_flag_enablena, {
6819 "NA services enabled", "tns.connect_flags.enablena", FT_BOOLEAN, 8,
6820 NULL((void*)0), 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6821 { &hf_tns_conn_flag_ichg, {
6822 "Interchange is involved", "tns.connect_flags.ichg", FT_BOOLEAN, 8,
6823 NULL((void*)0), 0x02, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6824 { &hf_tns_conn_flag_wantna, {
6825 "NA services wanted", "tns.connect_flags.wantna", FT_BOOLEAN, 8,
6826 NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6827
6828
6829 { &hf_tns_trace_cf1, {
6830 "Trace Cross Facility Item 1", "tns.trace_cf1", FT_UINT32, BASE_HEX,
6831 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6832 { &hf_tns_trace_cf2, {
6833 "Trace Cross Facility Item 2", "tns.trace_cf2", FT_UINT32, BASE_HEX,
6834 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6835 { &hf_tns_trace_cid, {
6836 "Trace Unique Connection ID", "tns.trace_cid", FT_UINT64, BASE_HEX,
6837 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6838 { &hf_tns_connect_data, {
6839 "Connect Data", "tns.connect_data", FT_STRING, BASE_NONE,
6840 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6841
6842 { &hf_tns_accept_data_length, {
6843 "Accept Data Length", "tns.accept_data_length", FT_UINT16,
6844 BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_byte_bytes)((0 ? (const struct unit_name_string*)0 : ((&units_byte_bytes
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6845 { &hf_tns_accept_data, {
6846 "Accept Data", "tns.accept_data", FT_STRING, BASE_NONE,
6847 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6848 { &hf_tns_accept_sdu, {
6849 "Session Data Unit Size (32-bit)", "tns.accept_sdu", FT_UINT32, BASE_DEC,
6850 NULL((void*)0), 0x0, "The session data unit a version 315 or later ACCEPT offers, past the 16-bit field's reach", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6851 { &hf_tns_accept_flags2, {
6852 "Flags 2", "tns.accept_flags2", FT_UINT32, BASE_HEX,
6853 NULL((void*)0), 0x0, "What a version 318 or later server offers the client", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6854 { &hf_tns_accept_flags2_check_oob, {
6855 "Check Out-of-Band", "tns.accept_flags2.check_oob", FT_BOOLEAN, 32,
6856 NULL((void*)0), 0x00000001, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6857 { &hf_tns_accept_flags2_end_of_response, {
6858 "End of Response", "tns.accept_flags2.end_of_response", FT_BOOLEAN, 32,
6859 NULL((void*)0), 0x02000000, "Replies end with an end-of-response marker, so the client can pipeline calls", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6860 { &hf_tns_accept_flags2_fast_auth, {
6861 "Fast Authentication", "tns.accept_flags2.fast_auth", FT_BOOLEAN, 32,
6862 NULL((void*)0), 0x10000000, "The client may send its protocol, data types and session key in one bundle", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6863 { &hf_tns_accept_data_offset, {
6864 "Offset to Accept Data", "tns.accept_data_offset", FT_UINT16, BASE_DEC,
6865 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6866
6867 { &hf_tns_refuse_reason_user, {
6868 "Refuse Reason (User)", "tns.refuse_reason_user", FT_UINT8, BASE_HEX,
6869 NULL((void*)0), 0x0, "Refuse Reason from Application", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6870 { &hf_tns_refuse_reason_system, {
6871 "Refuse Reason (System)", "tns.refuse_reason_system", FT_UINT8, BASE_HEX,
6872 NULL((void*)0), 0x0, "Refuse Reason from System", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6873 { &hf_tns_refuse_data_length, {
6874 "Refuse Data Length", "tns.refuse_data_length", FT_UINT16,
6875 BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_byte_bytes)((0 ? (const struct unit_name_string*)0 : ((&units_byte_bytes
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6876 { &hf_tns_refuse_data, {
6877 "Refuse Data", "tns.refuse_data", FT_STRING, BASE_NONE,
6878 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6879
6880 { &hf_tns_abort_reason_user, {
6881 "Abort Reason (User)", "tns.abort_reason_user", FT_UINT8, BASE_HEX,
6882 NULL((void*)0), 0x0, "Abort Reason from Application", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6883 { &hf_tns_abort_reason_system, {
6884 "Abort Reason (User)", "tns.abort_reason_system", FT_UINT8, BASE_HEX,
6885 NULL((void*)0), 0x0, "Abort Reason from System", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6886 { &hf_tns_abort_data, {
6887 "Abort Data", "tns.abort_data", FT_STRING, BASE_NONE,
6888 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6889
6890 { &hf_tns_marker_type, {
6891 "Marker Type", "tns.marker.type", FT_UINT8, BASE_HEX,
6892 VALS(tns_marker_types)((0 ? (const struct _value_string*)0 : ((tns_marker_types)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6893 { &hf_tns_marker_data_byte, {
6894 "Marker Data Byte", "tns.marker.databyte", FT_UINT8, BASE_HEX,
6895 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6896 { &hf_tns_marker_function, {
6897 "Marker Function", "tns.marker.function", FT_UINT8, BASE_DEC,
6898 VALS(tns_marker_functions)((0 ? (const struct _value_string*)0 : ((tns_marker_functions
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6899#if 0
6900 { &hf_tns_marker_data, {
6901 "Marker Data", "tns.marker.data", FT_UINT16, BASE_HEX,
6902 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6903#endif
6904
6905 { &hf_tns_control_cmd, {
6906 "Control Command", "tns.control.cmd", FT_UINT16, BASE_HEX,
6907 VALS(tns_control_cmds)((0 ? (const struct _value_string*)0 : ((tns_control_cmds)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6908 { &hf_tns_control_data, {
6909 "Control Data", "tns.control.data", FT_BYTES, BASE_NONE,
6910 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6911
6912 { &hf_tns_redirect_data_length, {
6913 "Redirect Data Length", "tns.redirect_data_length", FT_UINT16,
6914 BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_byte_bytes)((0 ? (const struct unit_name_string*)0 : ((&units_byte_bytes
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6915 { &hf_tns_redirect_data, {
6916 "Redirect Data", "tns.redirect_data", FT_STRING, BASE_NONE,
6917 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6918
6919 { &hf_tns_data_flag, {
6920 "Data Flag", "tns.data_flag", FT_UINT16, BASE_HEX,
6921 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6922 { &hf_tns_data_flag_send, {
6923 "Send Token", "tns.data_flag.send", FT_BOOLEAN, 16,
6924 NULL((void*)0), 0x1, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6925 { &hf_tns_data_flag_rc, {
6926 "Request Confirmation", "tns.data_flag.rc", FT_BOOLEAN, 16,
6927 NULL((void*)0), 0x2, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6928 { &hf_tns_data_flag_c, {
6929 "Confirmation", "tns.data_flag.c", FT_BOOLEAN, 16,
6930 NULL((void*)0), 0x4, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6931 { &hf_tns_data_flag_reserved, {
6932 "Reserved", "tns.data_flag.reserved", FT_BOOLEAN, 16,
6933 NULL((void*)0), 0x8, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6934 { &hf_tns_data_flag_more, {
6935 "More Data to Come", "tns.data_flag.more", FT_BOOLEAN, 16,
6936 NULL((void*)0), 0x0020, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6937 { &hf_tns_data_flag_eof, {
6938 "End of File", "tns.data_flag.eof", FT_BOOLEAN, 16,
6939 NULL((void*)0), 0x0040, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6940 { &hf_tns_data_flag_dic, {
6941 "Do Immediate Confirmation", "tns.data_flag.dic", FT_BOOLEAN, 16,
6942 NULL((void*)0), 0x0080, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6943 { &hf_tns_data_flag_rts, {
6944 "Request To Send", "tns.data_flag.rts", FT_BOOLEAN, 16,
6945 NULL((void*)0), 0x0100, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6946 { &hf_tns_data_flag_sntt, {
6947 "Send NT Trailer", "tns.data_flag.sntt", FT_BOOLEAN, 16,
6948 NULL((void*)0), 0x0200, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6949 { &hf_tns_data_flag_end_of_request, {
6950 "End of Request", "tns.data_flag.end_of_request", FT_BOOLEAN, 16,
6951 NULL((void*)0), 0x0800, "The packet ends one of a pipeline's calls", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6952 { &hf_tns_data_flag_begin_pipeline, {
6953 "Begin Pipeline", "tns.data_flag.begin_pipeline", FT_BOOLEAN, 16,
6954 NULL((void*)0), 0x1000, "The packet carries the first call of a pipeline", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6955 { &hf_tns_data_flag_end_of_response, {
6956 "End of Response", "tns.data_flag.end_of_response", FT_BOOLEAN, 16,
6957 NULL((void*)0), 0x2000, "The packet ends a reply, which closes with an end-of-response marker", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6958
6959 { &hf_tns_data_id, {
6960 "Data ID", "tns.data_id", FT_UINT32, BASE_HEX,
6961 VALS(tns_data_funcs)((0 ? (const struct _value_string*)0 : ((tns_data_funcs)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6962 { &hf_tns_data_length, {
6963 "Data Length", "tns.data_length", FT_UINT32,
6964 BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_byte_bytes)((0 ? (const struct unit_name_string*)0 : ((&units_byte_bytes
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6965
6966 { &hf_tns_data_oci_id, {
6967 "Call ID", "tns.data_oci.id", FT_UINT8, BASE_HEX|BASE_EXT_STRING0x00000200,
6968 &tns_data_oci_subfuncs_ext, 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6969
6970 { &hf_tns_data_tseq, {
6971 "TSeq", "tns.data_tseq", FT_UINT8, BASE_HEX,
6972 NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6973
6974 { &hf_tns_data_token, {
6975 "Token", "tns.data.token", FT_UINT64, BASE_DEC,
6976 NULL((void*)0), 0x0, "Call token (23ai); the reply echoes it", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6977 { &hf_tns_data_piggyback_id, {
6978 /* Also Call ID.
6979 Piggyback is a message what calls a small subset of functions
6980 declared in tns_data_oci_subfuncs. */
6981 "Call ID", "tns.data_piggyback.id", FT_UINT8, BASE_HEX|BASE_EXT_STRING0x00000200,
6982 &tns_data_oci_subfuncs_ext, 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6983
6984 { &hf_tns_data_unused, {
6985 "Unused", "tns.data.unused", FT_BYTES, BASE_NONE,
6986 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6987
6988 { &hf_tns_cursor, {
6989 "Cursor", "tns.data.cursor", FT_UINT32, BASE_DEC,
6990 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6991
6992 { &hf_tns_data_setp_acc_version, {
6993 "Accepted Version", "tns.data_setp_req.acc_vers", FT_UINT8, BASE_DEC,
6994 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6995 { &hf_tns_data_setp_cli_plat, {
6996 "Client Platform", "tns.data_setp_req.cli_plat", FT_STRINGZ, BASE_NONE,
6997 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
6998 { &hf_tns_data_setp_version, {
6999 "Version", "tns.data_setp_resp.version", FT_UINT8, BASE_DEC,
7000 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7001 { &hf_tns_data_setp_charset, {
7002 "Charset", "tns.data_setp_resp.charset", FT_UINT16, BASE_DEC,
7003 VALS(tns_charsets)((0 ? (const struct _value_string*)0 : ((tns_charsets)))), 0x0, "The database character set", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7004 { &hf_tns_data_setp_flags, {
7005 "Server Flags", "tns.data_setp_resp.flags", FT_UINT8, BASE_HEX,
7006 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7007 { &hf_tns_data_setp_ncharset, {
7008 "National Charset", "tns.data_setp_resp.ncharset", FT_UINT16, BASE_DEC,
7009 VALS(tns_charsets)((0 ? (const struct _value_string*)0 : ((tns_charsets)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7010 { &hf_tns_data_setp_compile_caps, {
7011 "Compile Capabilities", "tns.data_setp_resp.compile_caps", FT_BYTES, BASE_NONE,
7012 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7013 { &hf_tns_data_setp_runtime_caps, {
7014 "Runtime Capabilities", "tns.data_setp_resp.runtime_caps", FT_BYTES, BASE_NONE,
7015 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7016 { &hf_tns_data_setp_field_version, {
7017 "Field Version", "tns.data_setp_resp.field_version", FT_UINT8, BASE_DEC,
7018 VALS(tns_field_versions)((0 ? (const struct _value_string*)0 : ((tns_field_versions))
))
, 0x0, "The highest TTC field version the server offers", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7019 { &hf_tns_data_setp_banner, {
7020 "Server Banner", "tns.data_setp_resp.banner", FT_STRINGZ, BASE_NONE,
7021 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7022
7023 { &hf_tns_data_sns_cli_vers, {
7024 "Client Version", "tns.data_sns.cli_vers", FT_UINT32, BASE_CUSTOM,
7025 CF_FUNC(vsnum_to_vstext_basecustom)((const void *) (size_t) (vsnum_to_vstext_basecustom)), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7026 { &hf_tns_data_sns_srv_vers, {
7027 "Server Version", "tns.data_sns.srv_vers", FT_UINT32, BASE_CUSTOM,
7028 CF_FUNC(vsnum_to_vstext_basecustom)((const void *) (size_t) (vsnum_to_vstext_basecustom)), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7029 { &hf_tns_data_sns_srvcnt, {
7030 "Services", "tns.data_sns.srvcnt", FT_UINT16, BASE_DEC,
7031 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7032 { &hf_tns_data_sns_error, {
7033 "Error", "tns.data_sns.error", FT_UINT8, BASE_DEC,
7034 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7035 { &hf_tns_data_sns_service, {
7036 "Service", "tns.data_sns.service", FT_UINT16, BASE_DEC,
7037 VALS(tns_sns_services)((0 ? (const struct _value_string*)0 : ((tns_sns_services)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7038 { &hf_tns_data_sns_subpackets, {
7039 "Sub-packets", "tns.data_sns.subpackets", FT_UINT16, BASE_DEC,
7040 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7041 { &hf_tns_data_sns_svc_error, {
7042 "Service Error", "tns.data_sns.service_error", FT_UINT32, BASE_DEC,
7043 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7044 { &hf_tns_data_sns_sub_type, {
7045 "Sub-packet Type", "tns.data_sns.sub_type", FT_UINT16, BASE_DEC,
7046 VALS(tns_sns_subpacket_types)((0 ? (const struct _value_string*)0 : ((tns_sns_subpacket_types
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7047 { &hf_tns_data_sns_version, {
7048 "Version", "tns.data_sns.version", FT_UINT32, BASE_HEX,
7049 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7050 { &hf_tns_data_sns_sub_data, {
7051 "Sub-packet Data", "tns.data_sns.sub_data", FT_BYTES, BASE_NONE,
7052 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7053 { &hf_tns_data_sns_encryption, {
7054 "Encryption Algorithm", "tns.data_sns.encryption", FT_UINT8, BASE_DEC,
7055 VALS(tns_sns_encryption_algs)((0 ? (const struct _value_string*)0 : ((tns_sns_encryption_algs
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7056 { &hf_tns_data_sns_integrity, {
7057 "Integrity Algorithm", "tns.data_sns.integrity", FT_UINT8, BASE_DEC,
7058 VALS(tns_sns_integrity_algs)((0 ? (const struct _value_string*)0 : ((tns_sns_integrity_algs
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7059
7060 { &hf_tns_data_setdt_charset_in, {
7061 "Charset In", "tns.data_setdt.charset_in", FT_UINT16, BASE_DEC,
7062 VALS(tns_charsets)((0 ? (const struct _value_string*)0 : ((tns_charsets)))), 0x0, "NLS_LANGUAGE charset id", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7063 { &hf_tns_data_setdt_charset_out, {
7064 "Charset Out", "tns.data_setdt.charset_out", FT_UINT16, BASE_DEC,
7065 VALS(tns_charsets)((0 ? (const struct _value_string*)0 : ((tns_charsets)))), 0x0, "NLS_NCHAR charset id", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7066 { &hf_tns_data_setdt_flag, {
7067 "Flag", "tns.data_setdt.flag", FT_UINT8, BASE_HEX,
7068 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7069 { &hf_tns_data_setdt_caphdr, {
7070 "Capability Header", "tns.data_setdt.caphdr", FT_BYTES, BASE_NONE,
7071 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7072 { &hf_tns_data_setdt_caphdr_version, {
7073 "Version", "tns.data_setdt.caphdr.version", FT_UINT24, BASE_HEX,
7074 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7075 { &hf_tns_data_setdt_caphdr_flags, {
7076 "Flags", "tns.data_setdt.caphdr.flags", FT_BYTES, BASE_NONE,
7077 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7078 { &hf_tns_data_field_version, {
7079 "Field Version", "tns.data.field_version", FT_UINT8, BASE_DEC,
7080 VALS(tns_field_versions)((0 ? (const struct _value_string*)0 : ((tns_field_versions))
))
, 0x0, "TTC field version in force on the connection", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7081 { &hf_tns_data_setdt_field_version, {
7082 "Field Version", "tns.data_setdt.field_version", FT_UINT8, BASE_DEC,
7083 VALS(tns_field_versions)((0 ? (const struct _value_string*)0 : ((tns_field_versions))
))
, 0x0, "TTC field version the connection uses", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7084 { &hf_tns_data_setdt_tblhdr, {
7085 "Table Header", "tns.data_setdt.tblhdr", FT_BYTES, BASE_NONE,
7086 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7087 { &hf_tns_data_setdt_idmap, {
7088 "Identity Map", "tns.data_setdt.idmap", FT_BYTES, BASE_NONE,
7089 NULL((void*)0), 0x0, "245 entries: type N -> repr N (default mapping)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7090 { &hf_tns_data_setdt_overrides, {
7091 "Type Overrides", "tns.data_setdt.overrides", FT_NONE, BASE_NONE,
7092 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7093 { &hf_tns_data_setdt_override_client, {
7094 "Client Type", "tns.data_setdt.override.client", FT_UINT8, BASE_DEC,
7095 VALS(tns_data_types)((0 ? (const struct _value_string*)0 : ((tns_data_types)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7096 { &hf_tns_data_setdt_override_repr, {
7097 "Server Repr", "tns.data_setdt.override.repr", FT_UINT8, BASE_DEC,
7098 VALS(tns_data_types)((0 ? (const struct _value_string*)0 : ((tns_data_types)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7099 { &hf_tns_data_setdt_override_format, {
7100 "Format", "tns.data_setdt.override.format", FT_UINT8, BASE_DEC,
7101 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7102
7103 { &hf_tns_data_rpa_num_al8o4, {
7104 "Number of al8o4 Words", "tns.data_rpa.num_al8o4", FT_UINT32, BASE_DEC,
7105 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7106 { &hf_tns_data_rpa_al8o4, {
7107 "al8o4", "tns.data_rpa.al8o4", FT_UINT32, BASE_HEX,
7108 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7109 { &hf_tns_data_rpa_al8txl, {
7110 "al8txl", "tns.data_rpa.al8txl", FT_BYTES, BASE_NONE,
7111 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7112 { &hf_tns_data_rpa_num_kv, {
7113 "Number of Key/Value Pairs", "tns.data_rpa.num_kv", FT_UINT32, BASE_DEC,
7114 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7115 { &hf_tns_data_rpa_registration, {
7116 "Registration", "tns.data_rpa.registration", FT_BYTES, BASE_NONE,
7117 NULL((void*)0), 0x0, "Query registration; the last 8 bytes are the query id", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7118 { &hf_tns_data_rpa_num_rowcounts, {
7119 "Number of Row Counts", "tns.data_rpa.num_rowcounts", FT_UINT32, BASE_DEC,
7120 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7121 { &hf_tns_data_rpa_dml_rowcount, {
7122 "DML Row Count", "tns.data_rpa.dml_rowcount", FT_UINT64, BASE_DEC,
7123 NULL((void*)0), 0x0, "Rows one iteration of an array DML affected", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7124 { &hf_tns_data_spb_opcode, {
7125 "Opcode", "tns.data_spb.opcode", FT_UINT8, BASE_DEC,
7126 VALS(tns_spb_opcodes)((0 ? (const struct _value_string*)0 : ((tns_spb_opcodes)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7127 { &hf_tns_data_spb_ltxid, {
7128 "Logical Transaction Id", "tns.data_spb.ltxid", FT_BYTES, BASE_NONE,
7129 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7130 { &hf_tns_data_spb_os_pid, {
7131 "OS PID", "tns.data_spb.os_pid", FT_STRING, BASE_NONE,
7132 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7133 { &hf_tns_data_spb_num_kv, {
7134 "Number of Key/Value Pairs", "tns.data_spb.num_kv", FT_UINT32, BASE_DEC,
7135 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7136 { &hf_tns_data_spb_flags, {
7137 "Flags", "tns.data_spb.flags", FT_UINT32, BASE_HEX,
7138 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7139 { &hf_tns_data_spb_session_id, {
7140 "Session Id", "tns.data_spb.session_id", FT_UINT32, BASE_DEC,
7141 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7142 { &hf_tns_data_spb_serial_num, {
7143 "Serial Number", "tns.data_spb.serial_num", FT_UINT16, BASE_DEC,
7144 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7145 { &hf_tns_data_kv_text, {
7146 "Text Value", "tns.data_kv.text", FT_STRING, BASE_NONE,
7147 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7148 { &hf_tns_data_kv_binary, {
7149 "Binary Value", "tns.data_kv.binary", FT_BYTES, BASE_NONE,
7150 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7151 { &hf_tns_data_kv_keyword, {
7152 "Keyword", "tns.data_kv.keyword", FT_UINT16, BASE_DEC,
7153 VALS(tns_kv_keywords)((0 ? (const struct _value_string*)0 : ((tns_kv_keywords)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7154 { &hf_tns_data_wrn_code, {
7155 "Warning Code", "tns.data_wrn.code", FT_UINT16, BASE_DEC,
7156 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7157 { &hf_tns_data_wrn_length, {
7158 "Message Length", "tns.data_wrn.length", FT_UINT16, BASE_DEC,
7159 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7160 { &hf_tns_data_wrn_flags, {
7161 "Flags", "tns.data_wrn.flags", FT_UINT16, BASE_HEX,
7162 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7163 { &hf_tns_data_wrn_message, {
7164 "Message", "tns.data_wrn.message", FT_STRING, BASE_NONE,
7165 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7166 { &hf_tns_data_oci_oer_status, {
7167 "Status", "tns.data_oer.oci_status", FT_UINT8, BASE_DEC,
7168 VALS(tns_oci_oer_status_vals)((0 ? (const struct _value_string*)0 : ((tns_oci_oer_status_vals
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7169 { &hf_tns_data_oci_oer_seq, {
7170 "End-to-End Sequence", "tns.data_oer.seq", FT_UINT16, BASE_DEC,
7171 NULL((void*)0), 0x0, "A per-session counter the server advances with each reply", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7172 { &hf_tns_data_oci_oer_category, {
7173 "Statement Category", "tns.data_oer.category", FT_UINT8, BASE_DEC,
7174 NULL((void*)0), 0x0, "2 for a statement that produces rows or values, 1 for one that does not", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7175 { &hf_tns_data_oci_oer_error_pos, {
7176 "Error Position", "tns.data_oer.error_pos", FT_UINT8, BASE_DEC,
7177 NULL((void*)0), 0x0, "Offset into the SQL text of the parse error", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7178 { &hf_tns_data_oci_oer_command, {
7179 "Command Type", "tns.data_oer.command_type", FT_UINT8, BASE_DEC,
7180 VALS(tns_command_types)((0 ? (const struct _value_string*)0 : ((tns_command_types)))
)
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7181 { &hf_tns_data_oci_oer_call_seq, {
7182 "Call Sequence", "tns.data_oer.call_seq", FT_UINT16, BASE_DEC,
7183 NULL((void*)0), 0x0, "Sequence number of the call this status answers", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7184 { &hf_tns_data_auth_mode, {
7185 "Authentication Mode", "tns.data_auth.mode", FT_UINT32, BASE_HEX,
7186 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7187 { &hf_tns_data_auth_mode_logon, {
7188 "Logon", "tns.data_auth.mode.logon", FT_BOOLEAN, 32,
7189 NULL((void*)0), 0x00000001, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7190 { &hf_tns_data_auth_mode_change_password, {
7191 "Change Password", "tns.data_auth.mode.change_password", FT_BOOLEAN, 32,
7192 NULL((void*)0), 0x00000002, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7193 { &hf_tns_data_auth_mode_sysdba, {
7194 "SYSDBA", "tns.data_auth.mode.sysdba", FT_BOOLEAN, 32,
7195 NULL((void*)0), 0x00000020, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7196 { &hf_tns_data_auth_mode_sysoper, {
7197 "SYSOPER", "tns.data_auth.mode.sysoper", FT_BOOLEAN, 32,
7198 NULL((void*)0), 0x00000040, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7199 { &hf_tns_data_auth_mode_with_password, {
7200 "With Password", "tns.data_auth.mode.with_password", FT_BOOLEAN, 32,
7201 NULL((void*)0), 0x00000100, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7202 { &hf_tns_data_auth_user, {
7203 "User", "tns.data_auth.user", FT_STRING, BASE_NONE,
7204 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7205 { &hf_tns_data_sta_call_status, {
7206 "Call Status", "tns.data_sta.call_status", FT_UINT32, BASE_HEX,
7207 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7208 { &hf_tns_data_sta_seq, {
7209 "End-to-End Sequence", "tns.data_sta.seq", FT_UINT16, BASE_DEC,
7210 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7211 { &hf_tns_data_call_status_txn, {
7212 "Transaction in progress", "tns.data.call_status.txn_in_progress", FT_BOOLEAN, 32,
7213 NULL((void*)0), TNS_CALL_STATUS_TXN_IN_PROGRESS0x00000002, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7214 { &hf_tns_data_call_status_sess_release, {
7215 "Session release", "tns.data.call_status.sess_release", FT_BOOLEAN, 32,
7216 NULL((void*)0), TNS_CALL_STATUS_SESS_RELEASE0x00008000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7217 { &hf_tns_data_oer_call_status, {
7218 "Call Status", "tns.data_oer.call_status", FT_INT32, BASE_DEC,
7219 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7220 { &hf_tns_data_oer_rowcount, {
7221 "Row Count", "tns.data_oer.rowcount", FT_INT32, BASE_DEC,
7222 NULL((void*)0), 0x0, "The rows the call applied - on an error, the rows it managed before failing (11g)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7223 { &hf_tns_data_oer_err_code, {
7224 "Error Code", "tns.data_oer.err_code", FT_INT32, BASE_DEC,
7225 NULL((void*)0), 0x0, "ORA-NNNNN (0 = success)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7226 { &hf_tns_data_oer_cursor_id, {
7227 "Cursor Id", "tns.data_oer.cursor_id", FT_INT32, BASE_DEC,
7228 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7229 { &hf_tns_data_oer_n_batch_errcodes, {
7230 "Batch Error Codes", "tns.data_oer.n_batch_errcodes", FT_INT32, BASE_DEC,
7231 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7232 { &hf_tns_data_oer_n_batch_offsets, {
7233 "Batch Error Offsets", "tns.data_oer.n_batch_offsets", FT_INT32, BASE_DEC,
7234 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7235 { &hf_tns_data_oer_n_batch_messages, {
7236 "Batch Error Messages", "tns.data_oer.n_batch_messages", FT_INT32, BASE_DEC,
7237 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7238 { &hf_tns_data_oer_err_num_ext, {
7239 "Error Number", "tns.data_oer.err_num", FT_UINT32, BASE_DEC,
7240 NULL((void*)0), 0x0, "The error code at its full width (12.1 and later)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7241 { &hf_tns_data_oer_rowcount_ext, {
7242 "Row Count (64 bit)", "tns.data_oer.rowcount64", FT_UINT64, BASE_DEC,
7243 NULL((void*)0), 0x0, "The rows the call applied, at full width (12.1 and later)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7244 { &hf_tns_data_oer_sql_type, {
7245 "SQL Type", "tns.data_oer.sql_type", FT_UINT32, BASE_DEC,
7246 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7247 { &hf_tns_data_oer_checksum, {
7248 "Server Checksum", "tns.data_oer.checksum", FT_UINT32, BASE_HEX,
7249 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7250 { &hf_tns_data_oer_warn_flags, {
7251 "Warning Flags", "tns.data_oer.warn_flags", FT_UINT8, BASE_HEX,
7252 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7253 { &hf_tns_data_oer_warn_compile, {
7254 "Compiled with errors", "tns.data_oer.warn_flags.compilation_error", FT_BOOLEAN, 8,
7255 NULL((void*)0), TNS_WARN_COMPILATION_ERROR0x20, "A PL/SQL object was created in an invalid state", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7256 { &hf_tns_data_oer_message, {
7257 "Message", "tns.data_oer.message", FT_STRING, BASE_NONE,
7258 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7259
7260 { &hf_tns_data_opi_version2_banner_len, {
7261 "Banner Length", "tns.data_opi.vers2.banner_len", FT_UINT8, BASE_DEC,
7262 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7263 { &hf_tns_data_opi_version2_banner, {
7264 "Banner", "tns.data_opi.vers2.banner", FT_STRING, BASE_NONE,
7265 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7266 { &hf_tns_data_opi_version2_vsnum, {
7267 "Version", "tns.data_opi.vers2.version", FT_UINT32, BASE_CUSTOM,
7268 CF_FUNC(vsnum_to_vstext_basecustom)((const void *) (size_t) (vsnum_to_vstext_basecustom)), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7269
7270 { &hf_tns_data_opi_num_of_params, {
7271 "Number of parameters", "tns.data_opi.num_of_params", FT_UINT8, BASE_DEC,
7272 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7273 { &hf_tns_data_opi_param_length, {
7274 "Length", "tns.data_opi.param_length", FT_UINT8, BASE_DEC,
7275 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7276 { &hf_tns_data_opi_param_name, {
7277 "Name", "tns.data_opi.param_name", FT_STRING, BASE_NONE,
7278 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7279 { &hf_tns_data_opi_param_value, {
7280 "Value", "tns.data_opi.param_value", FT_STRING, BASE_NONE,
7281 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7282
7283 { &hf_tns_data_iov_num_binds, {
7284 "Number of Binds", "tns.data_iov.num_binds", FT_UINT32, BASE_DEC,
7285 NULL((void*)0), 0x0, "num_iters * 256 + num_requests", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7286 { &hf_tns_data_iov_bind_dir, {
7287 "Bind Direction", "tns.data_iov.bind_dir", FT_UINT8, BASE_DEC,
7288 VALS(tns_iov_bind_dirs)((0 ? (const struct _value_string*)0 : ((tns_iov_bind_dirs)))
)
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7289
7290 { &hf_tns_data_bind_retcode, {
7291 "Return Code", "tns.data_bind.retcode", FT_INT32, BASE_DEC,
7292 NULL((void*)0), 0x0, "Non-zero when an OUT value was truncated", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7293 { &hf_tns_data_dcb_num_columns, {
7294 "Number of Columns", "tns.data_dcb.num_columns", FT_UINT32, BASE_DEC,
7295 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7296 { &hf_tns_data_col_type, {
7297 "Data Type", "tns.data_col.type", FT_UINT8, BASE_DEC,
7298 VALS(tns_data_types)((0 ? (const struct _value_string*)0 : ((tns_data_types)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7299 { &hf_tns_data_col_precision, {
7300 "Precision", "tns.data_col.precision", FT_UINT8, BASE_DEC,
7301 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7302 { &hf_tns_data_col_scale, {
7303 "Scale", "tns.data_col.scale", FT_INT32, BASE_DEC,
7304 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7305 { &hf_tns_data_col_max_length, {
7306 "Max Data Length", "tns.data_col.max_length", FT_UINT32, BASE_DEC,
7307 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7308 { &hf_tns_data_col_charset, {
7309 "Charset", "tns.data_col.charset", FT_UINT32, BASE_DEC,
7310 VALS(tns_charsets)((0 ? (const struct _value_string*)0 : ((tns_charsets)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7311 { &hf_tns_data_col_csform, {
7312 "Charset Form", "tns.data_col.csform", FT_UINT8, BASE_DEC,
7313 VALS(tns_csform_vals)((0 ? (const struct _value_string*)0 : ((tns_csform_vals)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7314 { &hf_tns_data_col_max_size, {
7315 "Max Size", "tns.data_col.max_size", FT_UINT32, BASE_DEC,
7316 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7317 { &hf_tns_data_col_nulls_ok, {
7318 "Nulls Allowed", "tns.data_col.nulls_ok", FT_UINT8, BASE_DEC,
7319 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7320 { &hf_tns_data_col_name, {
7321 "Column Name", "tns.data_col.name", FT_STRING, BASE_NONE,
7322 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7323
7324 { &hf_tns_data_col_uds_flags, {
7325 "UDS Flags", "tns.data_col.uds_flags", FT_UINT32, BASE_HEX,
7326 NULL((void*)0), 0x0, "Marks a JSON column", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7327 { &hf_tns_data_col_domain_schema, {
7328 "Domain Schema", "tns.data_col.domain_schema", FT_STRING, BASE_NONE,
7329 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7330 { &hf_tns_data_col_domain_name, {
7331 "Domain Name", "tns.data_col.domain_name", FT_STRING, BASE_NONE,
7332 NULL((void*)0), 0x0, "The column's SQL domain", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7333 { &hf_tns_data_col_annotation, {
7334 "Annotation", "tns.data_col.annotation", FT_STRING, BASE_NONE,
7335 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7336 { &hf_tns_data_col_vector_dims, {
7337 "Vector Dimensions", "tns.data_col.vector_dims", FT_UINT32, BASE_DEC,
7338 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7339 { &hf_tns_data_col_vector_format, {
7340 "Vector Format", "tns.data_col.vector_format", FT_UINT8, BASE_DEC,
7341 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7342 { &hf_tns_data_rxh_num_requests, {
7343 "Number of Requests", "tns.data_rxh.num_requests", FT_UINT32, BASE_DEC,
7344 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7345 { &hf_tns_data_rxh_iter_num, {
7346 "Iteration Number", "tns.data_rxh.iter_num", FT_UINT32, BASE_DEC,
7347 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7348 { &hf_tns_data_bit_vector, {
7349 "Bit Vector", "tns.data.bit_vector", FT_BYTES, BASE_NONE,
7350 NULL((void*)0), 0x0, "Columns the next row sends; a clear bit repeats the previous row's value", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7351 { &hf_tns_data_bvc_num_cols_sent, {
7352 "Columns Sent", "tns.data_bvc.num_cols_sent", FT_UINT16, BASE_DEC,
7353 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7354 { &hf_tns_data_irs_num_results, {
7355 "Number of Result Sets", "tns.data_irs.num_results", FT_UINT32, BASE_DEC,
7356 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7357 { &hf_tns_data_rxh_num_iters, {
7358 "Number of Iterations", "tns.data_rxh.num_iters", FT_UINT32, BASE_DEC,
7359 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7360
7361 { &hf_tns_data_all8_options, {
7362 "Options", "tns.data_all8.options", FT_UINT32, BASE_HEX,
7363 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7364 { &hf_tns_data_all8_opt_parse, {
7365 "Parse", "tns.data_all8.options.parse", FT_BOOLEAN, 32,
7366 NULL((void*)0), 0x00000001, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7367 { &hf_tns_data_all8_opt_bind, {
7368 "Bind Values Present", "tns.data_all8.options.bind", FT_BOOLEAN, 32,
7369 NULL((void*)0), 0x00000008, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7370 { &hf_tns_data_all8_opt_define, {
7371 "Define Columns Present", "tns.data_all8.options.define", FT_BOOLEAN, 32,
7372 NULL((void*)0), 0x00000010, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7373 { &hf_tns_data_all8_opt_execute, {
7374 "Execute", "tns.data_all8.options.execute", FT_BOOLEAN, 32,
7375 NULL((void*)0), 0x00000020, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7376 { &hf_tns_data_all8_opt_commit, {
7377 "Autocommit", "tns.data_all8.options.commit", FT_BOOLEAN, 32,
7378 NULL((void*)0), 0x00000100, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7379 { &hf_tns_data_all8_opt_plsql, {
7380 "PL/SQL Binds", "tns.data_all8.options.plsql", FT_BOOLEAN, 32,
7381 NULL((void*)0), 0x00000400, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7382 { &hf_tns_data_all8_opt_fetch, {
7383 "Fetch", "tns.data_all8.options.fetch", FT_BOOLEAN, 32,
7384 NULL((void*)0), 0x00000040, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7385 { &hf_tns_data_all8_opt_not_plsql, {
7386 "Not PL/SQL", "tns.data_all8.options.not_plsql", FT_BOOLEAN, 32,
7387 NULL((void*)0), 0x00008000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7388 { &hf_tns_data_all8_parse_only, {
7389 "Parse Only", "tns.data_all8.parse_only", FT_BOOLEAN, BASE_NONE,
7390 NULL((void*)0), 0x0, "The execute asks for no work: nothing to run, nothing to fetch", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7391 { &hf_tns_data_all8_opt_describe, {
7392 "Describe", "tns.data_all8.options.describe", FT_BOOLEAN, 32,
7393 NULL((void*)0), 0x00020000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7394 { &hf_tns_data_all8_opt_batch_errors, {
7395 "Batch Errors", "tns.data_all8.options.batch_errors", FT_BOOLEAN, 32,
7396 NULL((void*)0), 0x00080000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7397 { &hf_tns_data_all8_fetch_rows, {
7398 "Fetch Rows", "tns.data_all8.fetch_rows", FT_UINT32, BASE_DEC,
7399 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7400 { &hf_tns_data_all8_iterations, {
7401 "Execution Count", "tns.data_all8.iterations", FT_UINT32, BASE_DEC,
7402 NULL((void*)0), 0x0, "Number of times a DML statement runs (array DML)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7403 { &hf_tns_data_all8_prefetch, {
7404 "Prefetch Rows", "tns.data_all8.prefetch", FT_UINT32, BASE_DEC,
7405 NULL((void*)0), 0x0, "Rows a query returns with the execute, before any fetch", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7406 { &hf_tns_data_all8_is_query, {
7407 "Query", "tns.data_all8.is_query", FT_BOOLEAN, BASE_NONE,
7408 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7409 { &hf_tns_data_all8_exec_flags, {
7410 "Execute Flags", "tns.data_all8.exec_flags", FT_UINT32, BASE_HEX,
7411 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7412 { &hf_tns_data_all8_xflag_scrollable, {
7413 "Scrollable", "tns.data_all8.exec_flags.scrollable", FT_BOOLEAN, 32,
7414 NULL((void*)0), 0x00000002, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7415 { &hf_tns_data_all8_xflag_no_cancel_on_eof, {
7416 "No Cancel on EOF", "tns.data_all8.exec_flags.no_cancel_on_eof", FT_BOOLEAN, 32,
7417 NULL((void*)0), 0x00000080, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7418 { &hf_tns_data_all8_xflag_dml_rowcounts, {
7419 "DML Row Counts", "tns.data_all8.exec_flags.dml_rowcounts", FT_BOOLEAN, 32,
7420 NULL((void*)0), 0x00004000, "Return the rows each iteration of an array DML affected", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7421 { &hf_tns_data_all8_xflag_implicit_rs, {
7422 "Implicit Result Sets", "tns.data_all8.exec_flags.implicit_resultset", FT_BOOLEAN, 32,
7423 NULL((void*)0), 0x00008000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7424 { &hf_tns_data_all8_fetch_orientation, {
7425 "Fetch Orientation", "tns.data_all8.fetch_orientation", FT_UINT32, BASE_HEX,
7426 VALS(tns_fetch_orientations)((0 ? (const struct _value_string*)0 : ((tns_fetch_orientations
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7427 { &hf_tns_data_all8_fetch_pos, {
7428 "Fetch Position", "tns.data_all8.fetch_pos", FT_UINT32, BASE_DEC,
7429 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7430 { &hf_tns_data_reexec_iterations, {
7431 "Execution Count", "tns.data_reexec.iterations", FT_UINT32, BASE_DEC,
7432 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7433 { &hf_tns_data_reexec_options2, {
7434 "Options 2", "tns.data_reexec.options2", FT_UINT32, BASE_HEX,
7435 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7436 { &hf_tns_data_reexec_opt2_commit, {
7437 "Autocommit", "tns.data_reexec.options2.commit", FT_BOOLEAN, 32,
7438 NULL((void*)0), 0x00000001, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7439 { &hf_tns_data_all8_oci_preamble, {
7440 "Preamble", "tns.data_all8.oci_preamble", FT_STRING, BASE_NONE,
7441 NULL((void*)0), 0x0, "The fixed execute preamble of an OCI client", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7442 { &hf_tns_data_all8_define_count, {
7443 "Define Count", "tns.data_all8.define_count", FT_UINT32, BASE_DEC,
7444 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7445 { &hf_tns_data_all8_bind_count, {
7446 "Bind Count", "tns.data_all8.bind_count", FT_UINT32, BASE_DEC,
7447 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7448 { &hf_tns_data_all8_sql, {
7449 "SQL Text", "tns.data_all8.sql", FT_STRING, BASE_NONE,
7450 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7451 { &hf_tns_data_bind_value, {
7452 "Bind Value", "tns.data_bind.value", FT_BYTES, BASE_NONE,
7453 NULL((void*)0), 0x0, "Raw type-encoded bind value", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7454 { &hf_tns_data_fetch_rows, {
7455 "Rows to Fetch", "tns.data_fetch.rows", FT_UINT32, BASE_DEC,
7456 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7457 { &hf_tns_data_kod_opcode, {
7458 "Describe Opcode", "tns.data_kod.opcode", FT_UINT32, BASE_DEC,
7459 VALS(tns_kod_opcodes)((0 ? (const struct _value_string*)0 : ((tns_kod_opcodes)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7460 { &hf_tns_data_kod_kind, {
7461 "Message Kind", "tns.data_kod.kind", FT_UINT8, BASE_DEC,
7462 VALS(tns_kod_kinds)((0 ? (const struct _value_string*)0 : ((tns_kod_kinds)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7463 { &hf_tns_data_kod_schema, {
7464 "Schema", "tns.data_kod.schema", FT_STRING, BASE_NONE,
7465 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7466 { &hf_tns_data_kod_name, {
7467 "Type Name", "tns.data_kod.name", FT_STRING, BASE_NONE,
7468 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7469 { &hf_tns_data_kod_oid, {
7470 "Object Id", "tns.data_kod.oid", FT_BYTES, BASE_NONE,
7471 NULL((void*)0), 0x0, "The id of the type described", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7472 { &hf_tns_data_kod_type_oid, {
7473 "Type Id", "tns.data_kod.type_oid", FT_BYTES, BASE_NONE,
7474 NULL((void*)0), 0x0, "The id of the system type the descriptor is an instance of", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7475 { &hf_tns_data_kod_system_type, {
7476 "System Type", "tns.data_kod.system_type", FT_UINT8, BASE_HEX,
7477 VALS(tns_kod_system_types)((0 ? (const struct _value_string*)0 : ((tns_kod_system_types
))))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7478 { &hf_tns_data_kod_image, {
7479 "Descriptor Image", "tns.data_kod.image", FT_BYTES, BASE_NONE,
7480 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7481 { &hf_tns_data_kod_version, {
7482 "Type Version", "tns.data_kod.version", FT_STRING, BASE_NONE,
7483 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7484 { &hf_tns_data_kod_typecode, {
7485 "Typecode", "tns.data_kod.typecode", FT_UINT16, BASE_DEC,
7486 VALS(tns_kod_typecodes)((0 ? (const struct _value_string*)0 : ((tns_kod_typecodes)))
)
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7487 { &hf_tns_data_lob_op, {
7488 "LOB Operation", "tns.data_lob.op", FT_UINT32, BASE_HEX,
7489 VALS(tns_lob_ops)((0 ? (const struct _value_string*)0 : ((tns_lob_ops)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7490 { &hf_tns_data_lob_offset, {
7491 "Source Offset", "tns.data_lob.offset", FT_UINT64, BASE_DEC,
7492 NULL((void*)0), 0x0, "1-based offset into the LOB", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7493 { &hf_tns_data_lob_locator, {
7494 "Locator", "tns.data_lob.locator", FT_BYTES, BASE_NONE,
7495 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7496 { &hf_tns_data_lob_directory, {
7497 "Directory", "tns.data_lob.directory", FT_STRING, BASE_NONE,
7498 NULL((void*)0), 0x0, "The directory object a BFILE's locator names", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7499 { &hf_tns_data_lob_file_name, {
7500 "File Name", "tns.data_lob.file_name", FT_STRING, BASE_NONE,
7501 NULL((void*)0), 0x0, "The file a BFILE's locator names", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7502 { &hf_tns_data_lob_charset, {
7503 "Charset", "tns.data_lob.charset", FT_UINT32, BASE_DEC,
7504 VALS(tns_charsets)((0 ? (const struct _value_string*)0 : ((tns_charsets)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7505 { &hf_tns_data_lob_data, {
7506 "Data", "tns.data_lob.data", FT_BYTES, BASE_NONE,
7507 NULL((void*)0), 0x0, "LOB content; UTF-16BE for a CLOB", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7508 { &hf_tns_data_lob_total_size, {
7509 "Total Locator Size", "tns.data_lob.total_size", FT_UINT32, BASE_DEC,
7510 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7511 { &hf_tns_data_pgy_schema, {
7512 "Current Schema", "tns.data_piggyback.schema", FT_STRING, BASE_NONE,
7513 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7514 { &hf_tns_data_pgy_session_state, {
7515 "Session State", "tns.data_piggyback.session_state", FT_UINT64, BASE_HEX,
7516 NULL((void*)0), 0x0, "Request boundary: the client begins or ends a request", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7517 { &hf_tns_data_pgy_e2e_flags, {
7518 "Changed Attributes", "tns.data_piggyback.e2e_flags", FT_UINT32, BASE_HEX,
7519 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7520 { &hf_tns_data_pgy_client_id, {
7521 "Client Identifier", "tns.data_piggyback.client_id", FT_STRING, BASE_NONE,
7522 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7523 { &hf_tns_data_pgy_module, {
7524 "Module", "tns.data_piggyback.module", FT_STRING, BASE_NONE,
7525 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7526 { &hf_tns_data_pgy_action, {
7527 "Action", "tns.data_piggyback.action", FT_STRING, BASE_NONE,
7528 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7529 { &hf_tns_data_pgy_client_info, {
7530 "Client Info", "tns.data_piggyback.client_info", FT_STRING, BASE_NONE,
7531 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7532 { &hf_tns_data_pgy_dbop, {
7533 "Database Operation", "tns.data_piggyback.dbop", FT_STRING, BASE_NONE,
7534 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7535 { &hf_tns_data_pgy_error_set_id, {
7536 "Error Set Id", "tns.data_piggyback.error_set_id", FT_UINT16, BASE_DEC,
7537 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7538 { &hf_tns_data_pgy_error_set_mode, {
7539 "Error Set Mode", "tns.data_piggyback.error_set_mode", FT_UINT8, BASE_DEC,
7540 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7541 { &hf_tns_data_pgy_pipeline_mode, {
7542 "Pipeline Mode", "tns.data_piggyback.pipeline_mode", FT_UINT8, BASE_DEC,
7543 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7544 { &hf_tns_data_pgy_sec_flags, {
7545 "Security Context Flags", "tns.data_piggyback.sec_flags", FT_UINT32, BASE_HEX,
7546 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7547 { &hf_tns_data_pgy_sec_key, {
7548 "Security Context Key", "tns.data_piggyback.sec_key", FT_STRING, BASE_NONE,
7549 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7550 { &hf_tns_data_pgy_sec_value, {
7551 "Security Context Value", "tns.data_piggyback.sec_value", FT_BYTES, BASE_NONE,
7552 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7553 { &hf_tns_data_lob_text, {
7554 "Text", "tns.data_lob.text", FT_STRING, BASE_NONE,
7555 NULL((void*)0), 0x0, "A CLOB's content, decoded as its locator says", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7556 { &hf_tns_data_release_tag, {
7557 "Tag", "tns.data_release.tag", FT_STRING, BASE_NONE,
7558 NULL((void*)0), 0x0, "Session tag for the pool", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7559 { &hf_tns_data_release_mode, {
7560 "Release Mode", "tns.data_release.mode", FT_UINT32, BASE_HEX,
7561 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7562 { &hf_tns_data_release_mode_deauth, {
7563 "Deauthenticate", "tns.data_release.mode.deauthenticate", FT_BOOLEAN, 32,
7564 NULL((void*)0), 0x00000002, "The session is being closed, not just returned", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7565 { &hf_tns_data_tpc_switch_op, {
7566 "Operation", "tns.data_tpc.switch_op", FT_UINT32, BASE_HEX,
7567 VALS(tns_tpc_switch_ops)((0 ? (const struct _value_string*)0 : ((tns_tpc_switch_ops))
))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7568 { &hf_tns_data_tpc_change_op, {
7569 "Operation", "tns.data_tpc.change_op", FT_UINT32, BASE_HEX,
7570 VALS(tns_tpc_change_ops)((0 ? (const struct _value_string*)0 : ((tns_tpc_change_ops))
))
, 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7571 { &hf_tns_data_tpc_format_id, {
7572 "XID Format Id", "tns.data_tpc.format_id", FT_UINT32, BASE_DEC,
7573 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7574 { &hf_tns_data_tpc_gtrid, {
7575 "Global Transaction Id", "tns.data_tpc.gtrid", FT_BYTES, BASE_NONE,
7576 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7577 { &hf_tns_data_tpc_bqual, {
7578 "Branch Qualifier", "tns.data_tpc.bqual", FT_BYTES, BASE_NONE,
7579 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7580 { &hf_tns_data_tpc_flags, {
7581 "Flags", "tns.data_tpc.flags", FT_UINT32, BASE_HEX,
7582 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7583 { &hf_tns_data_tpc_timeout, {
7584 "Timeout", "tns.data_tpc.timeout", FT_UINT32, BASE_DEC,
7585 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7586 { &hf_tns_data_tpc_state, {
7587 "State", "tns.data_tpc.state", FT_UINT32, BASE_DEC,
7588 VALS(tns_tpc_states)((0 ? (const struct _value_string*)0 : ((tns_tpc_states)))), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7589 { &hf_tns_data_tpc_context, {
7590 "Transaction Context", "tns.data_tpc.context", FT_BYTES, BASE_NONE,
7591 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7592 { &hf_tns_data_tpc_app_value, {
7593 "Application Value", "tns.data_tpc.app_value", FT_UINT32, BASE_DEC,
7594 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7595 { &hf_tns_data_tpc_internal_name, {
7596 "Internal Name", "tns.data_tpc.internal_name", FT_STRING, BASE_NONE,
7597 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7598 { &hf_tns_data_tpc_external_name, {
7599 "External Name", "tns.data_tpc.external_name", FT_STRING, BASE_NONE,
7600 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7601 { &hf_tns_data_lob_flag, {
7602 "Result", "tns.data_lob.flag", FT_BOOLEAN, BASE_NONE,
7603 NULL((void*)0), 0x0, "Whether the LOB is open, or the file exists", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7604 { &hf_tns_data_lob_amount, {
7605 "Amount", "tns.data_lob.amount", FT_UINT64, BASE_DEC,
7606 NULL((void*)0), 0x0, "Characters for a CLOB, bytes for a BLOB; the mode for OPEN", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7607 { &hf_tns_data_col_value, {
7608 "Column Value", "tns.data_col.value", FT_BYTES, BASE_NONE,
7609 NULL((void*)0), 0x0, "Raw type-encoded row column value", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7610
7611 { &hf_tns_data_lob_size, {
7612 "LOB Size", "tns.data_lob.size", FT_UINT64, BASE_DEC,
7613 NULL((void*)0), 0x0, "Characters for a CLOB, bytes for a BLOB", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7614 { &hf_tns_data_lob_chunk_size, {
7615 "LOB Chunk Size", "tns.data_lob.chunk_size", FT_UINT32, BASE_DEC,
7616 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7617 { &hf_tns_data_json_image, {
7618 "OSON Image", "tns.data_json.image", FT_BYTES, BASE_NONE,
7619 NULL((void*)0), 0x0, "Binary JSON (OSON) value", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7620 { &hf_tns_data_vector_image, {
7621 "Vector Image", "tns.data_vector.image", FT_BYTES, BASE_NONE,
7622 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7623 { &hf_tns_data_obj_toid, {
7624 "Type OID", "tns.data_obj.toid", FT_BYTES, BASE_NONE,
7625 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7626 { &hf_tns_data_obj_image, {
7627 "Object Image", "tns.data_obj.image", FT_BYTES, BASE_NONE,
7628 NULL((void*)0), 0x0, "Packed object attributes, or an XMLType document", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7629 { &hf_tns_data_descriptor_row_count, {
7630 "Row Count", "tns.data_descriptor.row_count", FT_UINT32, BASE_DEC,
7631 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7632 { &hf_tns_data_descriptor_row_size, {
7633 "Row Size", "tns.data_descriptor.row_size", FT_UINT32, BASE_DEC,
7634 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7635
7636 { &hf_tns_reserved_byte, {
7637 "Reserved Byte", "tns.reserved_byte", FT_BYTES, BASE_NONE,
7638 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
7639 { &hf_tns_packet_type, {
7640 "Packet Type", "tns.type", FT_UINT8, BASE_DEC,
7641 VALS(tns_type_vals)((0 ? (const struct _value_string*)0 : ((tns_type_vals)))), 0x0, "Type of TNS packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }}
7642
7643 };
7644
7645 static int *ett[] = {
7646 &ett_tns,
7647 &ett_tns_connect,
7648 &ett_tns_accept,
7649 &ett_tns_refuse,
7650 &ett_tns_abort,
7651 &ett_tns_redirect,
7652 &ett_tns_marker,
7653 &ett_tns_attention,
7654 &ett_tns_control,
7655 &ett_tns_data,
7656 &ett_tns_data_flag,
7657 &ett_tns_acc_versions,
7658 &ett_tns_opi_params,
7659 &ett_tns_opi_par,
7660 &ett_tns_sopt_flag,
7661 &ett_tns_ntp_flag,
7662 &ett_tns_conn_flag,
7663 &ett_tns_accept_flags2,
7664 &ett_tns_rows,
7665 &ett_tns_setdt_caphdr,
7666 &ett_tns_setdt_overrides,
7667 &ett_tns_setdt_override,
7668 &ett_tns_oer,
7669 &ett_tns_kod,
7670 &ett_tns_call_status,
7671 &ett_tns_warn_flags,
7672 &ett_tns_auth_mode,
7673 &ett_tns_sns_service,
7674 &ett_tns_sns_subpacket,
7675 &ett_tns_release_mode,
7676 &ett_tns_rpa,
7677 &ett_tns_kv,
7678 &ett_tns_iov,
7679 &ett_tns_dcb_col,
7680 &ett_tns_all8_options,
7681 &ett_tns_all8_i4,
7682 &ett_tns_all8_exec_flags,
7683 &ett_tns_binds,
7684 &ett_tns_bind,
7685 &ett_tns_defines,
7686 &ett_tns_reexec_options2,
7687 &ett_tns_bind_row,
7688 &ett_tns_rxd_row,
7689 &ett_tns_value,
7690 &ett_tns_irs,
7691 &ett_tns_out_binds,
7692 &ett_sql
7693 };
7694
7695 static ei_register_info ei[] = {
7696 { &ei_tns_connect_data_next_packet, { "tns.connect_data.next_packet", PI_REQUEST_CODE0x04000000, PI_CHAT0x00200000, "Long Connect Data (> 221 bytes) carried in subsequent Data packet", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
7697 { &ei_tns_data_descriptor_size_mismatch, { "tns.data_descriptor.size_mismatch", PI_PROTOCOL0x09000000, PI_WARN0x00600000, "Data size from summing row sizes differs from size in descriptor", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
7698 { &ei_tns_data_piggyback_cursors, { "tns.data.piggyback.cursors.invalid", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Cursor count is larger than the data left in the packet", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
7699 { &ei_tns_data_count_too_large, { "tns.data.count.invalid", PI_MALFORMED0x07000000, PI_ERROR0x00800000, "Count is larger than the data left in the packet", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
7700 { &ei_tns_data_compilation_error, { "tns.data_oer.compilation_error", PI_RESPONSE_CODE0x03000000, PI_NOTE0x00400000, "The statement created a PL/SQL object that compiled with errors", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
7701 { &ei_tns_data_encrypted, { "tns.data.encrypted", PI_DECRYPTION0x0c000000, PI_NOTE0x00400000, "Encrypted by native network encryption", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
7702 };
7703
7704 module_t *tns_module;
7705 expert_module_t* expert_tns;
7706
7707 proto_tns = proto_register_protocol("Transparent Network Substrate Protocol", "TNS", "tns");
7708 proto_register_field_array(proto_tns, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
7709 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
7710 expert_tns = expert_register_protocol(proto_tns);
7711 expert_register_field_array(expert_tns, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
7712 tns_handle = register_dissector("tns", dissect_tns, proto_tns);
7713
7714 tns_module = prefs_register_protocol(proto_tns, NULL((void*)0));
7715 prefs_register_bool_preference(tns_module, "desegment_tns_messages",
7716 "Reassemble TNS messages spanning multiple TCP segments",
7717 "Whether the TNS dissector should reassemble messages spanning multiple TCP segments. "
7718 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
7719 &tns_desegment);
7720}
7721
7722void
7723proto_reg_handoff_tns(void)
7724{
7725 dissector_add_uint_with_preference("tcp.port", TCP_PORT_TNS1521, tns_handle);
7726}
7727
7728/*
7729 * Editor modelines - https://www.wireshark.org/tools/modelines.html
7730 *
7731 * Local variables:
7732 * c-basic-offset: 8
7733 * tab-width: 8
7734 * indent-tabs-mode: t
7735 * End:
7736 *
7737 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
7738 * :indentSize=8:tabSize=8:noTabs=false:
7739 */