Bug Summary

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