Bug Summary

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