Bug Summary

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