Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-tns.c
Warning:line 1129, 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-03-100305-3662-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
24#include <wsutil/array.h>
25
26void proto_register_tns(void);
27
28#define TNS_HDR_LEN8 8
29
30/* Packet Types */
31#define TNS_TYPE_CONNECT1 1
32#define TNS_TYPE_ACCEPT2 2
33#define TNS_TYPE_ACK3 3
34#define TNS_TYPE_REFUSE4 4
35#define TNS_TYPE_REDIRECT5 5
36#define TNS_TYPE_DATA6 6
37#define TNS_TYPE_NULL7 7
38#define TNS_TYPE_ABORT9 9
39#define TNS_TYPE_RESEND11 11
40#define TNS_TYPE_MARKER12 12
41#define TNS_TYPE_ATTENTION13 13
42#define TNS_TYPE_CONTROL14 14
43#define TNS_TYPE_DD15 15
44#define TNS_TYPE_MAX19 19
45
46/*
47 * Oracle datatype codes as they appear on the wire and in tns_data_types[].
48 * python-oracledb lists most of these as its ORA_TYPE_NUM_* constants.
49 */
50#define TNS_DATATYPE_VARCHAR1 1
51#define TNS_DATATYPE_NUMBER2 2
52#define TNS_DATATYPE_INTEGER3 3 /* BINARY_INTEGER */
53#define TNS_DATATYPE_FLOAT4 4
54#define TNS_DATATYPE_STRING5 5
55#define TNS_DATATYPE_VARNUM6 6
56#define TNS_DATATYPE_DECIMAL7 7
57#define TNS_DATATYPE_LONG8 8
58#define TNS_DATATYPE_VCS9 9
59#define TNS_DATATYPE_ROWID11 11 /* RID */
60#define TNS_DATATYPE_DATE12 12
61#define TNS_DATATYPE_VBI15 15
62#define TNS_DATATYPE_RAW23 23
63#define TNS_DATATYPE_LONG_RAW24 24
64#define TNS_DATATYPE_CHAR96 96
65#define TNS_DATATYPE_BINARY_FLOAT100 100
66#define TNS_DATATYPE_BINARY_DOUBLE101 101
67#define TNS_DATATYPE_REFCURSOR102 102
68#define TNS_DATATYPE_ROWID_EXT104 104 /* ROWID */
69#define TNS_DATATYPE_ADT109 109 /* object */
70#define TNS_DATATYPE_REF111 111
71#define TNS_DATATYPE_CLOB112 112
72#define TNS_DATATYPE_BLOB113 113
73#define TNS_DATATYPE_BFILE114 114
74#define TNS_DATATYPE_RSET116 116
75#define TNS_DATATYPE_JSON119 119 /* OSON */
76#define TNS_DATATYPE_VECTOR127 127
77#define TNS_DATATYPE_TIMESTAMP180 180
78#define TNS_DATATYPE_TIMESTAMP_TZ181 181
79#define TNS_DATATYPE_INTERVAL_YM182 182
80#define TNS_DATATYPE_INTERVAL_DS183 183
81#define TNS_DATATYPE_UROWID208 208
82#define TNS_DATATYPE_TIMESTAMP_LTZ231 231
83#define TNS_DATATYPE_BOOLEAN252 252
84
85/* DALC length byte marking a slot with no value (see get_dalc_custom). */
86#define TNS_DALC_ABSENT0xFD 0xFD
87
88/* TTC field versions (compile capability 7), as python-oracledb's
89 * TNS_CCAP_FIELD_VERSION_* name them. The wire shape of several messages
90 * depends on the one a connection negotiates. */
91#define TNS_CCAP_FIELD_VERSION7 7
92#define TNS_FV_11_26 6
93#define TNS_FV_12_17 7
94#define TNS_FV_12_28 8
95#define TNS_FV_12_2_EXT19 9
96#define TNS_FV_18_110 10
97#define TNS_FV_18_1_EXT_111 11
98#define TNS_FV_19_112 12
99#define TNS_FV_19_1_EXT_113 13
100#define TNS_FV_20_114 14
101#define TNS_FV_20_1_EXT_115 15
102#define TNS_FV_21_116 16
103#define TNS_FV_23_117 17
104#define TNS_FV_23_1_EXT_118 18
105#define TNS_FV_23_1_EXT_219 19
106#define TNS_FV_23_1_EXT_320 20
107#define TNS_FV_23_1_EXT_421 21
108#define TNS_FV_23_1_EXT_522 22
109#define TNS_FV_23_3_EXT_623 23
110#define TNS_FV_23_424 24
111
112/* Data Packet Functions */
113#define SQLNET_SET_PROTOCOL1 1
114#define SQLNET_SET_DATATYPES2 2
115#define SQLNET_USER_OCI_FUNC3 3
116#define SQLNET_RETURN_STATUS4 4
117#define SQLNET_ACCESS_USR_ADDR5 5
118#define SQLNET_ROW_TRANSF_HDR6 6
119#define SQLNET_ROW_TRANSF_DATA7 7
120#define SQLNET_RETURN_OPI_PARAM8 8
121#define SQLNET_FUNCCOMPLETE9 9
122#define SQLNET_NERROR_RET_DEF10 10
123#define SQLNET_IOVEC_4FAST_UPI11 11
124#define SQLNET_LONG_4FAST_UPI12 12
125#define SQLNET_INVOKE_USER_CB13 13
126#define SQLNET_LOB_FILE_DF14 14
127#define SQLNET_WARNING15 15
128#define SQLNET_DESCRIBE_INFO16 16
129#define SQLNET_PIGGYBACK_FUNC17 17
130#define SQLNET_SIG_4UCS18 18
131#define SQLNET_FLUSH_BIND_DATA19 19
132#define SQLNET_BIT_VECTOR21 21
133#define SQLNET_SERVER_PIGGYBACK23 23
134#define SQLNET_IMPLICIT_RESULTS27 27
135#define SQLNET_END_OF_RESPONSE29 29
136#define SQLNET_TOKEN33 33
137#define SQLNET_SNS0xdeadbeef 0xdeadbeef
138#define SQLNET_XTRN_PROCSERV_R132 32
139#define SQLNET_XTRN_PROCSERV_R268 68
140
141/* Return OPI Parameter's Type */
142#define OPI_VERSION21 1
143#define OPI_OSESSKEY2 2
144#define OPI_OAUTH3 3
145
146/* An OCI client's execute preamble: offsets from the TTI_FUN byte, and
147 * the 8-byte pointer indicator its fixed slots sit between. */
148#define TNS_OCI_INDICATOR0xfeffffffffffffffUL UINT64_C(0xfeffffffffffffff)0xfeffffffffffffffUL
149#define TNS_OCI_ALL8_CURSOR7 7
150#define TNS_OCI_ALL8_IND11 11
151#define TNS_OCI_ALL8_SQLLEN319 19
152#define TNS_OCI_ALL8_IND2_NARROW23 23
153#define TNS_OCI_ALL8_IND2_WIDE27 27
154
155/* OCI function ids (TTI_FUN sub-functions). */
156#define TTI_REEXECUTE4 4
157#define TTI_FETCH5 5
158#define TTI_REEXECUTE_AND_FETCH78 78
159#define TTI_ALL894 94
160#define TTI_LOBOPS96 96
161#define TTI_CLOSE_CURSORS105 105
162#define TTI_SET_END_TO_END_ATTR135 135
163#define TTI_SET_SCHEMA152 152
164#define TTI_SESSION_STATE176 176
165#define TTI_PIPELINE_BEGIN199 199
166#define TTI_END_USER_SEC_CTX205 205
167
168/* desegmentation of TNS over TCP */
169static bool_Bool tns_desegment = true1;
170
171static dissector_handle_t tns_handle;
172
173static int proto_tns;
174static int hf_tns_request;
175static int hf_tns_response;
176static int hf_tns_length;
177static int hf_tns_packet_checksum;
178static int hf_tns_header_checksum;
179static int hf_tns_packet_type;
180static int hf_tns_reserved_byte;
181static int hf_tns_version;
182static int hf_tns_compat_version;
183
184static int hf_tns_service_options;
185static int hf_tns_sopt_flag_bconn;
186static int hf_tns_sopt_flag_pc;
187static int hf_tns_sopt_flag_hc;
188static int hf_tns_sopt_flag_fd;
189static int hf_tns_sopt_flag_hd;
190static int hf_tns_sopt_flag_dc1;
191static int hf_tns_sopt_flag_dc2;
192static int hf_tns_sopt_flag_dio;
193static int hf_tns_sopt_flag_ap;
194static int hf_tns_sopt_flag_ra;
195static int hf_tns_sopt_flag_sa;
196
197static int hf_tns_sdu_size;
198static int hf_tns_max_tdu_size;
199
200static int hf_tns_nt_proto_characteristics;
201static int hf_tns_ntp_flag_hangon;
202static int hf_tns_ntp_flag_crel;
203static int hf_tns_ntp_flag_tduio;
204static int hf_tns_ntp_flag_srun;
205static int hf_tns_ntp_flag_dtest;
206static int hf_tns_ntp_flag_cbio;
207static int hf_tns_ntp_flag_asio;
208static int hf_tns_ntp_flag_pio;
209static int hf_tns_ntp_flag_grant;
210static int hf_tns_ntp_flag_handoff;
211static int hf_tns_ntp_flag_sigio;
212static int hf_tns_ntp_flag_sigpipe;
213static int hf_tns_ntp_flag_sigurg;
214static int hf_tns_ntp_flag_urgentio;
215static int hf_tns_ntp_flag_fdio;
216static int hf_tns_ntp_flag_testop;
217
218static int hf_tns_line_turnaround;
219static int hf_tns_value_of_one;
220static int hf_tns_connect_data_length;
221static int hf_tns_connect_data_offset;
222static int hf_tns_connect_data_max;
223
224static int hf_tns_connect_flags0;
225static int hf_tns_connect_flags1;
226static int hf_tns_conn_flag_nareq;
227static int hf_tns_conn_flag_nalink;
228static int hf_tns_conn_flag_enablena;
229static int hf_tns_conn_flag_ichg;
230static int hf_tns_conn_flag_wantna;
231
232static int hf_tns_connect_data;
233static int hf_tns_trace_cf1;
234static int hf_tns_trace_cf2;
235static int hf_tns_trace_cid;
236
237static int hf_tns_accept_data_length;
238static int hf_tns_accept_data_offset;
239static int hf_tns_accept_data;
240
241static int hf_tns_refuse_reason_user;
242static int hf_tns_refuse_reason_system;
243static int hf_tns_refuse_data_length;
244static int hf_tns_refuse_data;
245
246static int hf_tns_abort_reason_user;
247static int hf_tns_abort_reason_system;
248static int hf_tns_abort_data;
249
250static int hf_tns_marker_type;
251static int hf_tns_marker_data_byte;
252static int hf_tns_marker_function;
253/* static int hf_tns_marker_data; */
254
255static int hf_tns_redirect_data_length;
256static int hf_tns_redirect_data;
257
258static int hf_tns_control_cmd;
259static int hf_tns_control_data;
260
261static int hf_tns_data_flag;
262static int hf_tns_data_flag_send;
263static int hf_tns_data_flag_rc;
264static int hf_tns_data_flag_c;
265static int hf_tns_data_flag_reserved;
266static int hf_tns_data_flag_more;
267static int hf_tns_data_flag_eof;
268static int hf_tns_data_flag_dic;
269static int hf_tns_data_flag_rts;
270static int hf_tns_data_flag_sntt;
271
272static int hf_tns_data_id;
273static int hf_tns_data_length;
274static int hf_tns_data_oci_id;
275static int hf_tns_data_tseq;
276static int hf_tns_data_token;
277static int hf_tns_data_piggyback_id;
278static int hf_tns_data_unused;
279
280static int hf_tns_cursor;
281
282static int hf_tns_data_opi_version2_banner_len;
283static int hf_tns_data_opi_version2_banner;
284static int hf_tns_data_opi_version2_vsnum;
285
286static int hf_tns_data_opi_num_of_params;
287static int hf_tns_data_opi_param_length;
288static int hf_tns_data_opi_param_name;
289static int hf_tns_data_opi_param_value;
290
291static int hf_tns_data_setp_acc_version;
292static int hf_tns_data_setp_cli_plat;
293static int hf_tns_data_setp_version;
294static int hf_tns_data_setp_banner;
295
296static int hf_tns_data_sns_cli_vers;
297static int hf_tns_data_sns_srv_vers;
298static int hf_tns_data_sns_srvcnt;
299
300static int hf_tns_data_setdt_charset_in;
301static int hf_tns_data_setdt_charset_out;
302static int hf_tns_data_setdt_flag;
303static int hf_tns_data_setdt_caphdr;
304static int hf_tns_data_setdt_caphdr_version;
305static int hf_tns_data_setdt_caphdr_flags;
306static int hf_tns_data_setdt_field_version;
307static int hf_tns_data_field_version;
308static int hf_tns_data_setdt_tblhdr;
309static int hf_tns_data_setdt_idmap;
310static int hf_tns_data_setdt_overrides;
311static int hf_tns_data_setdt_override_client;
312static int hf_tns_data_setdt_override_repr;
313static int hf_tns_data_setdt_override_format;
314
315static int hf_tns_data_oer_call_status;
316static int hf_tns_data_oer_rowcount;
317static int hf_tns_data_oer_err_code;
318static int hf_tns_data_oer_cursor_id;
319static int hf_tns_data_oer_n_batch_errcodes;
320static int hf_tns_data_oer_n_batch_offsets;
321static int hf_tns_data_oer_n_batch_messages;
322static int hf_tns_data_oer_message;
323static int hf_tns_data_oer_err_num_ext;
324static int hf_tns_data_oer_rowcount_ext;
325static int hf_tns_data_oer_sql_type;
326static int hf_tns_data_oer_checksum;
327
328static int hf_tns_data_rpa_num_al8o4;
329static int hf_tns_data_rpa_al8o4;
330static int hf_tns_data_rpa_al8txl;
331static int hf_tns_data_rpa_num_kv;
332static int hf_tns_data_rpa_registration;
333static int hf_tns_data_rpa_num_rowcounts;
334static int hf_tns_data_rpa_dml_rowcount;
335static int hf_tns_data_spb_opcode;
336static int hf_tns_data_spb_ltxid;
337static int hf_tns_data_spb_os_pid;
338static int hf_tns_data_spb_num_kv;
339static int hf_tns_data_spb_flags;
340static int hf_tns_data_spb_session_id;
341static int hf_tns_data_spb_serial_num;
342static int hf_tns_data_kv_text;
343static int hf_tns_data_kv_binary;
344static int hf_tns_data_kv_keyword;
345
346static int hf_tns_data_wrn_code;
347static int hf_tns_data_wrn_length;
348static int hf_tns_data_wrn_flags;
349static int hf_tns_data_wrn_message;
350
351static int hf_tns_data_oci_oer_status;
352static int hf_tns_data_oci_oer_seq;
353static int hf_tns_data_oci_oer_category;
354static int hf_tns_data_oci_oer_error_pos;
355static int hf_tns_data_oci_oer_command;
356static int hf_tns_data_oci_oer_call_seq;
357
358static int hf_tns_data_sta_call_status;
359static int hf_tns_data_sta_seq;
360static int hf_tns_data_call_status_txn;
361static int hf_tns_data_call_status_sess_release;
362
363static int hf_tns_data_iov_num_binds;
364static int hf_tns_data_iov_bind_dir;
365static int hf_tns_data_bind_retcode;
366
367static int hf_tns_data_dcb_num_columns;
368static int hf_tns_data_col_type;
369static int hf_tns_data_col_precision;
370static int hf_tns_data_col_scale;
371static int hf_tns_data_col_max_length;
372static int hf_tns_data_col_charset;
373static int hf_tns_data_col_csform;
374static int hf_tns_data_col_max_size;
375static int hf_tns_data_col_nulls_ok;
376static int hf_tns_data_col_name;
377static int hf_tns_data_col_uds_flags;
378static int hf_tns_data_col_domain_schema;
379static int hf_tns_data_col_domain_name;
380static int hf_tns_data_col_annotation;
381static int hf_tns_data_col_vector_dims;
382static int hf_tns_data_col_vector_format;
383
384static int hf_tns_data_rxh_num_requests;
385static int hf_tns_data_rxh_iter_num;
386static int hf_tns_data_rxh_num_iters;
387static int hf_tns_data_bit_vector;
388static int hf_tns_data_bvc_num_cols_sent;
389static int hf_tns_data_irs_num_results;
390
391static int hf_tns_data_all8_options;
392static int hf_tns_data_all8_opt_parse;
393static int hf_tns_data_all8_opt_bind;
394static int hf_tns_data_all8_opt_define;
395static int hf_tns_data_all8_opt_execute;
396static int hf_tns_data_all8_opt_commit;
397static int hf_tns_data_all8_opt_plsql;
398static int hf_tns_data_all8_opt_fetch;
399static int hf_tns_data_all8_opt_not_plsql;
400static int hf_tns_data_all8_opt_describe;
401static int hf_tns_data_all8_opt_batch_errors;
402static int hf_tns_data_all8_iterations;
403static int hf_tns_data_all8_prefetch;
404static int hf_tns_data_all8_is_query;
405static int hf_tns_data_all8_exec_flags;
406static int hf_tns_data_all8_xflag_scrollable;
407static int hf_tns_data_all8_xflag_no_cancel_on_eof;
408static int hf_tns_data_all8_xflag_dml_rowcounts;
409static int hf_tns_data_all8_xflag_implicit_rs;
410static int hf_tns_data_all8_fetch_orientation;
411static int hf_tns_data_all8_fetch_pos;
412static int hf_tns_data_all8_fetch_rows;
413static int hf_tns_data_all8_bind_count;
414static int hf_tns_data_all8_define_count;
415static int hf_tns_data_all8_oci_preamble;
416static int hf_tns_data_all8_sql;
417static int hf_tns_data_bind_value;
418static int hf_tns_data_fetch_rows;
419static int hf_tns_data_reexec_iterations;
420static int hf_tns_data_reexec_options2;
421static int hf_tns_data_reexec_opt2_commit;
422static int hf_tns_data_lob_op;
423static int hf_tns_data_lob_offset;
424static int hf_tns_data_lob_locator;
425static int hf_tns_data_lob_charset;
426static int hf_tns_data_lob_data;
427static int hf_tns_data_lob_amount;
428static int hf_tns_data_lob_flag;
429static int hf_tns_data_lob_total_size;
430static int hf_tns_data_pgy_schema;
431static int hf_tns_data_pgy_session_state;
432static int hf_tns_data_pgy_e2e_flags;
433static int hf_tns_data_pgy_client_id;
434static int hf_tns_data_pgy_module;
435static int hf_tns_data_pgy_action;
436static int hf_tns_data_pgy_client_info;
437static int hf_tns_data_pgy_dbop;
438static int hf_tns_data_pgy_error_set_id;
439static int hf_tns_data_pgy_error_set_mode;
440static int hf_tns_data_pgy_pipeline_mode;
441static int hf_tns_data_pgy_sec_flags;
442static int hf_tns_data_pgy_sec_key;
443static int hf_tns_data_pgy_sec_value;
444static int hf_tns_data_col_value;
445static int hf_tns_data_lob_size;
446static int hf_tns_data_lob_chunk_size;
447static int hf_tns_data_json_image;
448static int hf_tns_data_vector_image;
449static int hf_tns_data_obj_toid;
450static int hf_tns_data_obj_image;
451
452static int hf_tns_data_descriptor_row_count;
453static int hf_tns_data_descriptor_row_size;
454
455static int ett_tns;
456static int ett_tns_connect;
457static int ett_tns_accept;
458static int ett_tns_refuse;
459static int ett_tns_abort;
460static int ett_tns_redirect;
461static int ett_tns_marker;
462static int ett_tns_attention;
463static int ett_tns_control;
464static int ett_tns_data;
465static int ett_tns_data_flag;
466static int ett_tns_acc_versions;
467static int ett_tns_opi_params;
468static int ett_tns_opi_par;
469static int ett_tns_sopt_flag;
470static int ett_tns_ntp_flag;
471static int ett_tns_conn_flag;
472static int ett_tns_rows;
473static int ett_tns_setdt_caphdr;
474static int ett_tns_setdt_overrides;
475static int ett_tns_setdt_override;
476static int ett_tns_oer;
477static int ett_tns_call_status;
478static int ett_tns_rpa;
479static int ett_tns_kv;
480static int ett_tns_iov;
481static int ett_tns_dcb_col;
482static int ett_tns_all8_options;
483static int ett_tns_all8_i4;
484static int ett_tns_all8_exec_flags;
485static int ett_tns_binds;
486static int ett_tns_bind;
487static int ett_tns_defines;
488static int ett_tns_reexec_options2;
489static int ett_tns_bind_row;
490static int ett_tns_rxd_row;
491static int ett_tns_value;
492static int ett_tns_irs;
493static int ett_tns_out_binds;
494static int ett_sql;
495
496static expert_field ei_tns_connect_data_next_packet;
497static expert_field ei_tns_data_descriptor_size_mismatch;
498static expert_field ei_tns_data_piggyback_cursors;
499static expert_field ei_tns_data_count_too_large;
500
501#define TCP_PORT_TNS1521 1521 /* Not IANA registered */
502
503static int * const tns_connect_flags[] = {
504 &hf_tns_conn_flag_nareq,
505 &hf_tns_conn_flag_nalink,
506 &hf_tns_conn_flag_enablena,
507 &hf_tns_conn_flag_ichg,
508 &hf_tns_conn_flag_wantna,
509 NULL((void*)0)
510};
511
512static int * const tns_service_options[] = {
513 &hf_tns_sopt_flag_bconn,
514 &hf_tns_sopt_flag_pc,
515 &hf_tns_sopt_flag_hc,
516 &hf_tns_sopt_flag_fd,
517 &hf_tns_sopt_flag_hd,
518 &hf_tns_sopt_flag_dc1,
519 &hf_tns_sopt_flag_dc2,
520 &hf_tns_sopt_flag_dio,
521 &hf_tns_sopt_flag_ap,
522 &hf_tns_sopt_flag_ra,
523 &hf_tns_sopt_flag_sa,
524 NULL((void*)0)
525};
526
527/* TTI_ALL8 (SQL execute) options bitmask. */
528static int * const tns_all8_options[] = {
529 &hf_tns_data_all8_opt_parse,
530 &hf_tns_data_all8_opt_bind,
531 &hf_tns_data_all8_opt_define,
532 &hf_tns_data_all8_opt_execute,
533 &hf_tns_data_all8_opt_fetch,
534 &hf_tns_data_all8_opt_commit,
535 &hf_tns_data_all8_opt_plsql,
536 &hf_tns_data_all8_opt_not_plsql,
537 &hf_tns_data_all8_opt_describe,
538 &hf_tns_data_all8_opt_batch_errors,
539 NULL((void*)0)
540};
541
542static const value_string tns_type_vals[] = {
543 {TNS_TYPE_CONNECT1, "Connect" },
544 {TNS_TYPE_ACCEPT2, "Accept" },
545 {TNS_TYPE_ACK3, "Acknowledge" },
546 {TNS_TYPE_REFUSE4, "Refuse" },
547 {TNS_TYPE_REDIRECT5, "Redirect" },
548 {TNS_TYPE_DATA6, "Data" },
549 {TNS_TYPE_NULL7, "Null" },
550 {TNS_TYPE_ABORT9, "Abort" },
551 {TNS_TYPE_RESEND11, "Resend"},
552 {TNS_TYPE_MARKER12, "Marker"},
553 {TNS_TYPE_ATTENTION13, "Attention"},
554 {TNS_TYPE_CONTROL14, "Control"},
555 {TNS_TYPE_DD15, "Data Descriptor"},
556 {0, NULL((void*)0)}
557};
558
559static const value_string tns_data_funcs[] = {
560 {SQLNET_SET_PROTOCOL1, "Set Protocol"},
561 {SQLNET_SET_DATATYPES2, "Set Datatypes"},
562 {SQLNET_USER_OCI_FUNC3, "User OCI Functions"},
563 {SQLNET_RETURN_STATUS4, "Return Status"},
564 {SQLNET_ACCESS_USR_ADDR5, "Access User Address Space"},
565 {SQLNET_ROW_TRANSF_HDR6, "Row Transfer Header"},
566 {SQLNET_ROW_TRANSF_DATA7, "Row Transfer Data"},
567 {SQLNET_RETURN_OPI_PARAM8, "Return OPI Parameter"},
568 {SQLNET_FUNCCOMPLETE9, "Function Complete"},
569 {SQLNET_NERROR_RET_DEF10, "N Error return definitions follow"},
570 {SQLNET_IOVEC_4FAST_UPI11, "Sending I/O Vec only for fast UPI"},
571 {SQLNET_LONG_4FAST_UPI12, "Sending long for fast UPI"},
572 {SQLNET_INVOKE_USER_CB13, "Invoke user callback"},
573 {SQLNET_LOB_FILE_DF14, "LOB/FILE data follows"},
574 {SQLNET_WARNING15, "Warning messages - may be a set of them"},
575 {SQLNET_DESCRIBE_INFO16, "Describe Information"},
576 {SQLNET_PIGGYBACK_FUNC17, "Piggy back function follow"},
577 {SQLNET_SIG_4UCS18, "Signals special action for untrusted callout support"},
578 {SQLNET_FLUSH_BIND_DATA19, "Flush Out Bind data in DML/w RETURN when error"},
579 {SQLNET_BIT_VECTOR21, "Bit Vector"},
580 {SQLNET_SERVER_PIGGYBACK23, "Server-side Piggyback"},
581 {SQLNET_IMPLICIT_RESULTS27, "Implicit Result Sets"},
582 {SQLNET_END_OF_RESPONSE29, "End of Response"},
583 {SQLNET_TOKEN33, "Token"},
584 {SQLNET_XTRN_PROCSERV_R132, "External Procedures and Services Registrations"},
585 {SQLNET_XTRN_PROCSERV_R268, "External Procedures and Services Registrations"},
586 {SQLNET_SNS0xdeadbeef, "Secure Network Services"},
587 {0, NULL((void*)0)}
588};
589
590/* The second options word of a re-execute. */
591static int * const tns_reexec_options2[] = {
592 &hf_tns_data_reexec_opt2_commit,
593 NULL((void*)0)
594};
595
596/* Execute flags, the al8i4[9] word of a TTI_ALL8 execute. */
597static int * const tns_all8_exec_flags[] = {
598 &hf_tns_data_all8_xflag_scrollable,
599 &hf_tns_data_all8_xflag_no_cancel_on_eof,
600 &hf_tns_data_all8_xflag_dml_rowcounts,
601 &hf_tns_data_all8_xflag_implicit_rs,
602 NULL((void*)0)
603};
604
605/* Scrollable-cursor fetch orientation, al8i4[10] of a TTI_ALL8 execute. */
606static const value_string tns_fetch_orientations[] = {
607 {0x00, "None"},
608 {0x01, "Current"},
609 {0x02, "Next"},
610 {0x04, "First"},
611 {0x08, "Last"},
612 {0x10, "Prior"},
613 {0x20, "Absolute"},
614 {0x40, "Relative"},
615 {0, NULL((void*)0)}
616};
617
618/* Server-side piggyback opcodes (python-oracledb's
619 * TNS_SERVER_PIGGYBACK_*). */
620#define TNS_SPB_QUERY_CACHE_INVALIDATION1 1
621#define TNS_SPB_OS_PID_MTS2 2
622#define TNS_SPB_TRACE_EVENT3 3
623#define TNS_SPB_SESS_RET4 4
624#define TNS_SPB_SYNC5 5
625#define TNS_SPB_LTXID7 7
626#define TNS_SPB_AC_REPLAY_CONTEXT8 8
627#define TNS_SPB_EXT_SYNC9 9
628#define TNS_SPB_SESS_SIGNATURE10 10
629
630static const value_string tns_spb_opcodes[] = {
631 {TNS_SPB_QUERY_CACHE_INVALIDATION1, "Query Cache Invalidation"},
632 {TNS_SPB_OS_PID_MTS2, "OS PID (shared server)"},
633 {TNS_SPB_TRACE_EVENT3, "Trace Event"},
634 {TNS_SPB_SESS_RET4, "Session Return"},
635 {TNS_SPB_SYNC5, "Session State Sync"},
636 {TNS_SPB_LTXID7, "Logical Transaction Id"},
637 {TNS_SPB_AC_REPLAY_CONTEXT8, "Application Continuity Replay Context"},
638 {TNS_SPB_EXT_SYNC9, "Extended Sync"},
639 {TNS_SPB_SESS_SIGNATURE10, "Session Signature"},
640 {0, NULL((void*)0)}
641};
642
643/* Status byte of an OCI client's status block. */
644static const value_string tns_oci_oer_status_vals[] = {
645 {1, "Success"},
646 {5, "Error"},
647 {0, NULL((void*)0)}
648};
649
650/* Statement command types, as V$SQL.COMMAND_TYPE numbers them. */
651static const value_string tns_command_types[] = {
652 {1, "CREATE TABLE"},
653 {2, "INSERT"},
654 {3, "SELECT"},
655 {6, "UPDATE"},
656 {7, "DELETE"},
657 {9, "CREATE INDEX"},
658 {12, "DROP TABLE"},
659 {15, "ALTER TABLE"},
660 {21, "CREATE VIEW"},
661 {22, "DROP VIEW"},
662 {44, "COMMIT"},
663 {45, "ROLLBACK"},
664 {47, "PL/SQL EXECUTE"},
665 {85, "TRUNCATE TABLE"},
666 {0, NULL((void*)0)}
667};
668
669static const value_string tns_field_versions[] = {
670 {TNS_FV_11_26, "11.2"},
671 {TNS_FV_12_17, "12.1"},
672 {TNS_FV_12_28, "12.2"},
673 {TNS_FV_12_2_EXT19, "12.2 ext 1"},
674 {TNS_FV_18_110, "18.1"},
675 {TNS_FV_18_1_EXT_111, "18.1 ext 1"},
676 {TNS_FV_19_112, "19.1"},
677 {TNS_FV_19_1_EXT_113, "19.1 ext 1"},
678 {TNS_FV_20_114, "20.1"},
679 {TNS_FV_20_1_EXT_115, "20.1 ext 1"},
680 {TNS_FV_21_116, "21.1"},
681 {TNS_FV_23_117, "23.1"},
682 {TNS_FV_23_1_EXT_118, "23.1 ext 1"},
683 {TNS_FV_23_1_EXT_219, "23.1 ext 2"},
684 {TNS_FV_23_1_EXT_320, "23.1 ext 3"},
685 {TNS_FV_23_1_EXT_421, "23.1 ext 4"},
686 {TNS_FV_23_1_EXT_522, "23.1 ext 5"},
687 {TNS_FV_23_3_EXT_623, "23.3 ext 6"},
688 {TNS_FV_23_424, "23.4"},
689 {0, NULL((void*)0)}
690};
691
692/* Keyword numbers of the key/value pairs a server reports back, for a
693 * session attribute a statement changed (python-oracledb's
694 * TNS_KEYWORD_NUM_*). */
695static const value_string tns_kv_keywords[] = {
696 {168, "CURRENT_SCHEMA"},
697 {172, "EDITION"},
698 {201, "TRANSACTION_ID"},
699 {0, NULL((void*)0)}
700};
701
702/* Oracle TNS native data-type ids. Used by the Set Datatypes
703 * negotiation to label override entries with human names. */
704static const value_string tns_data_types[] = {
705 {TNS_DATATYPE_VARCHAR1, "VARCHAR"},
706 {TNS_DATATYPE_NUMBER2, "NUMBER"},
707 {TNS_DATATYPE_INTEGER3, "BINARY_INTEGER"},
708 {TNS_DATATYPE_FLOAT4, "FLOAT"},
709 {TNS_DATATYPE_STRING5, "STRING"},
710 {TNS_DATATYPE_VARNUM6, "VARNUM"},
711 {TNS_DATATYPE_DECIMAL7, "DECIMAL"},
712 {TNS_DATATYPE_LONG8, "LONG"},
713 {TNS_DATATYPE_VCS9, "VCS"},
714 {TNS_DATATYPE_ROWID11, "RID"},
715 {TNS_DATATYPE_DATE12, "DATE"},
716 {TNS_DATATYPE_VBI15, "VBI"},
717 {TNS_DATATYPE_RAW23, "RAW"},
718 {TNS_DATATYPE_LONG_RAW24, "LONG RAW"},
719 {TNS_DATATYPE_CHAR96, "CHAR"},
720 {TNS_DATATYPE_BINARY_FLOAT100, "BINARY_FLOAT"},
721 {TNS_DATATYPE_BINARY_DOUBLE101, "BINARY_DOUBLE"},
722 {TNS_DATATYPE_REFCURSOR102, "REFCURSOR"},
723 {TNS_DATATYPE_ROWID_EXT104, "ROWID"},
724 {TNS_DATATYPE_ADT109, "ADT"},
725 {TNS_DATATYPE_REF111, "REF"},
726 {TNS_DATATYPE_CLOB112, "CLOB"},
727 {TNS_DATATYPE_BLOB113, "BLOB"},
728 {TNS_DATATYPE_BFILE114, "BFILE"},
729 {TNS_DATATYPE_RSET116, "RSET"},
730 {TNS_DATATYPE_JSON119, "JSON"},
731 {TNS_DATATYPE_VECTOR127, "VECTOR"},
732 {TNS_DATATYPE_TIMESTAMP180, "TIMESTAMP"},
733 {TNS_DATATYPE_TIMESTAMP_TZ181, "TIMESTAMP WITH TIME ZONE"},
734 {TNS_DATATYPE_INTERVAL_YM182, "INTERVAL YEAR TO MONTH"},
735 {TNS_DATATYPE_INTERVAL_DS183, "INTERVAL DAY TO SECOND"},
736 {TNS_DATATYPE_UROWID208, "UROWID"},
737 {TNS_DATATYPE_TIMESTAMP_LTZ231, "TIMESTAMP WITH LOCAL TIME ZONE"},
738 {TNS_DATATYPE_BOOLEAN252, "BOOLEAN"},
739 {0, NULL((void*)0)}
740};
741
742/* Oracle NLS character-set ids - the well-known subset, enough to name
743 * the charsets seen in a Set Datatypes negotiation. */
744static const value_string tns_charsets[] = {
745 {31, "WE8ISO8859P1"},
746 {32, "EE8ISO8859P2"},
747 {35, "CL8ISO8859P5"},
748 {170, "EE8MSWIN1250"},
749 {171, "CL8MSWIN1251"},
750 {178, "WE8MSWIN1252"},
751 {830, "JA16EUC"},
752 {852, "ZHS16GBK"},
753 {865, "ZHT16BIG5"},
754 {867, "ZHT16MSWIN950"},
755 {871, "US7ASCII"},
756 {873, "AL32UTF8"},
757 {2000, "AL16UTF16"},
758 {0, NULL((void*)0)}
759};
760
761/* TTI_LOBOPS operation opcodes. */
762#define TNS_LOB_OP_FILE_ISOPEN0x00400 0x00400
763#define TNS_LOB_OP_FILE_EXISTS0x00800 0x00800
764#define TNS_LOB_OP_CREATE_TEMP0x00110 0x00110
765#define TNS_LOB_OP_IS_OPEN0x11000 0x11000
766
767static const value_string tns_lob_ops[] = {
768 {0x00001, "GET_LENGTH"},
769 {0x00002, "READ"},
770 {0x00020, "TRIM"},
771 {0x00040, "WRITE"},
772 {0x00100, "FILE_OPEN"},
773 {0x00110, "CREATE_TEMP"},
774 {0x00111, "FREE_TEMP"},
775 {0x00200, "FILE_CLOSE"},
776 {0x00400, "FILE_ISOPEN"},
777 {0x00800, "FILE_EXISTS"},
778 {0x04000, "GET_CHUNK_SIZE"},
779 {0x08000, "OPEN"},
780 {0x10000, "CLOSE"},
781 {0x11000, "IS_OPEN"},
782 {0x80000, "ARRAY"},
783 {0, NULL((void*)0)}
784};
785
786/* Column character-set form (csfrm) in an OAC descriptor: whether char data
787 * is in the database charset or the national (AL16UTF16) charset. */
788#define TNS_CSFORM_NCHAR2 2
789static const value_string tns_csform_vals[] = {
790 {1, "Database charset"},
791 {2, "National (AL16UTF16)"},
792 {0, NULL((void*)0)}
793};
794
795/* Bind directions reported per bind in a TTI_IOV vector (TNS_BIND_DIR_*),
796 * cross-referenced with python-oracledb's constants. */
797#define TNS_BIND_DIR_INPUT32 32
798static const value_string tns_iov_bind_dirs[] = {
799 {16, "OUT"},
800 {32, "IN"},
801 {48, "IN OUT"},
802 {0, NULL((void*)0)}
803};
804
805static const value_string tns_data_oci_subfuncs[] = {
806 {1, "Logon to Oracle"},
807 {2, "Open Cursor"},
808 {3, "Parse a Row"},
809 {4, "Execute a Row"},
810 {5, "Fetch a Row"},
811 {8, "Close Cursor"},
812 {9, "Logoff of Oracle"},
813 {10, "Describe a select list column"},
814 {11, "Define where the column goes"},
815 {12, "Auto commit on"},
816 {13, "Auto commit off"},
817 {14, "Commit"},
818 {15, "Rollback"},
819 {16, "Set fatal error options"},
820 {17, "Resume current operation"},
821 {18, "Get Oracle version-date string"},
822 {19, "Until we get rid of OASQL"},
823 {20, "Cancel the current operation"},
824 {21, "Get error message"},
825 {22, "Exit Oracle command"},
826 {23, "Special function"},
827 {24, "Abort"},
828 {25, "Dequeue by RowID"},
829 {26, "Fetch a long column value"},
830 {27, "Create Access Module"},
831 {28, "Save Access Module Statement"},
832 {29, "Save Access Module"},
833 {30, "Parse Access Module Statement"},
834 {31, "How many items?"},
835 {32, "Initialize Oracle"},
836 {33, "Change User ID"},
837 {34, "Bind by reference positional"},
838 {35, "Get n'th Bind Variable"},
839 {36, "Get n'th Into Variable"},
840 {37, "Bind by reference"},
841 {38, "Bind by reference numeric"},
842 {39, "Parse and Execute"},
843 {40, "Parse for syntax (only)"},
844 {41, "Parse for syntax and SQL Dictionary lookup"},
845 {42, "Continue serving after EOF"},
846 {43, "Array describe"},
847 {44, "Init sys pars command table"},
848 {45, "Finalize sys pars command table"},
849 {46, "Put sys par in command table"},
850 {47, "Get sys pars from command table"},
851 {48, "Start Oracle (V6)"},
852 {49, "Shutdown Oracle (V6)"},
853 {50, "Run Independent Process (V6)"},
854 {51, "Test RAM (V6)"},
855 {52, "Archive operation (V6)"},
856 {53, "Media Recovery - start (V6)"},
857 {54, "Media Recovery - record tablespace to recover (V6)"},
858 {55, "Media Recovery - get starting log seq # (V6)"},
859 {56, "Media Recovery - recover using offline log (V6)"},
860 {57, "Media Recovery - cancel media recovery (V6)"},
861 {58, "Logon to Oracle (V6)"},
862 {59, "Get Oracle version-date string in new format"},
863 {60, "Initialize Oracle"},
864 {61, "Reserved for MAC; close all cursors"},
865 {62, "Bundled execution call"},
866 {65, "For direct loader: functions"},
867 {66, "For direct loader: buffer transfer"},
868 {67, "Distrib. trans. mgr. RPC"},
869 {68, "Describe indexes for distributed query"},
870 {69, "Session operations"},
871 {70, "Execute using synchronized system commit numbers"},
872 {71, "Fast UPI calls to OPIAL7"},
873 {72, "Long Fetch (V7)"},
874 {73, "Call OPIEXE from OPIALL: no two-task access"},
875 {74, "Parse Call (V7) to deal with various flavours"},
876 {76, "RPC call from PL/SQL"},
877 {77, "Do a KGL operation"},
878 {78, "Execute and Fetch"},
879 {79, "X/Open XA operation"},
880 {80, "New KGL operation call"},
881 {81, "2nd Half of Logon"},
882 {82, "1st Half of Logon"},
883 {83, "Do Streaming Operation"},
884 {84, "Open Session (71 interface)"},
885 {85, "X/Open XA operations (71 interface)"},
886 {86, "Debugging operations"},
887 {87, "Special debugging operations"},
888 {88, "XA Start"},
889 {89, "XA Switch and Commit"},
890 {90, "Direct copy from db buffers to client address"},
891 {91, "OKOD Call (In Oracle <= 7 this used to be Connect"},
892 {93, "RPI Callback with ctxdef"},
893 {94, "Bundled execution call (V7)"},
894 {95, "Do Streaming Operation without begintxn"},
895 {96, "LOB and FILE related calls"},
896 {97, "File Create call"},
897 {98, "Describe query (V8) call"},
898 {99, "Connect (non-blocking attach host)"},
899 {100, "Open a recursive cursor"},
900 {101, "Bundled KPR Execution"},
901 {102, "Bundled PL/SQL execution"},
902 {103, "Transaction start, attach, detach"},
903 {104, "Transaction commit, rollback, recover"},
904 {105, "Cursor close all"},
905 {106, "Failover into piggyback"},
906 {107, "Session switching piggyback (V8)"},
907 {108, "Do Dummy Defines"},
908 {109, "Init sys pars (V8)"},
909 {110, "Finalize sys pars (V8)"},
910 {111, "Put sys par in par space (V8)"},
911 {112, "Terminate sys pars (V8)"},
912 {114, "Init Untrusted Callbacks"},
913 {115, "Generic authentication call"},
914 {116, "FailOver Get Instance call"},
915 {117, "Oracle Transaction service Commit remote sites"},
916 {118, "Get the session key"},
917 {119, "Describe any (V8)"},
918 {120, "Cancel All"},
919 {121, "AQ Enqueue"},
920 {122, "AQ Dequeue"},
921 {123, "Object transfer"},
922 {124, "RFS Call"},
923 {125, "Kernel programmatic notification"},
924 {126, "Listen"},
925 {127, "Oracle Transaction service Commit remote sites (V >= 8.1.3)"},
926 {128, "Dir Path Prepare"},
927 {129, "Dir Path Load Stream"},
928 {130, "Dir Path Misc. Ops"},
929 {131, "Memory Stats"},
930 {132, "AQ Properties Status"},
931 {134, "Remote Fetch Archive Log FAL"},
932 {135, "Client ID propagation"},
933 {136, "DR Server CNX Process"},
934 {138, "SPFILE parameter put"},
935 {139, "KPFC exchange"},
936 {140, "Object Transfer (V8.2)"},
937 {141, "Push Transaction"},
938 {142, "Pop Transaction"},
939 {143, "KFN Operation"},
940 {144, "Dir Path Unload Stream"},
941 {145, "AQ batch enqueue dequeue"},
942 {146, "File Transfer"},
943 {147, "Ping"},
944 {148, "TSM"},
945 {150, "Begin TSM"},
946 {151, "End TSM"},
947 {152, "Set schema"},
948 {153, "Fetch from suspended result set"},
949 {154, "Key/Value pair"},
950 {155, "XS Create session Operation"},
951 {156, "XS Session Roundtrip Operation"},
952 {157, "XS Piggyback Operation"},
953 {158, "KSRPC Execution"},
954 {159, "Streams combined capture apply"},
955 {160, "AQ replay information"},
956 {161, "SSCR"},
957 {162, "Session Get"},
958 {163, "Session RLS"},
959 {165, "Workload replay data"},
960 {166, "Replay statistic data"},
961 {167, "Query Cache Stats"},
962 {168, "Query Cache IDs"},
963 {169, "RPC Test Stream"},
964 {170, "Replay PL/SQL RPC"},
965 {171, "XStream Out"},
966 {172, "Golden Gate RPC"},
967 {0, NULL((void*)0)}
968};
969static 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) }
;
970
971/* The final byte of a TNS_MARKER body selects break vs reset:
972 * 01 00 01 = break, 01 00 02 = reset. */
973static const value_string tns_marker_functions[] = {
974 {1, "Break (interrupt call)"},
975 {2, "Reset (clear line)"},
976 {0, NULL((void*)0)}
977};
978
979static const value_string tns_marker_types[] = {
980 {0, "Data Marker - 0 Data Bytes"},
981 {1, "Data Marker - 1 Data Bytes"},
982 {2, "Attention Marker"},
983 {0, NULL((void*)0)}
984};
985
986static const value_string tns_control_cmds[] = {
987 {1, "Oracle Trace Command"},
988 {0, NULL((void*)0)}
989};
990
991/* What a value decoder needs to know about one column or bind: its
992 * datatype, character set form, and the data length (buffer size) the
993 * describe gave it. */
994typedef struct _tns_column_t {
995 uint8_t type;
996 uint8_t csform; /* character set form: 2 = national */
997 uint32_t data_len;
998} tns_column_t;
999
1000/* Columns from the most recent describe (TTI_DCB), threaded to a later
1001 * TTI_RXD response so its row values can be split per column. */
1002typedef struct _tns_describe_t {
1003 uint32_t num_cols;
1004 tns_column_t *cols;
1005} tns_describe_t;
1006
1007/* The bind types of a cursor, from the execute that opened it. A later
1008 * execute of the same cursor may send its values with no descriptors. */
1009typedef struct _tns_binds_t {
1010 uint32_t count;
1011 uint32_t num_return; /* the last num_return are RETURNING ... INTO binds */
1012 tns_column_t *cols;
1013} tns_binds_t;
1014
1015/* The call a response answers: some response messages can only be read
1016 * knowing what was asked. */
1017typedef struct _tns_call_t {
1018 uint8_t func; /* OCI function id */
1019 uint32_t exec_flags; /* al8i4[9] of a TTI_ALL8 execute */
1020 uint32_t num_binds; /* bind types of an execute */
1021 uint32_t num_return; /* ... of which the last are RETURNING ... INTO binds */
1022 tns_column_t *binds;
1023 uint32_t lob_op; /* TTI_LOBOPS operation */
1024 uint32_t lob_locator_len; /* ... its source locator length */
1025 bool_Bool lob_amount; /* ... whether it sent an amount */
1026} tns_call_t;
1027
1028typedef struct _tns_conv_info_t {
1029 uint32_t pending_connect_data;
1030 /* The most recent call the client made. */
1031 tns_call_t *last_call;
1032 /* The client speaks the OCI dialect: fixed-width little-endian
1033 * integers and 8-byte pointer indicators, where a thin client uses
1034 * variable-length integers and 1-byte pointer flags. */
1035 bool_Bool oci_dialect;
1036 /* The TTC field version the client and server settled on, from the
1037 * client's TTI_DTY; 0 until seen. */
1038 uint8_t field_version;
1039 tns_describe_t *last_describe;
1040 /* Bind types of an execute that opened a new cursor, waiting for the
1041 * status that names the cursor id. */
1042 tns_binds_t *pending_binds;
1043 /* Cursor id -> tns_binds_t. */
1044 wmem_map_t *cursor_binds;
1045} tns_conv_info_t;
1046
1047/* p_add_proto_data key for the describe a TTI_RXD response packet uses. */
1048#define TNS_PROTO_DATA_DESCRIBE1 1
1049/* p_add_proto_data key for the remembered binds of a re-execute. */
1050#define TNS_PROTO_DATA_BINDS2 2
1051/* p_add_proto_data key for the call a response packet answers. */
1052#define TNS_PROTO_DATA_CALL3 3
1053/* p_add_proto_data key for whether a packet is in the OCI dialect. */
1054#define TNS_PROTO_DATA_OCI4 4
1055/* p_add_proto_data key for the field version in force for a packet. */
1056#define TNS_PROTO_DATA_FV5 5
1057
1058/* Execute flag asking for the rows each array DML iteration affected. */
1059#define TNS_EXEC_FLAGS_DML_ROWCOUNTS0x4000 0x4000
1060
1061void proto_reg_handoff_tns(void);
1062static int dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)));
1063
1064static tns_conv_info_t*
1065tns_get_conv_info(packet_info *pinfo)
1066{
1067 conversation_t *conversation = find_or_create_conversation(pinfo);
1068
1069 tns_conv_info_t *tns_info = (tns_conv_info_t *)conversation_get_proto_data(conversation, proto_tns);
1070 if (!tns_info) {
1071 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
)))
;
1072 tns_info->cursor_binds = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
1073 conversation_add_proto_data(conversation, proto_tns, tns_info);
1074 }
1075 return tns_info;
1076}
1077
1078/* The TTC field version negotiated on the packet's connection, or 0 when
1079 * the negotiation was not seen - which the decoders read as the 11g
1080 * shape. Stored per packet on the first pass. */
1081static unsigned tns_field_version(packet_info *pinfo)
1082{
1083 void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_FV5);
1084 if ( stored || PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
1085 return stored ? GPOINTER_TO_UINT(stored)((guint) (gulong) (stored)) - 1 : 0;
1086
1087 unsigned fv = tns_get_conv_info(pinfo)->field_version;
1088 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_FV5, GUINT_TO_POINTER(fv + 1)((gpointer) (gulong) (fv + 1)));
1089 return fv;
1090}
1091
1092/* Whether the connection is known to predate 11g (a 10g server): its
1093 * describe lacks the fields 11g added. */
1094static bool_Bool tns_before_11g(packet_info *pinfo)
1095{
1096 unsigned fv = tns_field_version(pinfo);
1097 return fv != 0 && fv < TNS_FV_11_26;
1098}
1099
1100static unsigned get_data_func_id(tvbuff_t *tvb, int offset)
1101{
1102 /* Determine Data Function id */
1103 uint8_t first_byte;
1104
1105 first_byte =
1106 tvb_reported_length_remaining(tvb, offset) > 0 ? tvb_get_uint8(tvb, offset) : 0;
1107
1108 if ( tvb_bytes_exist(tvb, offset, 4) && first_byte == 0xDE &&
1109 tvb_get_uint24(tvb, offset+1, ENC_BIG_ENDIAN0x00000000) == 0xADBEEF )
1110 {
1111 return SQLNET_SNS0xdeadbeef;
1112 }
1113 else
1114 {
1115 return (unsigned)first_byte;
1116 }
1117}
1118
1119static int get_strtype_custom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1120{
1121 int ret = 1; // 1st byte contains 254 or length if smaller than 64
1122 int len = 0;
1123
1124 wmem_strbuf_t *strbuf = wmem_strbuf_new(pinfo->pool, "");
1125
1126 len = tvb_get_uint8(tvb, offset);
1127 if (len == 254) {
1128 int actual_len = 0;
1129 len = 0;
Value stored to 'len' is never read
1130 do { // walk over the chunks
1131 len = tvb_get_uint8(tvb, offset + ret);
1132 ret++; // 1st byte with the chunk size
1133 wmem_strbuf_append(strbuf, (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset + ret, len, ENC_ASCII0x00000000|ENC_NA0x00000000));
1134 ret += len; // length of the string's chunk
1135 actual_len += len;
1136 } while (len == 64);
1137 ret++; // has to be null-terminated
1138 len = actual_len;
1139 }
1140 else {
1141 ret += len;
1142 wmem_strbuf_append(strbuf, (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset + 1, len, ENC_ASCII0x00000000|ENC_NA0x00000000));
1143 }
1144
1145 proto_tree_add_uint(tree, hf_tns_data_opi_param_length, tvb, offset, 1, len);
1146 proto_tree_add_string(tree, hf_tns_data_opi_param_value, tvb, offset+1, ret-1, wmem_strbuf_get_str(strbuf));
1147
1148 return ret;
1149}
1150
1151/* Decode an Oracle variable-length integer (ub4 / sb4):
1152 * a length byte, then that many big-endian magnitude bytes. The low 7 bits
1153 * of the length byte are the magnitude width (0..4); the high bit flags a
1154 * negative value in sign-magnitude form (not two's complement) — so -1 is
1155 * 0x81 0x01 and NUMBER scale -127 is 0x81 0x7f.
1156 * Returns the number of bytes consumed. */
1157static int get_sb4_custom(tvbuff_t *tvb, int offset, int *result)
1158{
1159 uint8_t first_byte = tvb_get_uint8(tvb, offset); // Contains length of a value
1160 bool_Bool negative = (first_byte & 0x80) != 0;
1161 uint8_t width = first_byte & 0x7f;
1162 int magnitude = 0;
1163
1164 switch(width)
1165 {
1166 case 0:
1167 magnitude = 0;
1168 break;
1169 case 1:
1170 magnitude = tvb_get_uint8(tvb, offset+1);
1171 break;
1172 case 2:
1173 magnitude = tvb_get_ntohs(tvb, offset+1);
1174 break;
1175 case 3:
1176 magnitude = tvb_get_ntoh24(tvb, offset+1);
1177 break;
1178 case 4:
1179 magnitude = tvb_get_ntohl(tvb, offset+1);
1180 break;
1181 default:
1182 /* Width 5..0x7f is not a valid 1..4-byte integer. In practice
1183 * only a raw ub2 counter read through this helper reaches here;
1184 * the historic client behaviour is to consume two bytes and
1185 * return the negated second byte, which keeps the stream
1186 * aligned. The value is discarded by such callers. */
1187 if ( tvb_reported_length_remaining(tvb, offset) < 2 )
1188 {
1189 /* Not even that second byte is present. The width came
1190 * off the wire, so this is malformed input rather than
1191 * a bug in the dissector - step over the width alone. */
1192 *result = 0;
1193 return 1;
1194 }
1195 *result = -(int)tvb_get_uint8(tvb, offset+1);
1196 return 2;
1197 }
1198 *result = negative ? -magnitude : magnitude;
1199 return width + 1;
1200}
1201
1202/* Decode an Oracle variable-length ub8: a width byte (0..8), then that
1203 * many big-endian bytes. Returns the number of bytes consumed. */
1204static int get_ub8_custom(tvbuff_t *tvb, int offset, uint64_t *result)
1205{
1206 uint8_t width = tvb_get_uint8(tvb, offset);
1207 uint64_t value = 0;
1208
1209 if ( width > 8 )
1210 {
1211 /* Not a valid width; the value came off the wire, so step over
1212 * the width byte alone rather than claim bytes. */
1213 *result = 0;
1214 return 1;
1215 }
1216 for ( int i = 0; i < width; i++ )
1217 value = (value << 8) | tvb_get_uint8(tvb, offset + 1 + i);
1218 *result = value;
1219 return 1 + width;
1220}
1221
1222/* Walk the chunks of a chunked (0xFE) value, starting after the 0xFE:
1223 * (length, bytes) pairs until a zero length. A length is one byte up to
1224 * field version 12.1 and a variable-length ub4 from 12.2 on. The data is
1225 * appended to strbuf as UTF-8 when strbuf is not NULL. Returns the bytes
1226 * consumed, the terminating zero included. */
1227static int tns_chunks_len(tvbuff_t *tvb, packet_info *pinfo, int offset, wmem_strbuf_t *strbuf)
1228{
1229 bool_Bool ub4_lengths = tns_field_version(pinfo) >= TNS_FV_12_28;
1230 int o = offset;
1231
1232 while ( tvb_reported_length_remaining(tvb, o) > 0 )
1233 {
1234 int chunk_len;
1235 if ( ub4_lengths )
1236 o += get_sb4_custom(tvb, o, &chunk_len);
1237 else
1238 {
1239 chunk_len = tvb_get_uint8(tvb, o);
1240 o += 1;
1241 }
1242 if ( chunk_len <= 0 )
1243 break;
1244 if ( strbuf )
1245 wmem_strbuf_append(strbuf, (const char *)tvb_get_string_enc(pinfo->pool, tvb, o, chunk_len, ENC_UTF_80x00000002|ENC_NA0x00000000));
1246 o += chunk_len;
1247 }
1248 return o - offset;
1249}
1250
1251/* Decode a DALC (Data-Length-And-Content) blob. The leading byte is a
1252 * length only in the middle of its range:
1253 *
1254 * 0x00 empty
1255 * 0x01..0xFC that many data bytes follow (252 is the longest)
1256 * 0xFD absent value: the two-byte placeholder FD 01, no data
1257 * 0xFE chunked: (len, bytes) pairs until a 0-length chunk
1258 * 0xFF null - a marker only, no data follows
1259 *
1260 * The top three bytes are markers, not lengths. The null marker consumes
1261 * just itself. The absent-value placeholder fills a bind slot that has no
1262 * inline value - a pure OUT bind, or a NULL of a type with no inline form
1263 * such as BOOLEAN - and consumes itself plus the 0x01 after it. Reading
1264 * either as a length would claim bytes that are not there and misalign
1265 * every field after it, so they have to be spelled out rather than left
1266 * to the default.
1267 *
1268 * The chunk lengths in the 0xFE form are single bytes up to field version
1269 * 12.1, and variable-length ub4s from 12.2 on.
1270 *
1271 * Returns the number of bytes consumed from the tvb and, when content
1272 * is non-empty, a UTF-8 string allocated from pinfo->pool. */
1273static int get_dalc_custom(tvbuff_t *tvb, packet_info *pinfo, int offset, const char **out_str)
1274{
1275 uint8_t first = tvb_get_uint8(tvb, offset);
1276 if ( first == 0 || first == 255 )
1277 {
1278 if ( out_str )
1279 *out_str = NULL((void*)0);
1280 return 1;
1281 }
1282 if ( first == TNS_DALC_ABSENT0xFD )
1283 {
1284 if ( out_str )
1285 *out_str = NULL((void*)0);
1286 return 2;
1287 }
1288 if ( first != 254 )
1289 {
1290 if ( out_str )
1291 *out_str = (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset + 1, first, ENC_UTF_80x00000002|ENC_NA0x00000000);
1292 return 1 + first;
1293 }
1294
1295 /* Chunked form: (len, bytes)+ until a zero-length chunk. */
1296 wmem_strbuf_t *strbuf = wmem_strbuf_new(pinfo->pool, "");
1297 int used = 1 + tns_chunks_len(tvb, pinfo, offset + 1, strbuf);
1298 if ( out_str )
1299 *out_str = wmem_strbuf_get_str(strbuf);
1300 return used;
1301}
1302
1303/* Decode a bytes_with_length / str_with_length field: a ub4 count, and
1304 * a DALC carrying the value only when that count is non-zero. The count
1305 * is not simply a byte to step over - an empty field is the count
1306 * alone, so reading a DALC anyway consumes whatever follows it.
1307 * Returns bytes consumed; *out_str (when non-NULL) gets the string, or
1308 * NULL when the field is empty. */
1309static int get_field_with_length(tvbuff_t *tvb, packet_info *pinfo, int offset, const char **out_str)
1310{
1311 int count = 0;
1312 int used = get_sb4_custom(tvb, offset, &count);
1313 if ( out_str )
1314 *out_str = NULL((void*)0);
1315 if ( count > 0 )
1316 used += get_dalc_custom(tvb, pinfo, offset + used, out_str);
1317 return used;
1318}
1319
1320/* Render an Oracle NUMBER value as a decimal string.
1321 * Base-100 float: byte 0 is the biased exponent (top bit = sign, inverted
1322 * for negatives); the rest are base-100 mantissa groups, with a trailing
1323 * 0x66 terminator on negatives.
1324 * Returns a pinfo->pool string, or NULL if the value is not renderable. */
1325static const char *tns_format_number(packet_info *pinfo, const uint8_t *data, int len)
1326{
1327 if ( len <= 0 )
1328 return NULL((void*)0);
1329 if ( len == 1 )
1330 return (data[0] == 0x80) ? "0" : NULL((void*)0); /* 0x80 = zero; sentinels skipped */
1331
1332 uint8_t exp_byte = data[0];
1333 bool_Bool is_pos = (exp_byte & 0x80) != 0;
1334 int exponent = is_pos ? (exp_byte & 0x7f) - 65 : ((~exp_byte) & 0x7f) - 65;
1335
1336 int mant_len = len - 1;
1337 if ( !is_pos && mant_len > 0 && data[len - 1] == 0x66 )
1338 mant_len--; /* drop the negative terminator */
1339
1340 /* Build the base-100 digit string (two decimal digits per group). */
1341 wmem_strbuf_t *digits = wmem_strbuf_new(pinfo->pool, "");
1342 for ( int i = 0; i < mant_len; i++ )
1343 {
1344 int pair = is_pos ? (data[1 + i] - 1) : (101 - data[1 + i]);
1345 if ( pair < 0 || pair > 99 )
1346 return NULL((void*)0); /* malformed */
1347 wmem_strbuf_append_printf(digits, "%02d", pair);
1348 }
1349 const char *ds = wmem_strbuf_get_str(digits);
1350 int dlen = (int)wmem_strbuf_get_len(digits);
1351 int int_digits = (exponent + 1) * 2;
1352
1353 wmem_strbuf_t *ip = wmem_strbuf_new(pinfo->pool, "");
1354 wmem_strbuf_t *fp = wmem_strbuf_new(pinfo->pool, "");
1355 if ( int_digits >= dlen )
1356 {
1357 wmem_strbuf_append(ip, ds);
1358 for ( int i = 0; i < int_digits - dlen; i++ )
1359 wmem_strbuf_append_c(ip, '0');
1360 }
1361 else if ( int_digits <= 0 )
1362 {
1363 wmem_strbuf_append_c(ip, '0');
1364 for ( int i = 0; i < -int_digits; i++ )
1365 wmem_strbuf_append_c(fp, '0');
1366 wmem_strbuf_append(fp, ds);
1367 }
1368 else
1369 {
1370 wmem_strbuf_append(ip, wmem_strndup(pinfo->pool, ds, int_digits));
1371 wmem_strbuf_append(fp, ds + int_digits);
1372 }
1373
1374 /* Trim leading zeros on the integer part, trailing zeros on the fraction. */
1375 const char *ips = wmem_strbuf_get_str(ip);
1376 while ( ips[0] == '0' && ips[1] != '\0' )
1377 ips++;
1378 char *fps = wmem_strdup(pinfo->pool, wmem_strbuf_get_str(fp));
1379 int flen = (int)strlen(fps);
1380 while ( flen > 0 && fps[flen - 1] == '0' )
1381 fps[--flen] = '\0';
1382
1383 const char *sign = is_pos ? "" : "-";
1384 if ( flen > 0 )
1385 return wmem_strdup_printf(pinfo->pool, "%s%s.%s", sign, ips, fps);
1386 return wmem_strdup_printf(pinfo->pool, "%s%s", sign, ips);
1387}
1388
1389/* Render an Oracle DATE / TIMESTAMP value as an
1390 * ISO-ish string. 7 bytes: century+100, year+100, month, day, hour+1,
1391 * minute+1, second+1; 11 bytes add 4-byte big-endian nanoseconds.
1392 * Returns a pinfo->pool string, or NULL. */
1393static const char *tns_format_date(packet_info *pinfo, const uint8_t *data, int len)
1394{
1395 if ( len < 7 )
1396 return NULL((void*)0);
1397 int year = (data[0] - 100) * 100 + (data[1] - 100);
1398 int month = data[2], day = data[3];
1399 int hour = data[4] - 1, minute = data[5] - 1, second = data[6] - 1;
1400 if ( month < 1 || month > 12 || day < 1 || day > 31 ||
1401 hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59 )
1402 return NULL((void*)0);
1403 if ( len >= 11 )
1404 {
1405 uint32_t nsec = ((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) |
1406 ((uint32_t)data[9] << 8) | data[10];
1407 if ( nsec > 0 )
1408 return wmem_strdup_printf(pinfo->pool, "%04d-%02d-%02d %02d:%02d:%02d.%09u",
1409 year, month, day, hour, minute, second, nsec);
1410 }
1411 return wmem_strdup_printf(pinfo->pool, "%04d-%02d-%02d %02d:%02d:%02d",
1412 year, month, day, hour, minute, second);
1413}
1414
1415/* Days since 1970-01-01 of a proleptic Gregorian date, and back. */
1416static int64_t tns_days_from_civil(int64_t y, unsigned m, unsigned d)
1417{
1418 y -= m <= 2;
1419 int64_t era = (y >= 0 ? y : y - 399) / 400;
1420 unsigned yoe = (unsigned)(y - era * 400);
1421 unsigned doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
1422 unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
1423 return era * 146097 + (int64_t)doe - 719468;
1424}
1425
1426static void tns_civil_from_days(int64_t z, int64_t *y, unsigned *m, unsigned *d)
1427{
1428 z += 719468;
1429 int64_t era = (z >= 0 ? z : z - 146096) / 146097;
1430 unsigned doe = (unsigned)(z - era * 146097);
1431 unsigned yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
1432 unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
1433 unsigned mp = (5 * doy + 2) / 153;
1434 *d = doy - (153 * mp + 2) / 5 + 1;
1435 *m = mp < 10 ? mp + 3 : mp - 9;
1436 *y = (int64_t)yoe + era * 400 + (*m <= 2);
1437}
1438
1439/* Render an Oracle TIMESTAMP WITH TIME ZONE value: 13 bytes, the
1440 * 11-byte TIMESTAMP form holding the instant in UTC, then two zone
1441 * bytes. With the top bit of the first clear they are an offset, hour
1442 * + 20 and minute + 60, and the value is shown in local time with that
1443 * offset; with it set they hold a named zone's region id,
1444 * ((b0 & 0x7f) << 6) + (b1 >> 2), and the value is shown in UTC.
1445 * Returns a pinfo->pool string, or NULL. */
1446static const char *tns_format_timestamp_tz(packet_info *pinfo, const uint8_t *data, int len)
1447{
1448 const char *utc;
1449 uint32_t nsec;
1450 int64_t minutes, days, year;
1451 unsigned month, day;
1452 int tz_hour, tz_min, minute_of_day;
1453 char sign;
1454
1455 if ( len != 13 )
1456 return tns_format_date(pinfo, data, len);
1457 utc = tns_format_date(pinfo, data, 11);
1458 if ( !utc )
1459 return NULL((void*)0);
1460 if ( data[11] & 0x80 )
1461 return wmem_strdup_printf(pinfo->pool, "%s UTC (time zone region %u)", utc,
1462 ((unsigned)(data[11] & 0x7f) << 6) + (data[12] >> 2));
1463
1464 /* Shift the UTC wall clock by the offset, in whole minutes. */
1465 tz_hour = data[11] - 20;
1466 tz_min = data[12] - 60;
1467 days = tns_days_from_civil((data[0] - 100) * 100 + (data[1] - 100), data[2], data[3]);
1468 minutes = days * 1440 + (data[4] - 1) * 60 + (data[5] - 1) + tz_hour * 60 + tz_min;
1469 days = minutes >= 0 ? minutes / 1440 : -((-minutes + 1439) / 1440);
1470 minute_of_day = (int)(minutes - days * 1440);
1471 tns_civil_from_days(days, &year, &month, &day);
1472
1473 nsec = ((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) | ((uint32_t)data[9] << 8) | data[10];
1474 /* The sign goes on the whole offset: -03:30 is hour -3, minute -30. */
1475 sign = (tz_hour < 0 || tz_min < 0) ? '-' : '+';
1476 if ( nsec )
1477 return wmem_strdup_printf(pinfo->pool, "%04" PRId64"l" "d" "-%02u-%02u %02d:%02d:%02d.%09u %c%02d:%02d",
1478 year, month, day, minute_of_day / 60, minute_of_day % 60, data[6] - 1, nsec,
1479 sign, abs(tz_hour), abs(tz_min));
1480 return wmem_strdup_printf(pinfo->pool, "%04" PRId64"l" "d" "-%02u-%02u %02d:%02d:%02d %c%02d:%02d",
1481 year, month, day, minute_of_day / 60, minute_of_day % 60, data[6] - 1,
1482 sign, abs(tz_hour), abs(tz_min));
1483}
1484
1485/* Render an Oracle INTERVAL YEAR TO MONTH (5 bytes: years as a
1486 * big-endian ub4 biased by 2^31, months biased by 60) or INTERVAL DAY TO
1487 * SECOND (11 bytes: days as a ub4 biased by 2^31, hours, minutes and
1488 * seconds each biased by 60, nanoseconds as a ub4 biased by 2^31). All
1489 * fields carry the interval's sign. Rendered as Oracle writes an
1490 * interval literal: [-]Y-MM, or [-]D HH:MM:SS[.fffffffff].
1491 * Returns a pinfo->pool string, or NULL. */
1492static const char *tns_format_interval(packet_info *pinfo, uint8_t dtype, const uint8_t *data, int len)
1493{
1494 int32_t lead = (int32_t)((((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) |
1495 ((uint32_t)data[2] << 8) | data[3]) - 0x80000000u);
1496
1497 if ( dtype == TNS_DATATYPE_INTERVAL_YM182 && len == 5 )
1498 {
1499 int months = data[4] - 60;
1500 bool_Bool neg = lead < 0 || months < 0;
1501 return wmem_strdup_printf(pinfo->pool, "%s%d-%02d", neg ? "-" : "",
1502 abs(lead), abs(months));
1503 }
1504 if ( dtype == TNS_DATATYPE_INTERVAL_DS183 && len == 11 )
1505 {
1506 int hours = data[4] - 60, minutes = data[5] - 60, seconds = data[6] - 60;
1507 int32_t nsec = (int32_t)((((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) |
1508 ((uint32_t)data[9] << 8) | data[10]) - 0x80000000u);
1509 bool_Bool neg = lead < 0 || hours < 0 || minutes < 0 || seconds < 0 || nsec < 0;
1510 if ( nsec )
1511 return wmem_strdup_printf(pinfo->pool, "%s%d %02d:%02d:%02d.%09d", neg ? "-" : "",
1512 abs(lead), abs(hours), abs(minutes), abs(seconds), abs(nsec));
1513 return wmem_strdup_printf(pinfo->pool, "%s%d %02d:%02d:%02d", neg ? "-" : "",
1514 abs(lead), abs(hours), abs(minutes), abs(seconds));
1515 }
1516 return NULL((void*)0);
1517}
1518
1519/* Render an Oracle BINARY_FLOAT (4 bytes) / BINARY_DOUBLE (8 bytes) value
1520 * Stored in an order-preserving IEEE-754 form: if the
1521 * high bit is set the value was positive (clear it), else it was negative
1522 * (invert all bits); then read as big-endian IEEE-754. Returns a
1523 * pinfo->pool string, or NULL. */
1524static const char *tns_format_binary_float(packet_info *pinfo, const uint8_t *data, int len)
1525{
1526 char buf[G_ASCII_DTOSTR_BUF_SIZE(29 + 10)];
1527
1528 if ( len == 4 )
1529 {
1530 uint32_t u = ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) |
1531 ((uint32_t)data[2] << 8) | data[3];
1532 u = (u & 0x80000000u) ? (u & 0x7fffffffu) : ~u;
1533 float f;
1534 memcpy(&f, &u, 4);
1535 /* Locale-independent '.' decimal separator. */
1536 g_ascii_formatd(buf, sizeof(buf), "%g", (double)f);
1537 return wmem_strdup(pinfo->pool, buf);
1538 }
1539 if ( len == 8 )
1540 {
1541 uint64_t u = 0;
1542 for ( int i = 0; i < 8; i++ )
1543 u = (u << 8) | data[i];
1544 u = (u & UINT64_C(0x8000000000000000)0x8000000000000000UL) ? (u & UINT64_C(0x7fffffffffffffff)0x7fffffffffffffffUL) : ~u;
1545 double d;
1546 memcpy(&d, &u, 8);
1547 g_ascii_formatd(buf, sizeof(buf), "%g", d);
1548 return wmem_strdup(pinfo->pool, buf);
1549 }
1550 return NULL((void*)0);
1551}
1552
1553/* The base-64 alphabet of Oracle's printable rowids. */
1554static const char tns_rowid_alphabet[] =
1555 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1556
1557/* Append value to buf as `digits` base-64 characters, most significant
1558 * first. */
1559static void tns_rowid_append(wmem_strbuf_t *buf, uint32_t value, int digits)
1560{
1561 char chars[6];
1562
1563 for ( int i = digits - 1; i >= 0; i-- )
1564 {
1565 chars[i] = tns_rowid_alphabet[value & 0x3f];
1566 value >>= 6;
1567 }
1568 wmem_strbuf_append_len(buf, chars, digits);
1569}
1570
1571/* Render a physical rowid as the 18-character extended rowid ROWIDTOCHAR
1572 * prints: object, file, block and slot in 6, 3, 6 and 3 base-64 digits.
1573 * Returns a pinfo->pool string. */
1574static const char *tns_format_rowid(packet_info *pinfo, uint32_t rba, uint32_t part, uint32_t block, uint32_t slot)
1575{
1576 wmem_strbuf_t *buf = wmem_strbuf_new(pinfo->pool, "");
1577
1578 tns_rowid_append(buf, rba, 6);
1579 tns_rowid_append(buf, part, 3);
1580 tns_rowid_append(buf, block, 6);
1581 tns_rowid_append(buf, slot, 3);
1582 return wmem_strbuf_get_str(buf);
1583}
1584
1585/* Render a universal rowid. A leading type byte of 1 marks a physical
1586 * rowid, printed as above; anything else is a logical one - an
1587 * index-organized table's, carrying its primary key - printed as "*" and
1588 * the base-64 of the bytes after the type byte, unpadded. Returns a
1589 * pinfo->pool string, or NULL. */
1590static const char *tns_format_urowid(packet_info *pinfo, const uint8_t *data, int len)
1591{
1592 if ( len >= 13 && data[0] == 1 )
1593 return tns_format_rowid(pinfo,
1594 ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 8) | data[4],
1595 ((uint32_t)data[5] << 8) | data[6],
1596 ((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) | ((uint32_t)data[9] << 8) | data[10],
1597 ((uint32_t)data[11] << 8) | data[12]);
1598 if ( len < 2 )
1599 return NULL((void*)0);
1600
1601 wmem_strbuf_t *buf = wmem_strbuf_new(pinfo->pool, "*");
1602 for ( int i = 1; i < len; i += 3 )
1603 {
1604 int n = MIN(3, len - i)(((3) < (len - i)) ? (3) : (len - i));
1605 uint32_t group = (uint32_t)data[i] << 16;
1606 if ( n > 1 )
1607 group |= (uint32_t)data[i + 1] << 8;
1608 if ( n > 2 )
1609 group |= data[i + 2];
1610 /* n bytes give n + 1 characters */
1611 for ( int k = 0; k <= n; k++ )
1612 wmem_strbuf_append_c(buf, tns_rowid_alphabet[(group >> (18 - 6 * k)) & 0x3f]);
1613 }
1614 return wmem_strbuf_get_str(buf);
1615}
1616
1617static void vsnum_to_vstext_basecustom(char *result, uint32_t vsnum)
1618{
1619 /*
1620 * Translate hex value to human readable version value, described at
1621 * http://docs.oracle.com/cd/B28359_01/server.111/b28310/dba004.htm
1622 */
1623 snprintf(result, ITEM_LABEL_LENGTH240, "%d.%d.%d.%d.%d",
1624 vsnum >> 24,
1625 (vsnum >> 20) & 0xf,
1626 (vsnum >> 12) & 0xf,
1627 (vsnum >> 8) & 0xf,
1628 vsnum & 0xff);
1629}
1630
1631/* End-of-call status flags, carried by both TTI_OER and TTI_STA. */
1632#define TNS_CALL_STATUS_TXN_IN_PROGRESS0x00000002 0x00000002
1633#define TNS_CALL_STATUS_SESS_RELEASE0x00008000 0x00008000
1634
1635/* Break out the flag bits of a call status item. A client reads the
1636 * transaction bit to decide whether closing or releasing the connection
1637 * owes a rollback. */
1638static void tns_add_call_status_flags(proto_item *ti, tvbuff_t *tvb, int start, int len, uint32_t status)
1639{
1640 proto_tree *st = proto_item_add_subtree(ti, ett_tns_call_status);
1641 proto_tree_add_boolean(st, hf_tns_data_call_status_txn, tvb, start, len, status);
1642 proto_tree_add_boolean(st, hf_tns_data_call_status_sess_release, tvb, start, len, status);
1643}
1644
1645/* Decode an OAC (Oracle Access Column) descriptor — the type/format core
1646 * shared by describe columns and bind descriptors. Fields
1647 * use the Oracle variable-length form (get_sb4_custom). From field version
1648 * 12.2 the scale is a single signed byte, where 11g sends a variable-length
1649 * sb4 (NUMBER's default -127 as 0x81 0x7f), and a ub4 oaccolid follows the
1650 * max size.
1651 * When col is not NULL it receives the type and data length.
1652 * Returns the new offset. */
1653static int dissect_tns_oac(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, tns_column_t *col)
1654{
1655 int v = 0, start;
1656 uint64_t u = 0;
1657 bool_Bool fv_12_2 = tns_field_version(pinfo) >= TNS_FV_12_28;
1658
1659 if ( col )
1660 col->type = tvb_get_uint8(tvb, offset);
1661 /* type (ub1) */
1662 proto_tree_add_item(tree, hf_tns_data_col_type, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1663 offset += 1;
1664 /* flag (ub1, skip) */
1665 offset += 1;
1666 /* precision (sb1) */
1667 proto_tree_add_item(tree, hf_tns_data_col_precision, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1668 offset += 1;
1669 /* scale (may be negative — NUMBER default is -127) */
1670 start = offset;
1671 if ( fv_12_2 )
1672 {
1673 v = (int8_t)tvb_get_uint8(tvb, offset);
1674 offset += 1;
1675 }
1676 else
1677 offset += get_sb4_custom(tvb, offset, &v);
1678 proto_tree_add_int(tree, hf_tns_data_col_scale, tvb, start, offset - start, v);
1679 /* max data length / buffer size (ub4) */
1680 start = offset;
1681 offset += get_sb4_custom(tvb, offset, &v);
1682 proto_tree_add_uint(tree, hf_tns_data_col_max_length, tvb, start, offset - start, v);
1683 if ( col )
1684 col->data_len = (uint32_t)v;
1685 /* max array elements (ub4, skip) */
1686 offset += get_sb4_custom(tvb, offset, &v);
1687 /* cont flags (ub8, skip) */
1688 offset += get_ub8_custom(tvb, offset, &u);
1689 /* type OID (bytes_with_length, skip) */
1690 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
1691 /* version (ub4, skip) */
1692 offset += get_sb4_custom(tvb, offset, &v);
1693 /* charset id (ub4) */
1694 start = offset;
1695 offset += get_sb4_custom(tvb, offset, &v);
1696 proto_tree_add_uint(tree, hf_tns_data_col_charset, tvb, start, offset - start, v);
1697 /* charset form (ub1) */
1698 proto_tree_add_item(tree, hf_tns_data_col_csform, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1699 if ( col )
1700 col->csform = tvb_get_uint8(tvb, offset);
1701 offset += 1;
1702 /* max size (ub4) */
1703 start = offset;
1704 offset += get_sb4_custom(tvb, offset, &v);
1705 proto_tree_add_uint(tree, hf_tns_data_col_max_size, tvb, start, offset - start, v);
1706 /* oaccolid (ub4, skip) */
1707 if ( fv_12_2 )
1708 offset += get_sb4_custom(tvb, offset, &v);
1709
1710 return offset;
1711}
1712
1713/* Decode one per-column metadata block of a TTI_DCB describe (11g
1714 * shape): an OAC descriptor plus the nullability and naming fields.
1715 * When col is not NULL it receives what a row decoder needs.
1716 * Returns the new offset. */
1717static int dissect_tns_dcb_column(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int idx, tns_column_t *col)
1718{
1719 unsigned fv = tns_field_version(pinfo);
1720 int start;
1721 proto_tree *col_tree;
1722 proto_item *col_item;
1723 int col_start = offset, v = 0;
1724 uint8_t col_type = tvb_get_uint8(tvb, offset);
1725 const char *name = NULL((void*)0);
1726
1727 col_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
1728 ett_tns_dcb_col, &col_item, "Column %d", idx);
1729
1730 offset = dissect_tns_oac(tvb, pinfo, col_tree, offset, col);
1731
1732 /* nulls allowed (ub1) */
1733 proto_tree_add_item(col_tree, hf_tns_data_col_nulls_ok, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
1734 offset += 1;
1735 /* v7 name length (ub1, skip) */
1736 offset += 1;
1737 /* column name (str_with_length) */
1738 int name_start = offset;
1739 offset += get_field_with_length(tvb, pinfo, offset, &name);
1740 if ( name )
1741 proto_tree_add_string(col_tree, hf_tns_data_col_name, tvb, name_start, offset - name_start, name);
1742 /* schema name, type name (str_with_length, skip) */
1743 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
1744 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
1745 /* column position (ub4, skip) */
1746 offset += get_sb4_custom(tvb, offset, &v);
1747 /* uds flags (ub4) — an 11g addition; it marks a JSON column */
1748 if ( !tns_before_11g(pinfo) )
1749 {
1750 start = offset;
1751 offset += get_sb4_custom(tvb, offset, &v);
1752 proto_tree_add_uint(col_tree, hf_tns_data_col_uds_flags, tvb, start, offset - start, v);
1753 }
1754 /* 23ai: the column's SQL domain, its annotations, and a vector
1755 * column's dimensions and format */
1756 if ( fv >= TNS_FV_23_117 )
1757 {
1758 const char *str = NULL((void*)0);
1759 start = offset;
1760 offset += get_field_with_length(tvb, pinfo, offset, &str);
1761 if ( str )
1762 proto_tree_add_string(col_tree, hf_tns_data_col_domain_schema, tvb, start, offset - start, str);
1763 start = offset;
1764 offset += get_field_with_length(tvb, pinfo, offset, &str);
1765 if ( str )
1766 proto_tree_add_string(col_tree, hf_tns_data_col_domain_name, tvb, start, offset - start, str);
1767 }
1768 if ( fv >= TNS_FV_23_1_EXT_320 )
1769 {
1770 int num = 0;
1771 offset += get_sb4_custom(tvb, offset, &num);
1772 if ( num > 0 )
1773 {
1774 offset += 1;
1775 offset += get_sb4_custom(tvb, offset, &num);
1776 offset += 1;
1777 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
1778 {
1779 const char *key = NULL((void*)0), *value = NULL((void*)0);
1780 start = offset;
1781 offset += get_field_with_length(tvb, pinfo, offset, &key);
1782 offset += get_field_with_length(tvb, pinfo, offset, &value);
1783 proto_tree_add_string_format_value(col_tree, hf_tns_data_col_annotation, tvb,
1784 start, offset - start, key ? key : "", "%s = %s",
1785 key ? key : "", value ? value : "");
1786 offset += get_sb4_custom(tvb, offset, &v); /* flags */
1787 }
1788 offset += get_sb4_custom(tvb, offset, &v); /* flags */
1789 }
1790 }
1791 if ( fv >= TNS_FV_23_424 )
1792 {
1793 start = offset;
1794 offset += get_sb4_custom(tvb, offset, &v);
1795 proto_tree_add_uint(col_tree, hf_tns_data_col_vector_dims, tvb, start, offset - start, v);
1796 proto_tree_add_item(col_tree, hf_tns_data_col_vector_format, tvb, offset, 1, ENC_NA0x00000000);
1797 offset += 1;
1798 offset += 1; /* vector flags */
1799 }
1800
1801 if ( name )
1802 proto_item_append_text(col_item, ": %s (%s)", name,
1803 val_to_str_const(col_type, tns_data_types, "unknown"));
1804 proto_item_set_len(col_item, offset - col_start);
1805 return offset;
1806}
1807
1808/* Decode a describe body - the column metadata of a result set - as a
1809 * TTI_DCB carries it after its preamble: a ub4 max row size, a ub4 column
1810 * count, a reserved byte when there are columns, the columns, and a
1811 * trailer. When out is not NULL it receives the columns, allocated in
1812 * file scope. Returns the new offset. */
1813static int dissect_tns_describe_body(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, tns_describe_t **out)
1814{
1815 int v = 0, num_cols = 0, nc_start;
1816 tns_column_t *cols = NULL((void*)0);
1817
1818 /* max row size (ub4, skip) */
1819 offset += get_sb4_custom(tvb, offset, &v);
1820 /* number of columns */
1821 nc_start = offset;
1822 offset += get_sb4_custom(tvb, offset, &num_cols);
1823 proto_tree_add_uint(tree, hf_tns_data_dcb_num_columns, tvb, nc_start, offset - nc_start, num_cols);
1824 /* The count comes off the wire and sizes the allocation below, so a
1825 * count larger than the data left cannot be real - report it and
1826 * decode no columns. */
1827 if ( num_cols < 0 ||
1828 (unsigned)num_cols > tvb_reported_length_remaining(tvb, offset) )
1829 {
1830 proto_tree_add_expert(tree, pinfo, &ei_tns_data_count_too_large,
1831 tvb, nc_start, offset - nc_start);
1832 num_cols = 0;
1833 }
1834 if ( num_cols > 0 )
1835 offset += 1; /* reserved byte */
1836
1837 if ( out && num_cols > 0 )
1838 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
))))))
;
1839 for ( int i = 0; i < num_cols && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
1840 offset = dissect_tns_dcb_column(tvb, pinfo, tree, offset, i + 1,
1841 cols ? &cols[i] : NULL((void*)0));
1842 if ( cols )
1843 {
1844 tns_describe_t *desc = wmem_new0(wmem_file_scope(), tns_describe_t)((tns_describe_t*)wmem_alloc0((wmem_file_scope()), sizeof(tns_describe_t
)))
;
1845 desc->num_cols = num_cols;
1846 desc->cols = cols;
1847 *out = desc;
1848 }
1849
1850 /* Trailer: current date (bytes_with_length), four ub4 flags,
1851 * and the query-cache key (bytes_with_length) — all skipped. The key
1852 * came with the 11g result cache: a 10g describe ends after the
1853 * flags. */
1854 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
1855 for ( int i = 0; i < 4; i++ )
1856 offset += get_sb4_custom(tvb, offset, &v);
1857 if ( !tns_before_11g(pinfo) )
1858 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
1859 return offset;
1860}
1861
1862/* Decode one row/bind value by its data type, and add it as a
1863 * "<prefix> N (TYPE)" item under `hf`. Ordinary values are a
1864 * DALC blob; ROWID / UROWID / LONG / LOB / JSON / VECTOR / object carry
1865 * their own framings. Returns the new offset. */
1866static int dissect_tns_value(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint8_t dtype, uint8_t csform, int idx, int hf, const char *prefix)
1867{
1868 int v_start = offset, disp_start = offset, v = 0;
1869 int is_null = 0, is_absent = 0;
1870 uint8_t first;
1871 const char *rendered = NULL((void*)0);
1872 /* LOB metadata: size and chunk size, with where they sit */
1873 bool_Bool lob_meta = false0;
1874 uint64_t lob_size = 0;
1875 int lob_chunk = 0, size_start = 0, size_len = 0, lchunk_start = 0, lchunk_len = 0;
1876 int image_start = 0, image_len = 0, obj_toid_start = 0, obj_toid_len = 0;
1877 proto_item *ti;
1878
1879 switch ( dtype )
1880 {
1881 case TNS_DATATYPE_REFCURSOR102:
1882 {
1883 /* A cursor - a CURSOR(...) column, or a REF CURSOR OUT
1884 * bind: a ub1 length (a fixed value, ignored), the describe
1885 * of the cursor's result set inline, and the ub2 id the
1886 * client drains it with. The value's length is known only
1887 * once the describe is read, so read it once to size the
1888 * item and again to show it. */
1889 proto_item *ci;
1890 proto_tree *ct;
1891 int end, cursor = 0, start;
1892
1893 end = dissect_tns_describe_body(tvb, pinfo, NULL((void*)0), offset + 1, NULL((void*)0));
1894 end += get_sb4_custom(tvb, end, &cursor);
1895 ci = proto_tree_add_bytes_format(tree, hf, tvb, offset, end - offset, NULL((void*)0),
1896 "%s %d (%s): cursor %d", prefix, idx,
1897 val_to_str_const(dtype, tns_data_types, "unknown"), cursor);
1898 ct = proto_item_add_subtree(ci, ett_tns_value);
1899 offset = dissect_tns_describe_body(tvb, pinfo, ct, offset + 1, NULL((void*)0));
1900 start = offset;
1901 offset += get_sb4_custom(tvb, offset, &cursor);
1902 proto_tree_add_uint(ct, hf_tns_cursor, tvb, start, offset - start, cursor);
1903 return offset;
1904 }
1905
1906 case TNS_DATATYPE_ADT109:
1907 {
1908 /* An object - or an XMLType, which is an ADT by describe - is
1909 * framed the same way whether it is NULL or not:
1910 * bytes_with_length type OID | bytes_with_length OID |
1911 * bytes_with_length snapshot | ub2 version |
1912 * ub4 image length | ub2 flags | [DALC image]
1913 * A NULL object has an image length of 0 and no image. */
1914 int toid_start = offset, img_len = 0;
1915 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
1916 obj_toid_start = toid_start;
1917 obj_toid_len = offset - toid_start;
1918 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0)); /* OID */
1919 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0)); /* snapshot */
1920 offset += get_sb4_custom(tvb, offset, &v); /* version */
1921 offset += get_sb4_custom(tvb, offset, &img_len);
1922 offset += get_sb4_custom(tvb, offset, &v); /* flags */
1923 if ( img_len > 0 )
1924 {
1925 image_start = offset;
1926 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
1927 image_len = offset - image_start;
1928 rendered = wmem_strdup_printf(pinfo->pool, "object, %d-byte image", img_len);
1929 }
1930 else
1931 rendered = "NULL object";
1932 break;
1933 }
1934
1935 case TNS_DATATYPE_JSON119: /* OSON */
1936 case TNS_DATATYPE_VECTOR127:
1937 /* LOB-class, but the value itself rides in the row: the LOB
1938 * metadata framing with the image spliced in ahead of the
1939 * locator,
1940 * ub4 locator length | ub8 image size | ub4 chunk size |
1941 * DALC image | DALC locator
1942 * The locator is a placeholder. A 0x00 is NULL. A server may
1943 * instead send a bare locator, as for a CLOB, and leave the
1944 * image to a LOB read; that is told apart as for a CLOB. */
1945 first = tvb_get_uint8(tvb, offset);
1946 if ( first == 0 )
1947 {
1948 offset += 1;
1949 is_null = 1;
1950 break;
1951 }
1952 offset += get_sb4_custom(tvb, offset, &v);
1953 if ( v > 8 && tvb_get_uint8(tvb, offset) == v )
1954 {
1955 /* bare locator */
1956 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
1957 rendered = "locator only";
1958 break;
1959 }
1960 lob_meta = true1;
1961 size_start = offset;
1962 offset += get_ub8_custom(tvb, offset, &lob_size);
1963 size_len = offset - size_start;
1964 lchunk_start = offset;
1965 offset += get_sb4_custom(tvb, offset, &lob_chunk);
1966 lchunk_len = offset - lchunk_start;
1967 image_start = offset;
1968 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
1969 image_len = offset - image_start;
1970 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
1971 rendered = wmem_strdup_printf(pinfo->pool, "%s image, %" PRIu64"l" "u" " bytes",
1972 dtype == TNS_DATATYPE_JSON119 ? "OSON" : "vector", lob_size);
1973 break;
1974
1975 case TNS_DATATYPE_ROWID11:
1976 {
1977 /* a present indicator (0 / 0xff = NULL), then the object id
1978 * (ub4), file number (ub2), an unused byte, block number
1979 * (ub4) and slot number (ub2) */
1980 int rba = 0, part = 0, block = 0, slot = 0;
1981 first = tvb_get_uint8(tvb, offset);
1982 offset += 1;
1983 if ( first == 0 || first == 0xff )
1984 {
1985 is_null = 1;
1986 break;
1987 }
1988 offset += get_sb4_custom(tvb, offset, &rba);
1989 offset += get_sb4_custom(tvb, offset, &part);
1990 offset += 1;
1991 offset += get_sb4_custom(tvb, offset, &block);
1992 offset += get_sb4_custom(tvb, offset, &slot);
1993 rendered = tns_format_rowid(pinfo, (uint32_t)rba, (uint32_t)part, (uint32_t)block, (uint32_t)slot);
1994 break;
1995 }
1996
1997 case TNS_DATATYPE_UROWID208: /* ub4 num_bytes, a length echo byte, then the bytes */
1998 offset += get_sb4_custom(tvb, offset, &v);
1999 if ( v > 0 )
2000 {
2001 offset += 1;
2002 rendered = tns_format_urowid(pinfo, tvb_get_ptr(tvb, offset, v), v);
2003 offset += v;
2004 }
2005 else
2006 is_null = 1;
2007 break;
2008
2009 case TNS_DATATYPE_LONG8:
2010 case TNS_DATATYPE_LONG_RAW24: /* value then two trailing ub4 length indicators */
2011 first = tvb_get_uint8(tvb, offset);
2012 if ( first == 0 )
2013 {
2014 offset += 1;
2015 is_null = 1;
2016 }
2017 else if ( first == 0xfe ) /* chunked */
2018 offset += 1 + tns_chunks_len(tvb, pinfo, offset + 1, NULL((void*)0));
2019 else
2020 offset += 1 + first;
2021 offset += get_sb4_custom(tvb, offset, &v);
2022 offset += get_sb4_custom(tvb, offset, &v);
2023 break;
2024
2025 case TNS_DATATYPE_CLOB112:
2026 case TNS_DATATYPE_BLOB113:
2027 case TNS_DATATYPE_BFILE114:
2028 /* 0x00 NULL, else a ub4 locator length and the locator. A
2029 * server sends CLOB / BLOB in one of two forms: with the LOB's
2030 * size (ub8) and chunk size (ub4) between the two, or bare -
2031 * and which one it picks for a client is not known. They are
2032 * told apart by the byte after the length: the bare form's is
2033 * the locator's own length prefix (or 0xFE when chunked), the
2034 * metadata form's is the size's width, at most 8. A real
2035 * locator is far longer than 8 bytes, so the two cannot meet.
2036 * A BFILE is always bare. */
2037 first = tvb_get_uint8(tvb, offset);
2038 if ( first == 0 )
2039 {
2040 offset += 1;
2041 is_null = 1;
2042 }
2043 else
2044 {
2045 offset += get_sb4_custom(tvb, offset, &v);
2046 if ( dtype != TNS_DATATYPE_BFILE114 && v > 8 )
2047 {
2048 uint8_t next = tvb_get_uint8(tvb, offset);
2049 if ( next <= 8 && next != v )
2050 {
2051 lob_meta = true1;
2052 size_start = offset;
2053 offset += get_ub8_custom(tvb, offset, &lob_size);
2054 size_len = offset - size_start;
2055 lchunk_start = offset;
2056 offset += get_sb4_custom(tvb, offset, &lob_chunk);
2057 lchunk_len = offset - lchunk_start;
2058 rendered = wmem_strdup_printf(pinfo->pool, "locator, size %" PRIu64"l" "u", lob_size);
2059 }
2060 }
2061 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
2062 }
2063 break;
2064
2065 default: /* ordinary: a single DALC value */
2066 first = tvb_get_uint8(tvb, offset);
2067 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
2068 if ( first == 0 )
2069 is_null = 1;
2070 else if ( first == TNS_DALC_ABSENT0xFD )
2071 is_absent = 1;
2072 else
2073 {
2074 disp_start = v_start + 1; /* show the value bytes, not the length */
2075 /* Render common scalar types (never chunked): NUMBER as
2076 * decimal, DATE / TIMESTAMP / TIMESTAMP LTZ as a datetime. */
2077 if ( first != 254 && offset > disp_start )
2078 {
2079 const uint8_t *vb = tvb_get_ptr(tvb, disp_start, offset - disp_start);
2080 int vlen = offset - disp_start;
2081 /* A BINARY_INTEGER carries NUMBER bytes, not a native
2082 * integer. */
2083 if ( dtype == TNS_DATATYPE_NUMBER2 || dtype == TNS_DATATYPE_INTEGER3 )
2084 rendered = tns_format_number(pinfo, vb, vlen);
2085 else if ( dtype == TNS_DATATYPE_DATE12 || dtype == TNS_DATATYPE_TIMESTAMP180 || dtype == TNS_DATATYPE_TIMESTAMP_LTZ231 )
2086 rendered = tns_format_date(pinfo, vb, vlen);
2087 else if ( dtype == TNS_DATATYPE_TIMESTAMP_TZ181 )
2088 rendered = tns_format_timestamp_tz(pinfo, vb, vlen);
2089 else if ( (dtype == TNS_DATATYPE_INTERVAL_YM182 || dtype == TNS_DATATYPE_INTERVAL_DS183) && vlen >= 5 )
2090 rendered = tns_format_interval(pinfo, dtype, vb, vlen);
2091 else if ( dtype == TNS_DATATYPE_BOOLEAN252 )
2092 /* an encoded integer: 00 false, 01 01 true */
2093 rendered = vb[0] == 1 ? "TRUE" : "FALSE";
2094 else if ( dtype == TNS_DATATYPE_BINARY_FLOAT100 || dtype == TNS_DATATYPE_BINARY_DOUBLE101 )
2095 rendered = tns_format_binary_float(pinfo, vb, vlen);
2096 else if ( dtype == TNS_DATATYPE_VARCHAR1 || dtype == TNS_DATATYPE_STRING5 || dtype == TNS_DATATYPE_CHAR96 )
2097 /* VARCHAR / STRING / CHAR: character data, in the
2098 * session charset (ordinarily UTF-8), or UTF-16BE
2099 * for the national charset form (NCHAR,
2100 * NVARCHAR2) - in a column and an OUT bind alike. */
2101 rendered = (const char *)tvb_get_string_enc(pinfo->pool,
2102 tvb, disp_start, vlen,
2103 csform == TNS_CSFORM_NCHAR2 ? ENC_UTF_160x00000004|ENC_BIG_ENDIAN0x00000000 : ENC_UTF_80x00000002|ENC_NA0x00000000);
2104 }
2105 }
2106 break;
2107 }
2108
2109 if ( is_null )
2110 proto_tree_add_bytes_format(tree, hf, tvb,
2111 v_start, offset - v_start, NULL((void*)0), "%s %d (%s): NULL", prefix, idx,
2112 val_to_str_const(dtype, tns_data_types, "unknown"));
2113 else if ( is_absent )
2114 proto_tree_add_bytes_format(tree, hf, tvb,
2115 v_start, offset - v_start, NULL((void*)0), "%s %d (%s): no value", prefix, idx,
2116 val_to_str_const(dtype, tns_data_types, "unknown"));
2117 else if ( rendered )
2118 {
2119 ti = proto_tree_add_bytes_format(tree, hf, tvb,
2120 disp_start, offset - disp_start, NULL((void*)0), "%s %d (%s): %s", prefix, idx,
2121 val_to_str_const(dtype, tns_data_types, "unknown"), rendered);
2122 if ( dtype == TNS_DATATYPE_ADT109 )
2123 {
2124 proto_tree *vt = proto_item_add_subtree(ti, ett_tns_value);
2125 /* the type OID, without its ub4 count and DALC length */
2126 if ( obj_toid_len > 2 )
2127 {
2128 int w = 1 + (tvb_get_uint8(tvb, obj_toid_start) & 0x7f);
2129 proto_tree_add_item(vt, hf_tns_data_obj_toid, tvb,
2130 obj_toid_start + w + 1, obj_toid_len - w - 1, ENC_NA0x00000000);
2131 }
2132 if ( image_len > 1 )
2133 {
2134 bool_Bool chunked = tvb_get_uint8(tvb, image_start) == 0xfe;
2135 proto_tree_add_item(vt, hf_tns_data_obj_image, tvb,
2136 chunked ? image_start : image_start + 1, chunked ? image_len : image_len - 1, ENC_NA0x00000000);
2137 }
2138 }
2139 if ( lob_meta )
2140 {
2141 proto_tree *vt = proto_item_add_subtree(ti, ett_tns_value);
2142 proto_tree_add_uint64(vt, hf_tns_data_lob_size, tvb, size_start, size_len, lob_size);
2143 proto_tree_add_uint(vt, hf_tns_data_lob_chunk_size, tvb, lchunk_start, lchunk_len, lob_chunk);
2144 /* the image of a prefetched JSON / VECTOR value, without its
2145 * DALC length byte (chunked images are shown whole) */
2146 if ( image_len > 1 )
2147 {
2148 bool_Bool chunked = tvb_get_uint8(tvb, image_start) == 0xfe;
2149 proto_tree_add_item(vt, dtype == TNS_DATATYPE_JSON119 ? hf_tns_data_json_image : hf_tns_data_vector_image,
2150 tvb, chunked ? image_start : image_start + 1, chunked ? image_len : image_len - 1, ENC_NA0x00000000);
2151 }
2152 }
2153 }
2154 else
2155 proto_tree_add_bytes_format(tree, hf, tvb,
2156 disp_start, offset - disp_start, NULL((void*)0), "%s %d (%s)", prefix, idx,
2157 val_to_str_const(dtype, tns_data_types, "unknown"));
2158 return offset;
2159}
2160
2161/* The describe a row-data message is split by: the conversation's most
2162 * recent one, stored per packet on the first pass so a later pass uses
2163 * the same. */
2164static tns_describe_t *tns_current_describe(packet_info *pinfo)
2165{
2166 tns_describe_t *desc;
2167
2168 if ( PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
2169 return (tns_describe_t *)p_get_proto_data(wmem_file_scope(), pinfo,
2170 proto_tns, TNS_PROTO_DATA_DESCRIBE1);
2171
2172 desc = tns_get_conv_info(pinfo)->last_describe;
2173 if ( desc && !p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_DESCRIBE1) )
2174 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns,
2175 TNS_PROTO_DATA_DESCRIBE1, desc);
2176 return desc;
2177}
2178
2179/* Count the RETURNING ... INTO binds of a statement: the placeholders
2180 * after INTO, in a DML statement that has RETURNING ... INTO. Each
2181 * placeholder is a bind of its own, and those after INTO come last. A
2182 * PL/SQL block is never this form - a RETURNING INTO inside one is its
2183 * own PL/SQL, and its target an ordinary OUT bind. String literals and
2184 * comments are skipped. */
2185static unsigned tns_count_return_binds(const char *sql)
2186{
2187 const char *p = sql;
2188 bool_Bool first_word = true1, returning = false0, into = false0;
2189 unsigned n = 0;
2190
2191 while ( *p )
2192 {
2193 if ( *p == '\'' )
2194 {
2195 for ( p++; *p && *p != '\''; p++ )
2196 ;
2197 if ( *p )
2198 p++;
2199 }
2200 else if ( p[0] == '-' && p[1] == '-' )
2201 {
2202 while ( *p && *p != '\n' )
2203 p++;
2204 }
2205 else if ( p[0] == '/' && p[1] == '*' )
2206 {
2207 const char *end = strstr(p + 2, "*/");
2208 p = end ? end + 2 : p + strlen(p);
2209 }
2210 else if ( g_ascii_isalpha(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_ALPHA) != 0) )
2211 {
2212 const char *w = p;
2213 size_t len;
2214 while ( g_ascii_isalnum(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_ALNUM) != 0) || *p == '_' || *p == '$' || *p == '#' )
2215 p++;
2216 len = p - w;
2217 if ( first_word )
2218 {
2219 first_word = false0;
2220 if ( !((len == 6 && (g_ascii_strncasecmp(w, "INSERT", 6) == 0
2221 || g_ascii_strncasecmp(w, "UPDATE", 6) == 0
2222 || g_ascii_strncasecmp(w, "DELETE", 6) == 0))
2223 || (len == 5 && g_ascii_strncasecmp(w, "MERGE", 5) == 0)) )
2224 return 0;
2225 }
2226 else if ( !returning && len == 9 && g_ascii_strncasecmp(w, "RETURNING", 9) == 0 )
2227 returning = true1;
2228 else if ( returning && !into && len == 4 && g_ascii_strncasecmp(w, "INTO", 4) == 0 )
2229 into = true1;
2230 }
2231 else if ( *p == ':' && into && (g_ascii_isalnum(p[1])((g_ascii_table[(guchar) (p[1])] & G_ASCII_ALNUM) != 0) || p[1] == '_' || p[1] == '"') )
2232 {
2233 n++;
2234 for ( p++; g_ascii_isalnum(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_ALNUM) != 0) || *p == '_' || *p == '"'; p++ )
2235 ;
2236 }
2237 else
2238 p++;
2239 }
2240 return n;
2241}
2242
2243/* Look up the bind types remembered for a cursor, for an execute that
2244 * sends its values without descriptors. Stashed per packet on the first
2245 * pass, so a later pass gets the same answer. */
2246static tns_binds_t *tns_lookup_cursor_binds(packet_info *pinfo, uint32_t cursor)
2247{
2248 if ( PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
2249 return (tns_binds_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_BINDS2);
2250
2251 tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
2252 tns_binds_t *binds = (tns_binds_t *)wmem_map_lookup(tns_info->cursor_binds, GUINT_TO_POINTER(cursor)((gpointer) (gulong) (cursor)));
2253 if ( binds )
2254 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_BINDS2, binds);
2255 return binds;
2256}
2257
2258/* Decode the TTI_RXD value rows of a bind section - one row per
2259 * execution - with each value typed by cols[]. A CLOB / BLOB bind
2260 * carries a temp-LOB locator form not unpacked here, so rows with one are
2261 * left alone. Returns the new offset. */
2262static int dissect_tns_bind_rows(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, const tns_column_t *cols, uint32_t count)
2263{
2264 int rownum = 0;
2265
2266 for ( uint32_t i = 0; i < count; i++ )
2267 if ( cols[i].type == TNS_DATATYPE_CLOB112 || cols[i].type == TNS_DATATYPE_BLOB113 )
2268 return offset;
2269
2270 while ( tvb_reported_length_remaining(tvb, offset) > 0
2271 && tvb_get_uint8(tvb, offset) == SQLNET_ROW_TRANSF_DATA7 )
2272 {
2273 proto_tree *row_tree;
2274 proto_item *row_item;
2275 int r_start = offset;
2276
2277 offset += 1; /* TTI_RXD token */
2278 row_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
2279 ett_tns_bind_row, &row_item, "Row %d", ++rownum);
2280 for ( uint32_t i = 0; i < count
2281 && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
2282 offset = dissect_tns_value(tvb, pinfo, row_tree, offset,
2283 cols[i].type, cols[i].csform, i + 1, hf_tns_data_bind_value, "Bind");
2284 proto_item_set_len(row_item, offset - r_start);
2285 }
2286 return offset;
2287}
2288
2289/* Remember the call a request makes, so the response can be read in its
2290 * light. Returns the record to fill in, or NULL on a later pass. */
2291static tns_call_t *tns_remember_call(packet_info *pinfo, uint8_t func)
2292{
2293 if ( PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
2294 return NULL((void*)0);
2295
2296 tns_call_t *call = wmem_new0(wmem_file_scope(), tns_call_t)((tns_call_t*)wmem_alloc0((wmem_file_scope()), sizeof(tns_call_t
)))
;
2297 call->func = func;
2298 tns_get_conv_info(pinfo)->last_call = call;
2299 return call;
2300}
2301
2302/* The call a response packet answers, or NULL if none was seen. */
2303static tns_call_t *tns_answered_call(packet_info *pinfo)
2304{
2305 if ( PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
2306 return (tns_call_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_CALL3);
2307
2308 tns_call_t *call = tns_get_conv_info(pinfo)->last_call;
2309 if ( call )
2310 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_CALL3, call);
2311 return call;
2312}
2313
2314/* Decode num key/value pairs: each a ub2 text length and text, a ub2
2315 * binary length and bytes, and a ub2 keyword number saying which session
2316 * attribute the value is for. Returns the new offset. */
2317static int dissect_tns_kv_pairs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int num)
2318{
2319 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
2320 {
2321 proto_tree *kv_tree;
2322 proto_item *kv_item;
2323 const char *text = NULL((void*)0);
2324 int kv_start = offset, len = 0, keyword = 0, start;
2325
2326 kv_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1, ett_tns_kv,
2327 &kv_item, "Key/Value Pair %d", i + 1);
2328 offset += get_sb4_custom(tvb, offset, &len);
2329 if ( len > 0 )
2330 {
2331 start = offset;
2332 offset += get_dalc_custom(tvb, pinfo, offset, &text);
2333 proto_tree_add_string(kv_tree, hf_tns_data_kv_text, tvb, start, offset - start, text);
2334 }
2335 offset += get_sb4_custom(tvb, offset, &len);
2336 if ( len > 0 )
2337 {
2338 start = offset;
2339 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
2340 proto_tree_add_item(kv_tree, hf_tns_data_kv_binary, tvb, start + 1, offset - start - 1, ENC_NA0x00000000);
2341 }
2342 start = offset;
2343 offset += get_sb4_custom(tvb, offset, &keyword);
2344 proto_tree_add_uint(kv_tree, hf_tns_data_kv_keyword, tvb, start, offset - start, keyword);
2345 proto_item_append_text(kv_item, ": %s", val_to_str(pinfo->pool, keyword, tns_kv_keywords, "keyword %u"));
2346 if ( text )
2347 proto_item_append_text(kv_item, " = %s", text);
2348 proto_item_set_len(kv_item, offset - kv_start);
2349 }
2350 return offset;
2351}
2352
2353/* Decode the return-parameters block (TTI_RPA) that answers an execute,
2354 * ahead of its closing status. With DML_ROWCOUNTS requested it ends with
2355 * the rows each iteration of an array DML affected. Returns the new
2356 * offset. */
2357static int dissect_tns_return_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, bool_Bool rowcounts)
2358{
2359 proto_tree *rpa_tree;
2360 proto_item *rpa_item;
2361 int rpa_start = offset, num = 0, len = 0, start;
2362
2363 rpa_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_tns_rpa, &rpa_item, "Return Parameters");
2364
2365 /* al8o4l: a count of ub4 words */
2366 start = offset;
2367 offset += get_sb4_custom(tvb, offset, &num);
2368 proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_num_al8o4, tvb, start, offset - start, num);
2369 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
2370 {
2371 int v = 0;
2372 start = offset;
2373 offset += get_sb4_custom(tvb, offset, &v);
2374 proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_al8o4, tvb, start, offset - start, v);
2375 }
2376 /* al8txl: a byte count and the bytes */
2377 offset += get_sb4_custom(tvb, offset, &len);
2378 if ( len > 0 )
2379 {
2380 proto_tree_add_item(rpa_tree, hf_tns_data_rpa_al8txl, tvb, offset, len, ENC_NA0x00000000);
2381 offset += len;
2382 }
2383 /* key/value pairs: a changed session attribute is reported here */
2384 start = offset;
2385 offset += get_sb4_custom(tvb, offset, &num);
2386 proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_num_kv, tvb, start, offset - start, num);
2387 offset = dissect_tns_kv_pairs(tvb, pinfo, rpa_tree, offset, num);
2388 /* registration: a byte count and the bytes */
2389 offset += get_sb4_custom(tvb, offset, &len);
2390 if ( len > 0 )
2391 {
2392 proto_tree_add_item(rpa_tree, hf_tns_data_rpa_registration, tvb, offset, len, ENC_NA0x00000000);
2393 offset += len;
2394 }
2395 /* per-iteration row counts, when the execute asked for them */
2396 if ( rowcounts )
2397 {
2398 start = offset;
2399 offset += get_sb4_custom(tvb, offset, &num);
2400 proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_num_rowcounts, tvb, start, offset - start, num);
2401 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
2402 {
2403 uint64_t rows = 0;
2404 start = offset;
2405 offset += get_ub8_custom(tvb, offset, &rows);
2406 proto_tree_add_uint64(rpa_tree, hf_tns_data_rpa_dml_rowcount, tvb, start, offset - start, rows);
2407 }
2408 }
2409 proto_item_set_len(rpa_item, offset - rpa_start);
2410 return offset;
2411}
2412
2413/* From field version 23.1 ext 1 a call or piggyback header carries a ub8
2414 * token after its sequence number, which the reply echoes in a TOKEN
2415 * message. Returns the new offset. */
2416static int dissect_tns_call_token(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
2417{
2418 uint64_t token = 0;
2419 int start = offset;
2420
2421 if ( tns_field_version(pinfo) < TNS_FV_23_1_EXT_118 )
2422 return offset;
2423 offset += get_ub8_custom(tvb, offset, &token);
2424 proto_tree_add_uint64(tree, hf_tns_data_token, tvb, start, offset - start, token);
2425 return offset;
2426}
2427
2428/* Decode the body of a piggyback other than close-cursors. Layouts
2429 * follow python-oracledb's _write_*_piggyback. Sets *walk when the body
2430 * was understood, so the call behind it can be decoded. Returns the new
2431 * offset. */
2432static int dissect_tns_piggyback_body(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint8_t piggyback_id, bool_Bool *walk)
2433{
2434 int v = 0, start;
2435 uint64_t u = 0;
2436
2437 switch ( piggyback_id )
2438 {
2439 case TTI_LOBOPS96:
2440 {
2441 /* close temporary LOBs: a FREE_TEMP | ARRAY LOB operation
2442 * whose locators, each with its own ub2 length prefix, follow
2443 * back to back - as many bytes as the total says. */
2444 int total = 0, op = 0;
2445 offset += 1; /* pointer */
2446 start = offset;
2447 offset += get_sb4_custom(tvb, offset, &total);
2448 proto_tree_add_uint(tree, hf_tns_data_lob_total_size, tvb, start, offset - start, total);
2449 offset += 1; /* dest locator pointer */
2450 offset += get_sb4_custom(tvb, offset, &v); /* dest locator length */
2451 offset += get_sb4_custom(tvb, offset, &v); /* source locator */
2452 offset += get_sb4_custom(tvb, offset, &v);
2453 offset += 3; /* offsets, charset */
2454 start = offset;
2455 offset += get_sb4_custom(tvb, offset, &op);
2456 proto_tree_add_uint(tree, hf_tns_data_lob_op, tvb, start, offset - start, op);
2457 offset += 1; /* scn */
2458 offset += get_sb4_custom(tvb, offset, &v); /* losbscn */
2459 offset += get_ub8_custom(tvb, offset, &u); /* lobscnl */
2460 offset += get_ub8_custom(tvb, offset, &u);
2461 offset += 1;
2462 for ( int i = 0; i < 3; i++ ) /* array LOB fields */
2463 {
2464 offset += 1;
2465 offset += get_sb4_custom(tvb, offset, &v);
2466 }
2467 if ( total < 0 || (unsigned)total > tvb_reported_length_remaining(tvb, offset) )
2468 {
2469 proto_tree_add_expert(tree, pinfo, &ei_tns_data_count_too_large, tvb, offset, 0);
2470 return offset;
2471 }
2472 for ( int end = offset + total; offset + 2 <= end; )
2473 {
2474 int len = 2 + tvb_get_ntohs(tvb, offset);
2475 if ( offset + len > end )
2476 len = end - offset;
2477 proto_tree_add_item(tree, hf_tns_data_lob_locator, tvb, offset, len, ENC_NA0x00000000);
2478 offset += len;
2479 }
2480 break;
2481 }
2482
2483 case TTI_SET_SCHEMA152:
2484 {
2485 const char *schema = NULL((void*)0);
2486 offset += 1; /* pointer */
2487 start = offset;
2488 offset += get_field_with_length(tvb, pinfo, offset, &schema);
2489 if ( schema )
2490 proto_tree_add_string(tree, hf_tns_data_pgy_schema, tvb, start, offset - start, schema);
2491 break;
2492 }
2493
2494 case TTI_SESSION_STATE176:
2495 start = offset;
2496 offset += get_ub8_custom(tvb, offset, &u);
2497 proto_tree_add_uint64(tree, hf_tns_data_pgy_session_state, tvb, start, offset - start, u);
2498 break;
2499
2500 case TTI_PIPELINE_BEGIN199:
2501 start = offset;
2502 offset += get_sb4_custom(tvb, offset, &v);
2503 proto_tree_add_uint(tree, hf_tns_data_pgy_error_set_id, tvb, start, offset - start, v);
2504 proto_tree_add_item(tree, hf_tns_data_pgy_error_set_mode, tvb, offset, 1, ENC_NA0x00000000);
2505 offset += 1;
2506 proto_tree_add_item(tree, hf_tns_data_pgy_pipeline_mode, tvb, offset, 1, ENC_NA0x00000000);
2507 offset += 1;
2508 break;
2509
2510 case TTI_SET_END_TO_END_ATTR135:
2511 {
2512 /* End-to-end attributes: a flags word saying which changed,
2513 * then a (pointer, length) header for each attribute - some
2514 * never used - and finally the strings of those that have a
2515 * value, in the same order. */
2516 static int * const hfs[] = { &hf_tns_data_pgy_client_id, &hf_tns_data_pgy_module,
2517 &hf_tns_data_pgy_action, NULL((void*)0), &hf_tns_data_pgy_client_info, NULL((void*)0), NULL((void*)0),
2518 &hf_tns_data_pgy_dbop };
2519 int lens[array_length(hfs)(sizeof (hfs) / sizeof (hfs)[0])];
2520
2521 offset += 2; /* cidnam, cidser pointers */
2522 start = offset;
2523 offset += get_sb4_custom(tvb, offset, &v);
2524 proto_tree_add_uint(tree, hf_tns_data_pgy_e2e_flags, tvb, start, offset - start, v);
2525 for ( unsigned i = 0; i < array_length(hfs)(sizeof (hfs) / sizeof (hfs)[0]); i++ )
2526 {
2527 uint8_t ptr = tvb_get_uint8(tvb, offset);
2528 offset += 1;
2529 offset += get_sb4_custom(tvb, offset, &lens[i]);
2530 if ( !ptr || !hfs[i] )
2531 lens[i] = 0;
2532 if ( i == 3 ) /* cideci is followed by cidcct, cidecs */
2533 {
2534 offset += 1;
2535 offset += get_sb4_custom(tvb, offset, &v);
2536 }
2537 }
2538 for ( unsigned i = 0; i < array_length(hfs)(sizeof (hfs) / sizeof (hfs)[0]); i++ )
2539 {
2540 const char *str = NULL((void*)0);
2541 if ( lens[i] <= 0 )
2542 continue;
2543 start = offset;
2544 offset += get_dalc_custom(tvb, pinfo, offset, &str);
2545 if ( str )
2546 proto_tree_add_string(tree, *hfs[i], tvb, start, offset - start, str);
2547 }
2548 break;
2549 }
2550
2551 case TTI_END_USER_SEC_CTX205:
2552 {
2553 /* End-user security context: flags, then key/value pairs, each
2554 * a flags word and a key, a text and a value in the
2555 * bytes_with_length form. */
2556 int num = 0;
2557 start = offset;
2558 offset += get_sb4_custom(tvb, offset, &v);
2559 proto_tree_add_uint(tree, hf_tns_data_pgy_sec_flags, tvb, start, offset - start, v);
2560 offset += 1; /* pointer */
2561 offset += get_sb4_custom(tvb, offset, &num);
2562 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
2563 {
2564 const char *key = NULL((void*)0);
2565 offset += get_sb4_custom(tvb, offset, &v); /* flags */
2566 start = offset;
2567 offset += get_field_with_length(tvb, pinfo, offset, &key);
2568 if ( key )
2569 proto_tree_add_string(tree, hf_tns_data_pgy_sec_key, tvb, start, offset - start, key);
2570 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0)); /* text */
2571 start = offset;
2572 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
2573 proto_tree_add_item(tree, hf_tns_data_pgy_sec_value, tvb, start, offset - start, ENC_NA0x00000000);
2574 }
2575 break;
2576 }
2577
2578 default:
2579 /* An unknown body has an unknown length. */
2580 return offset;
2581 }
2582 *walk = true1;
2583 return offset;
2584}
2585
2586static void dissect_tns_data_descriptor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tns_tree, uint32_t length)
2587{
2588 /* This is used by Oracle 12c for at least sending LOB/FILE data. */
2589 proto_tree *dd_tree, *row_tree;
2590 proto_item *ti;
2591 uint32_t data_len, row_count, row_size, total_row_size = 0;
2592 int orig_offset = offset;
2593
2594 /* We only get here after tcp_dissect_pdus(), length is guaranteed. */
2595 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"
, 2595, (int64_t)length, (int64_t)8))))
;
2596
2597 dd_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL((void*)0), "Data Descriptor");
2598
2599 /* No idea what this is. Usually 0x0003. */
2600 offset += 4;
2601 proto_tree_add_item_ret_uint(dd_tree, hf_tns_data_length, tvb,
2602 offset, 4, ENC_BIG_ENDIAN0x00000000, &data_len);
2603 offset += 4;
2604
2605 /* This next parameter looks like: number of big endian shorts that follow,
2606 * the sum of the shorts equals the file length above - each short maxes
2607 * out at 0x1f7c = 8060, presumably related to the page size / max table
2608 * row size in Microsoft SQL Server? Something about how many rows it
2609 * would take to store this in-table?
2610 */
2611 proto_tree_add_item_ret_uint(dd_tree, hf_tns_data_descriptor_row_count, tvb,
2612 offset, 4, ENC_BIG_ENDIAN0x00000000, &row_count);
2613 offset += 4;
2614 row_tree = proto_tree_add_subtree(dd_tree, tvb, offset, row_count * 2,
2615 ett_tns_rows, &ti, "Rows");
2616 for (uint32_t i = 0; i < row_count; i++) {
2617 proto_tree_add_item_ret_uint(row_tree, hf_tns_data_descriptor_row_size, tvb,
2618 offset, 2, ENC_BIG_ENDIAN0x00000000, &row_size);
2619 total_row_size += row_size;
2620 offset += 2;
2621 }
2622 proto_item_append_text(ti, " (%u bytes)", total_row_size);
2623 if (total_row_size != data_len) {
2624 expert_add_info(pinfo, ti, &ei_tns_data_descriptor_size_mismatch);
2625 }
2626
2627 offset = orig_offset + (length - TNS_HDR_LEN8);
2628
2629 call_data_dissector(tvb_new_subset_length(tvb, offset, data_len), pinfo,
2630 dd_tree);
2631}
2632
2633/* State carried from one TTC message to the next within a packet. */
2634typedef struct _tns_msg_ctx_t {
2635 /* The decoder ended exactly on its message's last byte. */
2636 bool_Bool walk;
2637 /* Which columns the next row sends, from a row header or a TTI_BVC:
2638 * a clear bit means the value repeats the previous row's. NULL when
2639 * every column is sent. */
2640 const uint8_t *bit_vector;
2641 unsigned bit_vector_len;
2642 /* After a TTI_IOV: the call it answers and each bind's direction, so
2643 * the TTI_RXD after it can be read as the OUT bind values. */
2644 const tns_call_t *out_call;
2645 const uint8_t *bind_dirs;
2646} tns_msg_ctx_t;
2647
2648static 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);
2649
2650/* Whether a message that follows another in the same packet is one we
2651 * step into. A response is a run of messages back to back - a describe,
2652 * a row header, the rows, a status - and a request may put piggybacks in
2653 * front of its call. */
2654static bool_Bool tns_is_next_message(unsigned data_func_id, bool_Bool is_request)
2655{
2656 if ( is_request )
2657 return data_func_id == SQLNET_USER_OCI_FUNC3 || data_func_id == SQLNET_PIGGYBACK_FUNC17;
2658
2659 switch ( data_func_id )
2660 {
2661 case SQLNET_RETURN_STATUS4:
2662 case SQLNET_FUNCCOMPLETE9:
2663 case SQLNET_WARNING15:
2664 case SQLNET_LOB_FILE_DF14:
2665 case SQLNET_BIT_VECTOR21:
2666 case SQLNET_SERVER_PIGGYBACK23:
2667 case SQLNET_IMPLICIT_RESULTS27:
2668 case SQLNET_TOKEN33:
2669 case SQLNET_END_OF_RESPONSE29:
2670 case SQLNET_ROW_TRANSF_HDR6:
2671 case SQLNET_ROW_TRANSF_DATA7:
2672 case SQLNET_RETURN_OPI_PARAM8:
2673 case SQLNET_IOVEC_4FAST_UPI11:
2674 case SQLNET_DESCRIBE_INFO16:
2675 return true1;
2676 default:
2677 return false0;
2678 }
2679}
2680
2681static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tns_tree)
2682{
2683 proto_tree *data_tree;
2684 unsigned data_func_id;
2685 bool_Bool is_request;
2686 static int * const flags[] = {
2687 &hf_tns_data_flag_send,
2688 &hf_tns_data_flag_rc,
2689 &hf_tns_data_flag_c,
2690 &hf_tns_data_flag_reserved,
2691 &hf_tns_data_flag_more,
2692 &hf_tns_data_flag_eof,
2693 &hf_tns_data_flag_dic,
2694 &hf_tns_data_flag_rts,
2695 &hf_tns_data_flag_sntt,
2696 NULL((void*)0)
2697 };
2698
2699 is_request = pinfo->match_uint == pinfo->destport;
2700 data_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL((void*)0), "Data");
2701
2702 proto_tree_add_bitmask(data_tree, tvb, offset, hf_tns_data_flag, ett_tns_data_flag, flags, ENC_BIG_ENDIAN0x00000000);
2703 offset += 2;
2704 data_func_id = get_data_func_id(tvb, offset);
2705
2706 /* The field version the connection negotiated decides the shape of
2707 * several messages; show the one in force. */
2708 unsigned fv = tns_field_version(pinfo);
2709 if ( fv )
2710 proto_item_set_generated(proto_tree_add_uint(data_tree, hf_tns_data_field_version, tvb, 0, 0, fv));
2711
2712 /* Do this only if the Data message have a body. Otherwise, there are only Data flags. */
2713 int remaining = tvb_reported_length_remaining(tvb, offset);
2714 if ( remaining > 0 )
2715 {
2716 if (is_request) {
2717 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
2718 tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
2719 if ((uint32_t)remaining == tns_info->pending_connect_data) {
2720 col_append_str(pinfo->cinfo, COL_INFO, ", Connect Data");
2721 proto_tree_add_item(data_tree, hf_tns_connect_data, tvb,
2722 offset, -1, ENC_ASCII0x00000000);
2723 p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, 0,
2724 GUINT_TO_POINTER(tns_info->pending_connect_data)((gpointer) (gulong) (tns_info->pending_connect_data)));
2725 tns_info->pending_connect_data = 0;
2726 return;
2727 }
2728 } else {
2729 if (p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, 0) != NULL((void*)0)) {
2730 col_append_str(pinfo->cinfo, COL_INFO, ", Connect Data");
2731 proto_tree_add_item(data_tree, hf_tns_connect_data, tvb,
2732 offset, -1, ENC_ASCII0x00000000);
2733 return;
2734 }
2735 }
2736 }
2737 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(data_func_id, tns_data_funcs, "unknown"));
2738
2739 if ( (data_func_id != SQLNET_SNS0xdeadbeef) && (try_val_to_str(data_func_id, tns_data_funcs) != NULL((void*)0)) )
2740 {
2741 proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2742 offset += 1;
2743 }
2744 }
2745
2746 /* Decode the first message, then step into each one after it for as
2747 * long as the previous decoder ended exactly on its last byte. */
2748 tns_msg_ctx_t ctx = { 0 };
2749 offset = dissect_tns_message(tvb, offset, pinfo, data_tree, is_request, data_func_id, &ctx);
2750 while ( ctx.walk && tvb_reported_length_remaining(tvb, offset) > 0 )
2751 {
2752 data_func_id = tvb_get_uint8(tvb, offset);
2753 if ( !tns_is_next_message(data_func_id, is_request) )
2754 break;
2755 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(data_func_id, tns_data_funcs, "unknown"));
2756 proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2757 offset += 1;
2758 ctx.walk = false0;
2759 offset = dissect_tns_message(tvb, offset, pinfo, data_tree, is_request, data_func_id, &ctx);
2760 }
2761
2762 if ( tvb_reported_length_remaining(tvb, offset) > 0 )
2763 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, data_tree);
2764}
2765
2766/* Whether a packet belongs to a conversation whose client speaks the OCI
2767 * dialect. Stored per packet on the first pass. */
2768static bool_Bool tns_is_oci(packet_info *pinfo)
2769{
2770 void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_OCI4);
2771 if ( stored || PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
2772 return GPOINTER_TO_UINT(stored)((guint) (gulong) (stored)) == 2;
2773
2774 bool_Bool oci = tns_get_conv_info(pinfo)->oci_dialect;
2775 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)));
2776 return oci;
2777}
2778
2779/* Decode a server message to an OCI client. Its integers are fixed-width
2780 * little-endian, so only the status messages, whose layout is known, are
2781 * decoded; the rest is left to the data dissector. Returns the new
2782 * offset. */
2783static int dissect_tns_oci_message(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *data_tree, unsigned data_func_id)
2784{
2785 switch ( data_func_id )
2786 {
2787 case SQLNET_RETURN_STATUS4:
2788 {
2789 /* The OCI status block: 136 bytes, or a compact 24 for a
2790 * query's execute status, the end of a fetch and a no-row
2791 * status. Offsets count from the message id byte; a field
2792 * this decoder skips is a constant or not understood. The
2793 * error message follows the full form. */
2794 proto_tree *oer_tree;
2795 proto_item *oer_item;
2796 int base = offset - 1;
2797 bool_Bool full = tvb_reported_length_remaining(tvb, base) >= 136;
2798 uint32_t err_code;
2799
2800 if ( tvb_reported_length_remaining(tvb, base) < 24 )
2801 return offset;
2802 oer_tree = proto_tree_add_subtree(data_tree, tvb, base, full ? 136 : 24, ett_tns_oer, &oer_item,
2803 full ? "Oracle Error Return (OCI)" : "Oracle Error Return (OCI, compact)");
2804 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_status, tvb, base + 1, 1, ENC_NA0x00000000);
2805 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_seq, tvb, base + 5, 2, ENC_LITTLE_ENDIAN0x80000000);
2806 proto_tree_add_int(oer_tree, hf_tns_data_oer_rowcount, tvb, base + 8, 4, (int32_t)tvb_get_letohl(tvb, base + 8));
2807 err_code = tvb_get_letohl(tvb, base + 12);
2808 proto_tree_add_int(oer_tree, hf_tns_data_oer_err_code, tvb, base + 12, 4, (int32_t)err_code);
2809 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_category, tvb, base + 18, 1, ENC_NA0x00000000);
2810 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_error_pos, tvb, base + 20, 1, ENC_NA0x00000000);
2811 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_command, tvb, base + 22, 1, ENC_NA0x00000000);
2812 if ( !full )
2813 return base + 24;
2814 /* the sequence number of the call this answers - the client's
2815 * own, not the counter at offset 5 */
2816 proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_call_seq, tvb, base + 49, 2, ENC_LITTLE_ENDIAN0x80000000);
2817 offset = base + 136;
2818 if ( err_code != 0 && tvb_reported_length_remaining(tvb, offset) > 0 )
2819 {
2820 const char *msg = NULL((void*)0);
2821 int msg_start = offset;
2822 offset += get_dalc_custom(tvb, pinfo, offset, &msg);
2823 if ( msg )
2824 {
2825 proto_tree_add_string(oer_tree, hf_tns_data_oer_message, tvb, msg_start, offset - msg_start, msg);
2826 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", msg);
2827 }
2828 proto_item_set_len(oer_item, offset - base);
2829 }
2830 return offset;
2831 }
2832
2833 case SQLNET_FUNCCOMPLETE9:
2834 /* TTI_STA, answering a commit, a rollback or a logoff: a
2835 * ub4 LE call status and a ub2 LE end-to-end sequence */
2836 if ( !tvb_bytes_exist(tvb, offset, 6) )
2837 return offset;
2838 tns_add_call_status_flags(
2839 proto_tree_add_item(data_tree, hf_tns_data_sta_call_status, tvb, offset, 4, ENC_LITTLE_ENDIAN0x80000000),
2840 tvb, offset, 4, tvb_get_letohl(tvb, offset));
2841 proto_tree_add_item(data_tree, hf_tns_data_sta_seq, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN0x80000000);
2842 return offset + 6;
2843
2844 default:
2845 return offset;
2846 }
2847}
2848
2849/* Decode the body of one TTC message, whose id byte has already been
2850 * consumed. Sets ctx->walk when the decoder ended exactly on the
2851 * message's last byte, so the caller can step into whatever follows it.
2852 * Returns the new offset. */
2853static 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)
2854{
2855 /* The thin decoders below would misread the fixed-width integers of
2856 * a server talking to an OCI client. */
2857 if ( !is_request && data_func_id != SQLNET_SNS0xdeadbeef && data_func_id != SQLNET_RETURN_OPI_PARAM8
2858 && tns_is_oci(pinfo) )
2859 return dissect_tns_oci_message(tvb, offset, pinfo, data_tree, data_func_id);
2860
2861 /* Handle data functions that have more than just ID */
2862 switch (data_func_id)
2863 {
2864 case SQLNET_SET_PROTOCOL1:
2865 {
2866 proto_tree *versions_tree;
2867 proto_item *ti;
2868 char sep;
2869 if ( is_request )
2870 {
2871 versions_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_acc_versions, &ti, "Accepted Versions");
2872 sep = ':';
2873 for (;;) {
2874 /*
2875 * Add each accepted version as a
2876 * separate item.
2877 */
2878 uint8_t vers;
2879
2880 vers = tvb_get_uint8(tvb, offset);
2881 if (vers == 0) {
2882 /*
2883 * A version of 0 terminates
2884 * the list.
2885 */
2886 break;
2887 }
2888 proto_item_append_text(ti, "%c %u", sep, vers);
2889 sep = ',';
2890 proto_tree_add_uint(versions_tree, hf_tns_data_setp_acc_version, tvb, offset, 1, vers);
2891 offset += 1;
2892 }
2893 offset += 1; /* skip the 0 terminator */
2894 proto_item_set_end(ti, tvb, offset);
2895 proto_tree_add_item(data_tree, hf_tns_data_setp_cli_plat, tvb, offset, -1, ENC_ASCII0x00000000);
2896
2897 return tvb_reported_length(tvb); /* skip call_data_dissector */
2898 }
2899 else
2900 {
2901 unsigned len;
2902 versions_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_acc_versions, &ti, "Versions");
2903 sep = ':';
2904 for (;;) {
2905 /*
2906 * Add each version as a separate item.
2907 */
2908 uint8_t vers;
2909
2910 vers = tvb_get_uint8(tvb, offset);
2911 if (vers == 0) {
2912 /*
2913 * A version of 0 terminates
2914 * the list.
2915 */
2916 break;
2917 }
2918 proto_item_append_text(ti, "%c %u", sep, vers);
2919 sep = ',';
2920 proto_tree_add_uint(versions_tree, hf_tns_data_setp_version, tvb, offset, 1, vers);
2921 offset += 1;
2922 }
2923 offset += 1; /* skip the 0 terminator */
2924 proto_item_set_end(ti, tvb, offset);
2925 proto_tree_add_item_ret_length(data_tree, hf_tns_data_setp_banner, tvb, offset, -1, ENC_ASCII0x00000000|ENC_NA0x00000000, &len);
2926 offset += len;
2927 }
2928 break;
2929 }
2930
2931 case SQLNET_SET_DATATYPES2:
2932 {
2933 /* TTI_DTY: Data Type Negotiation, sent right after TTI_PRO
2934 * during the TTC handshake. The body is a fixed-shape blob
2935 * the client uses to tell the server which native Oracle
2936 * data types it understands and what wire representation it
2937 * wants for each. Layout cross-referenced with
2938 * python-oracledb.
2939 *
2940 * charset_in 2 bytes LE NLS_LANGUAGE charset id
2941 * charset_out 2 bytes LE NLS_NCHAR charset id
2942 * flag 1 byte capability flag (1 = std)
2943 * capability header 39 bytes version triple + flag bytes
2944 * table header 8 bytes group/sub counts
2945 * identity map 980 bytes 245 x (type, type, 1, 0)
2946 * type overrides var entries, terminated by 0
2947 */
2948 proto_tree *caphdr_tree, *ov_tree;
2949 proto_item *caphdr_item, *ov_item;
2950
2951 if ( !is_request )
2952 break;
2953
2954 proto_tree_add_item(data_tree, hf_tns_data_setdt_charset_in, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000);
2955 offset += 2;
2956 proto_tree_add_item(data_tree, hf_tns_data_setdt_charset_out, tvb, offset, 2, ENC_LITTLE_ENDIAN0x80000000);
2957 offset += 2;
2958 proto_tree_add_item(data_tree, hf_tns_data_setdt_flag, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2959 offset += 1;
2960
2961 caphdr_item = proto_tree_add_item(data_tree, hf_tns_data_setdt_caphdr, tvb, offset, 39, ENC_NA0x00000000);
2962 caphdr_tree = proto_item_add_subtree(caphdr_item, ett_tns_setdt_caphdr);
2963 proto_tree_add_item(caphdr_tree, hf_tns_data_setdt_caphdr_version, tvb, offset, 3, ENC_BIG_ENDIAN0x00000000);
2964 proto_tree_add_item(caphdr_tree, hf_tns_data_setdt_caphdr_flags, tvb, offset + 3, 36, ENC_NA0x00000000);
2965 /* The header opens with the length of the client's compile
2966 * capabilities, and capability 7 is the TTC field version.
2967 * The client has already lowered it to the server's, so it
2968 * is the one the connection uses. */
2969 if ( tvb_get_uint8(tvb, offset) > TNS_CCAP_FIELD_VERSION7 )
2970 {
2971 uint8_t fv = tvb_get_uint8(tvb, offset + 1 + TNS_CCAP_FIELD_VERSION7);
2972 proto_tree_add_item(caphdr_tree, hf_tns_data_setdt_field_version, tvb,
2973 offset + 1 + TNS_CCAP_FIELD_VERSION7, 1, ENC_NA0x00000000);
2974 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
2975 tns_get_conv_info(pinfo)->field_version = fv;
2976 }
2977 offset += 39;
2978
2979 proto_tree_add_item(data_tree, hf_tns_data_setdt_tblhdr, tvb, offset, 8, ENC_NA0x00000000);
2980 offset += 8;
2981 proto_tree_add_item(data_tree, hf_tns_data_setdt_idmap, tvb, offset, 980, ENC_NA0x00000000);
2982 offset += 980;
2983
2984 /* Walk type-override entries until the 0 terminator. Each
2985 * entry is (client_type, server_repr[, format]); a 0 in the
2986 * server_repr slot marks a short "client knows the id but
2987 * has no override" entry. */
2988 ov_item = proto_tree_add_item(data_tree, hf_tns_data_setdt_overrides, tvb, offset, -1, ENC_NA0x00000000);
2989 ov_tree = proto_item_add_subtree(ov_item, ett_tns_setdt_overrides);
2990 int ov_start = offset;
2991 while ( tvb_reported_length_remaining(tvb, offset) > 0 )
2992 {
2993 uint8_t client_type = tvb_get_uint8(tvb, offset);
2994 if ( client_type == 0 )
2995 {
2996 proto_tree_add_item(ov_tree, hf_tns_data_setdt_override_client, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
2997 offset += 1;
2998 break;
2999 }
3000 uint8_t repr = tvb_get_uint8(tvb, offset + 1);
3001 int entry_len = (repr == 0) ? 2 : 4;
3002 proto_tree *e_tree = proto_tree_add_subtree_format(ov_tree, tvb, offset, entry_len,
3003 ett_tns_setdt_override, NULL((void*)0), "Type %u (%s)",
3004 client_type, val_to_str_const(client_type, tns_data_types, "unknown"));
3005 proto_tree_add_item(e_tree, hf_tns_data_setdt_override_client, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
3006 if ( entry_len == 4 )
3007 {
3008 proto_tree_add_item(e_tree, hf_tns_data_setdt_override_repr, tvb, offset + 1, 1, ENC_BIG_ENDIAN0x00000000);
3009 proto_tree_add_item(e_tree, hf_tns_data_setdt_override_format, tvb, offset + 2, 1, ENC_BIG_ENDIAN0x00000000);
3010 }
3011 offset += entry_len;
3012 }
3013 proto_item_set_len(ov_item, offset - ov_start);
3014 break;
3015 }
3016
3017 case SQLNET_RETURN_STATUS4:
3018 {
3019 /* TTI_OER: server-side end-of-call status block. Emitted at
3020 * the end of every response — success or failure. Layout
3021 * cross-referenced with python-oracledb's
3022 * _process_error_info, in the Oracle 11g shape (no extended
3023 * ub4 error number / ub8 rowcount that 12c+ adds).
3024 *
3025 * All multi-byte integers are stored in the ub4 variable-
3026 * length form (see get_sb4_custom): first byte holds the
3027 * value's width (0..4), followed by that many big-endian
3028 * data bytes. */
3029 proto_tree *oer_tree;
3030 proto_item *oer_item;
3031 int oer_start = offset;
3032 int v;
3033
3034 oer_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_oer, &oer_item, "Oracle Error Return");
3035
3036 /* call_status */
3037 offset += get_sb4_custom(tvb, offset, &v);
3038 tns_add_call_status_flags(
3039 proto_tree_add_int(oer_tree, hf_tns_data_oer_call_status, tvb, oer_start, offset - oer_start, v),
3040 tvb, oer_start, offset - oer_start, (uint32_t)v);
3041 /* end-to-end seq# (skipped) */
3042 offset += get_sb4_custom(tvb, offset, &v);
3043 /* rowcount (DML affected rows on 11g) */
3044 int rc_start = offset;
3045 offset += get_sb4_custom(tvb, offset, &v);
3046 proto_tree_add_int(oer_tree, hf_tns_data_oer_rowcount, tvb, rc_start, offset - rc_start, v);
3047 /* err_code (ORA-NNNNN, 0 on success) */
3048 int ec_start = offset;
3049 int err_code = 0;
3050 offset += get_sb4_custom(tvb, offset, &err_code);
3051 proto_tree_add_int(oer_tree, hf_tns_data_oer_err_code, tvb, ec_start, offset - ec_start, err_code);
3052 /* array elem error #1, #2 (skipped) */
3053 offset += get_sb4_custom(tvb, offset, &v);
3054 offset += get_sb4_custom(tvb, offset, &v);
3055 /* cursor_id */
3056 int ci_start = offset;
3057 offset += get_sb4_custom(tvb, offset, &v);
3058 proto_tree_add_int(oer_tree, hf_tns_data_oer_cursor_id, tvb, ci_start, offset - ci_start, v);
3059 /* The status of an execute that opened a new cursor names it:
3060 * its bind types now belong to that cursor id. */
3061 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) && v != 0 )
3062 {
3063 tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
3064 if ( tns_info->pending_binds )
3065 {
3066 wmem_map_insert(tns_info->cursor_binds, GUINT_TO_POINTER(v)((gpointer) (gulong) (v)), tns_info->pending_binds);
3067 tns_info->pending_binds = NULL((void*)0);
3068 }
3069 }
3070 /* error position (skipped) */
3071 offset += get_sb4_custom(tvb, offset, &v);
3072 /* 6 single-byte fields: sql_type, fatal, flags, user_cursor_opts, upi_param, warn_flags */
3073 offset += 6;
3074 /* rowid: ub4 rba, ub2 part_id, 1 byte reserved, ub4 block, ub2 slot */
3075 offset += get_sb4_custom(tvb, offset, &v);
3076 offset += get_sb4_custom(tvb, offset, &v);
3077 offset += 1;
3078 offset += get_sb4_custom(tvb, offset, &v);
3079 offset += get_sb4_custom(tvb, offset, &v);
3080 /* os error (skipped) */
3081 offset += get_sb4_custom(tvb, offset, &v);
3082 /* statement #, call # (1 byte each) */
3083 offset += 2;
3084 /* padding ub2 + successful iterations ub4 */
3085 offset += get_sb4_custom(tvb, offset, &v);
3086 offset += get_sb4_custom(tvb, offset, &v);
3087 /* oerrdd (logical rowid), a bytes_with_length — skipped */
3088 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
3089
3090 /* Batch error arrays (array DML). The code and offset arrays
3091 * are each a ub4 count followed by one DALC packing that many
3092 * ub4 values back to back; the message array is a ub4 count,
3093 * an indicator byte, and then that many str_with_length
3094 * entries each with a 2-byte trailer. All three counts are
3095 * zero for an ordinary statement. */
3096 int n_codes = 0, n_offs = 0, n_msgs = 0;
3097 int nb_start = offset;
3098 offset += get_sb4_custom(tvb, offset, &n_codes);
3099 proto_tree_add_int(oer_tree, hf_tns_data_oer_n_batch_errcodes, tvb, nb_start, offset - nb_start, n_codes);
3100 if ( n_codes > 0 )
3101 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
3102 nb_start = offset;
3103 offset += get_sb4_custom(tvb, offset, &n_offs);
3104 proto_tree_add_int(oer_tree, hf_tns_data_oer_n_batch_offsets, tvb, nb_start, offset - nb_start, n_offs);
3105 if ( n_offs > 0 )
3106 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
3107 nb_start = offset;
3108 offset += get_sb4_custom(tvb, offset, &n_msgs);
3109 proto_tree_add_int(oer_tree, hf_tns_data_oer_n_batch_messages, tvb, nb_start, offset - nb_start, n_msgs);
3110 if ( n_msgs > 0 )
3111 {
3112 offset += 1;
3113 for ( int i = 0; i < n_msgs; i++ )
3114 {
3115 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
3116 offset += 2;
3117 }
3118 }
3119
3120 /* From 12.1 the block goes on with the error number and row
3121 * count at their full widths (a ub4 and a ub8), and from 20.1
3122 * with the SQL type and a server checksum. The extended error
3123 * number is the one that says whether a message follows. */
3124 unsigned fv = tns_field_version(pinfo);
3125 if ( fv >= TNS_FV_12_17 )
3126 {
3127 uint64_t rows = 0;
3128 int start = offset;
3129 offset += get_sb4_custom(tvb, offset, &err_code);
3130 proto_tree_add_uint(oer_tree, hf_tns_data_oer_err_num_ext, tvb, start, offset - start, err_code);
3131 start = offset;
3132 offset += get_ub8_custom(tvb, offset, &rows);
3133 proto_tree_add_uint64(oer_tree, hf_tns_data_oer_rowcount_ext, tvb, start, offset - start, rows);
3134 }
3135 if ( fv >= TNS_FV_20_114 )
3136 {
3137 int start = offset;
3138 offset += get_sb4_custom(tvb, offset, &v);
3139 proto_tree_add_uint(oer_tree, hf_tns_data_oer_sql_type, tvb, start, offset - start, v);
3140 start = offset;
3141 offset += get_sb4_custom(tvb, offset, &v);
3142 proto_tree_add_uint(oer_tree, hf_tns_data_oer_checksum, tvb, start, offset - start, v);
3143 }
3144
3145 /* Trailing message DALC — present (and meaningful) only when
3146 * err_code is non-zero. */
3147 if ( err_code != 0 && tvb_reported_length_remaining(tvb, offset) > 0 )
3148 {
3149 const char *msg = NULL((void*)0);
3150 int msg_start = offset;
3151 offset += get_dalc_custom(tvb, pinfo, offset, &msg);
3152 if ( msg )
3153 {
3154 proto_tree_add_string(oer_tree, hf_tns_data_oer_message, tvb, msg_start, offset - msg_start, msg);
3155 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", msg);
3156 }
3157 }
3158 proto_item_set_len(oer_item, offset - oer_start);
3159 /* With the field version known the block ends where it
3160 * should, so an end-of-response marker after it can be read. */
3161 ctx->walk = fv != 0;
3162 break;
3163 }
3164
3165 case SQLNET_FUNCCOMPLETE9:
3166 {
3167 /* TTI_STA: a bare status, with no error block. It answers a
3168 * commit, a rollback or a logoff: a ub4 call status and the
3169 * ub2 end-to-end sequence number. */
3170 int v = 0, start;
3171
3172 if ( is_request )
3173 break;
3174
3175 start = offset;
3176 offset += get_sb4_custom(tvb, offset, &v);
3177 tns_add_call_status_flags(
3178 proto_tree_add_uint(data_tree, hf_tns_data_sta_call_status, tvb, start, offset - start, v),
3179 tvb, start, offset - start, (uint32_t)v);
3180 start = offset;
3181 offset += get_sb4_custom(tvb, offset, &v);
3182 proto_tree_add_uint(data_tree, hf_tns_data_sta_seq, tvb, start, offset - start, v);
3183 ctx->walk = true1;
3184 break;
3185 }
3186
3187 case SQLNET_LOB_FILE_DF14:
3188 {
3189 /* LOB content: what a TTI_LOBOPS READ returns, ahead of the
3190 * return parameters. Raw bytes for a BLOB or BFILE, the LOB's
3191 * character set (usually UTF-16BE) for a CLOB. */
3192 int start = offset;
3193
3194 if ( is_request )
3195 break;
3196
3197 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
3198 if ( tvb_get_uint8(tvb, start) == 0xfe ) /* chunked: shown whole */
3199 proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start, offset - start, ENC_NA0x00000000);
3200 else if ( offset - start > 1 )
3201 proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start + 1, offset - start - 1, ENC_NA0x00000000);
3202 ctx->walk = true1;
3203 break;
3204 }
3205
3206 case SQLNET_WARNING15:
3207 {
3208 /* TTI_WRN: a warning that does not fail the call - PL/SQL
3209 * compiled with errors, say. A ub2 warning number, a ub2
3210 * message length and ub2 flags, then the message itself when
3211 * both are non-zero. */
3212 int code = 0, len = 0, v = 0, start;
3213
3214 if ( is_request )
3215 break;
3216
3217 start = offset;
3218 offset += get_sb4_custom(tvb, offset, &code);
3219 proto_tree_add_uint(data_tree, hf_tns_data_wrn_code, tvb, start, offset - start, code);
3220 start = offset;
3221 offset += get_sb4_custom(tvb, offset, &len);
3222 proto_tree_add_uint(data_tree, hf_tns_data_wrn_length, tvb, start, offset - start, len);
3223 start = offset;
3224 offset += get_sb4_custom(tvb, offset, &v);
3225 proto_tree_add_uint(data_tree, hf_tns_data_wrn_flags, tvb, start, offset - start, v);
3226 if ( code != 0 && len > 0 )
3227 {
3228 const char *msg = NULL((void*)0);
3229 start = offset;
3230 offset += get_dalc_custom(tvb, pinfo, offset, &msg);
3231 if ( msg )
3232 {
3233 proto_tree_add_string(data_tree, hf_tns_data_wrn_message, tvb, start, offset - start, msg);
3234 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", msg);
3235 }
3236 }
3237 ctx->walk = true1;
3238 break;
3239 }
3240
3241 case SQLNET_SERVER_PIGGYBACK23:
3242 {
3243 /* A piggyback from the server: state it pushes to the client
3244 * alongside a reply, selected by an opcode. Layouts follow
3245 * python-oracledb's _process_server_side_piggyback. */
3246 int v = 0, num = 0, start;
3247 uint8_t opcode;
3248
3249 if ( is_request )
3250 break;
3251
3252 proto_tree_add_item_ret_uint8(data_tree, hf_tns_data_spb_opcode, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &opcode);
3253 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3254 val_to_str_const(opcode, tns_spb_opcodes, "unknown"));
3255 offset += 1;
3256 switch ( opcode )
3257 {
3258 case TNS_SPB_QUERY_CACHE_INVALIDATION1:
3259 case TNS_SPB_TRACE_EVENT3:
3260 break;
3261 case TNS_SPB_LTXID7:
3262 offset += get_sb4_custom(tvb, offset, &v);
3263 if ( v > 0 )
3264 {
3265 start = offset;
3266 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
3267 proto_tree_add_item(data_tree, hf_tns_data_spb_ltxid, tvb, start + 1, offset - start - 1, ENC_NA0x00000000);
3268 }
3269 break;
3270 case TNS_SPB_OS_PID_MTS2:
3271 {
3272 const char *pid = NULL((void*)0);
3273 offset += get_sb4_custom(tvb, offset, &v);
3274 start = offset;
3275 offset += get_dalc_custom(tvb, pinfo, offset, &pid);
3276 if ( pid )
3277 proto_tree_add_string(data_tree, hf_tns_data_spb_os_pid, tvb, start, offset - start, pid);
3278 break;
3279 }
3280 case TNS_SPB_SYNC5:
3281 /* Session state the statement changed - a new current
3282 * schema, edition or NLS setting - as key/value pairs. */
3283 offset += get_sb4_custom(tvb, offset, &v); /* number of DTYs */
3284 offset += 1; /* length of DTYs */
3285 start = offset;
3286 offset += get_sb4_custom(tvb, offset, &num);
3287 proto_tree_add_uint(data_tree, hf_tns_data_spb_num_kv, tvb, start, offset - start, num);
3288 offset += 1; /* length */
3289 offset = dissect_tns_kv_pairs(tvb, pinfo, data_tree, offset, num);
3290 start = offset;
3291 offset += get_sb4_custom(tvb, offset, &v);
3292 proto_tree_add_uint(data_tree, hf_tns_data_spb_flags, tvb, start, offset - start, v);
3293 break;
3294 case TNS_SPB_EXT_SYNC9:
3295 offset += get_sb4_custom(tvb, offset, &v); /* number of DTYs */
3296 offset += 1; /* length of DTYs */
3297 break;
3298 case TNS_SPB_AC_REPLAY_CONTEXT8:
3299 offset += get_sb4_custom(tvb, offset, &v); /* number of DTYs */
3300 offset += 1; /* length of DTYs */
3301 offset += get_sb4_custom(tvb, offset, &v); /* flags */
3302 offset += get_sb4_custom(tvb, offset, &v); /* error code */
3303 offset += 1; /* queue */
3304 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0)); /* replay context */
3305 break;
3306 case TNS_SPB_SESS_RET4:
3307 offset += get_sb4_custom(tvb, offset, &v); /* number of DTYs */
3308 offset += 1; /* length of DTYs */
3309 offset += get_sb4_custom(tvb, offset, &num);
3310 if ( num > 0 )
3311 {
3312 offset += 1;
3313 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3314 {
3315 offset += get_sb4_custom(tvb, offset, &v); /* key */
3316 if ( v > 0 )
3317 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
3318 offset += get_sb4_custom(tvb, offset, &v); /* value */
3319 if ( v > 0 )
3320 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
3321 offset += get_sb4_custom(tvb, offset, &v); /* flags */
3322 }
3323 }
3324 start = offset;
3325 offset += get_sb4_custom(tvb, offset, &v);
3326 proto_tree_add_uint(data_tree, hf_tns_data_spb_flags, tvb, start, offset - start, v);
3327 start = offset;
3328 offset += get_sb4_custom(tvb, offset, &v);
3329 proto_tree_add_uint(data_tree, hf_tns_data_spb_session_id, tvb, start, offset - start, v);
3330 start = offset;
3331 offset += get_sb4_custom(tvb, offset, &v);
3332 proto_tree_add_uint(data_tree, hf_tns_data_spb_serial_num, tvb, start, offset - start, v);
3333 break;
3334 case TNS_SPB_SESS_SIGNATURE10:
3335 {
3336 uint64_t u = 0;
3337 offset += get_sb4_custom(tvb, offset, &v); /* number of DTYs */
3338 offset += 1; /* length of DTYs */
3339 offset += get_ub8_custom(tvb, offset, &u); /* signature flags */
3340 offset += get_ub8_custom(tvb, offset, &u); /* client signature */
3341 offset += get_ub8_custom(tvb, offset, &u); /* server signature */
3342 break;
3343 }
3344 default:
3345 /* Unknown opcode: its length is unknown too. */
3346 return offset;
3347 }
3348 ctx->walk = true1;
3349 break;
3350 }
3351
3352 case SQLNET_IMPLICIT_RESULTS27:
3353 {
3354 /* The result sets a PL/SQL block returned with
3355 * DBMS_SQL.RETURN_RESULT: a ub4 count, then per result a
3356 * length-prefixed opaque blob, the describe of its columns,
3357 * and the ub2 cursor id the client fetches it with. */
3358 int num = 0, start;
3359
3360 if ( is_request )
3361 break;
3362
3363 start = offset;
3364 offset += get_sb4_custom(tvb, offset, &num);
3365 proto_tree_add_uint(data_tree, hf_tns_data_irs_num_results, tvb, start, offset - start, num);
3366 for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3367 {
3368 proto_tree *rs_tree;
3369 proto_item *rs_item;
3370 int rs_start = offset, cursor = 0;
3371
3372 rs_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, -1,
3373 ett_tns_irs, &rs_item, "Result Set %d", i + 1);
3374 offset += 1 + tvb_get_uint8(tvb, offset);
3375 offset = dissect_tns_describe_body(tvb, pinfo, rs_tree, offset, NULL((void*)0));
3376 start = offset;
3377 offset += get_sb4_custom(tvb, offset, &cursor);
3378 proto_tree_add_uint(rs_tree, hf_tns_cursor, tvb, start, offset - start, cursor);
3379 proto_item_append_text(rs_item, ": cursor %d", cursor);
3380 proto_item_set_len(rs_item, offset - rs_start);
3381 }
3382 ctx->walk = true1;
3383 break;
3384 }
3385
3386 case SQLNET_TOKEN33:
3387 {
3388 /* the token of the call this answers */
3389 uint64_t token = 0;
3390 int start = offset;
3391
3392 if ( is_request )
3393 break;
3394 offset += get_ub8_custom(tvb, offset, &token);
3395 proto_tree_add_uint64(data_tree, hf_tns_data_token, tvb, start, offset - start, token);
3396 ctx->walk = true1;
3397 break;
3398 }
3399
3400 case SQLNET_END_OF_RESPONSE29:
3401 /* Marks the end of a response for a client that negotiated
3402 * it; there is no body. */
3403 ctx->walk = true1;
3404 break;
3405
3406 case SQLNET_IOVEC_4FAST_UPI11:
3407 {
3408 /* TTI_IOV: the server's I/O vector for an executed anonymous
3409 * PL/SQL block that carried bind variables. It lists each
3410 * bind's direction (IN / OUT / IN OUT); when any bind is
3411 * OUT / IN OUT the returned values follow as a TTI_RXD row.
3412 * Layout cross-referenced with python-oracledb's
3413 * _process_io_vector, and
3414 * verified against XE 11g.
3415 *
3416 * All the leading counters are stored in the ub4 variable-
3417 * length form (see get_sb4_custom). The per-bind directions
3418 * are one raw byte each. The trailing RXD values need each
3419 * bind's declared type to decode, so they are read only when
3420 * the execute this answers was seen. */
3421 int num_requests = 0, num_iters = 0, v = 0, bv_len = 0, rid_len = 0;
3422
3423 if ( !is_request )
3424 {
3425 /* flag (ub1, skip) */
3426 offset += 1;
3427 offset += get_sb4_custom(tvb, offset, &num_requests);
3428 offset += get_sb4_custom(tvb, offset, &num_iters);
3429 int num_binds = num_iters * 256 + num_requests;
3430 proto_tree_add_uint(data_tree, hf_tns_data_iov_num_binds, tvb, offset, 0, num_binds);
3431 /* num iters this time (skip) */
3432 offset += get_sb4_custom(tvb, offset, &v);
3433 /* uac buffer length (skip) */
3434 offset += get_sb4_custom(tvb, offset, &v);
3435 /* fast-fetch bit-vector: length + bytes (skip) */
3436 offset += get_sb4_custom(tvb, offset, &bv_len);
3437 if ( bv_len > 0 )
3438 offset += bv_len;
3439 /* rowid: length + bytes (skip) */
3440 offset += get_sb4_custom(tvb, offset, &rid_len);
3441 if ( rid_len > 0 )
3442 offset += rid_len;
3443
3444 /* Per-bind direction bytes, in bind order. Bound by both
3445 * the reported count and the bytes actually present so a
3446 * malformed vector cannot run away. */
3447 proto_tree *iov_tree;
3448 proto_item *iov_item;
3449 int iov_start = offset;
3450 iov_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_iov, &iov_item, "Bind Directions");
3451 for ( int i = 0; i < num_binds && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3452 {
3453 proto_tree_add_item(iov_tree, hf_tns_data_iov_bind_dir, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
3454 offset += 1;
3455 }
3456 proto_item_set_len(iov_item, offset - iov_start);
3457
3458 /* The OUT and IN OUT values follow as a TTI_RXD, typed by
3459 * the binds of the execute this answers - readable only
3460 * when that execute was seen and bound as many. */
3461 const tns_call_t *call = tns_answered_call(pinfo);
3462 if ( call && call->binds && call->num_binds == (uint32_t)num_binds
3463 && offset - iov_start == num_binds )
3464 {
3465 ctx->out_call = call;
3466 ctx->bind_dirs = tvb_memdup(pinfo->pool, tvb, iov_start, num_binds);
3467 ctx->walk = true1;
3468 }
3469 }
3470 break;
3471 }
3472
3473 case SQLNET_DESCRIBE_INFO16:
3474 {
3475 /* TTI_DCB: describe (column metadata) for a SELECT result set,
3476 * in the Oracle 11g shape: a preamble, then the describe body.
3477 * The columns are remembered, once, so a later TTI_RXD can
3478 * split its row values. */
3479 tns_describe_t *desc = NULL((void*)0);
3480
3481 if ( is_request )
3482 break;
3483
3484 /* describe-info preamble (chunked bytes: cursor uuid + date) */
3485 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
3486 offset = dissect_tns_describe_body(tvb, pinfo, data_tree, offset,
3487 PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) ? NULL((void*)0) : &desc);
3488 if ( desc )
3489 tns_get_conv_info(pinfo)->last_describe = desc;
3490 ctx->walk = true1;
3491 break;
3492 }
3493
3494 case SQLNET_ROW_TRANSF_HDR6:
3495 {
3496 /* TTI_RXH: row transfer header, precedes the row data in a
3497 * SELECT response. All numeric fields use the ub4 variable-
3498 * length form. Layout cross-referenced with
3499 * python-oracledb's _process_row_header. */
3500 int v = 0, bv_len = 0, start;
3501
3502 if ( is_request )
3503 break;
3504
3505 /* flag (ub1, skip) */
3506 offset += 1;
3507 /* number of requests */
3508 start = offset;
3509 offset += get_sb4_custom(tvb, offset, &v);
3510 proto_tree_add_uint(data_tree, hf_tns_data_rxh_num_requests, tvb, start, offset - start, v);
3511 /* iteration number */
3512 start = offset;
3513 offset += get_sb4_custom(tvb, offset, &v);
3514 proto_tree_add_uint(data_tree, hf_tns_data_rxh_iter_num, tvb, start, offset - start, v);
3515 /* number of iterations */
3516 start = offset;
3517 offset += get_sb4_custom(tvb, offset, &v);
3518 proto_tree_add_uint(data_tree, hf_tns_data_rxh_num_iters, tvb, start, offset - start, v);
3519 /* buffer length (ub4, skip) */
3520 offset += get_sb4_custom(tvb, offset, &v);
3521 /* bit vector: length + [repeated length byte + vector bytes],
3522 * saying which columns the first row sends */
3523 offset += get_sb4_custom(tvb, offset, &bv_len);
3524 if ( bv_len > 0 )
3525 {
3526 offset += 1; /* repeated length byte */
3527 proto_tree_add_item(data_tree, hf_tns_data_bit_vector, tvb, offset, bv_len, ENC_NA0x00000000);
3528 ctx->bit_vector = tvb_memdup(pinfo->pool, tvb, offset, bv_len);
3529 ctx->bit_vector_len = bv_len;
3530 offset += bv_len; /* bit vector */
3531 }
3532 /* rxhrid (bytes_with_length, skip) */
3533 offset += get_field_with_length(tvb, pinfo, offset, NULL((void*)0));
3534 ctx->walk = true1;
3535 break;
3536 }
3537
3538 case SQLNET_BIT_VECTOR21:
3539 {
3540 /* TTI_BVC: which columns the next row sends. A row that
3541 * repeats values from the row before sends only the ones that
3542 * changed, and the clear bits name those it left out. A ub2
3543 * count of columns sent, then one bit per described column. */
3544 tns_describe_t *desc;
3545 int v = 0, start;
3546
3547 if ( is_request )
3548 break;
3549
3550 start = offset;
3551 offset += get_sb4_custom(tvb, offset, &v);
3552 proto_tree_add_uint(data_tree, hf_tns_data_bvc_num_cols_sent, tvb, start, offset - start, v);
3553 desc = tns_current_describe(pinfo);
3554 if ( !desc )
3555 break;
3556 unsigned bv_len = (desc->num_cols + 7) / 8;
3557 proto_tree_add_item(data_tree, hf_tns_data_bit_vector, tvb, offset, bv_len, ENC_NA0x00000000);
3558 ctx->bit_vector = tvb_memdup(pinfo->pool, tvb, offset, bv_len);
3559 ctx->bit_vector_len = bv_len;
3560 offset += bv_len;
3561 ctx->walk = true1;
3562 break;
3563 }
3564
3565 case SQLNET_ROW_TRANSF_DATA7:
3566 {
3567 /* TTI_RXD: row data for a SELECT result set — typically a
3568 * TTI_FETCH continuation, where the describe (TTI_DCB) arrived
3569 * in an earlier packet. Split each row into columns using the
3570 * types remembered from that describe (threaded through
3571 * conversation state); ordinary values are shown raw.
3572 *
3573 * The leading RXD token was already consumed above, so offset
3574 * sits on the first row's first value. A row that follows a
3575 * bit vector sends only the columns whose bit is set. */
3576 tns_describe_t *desc;
3577
3578 if ( is_request )
3579 break;
3580
3581 if ( ctx->bind_dirs )
3582 {
3583 /* The OUT and IN OUT bind values of a PL/SQL execute, in
3584 * bind order, each followed by its sb4 return code. Out of
3585 * a fetch, ROWID and UROWID come as strings and a LONG has
3586 * no trailing indicators. */
3587 proto_tree *ob_tree;
3588 proto_item *ob_item;
3589 int ob_start = offset, rc = 0, start;
3590
3591 ob_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
3592 ett_tns_out_binds, &ob_item, "Out Binds");
3593 for ( uint32_t i = 0; i < ctx->out_call->num_binds
3594 && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3595 {
3596 uint8_t btype = ctx->out_call->binds[i].type;
3597 if ( ctx->bind_dirs[i] == TNS_BIND_DIR_INPUT32 )
3598 continue;
3599 if ( btype == TNS_DATATYPE_ROWID11 || btype == TNS_DATATYPE_UROWID208
3600 || btype == TNS_DATATYPE_LONG8 )
3601 btype = TNS_DATATYPE_VARCHAR1;
3602 else if ( btype == TNS_DATATYPE_LONG_RAW24 )
3603 btype = TNS_DATATYPE_RAW23;
3604 offset = dissect_tns_value(tvb, pinfo, ob_tree, offset, btype,
3605 ctx->out_call->binds[i].csform, i + 1,
3606 hf_tns_data_bind_value, "Bind");
3607 start = offset;
3608 offset += get_sb4_custom(tvb, offset, &rc);
3609 proto_tree_add_int(ob_tree, hf_tns_data_bind_retcode, tvb, start, offset - start, rc);
3610 }
3611 proto_item_set_len(ob_item, offset - ob_start);
3612 ctx->bind_dirs = NULL((void*)0);
3613 ctx->walk = true1;
3614 break;
3615 }
3616
3617 const tns_call_t *rcall = tns_answered_call(pinfo);
3618 if ( rcall && rcall->num_return > 0 && rcall->binds )
3619 {
3620 /* The values a DML RETURNING ... INTO returned: for each
3621 * return bind a ub4 row count - every row the statement
3622 * touched - then that many values, each followed by its
3623 * sb4 return code. */
3624 proto_tree *rv_tree;
3625 proto_item *rv_item;
3626 int rv_start = offset, rc = 0, start;
3627
3628 rv_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
3629 ett_tns_out_binds, &rv_item, "Returned Values");
3630 for ( uint32_t i = rcall->num_binds - rcall->num_return; i < rcall->num_binds
3631 && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3632 {
3633 int rows = 0;
3634 offset += get_sb4_custom(tvb, offset, &rows);
3635 for ( int j = 0; j < rows && tvb_reported_length_remaining(tvb, offset) > 0; j++ )
3636 {
3637 offset = dissect_tns_value(tvb, pinfo, rv_tree, offset, rcall->binds[i].type,
3638 rcall->binds[i].csform, i + 1, hf_tns_data_bind_value, "Bind");
3639 start = offset;
3640 offset += get_sb4_custom(tvb, offset, &rc);
3641 proto_tree_add_int(rv_tree, hf_tns_data_bind_retcode, tvb, start, offset - start, rc);
3642 }
3643 }
3644 proto_item_set_len(rv_item, offset - rv_start);
3645 ctx->walk = true1;
3646 break;
3647 }
3648
3649 desc = tns_current_describe(pinfo);
3650
3651 if ( desc && desc->num_cols > 0 )
3652 {
3653 int rownum = 0, first_row = 1;
3654 while ( tvb_reported_length_remaining(tvb, offset) > 0 )
3655 {
3656 proto_tree *row_tree;
3657 proto_item *row_item;
3658 int r_start;
3659
3660 if ( !first_row )
3661 {
3662 if ( tvb_get_uint8(tvb, offset) != SQLNET_ROW_TRANSF_DATA7 )
3663 break;
3664 offset += 1; /* RXD token for subsequent rows */
3665 }
3666 first_row = 0;
3667
3668 r_start = offset;
3669 row_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, -1,
3670 ett_tns_rxd_row, &row_item, "Row %d", ++rownum);
3671 for ( uint32_t c = 0; c < desc->num_cols
3672 && tvb_reported_length_remaining(tvb, offset) > 0; c++ )
3673 {
3674 const tns_column_t *col = &desc->cols[c];
3675 if ( ctx->bit_vector && c / 8 < ctx->bit_vector_len
3676 && !(ctx->bit_vector[c / 8] & (1 << (c % 8))) )
3677 {
3678 proto_tree_add_bytes_format(row_tree, hf_tns_data_col_value,
3679 tvb, offset, 0, NULL((void*)0), "Column %u (%s): same as previous row",
3680 c + 1, val_to_str_const(col->type, tns_data_types, "unknown"));
3681 continue;
3682 }
3683 /* A column the describe gives no data length is
3684 * NULL by definition (SELECT NULL, SELECT '')
3685 * and sends no bytes at all - not even an empty
3686 * DALC. LONG, LONG RAW and UROWID are the
3687 * exceptions: they always carry their value. */
3688 if ( col->data_len == 0 && col->type != TNS_DATATYPE_LONG8
3689 && col->type != TNS_DATATYPE_LONG_RAW24
3690 && col->type != TNS_DATATYPE_UROWID208 )
3691 {
3692 proto_tree_add_bytes_format(row_tree, hf_tns_data_col_value,
3693 tvb, offset, 0, NULL((void*)0), "Column %u (%s): NULL (no data length)",
3694 c + 1, val_to_str_const(col->type, tns_data_types, "unknown"));
3695 continue;
3696 }
3697 offset = dissect_tns_value(tvb, pinfo, row_tree, offset,
3698 col->type, col->csform, c + 1, hf_tns_data_col_value, "Column");
3699 }
3700 proto_item_set_len(row_item, offset - r_start);
3701 /* A bit vector covers one row only. */
3702 ctx->bit_vector = NULL((void*)0);
3703 }
3704 ctx->walk = true1;
3705 }
3706 break;
3707 }
3708
3709 case SQLNET_USER_OCI_FUNC3:
3710 {
3711 guint32 oci_id = 0;
3712 tns_call_t *call;
3713 int fun_start = offset - 1; /* the TTI_FUN byte */
3714 proto_tree_add_item_ret_uint(data_tree, hf_tns_data_oci_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000, &oci_id);
3715 offset += 1;
3716 call = is_request ? tns_remember_call(pinfo, (uint8_t)oci_id) : NULL((void*)0);
3717 /* Name the specific OCI call in the Info column — otherwise every
3718 * function call reads only as the generic "User OCI Functions". */
3719 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
3720 val_to_str_ext_const(oci_id, &tns_data_oci_subfuncs_ext, "unknown"));
3721 proto_tree_add_item(data_tree, hf_tns_data_tseq, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
3722 offset += 1;
3723 offset = dissect_tns_call_token(tvb, pinfo, data_tree, offset);
3724 if((oci_id == 115) || (oci_id == 118)){
3725 proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 1, ENC_NA0x00000000);
3726 offset += 1;
3727 int user_len = 0;
3728 offset += get_sb4_custom(tvb, offset, &user_len);
3729 }
3730 else if ( oci_id == TTI_FETCH5 )
3731 {
3732 /* TTI_FETCH: fetch more rows from an open cursor.
3733 * [TTI_FUN, TTI_FETCH, seq] then cursor id and the row
3734 * count, both ub4. */
3735 int v = 0, start;
3736
3737 start = offset;
3738 offset += get_sb4_custom(tvb, offset, &v);
3739 proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, start, offset - start, v);
3740 start = offset;
3741 offset += get_sb4_custom(tvb, offset, &v);
3742 proto_tree_add_uint(data_tree, hf_tns_data_fetch_rows, tvb, start, offset - start, v);
3743 }
3744 else if ( oci_id == TTI_REEXECUTE4 || oci_id == TTI_REEXECUTE_AND_FETCH78 )
3745 {
3746 /* Re-execute of a cursor whose statement already ran and
3747 * whose bind types did not change: the cursor id, the
3748 * iteration count (the prefetch size for 78, the number
3749 * of executions for 4) and two options words, then one
3750 * TTI_RXD row of values per iteration with no bind
3751 * descriptors - the values are typed by the execute that
3752 * opened the cursor. */
3753 int v = 0, cursor = 0, start;
3754
3755 start = offset;
3756 offset += get_sb4_custom(tvb, offset, &cursor);
3757 proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, start, offset - start, cursor);
3758 start = offset;
3759 offset += get_sb4_custom(tvb, offset, &v);
3760 proto_tree_add_uint(data_tree, oci_id == TTI_REEXECUTE_AND_FETCH78 ?
3761 hf_tns_data_all8_prefetch : hf_tns_data_reexec_iterations,
3762 tvb, start, offset - start, v);
3763 start = offset;
3764 offset += get_sb4_custom(tvb, offset, &v);
3765 proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_all8_options,
3766 ett_tns_all8_options, tns_all8_options, (uint64_t)(uint32_t)v);
3767 start = offset;
3768 offset += get_sb4_custom(tvb, offset, &v);
3769 proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_reexec_options2,
3770 ett_tns_reexec_options2, tns_reexec_options2, (uint64_t)(uint32_t)v);
3771
3772 tns_binds_t *binds = tns_lookup_cursor_binds(pinfo, cursor);
3773 if ( binds && tvb_reported_length_remaining(tvb, offset) > 0 )
3774 {
3775 proto_item *binds_item;
3776 proto_tree *binds_tree;
3777 int binds_start = offset;
3778
3779 binds_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
3780 ett_tns_binds, &binds_item, "Binds");
3781 /* RETURNING ... INTO binds send no value */
3782 offset = dissect_tns_bind_rows(tvb, pinfo, binds_tree, offset, binds->cols,
3783 binds->count - binds->num_return);
3784 proto_item_set_len(binds_item, offset - binds_start);
3785 }
3786 if ( call && binds )
3787 {
3788 call->num_binds = binds->count;
3789 call->num_return = binds->num_return;
3790 call->binds = binds->cols;
3791 }
3792 }
3793 else if ( oci_id == TTI_ALL894 && tvb_bytes_exist(tvb, fun_start + TNS_OCI_ALL8_IND11, 8)
3794 && tvb_get_ntoh64(tvb, fun_start + TNS_OCI_ALL8_IND11) == TNS_OCI_INDICATOR0xfeffffffffffffffUL )
3795 {
3796 /* An OCI client's execute (sqlplus and other thick
3797 * clients): a fixed preamble of 8-byte pointer indicators
3798 * FE FF FF FF FF FF FF FF with little-endian scalar slots
3799 * between them, and the ub1-length-prefixed SQL at the
3800 * end. Offsets count from the TTI_FUN byte. The scalar
3801 * slots are 8 bytes wide or 4, fixed for a connection;
3802 * the second indicator tells which - it sits at 27 in the
3803 * wide form and 23 in the narrow one, and the two cannot
3804 * both hold. The cursor id and SQL length precede every
3805 * slot and do not move; the bind count and the SQL do. */
3806 int base = fun_start, bind_count_off, sql_off;
3807 uint32_t cursor, sql_len, bind_count;
3808 bool_Bool wide;
3809
3810 if ( tvb_bytes_exist(tvb, base + TNS_OCI_ALL8_IND2_WIDE27, 8)
3811 && tvb_get_ntoh64(tvb, base + TNS_OCI_ALL8_IND2_WIDE27) == TNS_OCI_INDICATOR0xfeffffffffffffffUL )
3812 wide = true1;
3813 else if ( tvb_bytes_exist(tvb, base + TNS_OCI_ALL8_IND2_NARROW23, 8)
3814 && tvb_get_ntoh64(tvb, base + TNS_OCI_ALL8_IND2_NARROW23) == TNS_OCI_INDICATOR0xfeffffffffffffffUL )
3815 wide = false0;
3816 else
3817 break;
3818 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
3819 tns_get_conv_info(pinfo)->oci_dialect = true1;
3820
3821 proto_tree_add_string(data_tree, hf_tns_data_all8_oci_preamble, tvb, base, 0,
3822 wide ? "OCI, wide (8-byte slots)" : "OCI, narrow (4-byte slots)");
3823 cursor = tvb_get_letohl(tvb, base + TNS_OCI_ALL8_CURSOR7);
3824 proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, base + TNS_OCI_ALL8_CURSOR7, 4, cursor);
3825 /* three times the SQL length */
3826 sql_len = tvb_get_letohl(tvb, base + TNS_OCI_ALL8_SQLLEN319) / 3;
3827 bind_count_off = base + (wide ? 83 : 71);
3828 sql_off = base + (wide ? 196 : 176);
3829 bind_count = tvb_get_letohl(tvb, bind_count_off);
3830 proto_tree_add_uint(data_tree, hf_tns_data_all8_bind_count, tvb, bind_count_off, 4, bind_count);
3831 if ( sql_len > 0 && tvb_bytes_exist(tvb, sql_off - 1, 1) )
3832 {
3833 const char *sql = NULL((void*)0);
3834 int start = sql_off - 1;
3835 uint8_t prefix = tvb_get_uint8(tvb, start);
3836
3837 if ( prefix == 0xfe || prefix == sql_len )
3838 {
3839 offset = start + get_dalc_custom(tvb, pinfo, start, &sql);
3840 if ( sql )
3841 {
3842 /* sqlplus NUL-terminates its own queries; the
3843 * string ends there */
3844 proto_tree_add_string(data_tree, hf_tns_data_all8_sql, tvb, start, offset - start, sql);
3845 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", sql);
3846 }
3847 }
3848 }
3849 }
3850 else if ( oci_id == TTI_ALL894 )
3851 {
3852 /* TTI_ALL8: the generic SQL execute — SELECT, DML and
3853 * PL/SQL all ride this call, in the Oracle 11g shape of a
3854 * thin client, whose integers use the ub4 variable-length
3855 * form. The bind (or define) descriptors and the value
3856 * rows follow the al8 array. */
3857 int v = 0, options = 0, cursor = 0, query_len = 0, all8_len = 0;
3858 int fetch = 0, bind_count = 0, define_count = 0, start;
3859 const uint8_t *sql = NULL((void*)0);
3860 uint8_t query_flag;
3861
3862 /* options (ub4) + flag breakdown */
3863 start = offset;
3864 offset += get_sb4_custom(tvb, offset, &options);
3865 proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_all8_options,
3866 ett_tns_all8_options, tns_all8_options, (uint64_t)(uint32_t)options);
3867 /* cursor id (ub4) */
3868 start = offset;
3869 offset += get_sb4_custom(tvb, offset, &cursor);
3870 proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, start, offset - start, cursor);
3871 /* query present flag (ub1) */
3872 query_flag = tvb_get_uint8(tvb, offset);
3873 offset += 1;
3874 /* query length (ub4) */
3875 offset += get_sb4_custom(tvb, offset, &query_len);
3876 /* all8 present flag (ub1) */
3877 offset += 1;
3878 /* all8 length (ub4) */
3879 offset += get_sb4_custom(tvb, offset, &all8_len);
3880 /* two reserved bytes */
3881 offset += 2;
3882 /* long max value (ub4, skip) */
3883 offset += get_sb4_custom(tvb, offset, &v);
3884 /* fetch rows (ub4) */
3885 start = offset;
3886 offset += get_sb4_custom(tvb, offset, &fetch);
3887 proto_tree_add_uint(data_tree, hf_tns_data_all8_fetch_rows, tvb, start, offset - start, fetch);
3888 /* max value (ub4, skip) */
3889 offset += get_sb4_custom(tvb, offset, &v);
3890 /* bind indicator (ub1) */
3891 offset += 1;
3892 /* bind count (ub4) */
3893 start = offset;
3894 offset += get_sb4_custom(tvb, offset, &bind_count);
3895 proto_tree_add_uint(data_tree, hf_tns_data_all8_bind_count, tvb, start, offset - start, bind_count);
3896 /* The count comes off the wire and sizes an allocation
3897 * further down, so a count larger than the data left
3898 * cannot be real - report it and decode no binds. */
3899 if ( bind_count < 0 ||
3900 (unsigned)bind_count > tvb_reported_length_remaining(tvb, offset) )
3901 {
3902 proto_tree_add_expert(data_tree, pinfo, &ei_tns_data_count_too_large,
3903 tvb, start, offset - start);
3904 bind_count = 0;
3905 }
3906 /* five reserved bytes */
3907 offset += 5;
3908 /* define-columns present flag (ub1) */
3909 offset += 1;
3910 /* define-columns count (ub4) */
3911 start = offset;
3912 offset += get_sb4_custom(tvb, offset, &define_count);
3913 proto_tree_add_uint(data_tree, hf_tns_data_all8_define_count, tvb, start, offset - start, define_count);
3914 if ( define_count < 0 ||
3915 (unsigned)define_count > tvb_reported_length_remaining(tvb, offset) )
3916 {
3917 proto_tree_add_expert(data_tree, pinfo, &ei_tns_data_count_too_large,
3918 tvb, start, offset - start);
3919 define_count = 0;
3920 }
3921 /* registration id (low half), the al8objlist / al8objlen /
3922 * al8blv pointers, al8blvl, the al8dnam pointer, al8dnaml
3923 * and the registration id's high half */
3924 offset += get_sb4_custom(tvb, offset, &v);
3925 offset += 3;
3926 offset += get_sb4_custom(tvb, offset, &v);
3927 offset += 1;
3928 offset += get_sb4_custom(tvb, offset, &v);
3929 offset += get_sb4_custom(tvb, offset, &v);
3930 /* 12.1 adds the per-row DML count block (a pointer, the
3931 * execution count, a pointer), 12.2 the SQL signature and
3932 * SQL id fields, 12.2 ext 1 the chunk ids */
3933 unsigned fv = tns_field_version(pinfo);
3934 if ( fv >= TNS_FV_12_17 )
3935 {
3936 offset += 1;
3937 offset += get_sb4_custom(tvb, offset, &v);
3938 offset += 1;
3939 }
3940 if ( fv >= TNS_FV_12_28 )
3941 {
3942 offset += 1;
3943 offset += get_sb4_custom(tvb, offset, &v);
3944 offset += 1;
3945 offset += get_sb4_custom(tvb, offset, &v);
3946 offset += 1;
3947 }
3948 if ( fv >= TNS_FV_12_2_EXT19 )
3949 {
3950 offset += 1;
3951 offset += get_sb4_custom(tvb, offset, &v);
3952 }
3953 /* SQL text: a flat run of query_len bytes on 11g, length
3954 * prefixed (and chunked when long) from 12.1 */
3955 if ( query_flag && query_len > 0 && fv >= TNS_FV_12_17 )
3956 {
3957 const char *text = NULL((void*)0);
3958 start = offset;
3959 offset += get_dalc_custom(tvb, pinfo, offset, &text);
3960 if ( text )
3961 {
3962 sql = (const uint8_t *)text;
3963 proto_tree_add_string(data_tree, hf_tns_data_all8_sql, tvb, start, offset - start, text);
3964 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", text);
3965 }
3966 }
3967 else if ( query_flag && query_len > 0 )
3968 {
3969 proto_tree_add_item_ret_string(data_tree, hf_tns_data_all8_sql, tvb,
3970 offset, query_len, ENC_UTF_80x00000002|ENC_NA0x00000000, pinfo->pool, &sql);
3971 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", sql);
3972 offset += query_len;
3973 }
3974 /* al8i4 option array: all8_len ub4 elements. Slot 1 is
3975 * the execution count for DML but the number of rows to
3976 * prefetch for a query, and slot 7 says which - so read
3977 * the array before showing any of it. */
3978 {
3979 int al8i4[13] = {0}, al8i4_start[13] = {0}, al8i4_len[13] = {0};
3980 int i4_start = offset;
3981 proto_tree *i4_tree;
3982 proto_item *i4_item;
3983
3984 for ( int i = 0; i < all8_len && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3985 {
3986 start = offset;
3987 offset += get_sb4_custom(tvb, offset, &v);
3988 if ( i < (int)array_length(al8i4)(sizeof (al8i4) / sizeof (al8i4)[0]) )
3989 {
3990 al8i4[i] = v;
3991 al8i4_start[i] = start;
3992 al8i4_len[i] = offset - start;
3993 }
3994 }
3995 if ( all8_len >= (int)array_length(al8i4)(sizeof (al8i4) / sizeof (al8i4)[0]) )
3996 {
3997 i4_tree = proto_tree_add_subtree(data_tree, tvb, i4_start, offset - i4_start,
3998 ett_tns_all8_i4, &i4_item, "Execute Arguments (al8i4)");
3999 proto_tree_add_uint(i4_tree, al8i4[7] ? hf_tns_data_all8_prefetch : hf_tns_data_all8_iterations,
4000 tvb, al8i4_start[1], al8i4_len[1], al8i4[1]);
4001 proto_tree_add_boolean(i4_tree, hf_tns_data_all8_is_query,
4002 tvb, al8i4_start[7], al8i4_len[7], al8i4[7]);
4003 proto_tree_add_bitmask_value(i4_tree, tvb, al8i4_start[9], hf_tns_data_all8_exec_flags,
4004 ett_tns_all8_exec_flags, tns_all8_exec_flags, (uint64_t)(uint32_t)al8i4[9]);
4005 proto_tree_add_uint(i4_tree, hf_tns_data_all8_fetch_orientation,
4006 tvb, al8i4_start[10], al8i4_len[10], al8i4[10]);
4007 proto_tree_add_uint(i4_tree, hf_tns_data_all8_fetch_pos,
4008 tvb, al8i4_start[11], al8i4_len[11], al8i4[11]);
4009 if ( call )
4010 call->exec_flags = (uint32_t)al8i4[9];
4011 }
4012 }
4013
4014 /* Bind section: one bare OAC descriptor per bind column,
4015 * then one TTI_RXD row of values per iteration. A cached
4016 * re-execute may leave the descriptors out and rely on
4017 * the ones the cursor was opened with. Whether they are
4018 * there is decided by the wire, not by the SQL text: an
4019 * execute with no SQL often still carries them (every
4020 * executemany after the first), and they are absent
4021 * exactly when the bind area starts on a TTI_RXD, in
4022 * which case the types remembered for the cursor apply.
4023 *
4024 * An execute that opens a new cursor (cursor id 0) learns
4025 * its id only from the status that answers it, so its
4026 * bind types wait for that. */
4027 tns_conv_info_t *tns_info = NULL((void*)0);
4028 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
4029 {
4030 tns_info = tns_get_conv_info(pinfo);
4031 if ( cursor == 0 )
4032 tns_info->pending_binds = NULL((void*)0);
4033 }
4034 if ( bind_count > 0 && tvb_reported_length_remaining(tvb, offset) > 0
4035 && tvb_get_uint8(tvb, offset) == SQLNET_ROW_TRANSF_DATA7 )
4036 {
4037 tns_binds_t *binds = cursor ? tns_lookup_cursor_binds(pinfo, cursor) : NULL((void*)0);
4038 if ( binds && binds->count == (uint32_t)bind_count )
4039 {
4040 if ( call )
4041 {
4042 call->num_binds = binds->count;
4043 call->num_return = binds->num_return;
4044 call->binds = binds->cols;
4045 }
4046 proto_item *binds_item;
4047 proto_tree *binds_tree;
4048 int binds_start = offset;
4049
4050 binds_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
4051 ett_tns_binds, &binds_item, "Binds");
4052 offset = dissect_tns_bind_rows(tvb, pinfo, binds_tree, offset, binds->cols,
4053 binds->count - binds->num_return);
4054 proto_item_set_len(binds_item, offset - binds_start);
4055 }
4056 }
4057 else if ( bind_count > 0 && tvb_reported_length_remaining(tvb, offset) > 0 )
4058 {
4059 proto_tree *binds_tree, *bind_tree;
4060 proto_item *binds_item, *bind_item;
4061 int binds_start = offset;
4062 tns_column_t *bcols;
4063
4064 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))))))
;
4065 binds_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
4066 ett_tns_binds, &binds_item, "Binds");
4067
4068 for ( int i = 0; i < bind_count && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4069 {
4070 int b_start = offset;
4071 uint8_t btype = tvb_get_uint8(tvb, offset);
4072 bind_tree = proto_tree_add_subtree_format(binds_tree, tvb, offset, -1,
4073 ett_tns_bind, &bind_item, "Bind %d: %s", i + 1,
4074 val_to_str_const(btype, tns_data_types, "unknown"));
4075 offset = dissect_tns_oac(tvb, pinfo, bind_tree, offset, &bcols[i]);
4076 /* Below 12.2 a CLOB/BLOB bind OAC still carries a
4077 * trailing oaccolid byte; from 12.2 every OAC does,
4078 * and the OAC decoder reads it. */
4079 if ( (btype == TNS_DATATYPE_CLOB112 || btype == TNS_DATATYPE_BLOB113)
4080 && tns_field_version(pinfo) < TNS_FV_12_28 )
4081 offset += 1;
4082 proto_item_set_len(bind_item, offset - b_start);
4083 }
4084
4085 /* A DML RETURNING ... INTO statement sends no values for
4086 * its return binds, the last ones. */
4087 unsigned num_return = sql ? tns_count_return_binds((const char *)sql) : 0;
4088 if ( num_return > (unsigned)bind_count )
4089 num_return = 0;
4090
4091 if ( call )
4092 {
4093 call->num_binds = bind_count;
4094 call->num_return = num_return;
4095 call->binds = bcols;
4096 }
4097
4098 /* Remember the types for later executes of the cursor
4099 * that leave the descriptors out. */
4100 if ( tns_info )
4101 {
4102 tns_binds_t *binds = wmem_new0(wmem_file_scope(), tns_binds_t)((tns_binds_t*)wmem_alloc0((wmem_file_scope()), sizeof(tns_binds_t
)))
;
4103 binds->count = bind_count;
4104 binds->num_return = num_return;
4105 binds->cols = bcols;
4106 if ( cursor != 0 )
4107 wmem_map_insert(tns_info->cursor_binds, GUINT_TO_POINTER(cursor)((gpointer) (gulong) (cursor)), binds);
4108 else
4109 tns_info->pending_binds = binds;
4110 }
4111
4112 /* Value rows: a TTI_RXD token then one DALC value per bind
4113 * column (an ordinary execute sends one row, executemany
4114 * sends N), decoded and rendered by the bind's type. */
4115 offset = dissect_tns_bind_rows(tvb, pinfo, binds_tree, offset, bcols, bind_count - num_return);
4116 proto_item_set_len(binds_item, offset - binds_start);
4117 }
4118
4119 /* Define section: a client that wants a column in some
4120 * other form than the describe gave - a CLOB as a string,
4121 * say - re-executes the cursor with the DEFINE option and
4122 * one OAC per column, in the bind OAC layout. It carries
4123 * no binds. */
4124 if ( define_count > 0 )
4125 {
4126 proto_tree *defs_tree, *def_tree;
4127 proto_item *defs_item, *def_item;
4128 int defs_start = offset;
4129 tns_column_t *dcols = NULL((void*)0);
4130
4131 if ( !PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited) )
4132 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))))))
;
4133 defs_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
4134 ett_tns_defines, &defs_item, "Defines");
4135 for ( int i = 0; i < define_count && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4136 {
4137 int d_start = offset;
4138 uint8_t dtype = tvb_get_uint8(tvb, offset);
4139 def_tree = proto_tree_add_subtree_format(defs_tree, tvb, offset, -1,
4140 ett_tns_bind, &def_item, "Define %d: %s", i + 1,
4141 val_to_str_const(dtype, tns_data_types, "unknown"));
4142 offset = dissect_tns_oac(tvb, pinfo, def_tree, offset, dcols ? &dcols[i] : NULL((void*)0));
4143 proto_item_set_len(def_item, offset - d_start);
4144 }
4145 proto_item_set_len(defs_item, offset - defs_start);
4146
4147 /* The rows that answer a define come framed the way
4148 * it asked - a CLOB defined as LONG arrives inline,
4149 * with no locator - and so do the rows of every later
4150 * execute of the cursor. Rows are still split by the
4151 * describe's columns, so replace each column's type
4152 * with the one its define gives. */
4153 if ( tns_info && dcols && tns_info->last_describe
4154 && tns_info->last_describe->num_cols == (uint32_t)define_count )
4155 {
4156 tns_describe_t *desc = wmem_new0(wmem_file_scope(), tns_describe_t)((tns_describe_t*)wmem_alloc0((wmem_file_scope()), sizeof(tns_describe_t
)))
;
4157 desc->num_cols = define_count;
4158 desc->cols = (tns_column_t *)wmem_memdup(wmem_file_scope(),
4159 tns_info->last_describe->cols, define_count * sizeof(tns_column_t));
4160 for ( int i = 0; i < define_count; i++ )
4161 {
4162 desc->cols[i].type = dcols[i].type;
4163 desc->cols[i].csform = dcols[i].csform;
4164 }
4165 tns_info->last_describe = desc;
4166 }
4167 }
4168 }
4169 else if ( oci_id == TTI_LOBOPS96 )
4170 {
4171 /* TTI_LOBOPS: the LOB operation family (read, write, get
4172 * length, create/free temp, open/close, BFILE ops). One
4173 * common request layout selects behaviour by the operation
4174 * opcode:
4175 * ub1 source pointer | ub4 source locator length |
4176 * ub1 dest pointer | ub4 dest length |
4177 * ub4 short source offset | ub4 short dest offset |
4178 * ub1 charset pointer | ub1 short amount pointer |
4179 * ub1 null-LOB pointer | ub4 operation |
4180 * ub1 SCN array pointer | ub1 SCN array length |
4181 * ub8 source offset | ub8 dest offset |
4182 * ub1 amount pointer | 3 x ub2 array-LOB slots (fixed) |
4183 * [locator] | [ub4 charset, CREATE_TEMP] |
4184 * [0x0E and the data, WRITE] | [ub8 amount]
4185 * The locator is as long as the source locator length says;
4186 * a temporary LOB's carries its own ub2 length prefix, which
4187 * that length counts. */
4188 int v = 0, op = 0, loc_len = 0, start;
4189 uint8_t src_ptr, charset_ptr, amount_ptr;
4190 uint64_t u = 0;
4191
4192 src_ptr = tvb_get_uint8(tvb, offset);
4193 offset += 1; /* source pointer flag */
4194 offset += get_sb4_custom(tvb, offset, &loc_len); /* source locator length */
4195 offset += 1; /* dest pointer flag */
4196 offset += get_sb4_custom(tvb, offset, &v); /* dest length */
4197 offset += get_sb4_custom(tvb, offset, &v); /* short source offset */
4198 offset += get_sb4_custom(tvb, offset, &v); /* short dest offset */
4199 charset_ptr = tvb_get_uint8(tvb, offset);
4200 offset += 3; /* charset / amount / null-lob flags */
4201 /* operation opcode */
4202 start = offset;
4203 offset += get_sb4_custom(tvb, offset, &op);
4204 proto_tree_add_uint(data_tree, hf_tns_data_lob_op, tvb, start, offset - start, op);
4205 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]",
4206 val_to_str_const(op, tns_lob_ops, "unknown"));
4207 /* scn-array pointer flag + length */
4208 offset += 2;
4209 /* source offset (ub8, 1-based into the LOB) */
4210 start = offset;
4211 offset += get_ub8_custom(tvb, offset, &u);
4212 proto_tree_add_uint64(data_tree, hf_tns_data_lob_offset, tvb, start, offset - start, u);
4213 /* dest offset (ub8, skip) */
4214 offset += get_ub8_custom(tvb, offset, &u);
4215 amount_ptr = tvb_get_uint8(tvb, offset);
4216 offset += 1; /* amount pointer flag */
4217 offset += 6; /* array-LOB slots */
4218 if ( src_ptr && loc_len > 0 )
4219 {
4220 proto_tree_add_item(data_tree, hf_tns_data_lob_locator, tvb, offset, loc_len, ENC_NA0x00000000);
4221 offset += loc_len;
4222 }
4223 if ( charset_ptr )
4224 {
4225 start = offset;
4226 offset += get_sb4_custom(tvb, offset, &v);
4227 proto_tree_add_uint(data_tree, hf_tns_data_lob_charset, tvb, start, offset - start, v);
4228 }
4229 if ( tvb_reported_length_remaining(tvb, offset) > 0
4230 && tvb_get_uint8(tvb, offset) == SQLNET_LOB_FILE_DF14 )
4231 {
4232 /* WRITE: a LOB_DATA marker, then the data */
4233 offset += 1;
4234 start = offset;
4235 offset += get_dalc_custom(tvb, pinfo, offset, NULL((void*)0));
4236 if ( tvb_get_uint8(tvb, start) == 0xfe ) /* chunked: shown whole */
4237 proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start, offset - start, ENC_NA0x00000000);
4238 else if ( offset - start > 1 )
4239 proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start + 1, offset - start - 1, ENC_NA0x00000000);
4240 }
4241 if ( amount_ptr )
4242 {
4243 start = offset;
4244 offset += get_ub8_custom(tvb, offset, &u);
4245 proto_tree_add_uint64(data_tree, hf_tns_data_lob_amount, tvb, start, offset - start, u);
4246 }
4247 if ( call )
4248 {
4249 call->lob_op = (uint32_t)op;
4250 call->lob_locator_len = src_ptr ? (uint32_t)loc_len : 0;
4251 call->lob_amount = amount_ptr != 0;
4252 }
4253 }
4254 break;
4255 }
4256 case SQLNET_RETURN_OPI_PARAM8:
4257 {
4258 uint8_t skip = 0, opi = 0;
4259
4260 if ( tvb_bytes_exist(tvb, offset, 11) )
4261 {
4262 /*
4263 * OPI_VERSION2 response has a following pattern:
4264 *
4265 * _ banner _ vsnum
4266 * / /
4267 * ..(.?)(Orac[le.+])(.?)(....).+$
4268 * |
4269 * \ banner length (if equal to 0 then next byte indicates the length).
4270 *
4271 * These differences (to skip 1 or 2 bytes) due to differences in the drivers.
4272 */
4273 /* Orac[le.+] */
4274 if ( tvb_get_ntohl(tvb, offset+2) == 0x4f726163 )
4275 {
4276 opi = OPI_VERSION21;
4277 skip = 1;
4278 }
4279
4280 else if ( tvb_get_ntohl(tvb, offset+3) == 0x4f726163 )
4281 {
4282 opi = OPI_VERSION21;
4283 skip = 2;
4284 }
4285
4286 /*
4287 * OPI_OSESSKEY response has a following pattern:
4288 *
4289 * _ pattern (v1|v2)
4290 * / _ params
4291 * / /
4292 * (....)(........)(.+).+$
4293 * ||
4294 * \ if these two bytes are equal to 0x0c00 then first byte is <Param Counts> (v1),
4295 * else next byte indicate it (v2).
4296 */
4297 /* ....AUTH (v1) */
4298 else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0000000c41555448 )
4299 {
4300 opi = OPI_OSESSKEY2;
4301 skip = 1;
4302 }
4303 /* ..AUTH_V (v2) */
4304 else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0c0c415554485f53 )
4305 {
4306 opi = OPI_OSESSKEY2;
4307 skip = 2;
4308 }
4309
4310 /*
4311 * OPI_OAUTH response has a following pattern:
4312 *
4313 * _ pattern (v1|v2)
4314 * / _ params
4315 * / /
4316 * (....)(........)(.+).+$
4317 * ||
4318 * \ if these two bytes are equal to 0x1300 then first byte is <Param Counts> (v1),
4319 * else next byte indicate it (v2).
4320 */
4321
4322 /* ....AUTH (v1) */
4323 else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0000001341555448 )
4324 {
4325 opi = OPI_OAUTH3;
4326 skip = 1;
4327 }
4328 /* ..AUTH_V (v2) */
4329 else if ( tvb_get_ntoh64(tvb, offset+3) == 0x1313415554485f56 )
4330 {
4331 opi = OPI_OAUTH3;
4332 skip = 2;
4333 }
4334 }
4335
4336 if ( opi == OPI_VERSION21 )
4337 {
4338 proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, skip, ENC_NA0x00000000);
4339 offset += skip;
4340
4341 uint8_t len = tvb_get_uint8(tvb, offset);
4342
4343 proto_tree_add_item(data_tree, hf_tns_data_opi_version2_banner_len, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4344 offset += 1;
4345
4346 proto_tree_add_item(data_tree, hf_tns_data_opi_version2_banner, tvb, offset, len, ENC_ASCII0x00000000);
4347 offset += len + (skip == 1 ? 1 : 0);
4348
4349 proto_tree_add_item(data_tree, hf_tns_data_opi_version2_vsnum, tvb, offset, 4, (skip == 1) ? ENC_BIG_ENDIAN0x00000000 : ENC_LITTLE_ENDIAN0x80000000);
4350 offset += 4;
4351 }
4352 else if ( opi == OPI_OSESSKEY2 || opi == OPI_OAUTH3 )
4353 {
4354 proto_tree *params_tree;
4355 proto_item *params_ti;
4356 unsigned par, params;
4357
4358 if ( skip == 1 )
4359 {
4360 proto_tree_add_item_ret_uint(data_tree, hf_tns_data_opi_num_of_params, tvb, offset, 1, ENC_NA0x00000000, &params);
4361 offset += 1;
4362
4363 proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 5, ENC_NA0x00000000);
4364 offset += 5;
4365 }
4366 else
4367 {
4368 proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 1, ENC_NA0x00000000);
4369 offset += 1;
4370
4371 proto_tree_add_item_ret_uint(data_tree, hf_tns_data_opi_num_of_params, tvb, offset, 1, ENC_NA0x00000000, &params);
4372 offset += 1;
4373
4374 proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 2, ENC_NA0x00000000);
4375 offset += 2;
4376 }
4377
4378 params_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_opi_params, &params_ti, "Parameters");
4379
4380 for ( par = 1; par <= params; par++ )
4381 {
4382 proto_tree *par_tree;
4383 proto_item *par_ti;
4384 unsigned len, offset_prev;
4385
4386 par_tree = proto_tree_add_subtree(params_tree, tvb, offset, -1, ett_tns_opi_par, &par_ti, "Parameter");
4387 proto_item_append_text(par_ti, " %u", par);
4388
4389 /* Name length */
4390 proto_tree_add_item_ret_uint(par_tree, hf_tns_data_opi_param_length, tvb, offset, 1, ENC_NA0x00000000, &len);
4391 offset += 1;
4392
4393 /* Name */
4394 if ( !(len == 0 || len == 2) ) /* Not empty (2 - SQLDeveloper specific sign). */
4395 {
4396 proto_tree_add_item(par_tree, hf_tns_data_opi_param_name, tvb, offset, len, ENC_ASCII0x00000000);
4397 offset += len;
4398 }
4399
4400 /* Value can be NULL. So, save offset to calculate unused data. */
4401 offset_prev = offset;
4402 offset += skip == 1 ? 4 : 2;
4403
4404 /* Value length */
4405 if ( opi == OPI_OSESSKEY2 )
4406 {
4407 len = get_strtype_custom(tvb, pinfo, par_tree, offset);
4408 }
4409 else /* OPI_OAUTH */
4410 {
4411 len = tvb_get_uint8(tvb, offset_prev) == 0 ? 0 : get_strtype_custom(tvb, pinfo, par_tree, offset);
4412 }
4413
4414 /*
4415 * Value
4416 * OPI_OSESSKEY: AUTH_VFR_DATA with length 0, 9, 0x39 comes without data.
4417 * OPI_OAUTH: AUTH_VFR_DATA with length 0, 0x39 comes without data.
4418 */
4419 if ( ((opi == OPI_OSESSKEY2) && !(len == 0 || len == 9 || len == 0x39))
4420 || ((opi == OPI_OAUTH3) && !(len == 0 || len == 0x39)) )
4421 {
4422 proto_tree_add_item(par_tree, hf_tns_data_unused, tvb, offset_prev, offset - offset_prev, ENC_NA0x00000000);
4423 offset += len;
4424
4425 offset_prev = offset; /* Save offset to calculate rest of unused data */
4426 }
4427 else
4428 {
4429 offset += 1;
4430 }
4431
4432 if ( opi == OPI_OSESSKEY2 )
4433 {
4434 /* SQL Developer specific fix */
4435 offset += tvb_get_uint8(tvb, offset) == 2 ? 5 : 3;
4436 }
4437 else /* OPI_OAUTH */
4438 {
4439 offset += len == 0 ? 1 : 3;
4440 }
4441
4442 if ( skip == 1 )
4443 {
4444 offset += 1 + ((len == 0 || len == 0x39) ? 3 : 4);
4445
4446 if ( opi == OPI_OAUTH3 )
4447 {
4448 offset += len == 0 ? 2 : 0;
4449 }
4450 }
4451
4452 proto_tree_add_item(par_tree, hf_tns_data_unused, tvb, offset_prev, offset - offset_prev, ENC_NA0x00000000);
4453 proto_item_set_end(par_ti, tvb, offset);
4454 }
4455 proto_item_set_end(params_ti, tvb, offset);
4456 }
4457 else if ( !is_request )
4458 {
4459 /* Not an authentication reply: an execute answers with
4460 * its return parameters. */
4461 tns_call_t *call = tns_answered_call(pinfo);
4462 if ( call && (call->func == TTI_ALL894 || call->func == TTI_REEXECUTE4
4463 || call->func == TTI_REEXECUTE_AND_FETCH78) )
4464 {
4465 offset = dissect_tns_return_params(tvb, pinfo, data_tree, offset,
4466 (call->exec_flags & TNS_EXEC_FLAGS_DML_ROWCOUNTS0x4000) != 0);
4467 ctx->walk = true1;
4468 }
4469 else if ( call && call->func == TTI_LOBOPS96 )
4470 {
4471 /* A LOB operation's reply: the locator as the server
4472 * now sees it - as long as the one sent, and changed
4473 * by a mutating call - then per operation the new
4474 * temporary LOB's charset, the amount, or a boolean. */
4475 uint64_t u = 0;
4476 int start;
4477
4478 if ( call->lob_locator_len > 0 )
4479 {
4480 proto_tree_add_item(data_tree, hf_tns_data_lob_locator, tvb, offset,
4481 call->lob_locator_len, ENC_NA0x00000000);
4482 offset += call->lob_locator_len;
4483 }
4484 if ( call->lob_op == TNS_LOB_OP_CREATE_TEMP0x00110 )
4485 {
4486 int v = 0;
4487 start = offset;
4488 offset += get_sb4_custom(tvb, offset, &v);
4489 proto_tree_add_uint(data_tree, hf_tns_data_lob_charset, tvb, start, offset - start, v);
4490 offset += 1; /* trailing flags */
4491 }
4492 else if ( call->lob_amount )
4493 {
4494 start = offset;
4495 offset += get_ub8_custom(tvb, offset, &u);
4496 proto_tree_add_uint64(data_tree, hf_tns_data_lob_amount, tvb, start, offset - start, u);
4497 }
4498 if ( call->lob_op == TNS_LOB_OP_IS_OPEN0x11000 || call->lob_op == TNS_LOB_OP_FILE_EXISTS0x00800
4499 || call->lob_op == TNS_LOB_OP_FILE_ISOPEN0x00400 )
4500 {
4501 proto_tree_add_item(data_tree, hf_tns_data_lob_flag, tvb, offset, 1, ENC_NA0x00000000);
4502 offset += 1;
4503 }
4504 ctx->walk = true1;
4505 }
4506 }
4507 break;
4508 }
4509
4510 case SQLNET_PIGGYBACK_FUNC17:
4511 {
4512 int cursors_len = 0;
4513 int cursors_start;
4514 uint8_t piggyback_id = tvb_get_uint8(tvb, offset);
4515 proto_tree_add_item(data_tree, hf_tns_data_piggyback_id, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4516 offset += 1;
4517 proto_tree_add_item(data_tree, hf_tns_data_tseq, tvb, offset, 1, ENC_BIG_ENDIAN0x00000000);
4518 offset += 1;
4519 offset = dissect_tns_call_token(tvb, pinfo, data_tree, offset);
4520 /* Only the close-cursors piggyback carries a cursor list:
4521 * a pointer byte, a ub4 count, then that many ub4 cursor
4522 * ids. The other piggybacks have bodies of their own. */
4523 if ( piggyback_id != TTI_CLOSE_CURSORS105 )
4524 {
4525 offset = dissect_tns_piggyback_body(tvb, pinfo, data_tree, offset, piggyback_id, &ctx->walk);
4526 break;
4527 }
4528 offset += 1; /* pointer */
4529 cursors_start = offset;
4530 offset += get_sb4_custom(tvb, offset, &cursors_len);
4531 /* The count comes off the wire and every cursor takes at
4532 * least one byte, so a count larger than the data left
4533 * cannot be real. Say so and stop, rather than looping on
4534 * a number somebody else chose. */
4535 if ( cursors_len < 0 ||
4536 (unsigned)cursors_len > tvb_reported_length_remaining(tvb, offset) )
4537 {
4538 proto_tree_add_expert(data_tree, pinfo, &ei_tns_data_piggyback_cursors,
4539 tvb, cursors_start, offset - cursors_start);
4540 break;
4541 }
4542 for(int i = 0; i < cursors_len; i++) {
4543 int cursor = 0;
4544 int len = get_sb4_custom(tvb, offset, &cursor);
4545 proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, offset, len, cursor);
4546 offset += len;
4547 }
4548 /* The call this piggyback rides in front of follows it. */
4549 ctx->walk = true1;
4550 break;
4551 }
4552 case SQLNET_SNS0xdeadbeef:
4553 {
4554 proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4555 offset += 4;
4556 proto_tree_add_item(data_tree, hf_tns_data_length, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
4557 offset += 2;
4558
4559 if ( is_request )
4560 {
4561 proto_tree_add_item(data_tree, hf_tns_data_sns_cli_vers, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4562 }
4563 else
4564 {
4565 proto_tree_add_item(data_tree, hf_tns_data_sns_srv_vers, tvb, offset, 4, ENC_BIG_ENDIAN0x00000000);
4566 }
4567 offset += 4;
4568
4569 proto_tree_add_item(data_tree, hf_tns_data_sns_srvcnt, tvb, offset, 2, ENC_BIG_ENDIAN0x00000000);
4570
4571 /* move back, to include data_id into data_dissector */
4572 offset -= 10;
4573 break;
4574 }
4575 }
4576
4577 return offset;
4578}
4579
4580static void dissect_tns_connect(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
4581{
4582 proto_tree *connect_tree;
4583 uint32_t cd_offset, cd_len;
4584 int tns_offset = offset-8;
4585 static int * const flags[] = {
4586 &hf_tns_ntp_flag_hangon,
4587 &hf_tns_ntp_flag_crel,
4588 &hf_tns_ntp_flag_tduio,
4589 &hf_tns_ntp_flag_srun,
4590 &hf_tns_ntp_flag_dtest,
4591 &hf_tns_ntp_flag_cbio,
4592 &hf_tns_ntp_flag_asio,
4593 &hf_tns_ntp_flag_pio,
4594 &hf_tns_ntp_flag_grant,
4595 &hf_tns_ntp_flag_handoff,
4596 &hf_tns_ntp_flag_sigio,
4597 &hf_tns_ntp_flag_sigpipe,
4598 &hf_tns_ntp_flag_sigurg,
4599 &hf_tns_ntp_flag_urgentio,
4600 &hf_tns_ntp_flag_fdio,
4601 &hf_tns_ntp_flag_testop,
4602 NULL((void*)0)
4603 };
4604
4605 connect_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
4606 ett_tns_connect, NULL((void*)0), "Connect");
4607
4608 proto_tree_add_item(connect_tree, hf_tns_version, tvb,
4609 offset, 2, ENC_BIG_ENDIAN0x00000000);
4610 offset += 2;
4611
4612 proto_tree_add_item(connect_tree, hf_tns_compat_version, tvb,
4613 offset, 2, ENC_BIG_ENDIAN0x00000000);
4614 offset += 2;
4615
4616 proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_service_options, ett_tns_sopt_flag, tns_service_options, ENC_BIG_ENDIAN0x00000000);
4617 offset += 2;
4618
4619 proto_tree_add_item(connect_tree, hf_tns_sdu_size, tvb,
4620 offset, 2, ENC_BIG_ENDIAN0x00000000);
4621 offset += 2;
4622
4623 proto_tree_add_item(connect_tree, hf_tns_max_tdu_size, tvb,
4624 offset, 2, ENC_BIG_ENDIAN0x00000000);
4625 offset += 2;
4626
4627 proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_nt_proto_characteristics, ett_tns_ntp_flag, flags, ENC_BIG_ENDIAN0x00000000);
4628 offset += 2;
4629
4630 proto_tree_add_item(connect_tree, hf_tns_line_turnaround, tvb,
4631 offset, 2, ENC_BIG_ENDIAN0x00000000);
4632 offset += 2;
4633
4634 proto_tree_add_item(connect_tree, hf_tns_value_of_one, tvb,
4635 offset, 2, ENC_NA0x00000000);
4636 offset += 2;
4637
4638 proto_tree_add_item_ret_uint(connect_tree, hf_tns_connect_data_length, tvb,
4639 offset, 2, ENC_BIG_ENDIAN0x00000000, &cd_len);
4640 offset += 2;
4641
4642 proto_tree_add_item_ret_uint(connect_tree, hf_tns_connect_data_offset, tvb,
4643 offset, 2, ENC_BIG_ENDIAN0x00000000, &cd_offset);
4644 offset += 2;
4645
4646 proto_tree_add_item(connect_tree, hf_tns_connect_data_max, tvb,
4647 offset, 4, ENC_BIG_ENDIAN0x00000000);
4648 offset += 4;
4649
4650 proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_connect_flags0, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN0x00000000);
4651 offset += 1;
4652
4653 proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_connect_flags1, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN0x00000000);
4654 offset += 1;
4655
4656 /*
4657 * XXX - sometimes it appears that this stuff isn't present
4658 * in the packet.
4659 */
4660 if ((uint32_t)(offset + 16) <= tns_offset+cd_offset)
4661 {
4662 proto_tree_add_item(connect_tree, hf_tns_trace_cf1, tvb,
4663 offset, 4, ENC_BIG_ENDIAN0x00000000);
4664 offset += 4;
4665
4666 proto_tree_add_item(connect_tree, hf_tns_trace_cf2, tvb,
4667 offset, 4, ENC_BIG_ENDIAN0x00000000);
4668 offset += 4;
4669
4670 proto_tree_add_item(connect_tree, hf_tns_trace_cid, tvb,
4671 offset, 8, ENC_BIG_ENDIAN0x00000000);
4672 /* offset += 8;*/
4673 }
4674
4675 if ( cd_len > 0)
4676 {
4677 /* Long Connect Data (> 221 bytes?) is not in the Connect PDU
4678 * but sent in an immediately following Data PDU.
4679 */
4680 if (tvb_reported_length_remaining(tvb, tns_offset + cd_offset)) {
4681 proto_tree_add_item(connect_tree, hf_tns_connect_data, tvb,
4682 tns_offset+cd_offset, -1, ENC_ASCII0x00000000);
4683 } else {
4684 proto_tree_add_expert(connect_tree, pinfo, &ei_tns_connect_data_next_packet, tvb, 0, 0);
4685 if (!PINFO_FD_VISITED(pinfo)((pinfo)->fd->visited)) {
4686 tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
4687 tns_info->pending_connect_data = cd_len;
4688 }
4689 }
4690 }
4691}
4692
4693static void dissect_tns_accept(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
4694{
4695 proto_tree *accept_tree;
4696 uint32_t accept_offset, accept_len;
4697 int tns_offset = offset-8;
4698
4699 accept_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
4700 ett_tns_accept, NULL((void*)0), "Accept");
4701
4702 proto_tree_add_item(accept_tree, hf_tns_version, tvb,
4703 offset, 2, ENC_BIG_ENDIAN0x00000000);
4704 offset += 2;
4705
4706 proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_service_options, ett_tns_sopt_flag, tns_service_options, ENC_BIG_ENDIAN0x00000000);
4707 offset += 2;
4708
4709 proto_tree_add_item(accept_tree, hf_tns_sdu_size, tvb,
4710 offset, 2, ENC_BIG_ENDIAN0x00000000);
4711 offset += 2;
4712
4713 proto_tree_add_item(accept_tree, hf_tns_max_tdu_size, tvb,
4714 offset, 2, ENC_BIG_ENDIAN0x00000000);
4715 offset += 2;
4716
4717 proto_tree_add_item(accept_tree, hf_tns_value_of_one, tvb,
4718 offset, 2, ENC_NA0x00000000);
4719 offset += 2;
4720
4721 proto_tree_add_item_ret_uint(accept_tree, hf_tns_accept_data_length, tvb,
4722 offset, 2, ENC_BIG_ENDIAN0x00000000, &accept_len);
4723 offset += 2;
4724
4725 proto_tree_add_item_ret_uint(accept_tree, hf_tns_accept_data_offset, tvb,
4726 offset, 2, ENC_BIG_ENDIAN0x00000000, &accept_offset);
4727 offset += 2;
4728
4729 proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_connect_flags0, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN0x00000000);
4730 offset += 1;
4731
4732 proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_connect_flags1, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN0x00000000);
4733 /* offset += 1; */
4734
4735 if ( accept_len > 0)
4736 {
4737 proto_tree_add_item(accept_tree, hf_tns_accept_data, tvb,
4738 tns_offset+accept_offset, -1, ENC_ASCII0x00000000);
4739 }
4740 return;
4741}
4742
4743
4744static void dissect_tns_refuse(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
4745{
4746 /* TODO
4747 * According to some reverse engineers, the refuse packet is also sent when the login fails.
4748 * Byte 54 shows if this is due to invalid ID (0x02) or password (0x03).
4749 * At now we do not have pcaps with such messages to check this statement.
4750 */
4751 proto_tree *refuse_tree;
4752
4753 refuse_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
4754 ett_tns_refuse, NULL((void*)0), "Refuse");
4755
4756 proto_tree_add_item(refuse_tree, hf_tns_refuse_reason_user, tvb,
4757 offset, 1, ENC_BIG_ENDIAN0x00000000);
4758 offset += 1;
4759
4760 proto_tree_add_item(refuse_tree, hf_tns_refuse_reason_system, tvb,
4761 offset, 1, ENC_BIG_ENDIAN0x00000000);
4762 offset += 1;
4763
4764 proto_tree_add_item(refuse_tree, hf_tns_refuse_data_length, tvb,
4765 offset, 2, ENC_BIG_ENDIAN0x00000000);
4766 offset += 2;
4767
4768 proto_tree_add_item(refuse_tree, hf_tns_refuse_data, tvb,
4769 offset, -1, ENC_ASCII0x00000000);
4770}
4771
4772
4773static void dissect_tns_abort(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
4774{
4775 proto_tree *abort_tree;
4776
4777 abort_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
4778 ett_tns_abort, NULL((void*)0), "Abort");
4779
4780 proto_tree_add_item(abort_tree, hf_tns_abort_reason_user, tvb,
4781 offset, 1, ENC_BIG_ENDIAN0x00000000);
4782 offset += 1;
4783
4784 proto_tree_add_item(abort_tree, hf_tns_abort_reason_system, tvb,
4785 offset, 1, ENC_BIG_ENDIAN0x00000000);
4786 offset += 1;
4787
4788 proto_tree_add_item(abort_tree, hf_tns_abort_data, tvb,
4789 offset, -1, ENC_ASCII0x00000000);
4790}
4791
4792
4793static void dissect_tns_marker(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tns_tree, int is_attention)
4794{
4795 proto_tree *marker_tree;
4796
4797 marker_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
4798 ett_tns_marker, NULL((void*)0), is_attention ? "Attention" : "Marker");
4799
4800 proto_tree_add_item(marker_tree, hf_tns_marker_type, tvb,
4801 offset, 1, ENC_BIG_ENDIAN0x00000000);
4802 offset += 1;
4803
4804 proto_tree_add_item(marker_tree, hf_tns_marker_data_byte, tvb,
4805 offset, 1, ENC_BIG_ENDIAN0x00000000);
4806 offset += 1;
4807
4808 /* The last byte selects break vs reset for a data marker. */
4809 if ( tvb_reported_length_remaining(tvb, offset) > 0 )
4810 {
4811 uint32_t func = tvb_get_uint8(tvb, offset);
4812 proto_tree_add_item(marker_tree, hf_tns_marker_function, tvb,
4813 offset, 1, ENC_BIG_ENDIAN0x00000000);
4814 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
4815 val_to_str_const(func, tns_marker_functions, "Unknown"));
4816 }
4817}
4818
4819static void dissect_tns_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
4820{
4821 proto_tree *redirect_tree;
4822
4823 redirect_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
4824 ett_tns_redirect, NULL((void*)0), "Redirect");
4825
4826 proto_tree_add_item(redirect_tree, hf_tns_redirect_data_length, tvb,
4827 offset, 2, ENC_BIG_ENDIAN0x00000000);
4828 offset += 2;
4829
4830 proto_tree_add_item(redirect_tree, hf_tns_redirect_data, tvb,
4831 offset, -1, ENC_ASCII0x00000000);
4832}
4833
4834static void dissect_tns_control(tvbuff_t *tvb, int offset, packet_info *pinfo _U___attribute__((unused)), proto_tree *tns_tree)
4835{
4836 proto_tree *control_tree;
4837
4838 control_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
4839 ett_tns_control, NULL((void*)0), "Control");
4840
4841 proto_tree_add_item(control_tree, hf_tns_control_cmd, tvb,
4842 offset, 2, ENC_BIG_ENDIAN0x00000000);
4843 offset += 2;
4844
4845 proto_tree_add_item(control_tree, hf_tns_control_data, tvb,
4846 offset, -1, ENC_NA0x00000000);
4847}
4848
4849static unsigned
4850get_tns_pdu_len(packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, void *data _U___attribute__((unused)))
4851{
4852 /*
4853 * Get the 16-bit length of the TNS message, including header
4854 */
4855 unsigned length = tvb_get_ntohs(tvb, offset);
4856 offset += 4;
4857 uint8_t type = tvb_get_uint8(tvb, offset);
4858 /* Type 0xf (data descriptor, LOB/FILE data) has data which follows
4859 * immediately (no new PDU header) but is not counted in the PDU
4860 * length field either.
4861 */
4862 if (type == TNS_TYPE_DD15) {
4863 offset += 8;
4864 if (!tvb_bytes_exist(tvb, offset, 4)) {
4865 /* return 0 makes tcp_dissect_pdus() report
4866 * DESEGMENT_ONE_MORE_SEGMENT to the TCP dissector.
4867 */
4868 return 0;
4869 }
4870 unsigned dd_len = tvb_get_ntohl(tvb, offset);
4871 return length + dd_len;
4872 }
4873 return length;
4874}
4875
4876static unsigned
4877get_tns_pdu_len_nochksum(packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, void *data _U___attribute__((unused)))
4878{
4879 /*
4880 * Get the 32-bit length of the TNS message, including header
4881 */
4882 unsigned length = tvb_get_ntohl(tvb, offset);
4883 offset += 4;
4884 uint8_t type = tvb_get_uint8(tvb, offset);
4885 /* Type 0xf (data descriptor, LOB/FILE data) has data which follows
4886 * immediately (no new PDU header) but is not counted in the PDU
4887 * length field either.
4888 */
4889 if (type == TNS_TYPE_DD15) {
4890 offset += 8;
4891 if (!tvb_bytes_exist(tvb, offset, 4)) {
4892 /* return 0 makes tcp_dissect_pdus() report
4893 * DESEGMENT_ONE_MORE_SEGMENT to the TCP dissector.
4894 */
4895 return 0;
4896 }
4897 unsigned dd_len = tvb_get_ntohl(tvb, offset);
4898 return length + dd_len;
4899 }
4900
4901 return length;
4902}
4903
4904static int
4905dissect_tns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
4906{
4907 uint32_t length;
4908 uint16_t chksum;
4909 uint8_t type;
4910
4911 /*
4912 * First, do a sanity check to make sure what we have
4913 * starts with a TNS PDU.
4914 */
4915 if (tvb_bytes_exist(tvb, 4, 1)) {
4916 /*
4917 * Well, we have the packet type; let's make sure
4918 * it's a known type.
4919 */
4920 type = tvb_get_uint8(tvb, 4);
4921 if (type < TNS_TYPE_CONNECT1 || type > TNS_TYPE_MAX19)
4922 return 0; /* it's not a known type */
4923 }
4924
4925 /*
4926 * In some messages (observed in Oracle12c) packet length has 4 bytes
4927 * instead of 2.
4928 *
4929 * If packet length has 2 bytes, length and checksum equals two unsigned
4930 * 16-bit numbers. Packet checksum is generally unused (equal zero),
4931 * but 10g client may set 2nd byte to 4.
4932 *
4933 * Else, Oracle 12c combine these two 16-bit numbers into one 32-bit.
4934 * This number represents the packet length. Checksum is omitted.
4935 */
4936 chksum = tvb_get_ntohs(tvb, 2);
4937
4938 length = (chksum == 0 || chksum == 4) ? 2 : 4;
4939
4940 tcp_dissect_pdus(tvb, pinfo, tree, tns_desegment, TNS_HDR_LEN8,
4941 (length == 2 ? get_tns_pdu_len : get_tns_pdu_len_nochksum),
4942 dissect_tns_pdu, data);
4943
4944 return tvb_captured_length(tvb);
4945}
4946
4947static int
4948dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))
4949{
4950 proto_tree *tns_tree, *ti;
4951 proto_item *hidden_item;
4952 unsigned offset = 0;
4953 uint32_t length;
4954 uint16_t chksum;
4955 uint8_t type;
4956
4957 col_set_str(pinfo->cinfo, COL_PROTOCOL, "TNS");
4958
4959 col_set_str(pinfo->cinfo, COL_INFO,
4960 (pinfo->match_uint == pinfo->destport) ? "Request" : "Response");
4961
4962 ti = proto_tree_add_item(tree, proto_tns, tvb, 0, -1, ENC_NA0x00000000);
4963 tns_tree = proto_item_add_subtree(ti, ett_tns);
4964
4965 if (pinfo->match_uint == pinfo->destport)
4966 {
4967 hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_request,
4968 tvb, offset, 0, true1);
4969 }
4970 else
4971 {
4972 hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_response,
4973 tvb, offset, 0, true1);
4974 }
4975 proto_item_set_hidden(hidden_item);
4976
4977 chksum = tvb_get_ntohs(tvb, offset+2);
4978 if (chksum == 0 || chksum == 4)
4979 {
4980 proto_tree_add_item_ret_uint(tns_tree, hf_tns_length, tvb, offset,
4981 2, ENC_BIG_ENDIAN0x00000000, &length);
4982 offset += 2;
4983 proto_tree_add_checksum(tns_tree, tvb, offset, hf_tns_packet_checksum,
4984 -1, NULL((void*)0), pinfo, 0, ENC_BIG_ENDIAN0x00000000, PROTO_CHECKSUM_NO_FLAGS0x00);
4985 offset += 2;
4986 }
4987 else
4988 {
4989 /* Oracle 12c uses checksum bytes as part of the packet length. */
4990 proto_tree_add_item_ret_uint(tns_tree, hf_tns_length, tvb, offset,
4991 4, ENC_BIG_ENDIAN0x00000000, &length);
4992 offset += 4;
4993 }
4994
4995 type = tvb_get_uint8(tvb, offset);
4996 proto_tree_add_uint(tns_tree, hf_tns_packet_type, tvb,
4997 offset, 1, type);
4998 offset += 1;
4999
5000 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s (%u)",
5001 val_to_str_const(type, tns_type_vals, "Unknown"), type);
5002
5003 proto_tree_add_item(tns_tree, hf_tns_reserved_byte, tvb,
5004 offset, 1, ENC_NA0x00000000);
5005 offset += 1;
5006
5007 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);
5008 offset += 2;
5009
5010 switch (type)
5011 {
5012 case TNS_TYPE_CONNECT1:
5013 dissect_tns_connect(tvb,offset,pinfo,tns_tree);
5014 break;
5015 case TNS_TYPE_ACCEPT2:
5016 dissect_tns_accept(tvb,offset,pinfo,tns_tree);
5017 break;
5018 case TNS_TYPE_REFUSE4:
5019 dissect_tns_refuse(tvb,offset,pinfo,tns_tree);
5020 break;
5021 case TNS_TYPE_REDIRECT5:
5022 dissect_tns_redirect(tvb,offset,pinfo,tns_tree);
5023 break;
5024 case TNS_TYPE_ABORT9:
5025 dissect_tns_abort(tvb,offset,pinfo,tns_tree);
5026 break;
5027 case TNS_TYPE_MARKER12:
5028 dissect_tns_marker(tvb,offset,pinfo,tns_tree, 0);
5029 break;
5030 case TNS_TYPE_ATTENTION13:
5031 dissect_tns_marker(tvb,offset,pinfo,tns_tree, 1);
5032 break;
5033 case TNS_TYPE_CONTROL14:
5034 dissect_tns_control(tvb,offset,pinfo,tns_tree);
5035 break;
5036 case TNS_TYPE_DATA6:
5037 dissect_tns_data(tvb,offset,pinfo,tns_tree);
5038 break;
5039 case TNS_TYPE_DD15:
5040 dissect_tns_data_descriptor(tvb,offset,pinfo,tns_tree, length);
5041 break;
5042 default:
5043 call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo,
5044 tns_tree);
5045 break;
5046 }
5047
5048 return tvb_captured_length(tvb);
5049}
5050
5051void proto_register_tns(void)
5052{
5053 static hf_register_info hf[] = {
5054 { &hf_tns_response, {
5055 "Response", "tns.response", FT_BOOLEAN, BASE_NONE,
5056 NULL((void*)0), 0x0, "true if TNS response", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5057 { &hf_tns_request, {
5058 "Request", "tns.request", FT_BOOLEAN, BASE_NONE,
5059 NULL((void*)0), 0x0, "true if TNS request", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5060 { &hf_tns_length, {
5061 "Packet Length", "tns.length", FT_UINT32, BASE_DEC,
5062 NULL((void*)0), 0x0, "Length of TNS packet", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5063 { &hf_tns_packet_checksum, {
5064 "Packet Checksum", "tns.packet_checksum", FT_UINT16, BASE_HEX,
5065 NULL((void*)0), 0x0, "Checksum of Packet Data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5066 { &hf_tns_header_checksum, {
5067 "Header Checksum", "tns.header_checksum", FT_UINT16, BASE_HEX,
5068 NULL((void*)0), 0x0, "Checksum of Header Data", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5069
5070 { &hf_tns_version, {
5071 "Version", "tns.version", FT_UINT16, BASE_DEC,
5072 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5073 { &hf_tns_compat_version, {
5074 "Version (Compatible)", "tns.compat_version", FT_UINT16, BASE_DEC,
5075 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5076
5077 { &hf_tns_service_options, {
5078 "Service Options", "tns.service_options", FT_UINT16, BASE_HEX,
5079 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5080
5081 { &hf_tns_sopt_flag_bconn, {
5082 "Broken Connect Notify", "tns.so_flag.bconn", FT_BOOLEAN, 16,
5083 NULL((void*)0), 0x2000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5084 { &hf_tns_sopt_flag_pc, {
5085 "Packet Checksum", "tns.so_flag.pc", FT_BOOLEAN, 16,
5086 NULL((void*)0), 0x1000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5087 { &hf_tns_sopt_flag_hc, {
5088 "Header Checksum", "tns.so_flag.hc", FT_BOOLEAN, 16,
5089 NULL((void*)0), 0x0800, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5090 { &hf_tns_sopt_flag_fd, {
5091 "Full Duplex", "tns.so_flag.fd", FT_BOOLEAN, 16,
5092 NULL((void*)0), 0x0400, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5093 { &hf_tns_sopt_flag_hd, {
5094 "Half Duplex", "tns.so_flag.hd", FT_BOOLEAN, 16,
5095 NULL((void*)0), 0x0200, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5096 { &hf_tns_sopt_flag_dc1, {
5097 "Don't Care", "tns.so_flag.dc1", FT_BOOLEAN, 16,
5098 NULL((void*)0), 0x0100, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5099 { &hf_tns_sopt_flag_dc2, {
5100 "Don't Care", "tns.so_flag.dc2", FT_BOOLEAN, 16,
5101 NULL((void*)0), 0x0080, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5102 { &hf_tns_sopt_flag_dio, {
5103 "Direct IO to Transport", "tns.so_flag.dio", FT_BOOLEAN, 16,
5104 NULL((void*)0), 0x0010, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5105 { &hf_tns_sopt_flag_ap, {
5106 "Attention Processing", "tns.so_flag.ap", FT_BOOLEAN, 16,
5107 NULL((void*)0), 0x0008, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5108 { &hf_tns_sopt_flag_ra, {
5109 "Can Receive Attention", "tns.so_flag.ra", FT_BOOLEAN, 16,
5110 NULL((void*)0), 0x0004, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5111 { &hf_tns_sopt_flag_sa, {
5112 "Can Send Attention", "tns.so_flag.sa", FT_BOOLEAN, 16,
5113 NULL((void*)0), 0x0002, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5114
5115
5116 { &hf_tns_sdu_size, {
5117 "Session Data Unit Size", "tns.sdu_size", FT_UINT16, BASE_DEC,
5118 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5119 { &hf_tns_max_tdu_size, {
5120 "Maximum Transmission Data Unit Size", "tns.max_tdu_size", FT_UINT16, BASE_DEC,
5121 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5122
5123 { &hf_tns_nt_proto_characteristics, {
5124 "NT Protocol Characteristics", "tns.nt_proto_characteristics", FT_UINT16, BASE_HEX,
5125 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5126 { &hf_tns_ntp_flag_hangon, {
5127 "Hangon to listener connect", "tns.ntp_flag.hangon", FT_BOOLEAN, 16,
5128 NULL((void*)0), 0x8000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5129 { &hf_tns_ntp_flag_crel, {
5130 "Confirmed release", "tns.ntp_flag.crel", FT_BOOLEAN, 16,
5131 NULL((void*)0), 0x4000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5132 { &hf_tns_ntp_flag_tduio, {
5133 "TDU based IO", "tns.ntp_flag.tduio", FT_BOOLEAN, 16,
5134 NULL((void*)0), 0x2000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5135 { &hf_tns_ntp_flag_srun, {
5136 "Spawner running", "tns.ntp_flag.srun", FT_BOOLEAN, 16,
5137 NULL((void*)0), 0x1000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5138 { &hf_tns_ntp_flag_dtest, {
5139 "Data test", "tns.ntp_flag.dtest", FT_BOOLEAN, 16,
5140 NULL((void*)0), 0x0800, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5141 { &hf_tns_ntp_flag_cbio, {
5142 "Callback IO supported", "tns.ntp_flag.cbio", FT_BOOLEAN, 16,
5143 NULL((void*)0), 0x0400, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5144 { &hf_tns_ntp_flag_asio, {
5145 "ASync IO Supported", "tns.ntp_flag.asio", FT_BOOLEAN, 16,
5146 NULL((void*)0), 0x0200, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5147 { &hf_tns_ntp_flag_pio, {
5148 "Packet oriented IO", "tns.ntp_flag.pio", FT_BOOLEAN, 16,
5149 NULL((void*)0), 0x0100, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5150 { &hf_tns_ntp_flag_grant, {
5151 "Can grant connection to another", "tns.ntp_flag.grant", FT_BOOLEAN, 16,
5152 NULL((void*)0), 0x0080, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5153 { &hf_tns_ntp_flag_handoff, {
5154 "Can handoff connection to another", "tns.ntp_flag.handoff", FT_BOOLEAN, 16,
5155 NULL((void*)0), 0x0040, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5156 { &hf_tns_ntp_flag_sigio, {
5157 "Generate SIGIO signal", "tns.ntp_flag.sigio", FT_BOOLEAN, 16,
5158 NULL((void*)0), 0x0020, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5159 { &hf_tns_ntp_flag_sigpipe, {
5160 "Generate SIGPIPE signal", "tns.ntp_flag.sigpipe", FT_BOOLEAN, 16,
5161 NULL((void*)0), 0x0010, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5162 { &hf_tns_ntp_flag_sigurg, {
5163 "Generate SIGURG signal", "tns.ntp_flag.sigurg", FT_BOOLEAN, 16,
5164 NULL((void*)0), 0x0008, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5165 { &hf_tns_ntp_flag_urgentio, {
5166 "Urgent IO supported", "tns.ntp_flag.urgentio", FT_BOOLEAN, 16,
5167 NULL((void*)0), 0x0004, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5168 { &hf_tns_ntp_flag_fdio, {
5169 "Full duplex IO supported", "tns.ntp_flag.dfio", FT_BOOLEAN, 16,
5170 NULL((void*)0), 0x0002, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5171 { &hf_tns_ntp_flag_testop, {
5172 "Test operation", "tns.ntp_flag.testop", FT_BOOLEAN, 16,
5173 NULL((void*)0), 0x0001, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5174
5175
5176
5177
5178 { &hf_tns_line_turnaround, {
5179 "Line Turnaround Value", "tns.line_turnaround", FT_UINT16, BASE_DEC,
5180 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5181 { &hf_tns_value_of_one, {
5182 "Value of 1 in Hardware", "tns.value_of_one", FT_BYTES, BASE_NONE,
5183 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5184
5185 { &hf_tns_connect_data_length, {
5186 "Length of Connect Data", "tns.connect_data_length", FT_UINT16,
5187 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) }},
5188 { &hf_tns_connect_data_offset, {
5189 "Offset to Connect Data", "tns.connect_data_offset", FT_UINT16, BASE_DEC,
5190 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5191 { &hf_tns_connect_data_max, {
5192 "Maximum Receivable Connect Data", "tns.connect_data_max", FT_UINT32, BASE_DEC,
5193 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5194
5195 { &hf_tns_connect_flags0, {
5196 "Connect Flags 0", "tns.connect_flags0", FT_UINT8, BASE_HEX,
5197 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5198 { &hf_tns_connect_flags1, {
5199 "Connect Flags 1", "tns.connect_flags1", FT_UINT8, BASE_HEX,
5200 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5201
5202 { &hf_tns_conn_flag_nareq, {
5203 "NA services required", "tns.connect_flags.nareq", FT_BOOLEAN, 8,
5204 NULL((void*)0), 0x10, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5205 { &hf_tns_conn_flag_nalink, {
5206 "NA services linked in", "tns.connect_flags.nalink", FT_BOOLEAN, 8,
5207 NULL((void*)0), 0x08, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5208 { &hf_tns_conn_flag_enablena, {
5209 "NA services enabled", "tns.connect_flags.enablena", FT_BOOLEAN, 8,
5210 NULL((void*)0), 0x04, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5211 { &hf_tns_conn_flag_ichg, {
5212 "Interchange is involved", "tns.connect_flags.ichg", FT_BOOLEAN, 8,
5213 NULL((void*)0), 0x02, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5214 { &hf_tns_conn_flag_wantna, {
5215 "NA services wanted", "tns.connect_flags.wantna", FT_BOOLEAN, 8,
5216 NULL((void*)0), 0x01, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5217
5218
5219 { &hf_tns_trace_cf1, {
5220 "Trace Cross Facility Item 1", "tns.trace_cf1", FT_UINT32, BASE_HEX,
5221 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5222 { &hf_tns_trace_cf2, {
5223 "Trace Cross Facility Item 2", "tns.trace_cf2", FT_UINT32, BASE_HEX,
5224 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5225 { &hf_tns_trace_cid, {
5226 "Trace Unique Connection ID", "tns.trace_cid", FT_UINT64, BASE_HEX,
5227 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5228 { &hf_tns_connect_data, {
5229 "Connect Data", "tns.connect_data", FT_STRING, BASE_NONE,
5230 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5231
5232 { &hf_tns_accept_data_length, {
5233 "Accept Data Length", "tns.accept_data_length", FT_UINT16,
5234 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) }},
5235 { &hf_tns_accept_data, {
5236 "Accept Data", "tns.accept_data", FT_STRING, BASE_NONE,
5237 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5238 { &hf_tns_accept_data_offset, {
5239 "Offset to Accept Data", "tns.accept_data_offset", FT_UINT16, BASE_DEC,
5240 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5241
5242 { &hf_tns_refuse_reason_user, {
5243 "Refuse Reason (User)", "tns.refuse_reason_user", FT_UINT8, BASE_HEX,
5244 NULL((void*)0), 0x0, "Refuse Reason from Application", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5245 { &hf_tns_refuse_reason_system, {
5246 "Refuse Reason (System)", "tns.refuse_reason_system", FT_UINT8, BASE_HEX,
5247 NULL((void*)0), 0x0, "Refuse Reason from System", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5248 { &hf_tns_refuse_data_length, {
5249 "Refuse Data Length", "tns.refuse_data_length", FT_UINT16,
5250 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) }},
5251 { &hf_tns_refuse_data, {
5252 "Refuse Data", "tns.refuse_data", FT_STRING, BASE_NONE,
5253 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5254
5255 { &hf_tns_abort_reason_user, {
5256 "Abort Reason (User)", "tns.abort_reason_user", FT_UINT8, BASE_HEX,
5257 NULL((void*)0), 0x0, "Abort Reason from Application", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5258 { &hf_tns_abort_reason_system, {
5259 "Abort Reason (User)", "tns.abort_reason_system", FT_UINT8, BASE_HEX,
5260 NULL((void*)0), 0x0, "Abort Reason from System", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5261 { &hf_tns_abort_data, {
5262 "Abort Data", "tns.abort_data", FT_STRING, BASE_NONE,
5263 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5264
5265 { &hf_tns_marker_type, {
5266 "Marker Type", "tns.marker.type", FT_UINT8, BASE_HEX,
5267 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) }},
5268 { &hf_tns_marker_data_byte, {
5269 "Marker Data Byte", "tns.marker.databyte", FT_UINT8, BASE_HEX,
5270 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5271 { &hf_tns_marker_function, {
5272 "Marker Function", "tns.marker.function", FT_UINT8, BASE_DEC,
5273 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) }},
5274#if 0
5275 { &hf_tns_marker_data, {
5276 "Marker Data", "tns.marker.data", FT_UINT16, BASE_HEX,
5277 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5278#endif
5279
5280 { &hf_tns_control_cmd, {
5281 "Control Command", "tns.control.cmd", FT_UINT16, BASE_HEX,
5282 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) }},
5283 { &hf_tns_control_data, {
5284 "Control Data", "tns.control.data", FT_BYTES, BASE_NONE,
5285 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5286
5287 { &hf_tns_redirect_data_length, {
5288 "Redirect Data Length", "tns.redirect_data_length", FT_UINT16,
5289 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) }},
5290 { &hf_tns_redirect_data, {
5291 "Redirect Data", "tns.redirect_data", FT_STRING, BASE_NONE,
5292 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5293
5294 { &hf_tns_data_flag, {
5295 "Data Flag", "tns.data_flag", FT_UINT16, BASE_HEX,
5296 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5297 { &hf_tns_data_flag_send, {
5298 "Send Token", "tns.data_flag.send", FT_BOOLEAN, 16,
5299 NULL((void*)0), 0x1, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5300 { &hf_tns_data_flag_rc, {
5301 "Request Confirmation", "tns.data_flag.rc", FT_BOOLEAN, 16,
5302 NULL((void*)0), 0x2, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5303 { &hf_tns_data_flag_c, {
5304 "Confirmation", "tns.data_flag.c", FT_BOOLEAN, 16,
5305 NULL((void*)0), 0x4, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5306 { &hf_tns_data_flag_reserved, {
5307 "Reserved", "tns.data_flag.reserved", FT_BOOLEAN, 16,
5308 NULL((void*)0), 0x8, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5309 { &hf_tns_data_flag_more, {
5310 "More Data to Come", "tns.data_flag.more", FT_BOOLEAN, 16,
5311 NULL((void*)0), 0x0020, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5312 { &hf_tns_data_flag_eof, {
5313 "End of File", "tns.data_flag.eof", FT_BOOLEAN, 16,
5314 NULL((void*)0), 0x0040, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5315 { &hf_tns_data_flag_dic, {
5316 "Do Immediate Confirmation", "tns.data_flag.dic", FT_BOOLEAN, 16,
5317 NULL((void*)0), 0x0080, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5318 { &hf_tns_data_flag_rts, {
5319 "Request To Send", "tns.data_flag.rts", FT_BOOLEAN, 16,
5320 NULL((void*)0), 0x0100, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5321 { &hf_tns_data_flag_sntt, {
5322 "Send NT Trailer", "tns.data_flag.sntt", FT_BOOLEAN, 16,
5323 NULL((void*)0), 0x0200, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5324
5325 { &hf_tns_data_id, {
5326 "Data ID", "tns.data_id", FT_UINT32, BASE_HEX,
5327 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) }},
5328 { &hf_tns_data_length, {
5329 "Data Length", "tns.data_length", FT_UINT32,
5330 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) }},
5331
5332 { &hf_tns_data_oci_id, {
5333 "Call ID", "tns.data_oci.id", FT_UINT8, BASE_HEX|BASE_EXT_STRING0x00000200,
5334 &tns_data_oci_subfuncs_ext, 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5335
5336 { &hf_tns_data_tseq, {
5337 "TSeq", "tns.data_tseq", FT_UINT8, BASE_HEX,
5338 NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5339
5340 { &hf_tns_data_token, {
5341 "Token", "tns.data.token", FT_UINT64, BASE_DEC,
5342 NULL((void*)0), 0x0, "Call token (23ai); the reply echoes it", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5343 { &hf_tns_data_piggyback_id, {
5344 /* Also Call ID.
5345 Piggyback is a message what calls a small subset of functions
5346 declared in tns_data_oci_subfuncs. */
5347 "Call ID", "tns.data_piggyback.id", FT_UINT8, BASE_HEX|BASE_EXT_STRING0x00000200,
5348 &tns_data_oci_subfuncs_ext, 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5349
5350 { &hf_tns_data_unused, {
5351 "Unused", "tns.data.unused", FT_BYTES, BASE_NONE,
5352 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5353
5354 { &hf_tns_cursor, {
5355 "Cursor", "tns.data.cursor", FT_UINT32, BASE_DEC,
5356 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5357
5358 { &hf_tns_data_setp_acc_version, {
5359 "Accepted Version", "tns.data_setp_req.acc_vers", FT_UINT8, BASE_DEC,
5360 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5361 { &hf_tns_data_setp_cli_plat, {
5362 "Client Platform", "tns.data_setp_req.cli_plat", FT_STRINGZ, BASE_NONE,
5363 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5364 { &hf_tns_data_setp_version, {
5365 "Version", "tns.data_setp_resp.version", FT_UINT8, BASE_DEC,
5366 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5367 { &hf_tns_data_setp_banner, {
5368 "Server Banner", "tns.data_setp_resp.banner", FT_STRINGZ, BASE_NONE,
5369 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5370
5371 { &hf_tns_data_sns_cli_vers, {
5372 "Client Version", "tns.data_sns.cli_vers", FT_UINT32, BASE_CUSTOM,
5373 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) }},
5374 { &hf_tns_data_sns_srv_vers, {
5375 "Server Version", "tns.data_sns.srv_vers", FT_UINT32, BASE_CUSTOM,
5376 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) }},
5377 { &hf_tns_data_sns_srvcnt, {
5378 "Services", "tns.data_sns.srvcnt", FT_UINT16, BASE_DEC,
5379 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5380
5381 { &hf_tns_data_setdt_charset_in, {
5382 "Charset In", "tns.data_setdt.charset_in", FT_UINT16, BASE_DEC,
5383 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) }},
5384 { &hf_tns_data_setdt_charset_out, {
5385 "Charset Out", "tns.data_setdt.charset_out", FT_UINT16, BASE_DEC,
5386 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) }},
5387 { &hf_tns_data_setdt_flag, {
5388 "Flag", "tns.data_setdt.flag", FT_UINT8, BASE_HEX,
5389 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5390 { &hf_tns_data_setdt_caphdr, {
5391 "Capability Header", "tns.data_setdt.caphdr", FT_BYTES, BASE_NONE,
5392 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5393 { &hf_tns_data_setdt_caphdr_version, {
5394 "Version", "tns.data_setdt.caphdr.version", FT_UINT24, BASE_HEX,
5395 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5396 { &hf_tns_data_setdt_caphdr_flags, {
5397 "Flags", "tns.data_setdt.caphdr.flags", FT_BYTES, BASE_NONE,
5398 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5399 { &hf_tns_data_field_version, {
5400 "Field Version", "tns.data.field_version", FT_UINT8, BASE_DEC,
5401 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) }},
5402 { &hf_tns_data_setdt_field_version, {
5403 "Field Version", "tns.data_setdt.field_version", FT_UINT8, BASE_DEC,
5404 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) }},
5405 { &hf_tns_data_setdt_tblhdr, {
5406 "Table Header", "tns.data_setdt.tblhdr", FT_BYTES, BASE_NONE,
5407 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5408 { &hf_tns_data_setdt_idmap, {
5409 "Identity Map", "tns.data_setdt.idmap", FT_BYTES, BASE_NONE,
5410 NULL((void*)0), 0x0, "245 entries: type N -> repr N (default mapping)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5411 { &hf_tns_data_setdt_overrides, {
5412 "Type Overrides", "tns.data_setdt.overrides", FT_NONE, BASE_NONE,
5413 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5414 { &hf_tns_data_setdt_override_client, {
5415 "Client Type", "tns.data_setdt.override.client", FT_UINT8, BASE_DEC,
5416 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) }},
5417 { &hf_tns_data_setdt_override_repr, {
5418 "Server Repr", "tns.data_setdt.override.repr", FT_UINT8, BASE_DEC,
5419 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) }},
5420 { &hf_tns_data_setdt_override_format, {
5421 "Format", "tns.data_setdt.override.format", FT_UINT8, BASE_DEC,
5422 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5423
5424 { &hf_tns_data_rpa_num_al8o4, {
5425 "Number of al8o4 Words", "tns.data_rpa.num_al8o4", FT_UINT32, BASE_DEC,
5426 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5427 { &hf_tns_data_rpa_al8o4, {
5428 "al8o4", "tns.data_rpa.al8o4", FT_UINT32, BASE_HEX,
5429 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5430 { &hf_tns_data_rpa_al8txl, {
5431 "al8txl", "tns.data_rpa.al8txl", FT_BYTES, BASE_NONE,
5432 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5433 { &hf_tns_data_rpa_num_kv, {
5434 "Number of Key/Value Pairs", "tns.data_rpa.num_kv", FT_UINT32, BASE_DEC,
5435 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5436 { &hf_tns_data_rpa_registration, {
5437 "Registration", "tns.data_rpa.registration", FT_BYTES, BASE_NONE,
5438 NULL((void*)0), 0x0, "Query registration; the last 8 bytes are the query id", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5439 { &hf_tns_data_rpa_num_rowcounts, {
5440 "Number of Row Counts", "tns.data_rpa.num_rowcounts", FT_UINT32, BASE_DEC,
5441 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5442 { &hf_tns_data_rpa_dml_rowcount, {
5443 "DML Row Count", "tns.data_rpa.dml_rowcount", FT_UINT64, BASE_DEC,
5444 NULL((void*)0), 0x0, "Rows one iteration of an array DML affected", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5445 { &hf_tns_data_spb_opcode, {
5446 "Opcode", "tns.data_spb.opcode", FT_UINT8, BASE_DEC,
5447 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) }},
5448 { &hf_tns_data_spb_ltxid, {
5449 "Logical Transaction Id", "tns.data_spb.ltxid", FT_BYTES, BASE_NONE,
5450 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5451 { &hf_tns_data_spb_os_pid, {
5452 "OS PID", "tns.data_spb.os_pid", FT_STRING, BASE_NONE,
5453 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5454 { &hf_tns_data_spb_num_kv, {
5455 "Number of Key/Value Pairs", "tns.data_spb.num_kv", FT_UINT32, BASE_DEC,
5456 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5457 { &hf_tns_data_spb_flags, {
5458 "Flags", "tns.data_spb.flags", FT_UINT32, BASE_HEX,
5459 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5460 { &hf_tns_data_spb_session_id, {
5461 "Session Id", "tns.data_spb.session_id", FT_UINT32, BASE_DEC,
5462 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5463 { &hf_tns_data_spb_serial_num, {
5464 "Serial Number", "tns.data_spb.serial_num", FT_UINT16, BASE_DEC,
5465 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5466 { &hf_tns_data_kv_text, {
5467 "Text Value", "tns.data_kv.text", FT_STRING, BASE_NONE,
5468 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5469 { &hf_tns_data_kv_binary, {
5470 "Binary Value", "tns.data_kv.binary", FT_BYTES, BASE_NONE,
5471 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5472 { &hf_tns_data_kv_keyword, {
5473 "Keyword", "tns.data_kv.keyword", FT_UINT16, BASE_DEC,
5474 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) }},
5475 { &hf_tns_data_wrn_code, {
5476 "Warning Code", "tns.data_wrn.code", FT_UINT16, BASE_DEC,
5477 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5478 { &hf_tns_data_wrn_length, {
5479 "Message Length", "tns.data_wrn.length", FT_UINT16, BASE_DEC,
5480 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5481 { &hf_tns_data_wrn_flags, {
5482 "Flags", "tns.data_wrn.flags", FT_UINT16, BASE_HEX,
5483 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5484 { &hf_tns_data_wrn_message, {
5485 "Message", "tns.data_wrn.message", FT_STRING, BASE_NONE,
5486 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5487 { &hf_tns_data_oci_oer_status, {
5488 "Status", "tns.data_oer.oci_status", FT_UINT8, BASE_DEC,
5489 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) }},
5490 { &hf_tns_data_oci_oer_seq, {
5491 "End-to-End Sequence", "tns.data_oer.seq", FT_UINT16, BASE_DEC,
5492 NULL((void*)0), 0x0, "A per-session counter the server advances with each reply", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5493 { &hf_tns_data_oci_oer_category, {
5494 "Statement Category", "tns.data_oer.category", FT_UINT8, BASE_DEC,
5495 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) }},
5496 { &hf_tns_data_oci_oer_error_pos, {
5497 "Error Position", "tns.data_oer.error_pos", FT_UINT8, BASE_DEC,
5498 NULL((void*)0), 0x0, "Offset into the SQL text of the parse error", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5499 { &hf_tns_data_oci_oer_command, {
5500 "Command Type", "tns.data_oer.command_type", FT_UINT8, BASE_DEC,
5501 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) }},
5502 { &hf_tns_data_oci_oer_call_seq, {
5503 "Call Sequence", "tns.data_oer.call_seq", FT_UINT16, BASE_DEC,
5504 NULL((void*)0), 0x0, "Sequence number of the call this status answers", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5505 { &hf_tns_data_sta_call_status, {
5506 "Call Status", "tns.data_sta.call_status", FT_UINT32, BASE_HEX,
5507 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5508 { &hf_tns_data_sta_seq, {
5509 "End-to-End Sequence", "tns.data_sta.seq", FT_UINT16, BASE_DEC,
5510 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5511 { &hf_tns_data_call_status_txn, {
5512 "Transaction in progress", "tns.data.call_status.txn_in_progress", FT_BOOLEAN, 32,
5513 NULL((void*)0), TNS_CALL_STATUS_TXN_IN_PROGRESS0x00000002, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5514 { &hf_tns_data_call_status_sess_release, {
5515 "Session release", "tns.data.call_status.sess_release", FT_BOOLEAN, 32,
5516 NULL((void*)0), TNS_CALL_STATUS_SESS_RELEASE0x00008000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5517 { &hf_tns_data_oer_call_status, {
5518 "Call Status", "tns.data_oer.call_status", FT_INT32, BASE_DEC,
5519 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5520 { &hf_tns_data_oer_rowcount, {
5521 "Row Count", "tns.data_oer.rowcount", FT_INT32, BASE_DEC,
5522 NULL((void*)0), 0x0, "DML affected rows (11g)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5523 { &hf_tns_data_oer_err_code, {
5524 "Error Code", "tns.data_oer.err_code", FT_INT32, BASE_DEC,
5525 NULL((void*)0), 0x0, "ORA-NNNNN (0 = success)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5526 { &hf_tns_data_oer_cursor_id, {
5527 "Cursor Id", "tns.data_oer.cursor_id", FT_INT32, BASE_DEC,
5528 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5529 { &hf_tns_data_oer_n_batch_errcodes, {
5530 "Batch Error Codes", "tns.data_oer.n_batch_errcodes", FT_INT32, BASE_DEC,
5531 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5532 { &hf_tns_data_oer_n_batch_offsets, {
5533 "Batch Error Offsets", "tns.data_oer.n_batch_offsets", FT_INT32, BASE_DEC,
5534 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5535 { &hf_tns_data_oer_n_batch_messages, {
5536 "Batch Error Messages", "tns.data_oer.n_batch_messages", FT_INT32, BASE_DEC,
5537 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5538 { &hf_tns_data_oer_err_num_ext, {
5539 "Error Number", "tns.data_oer.err_num", FT_UINT32, BASE_DEC,
5540 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) }},
5541 { &hf_tns_data_oer_rowcount_ext, {
5542 "Row Count (64 bit)", "tns.data_oer.rowcount64", FT_UINT64, BASE_DEC,
5543 NULL((void*)0), 0x0, "The row count at its full width (12.1 and later)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5544 { &hf_tns_data_oer_sql_type, {
5545 "SQL Type", "tns.data_oer.sql_type", FT_UINT32, BASE_DEC,
5546 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5547 { &hf_tns_data_oer_checksum, {
5548 "Server Checksum", "tns.data_oer.checksum", FT_UINT32, BASE_HEX,
5549 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5550 { &hf_tns_data_oer_message, {
5551 "Message", "tns.data_oer.message", FT_STRING, BASE_NONE,
5552 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5553
5554 { &hf_tns_data_opi_version2_banner_len, {
5555 "Banner Length", "tns.data_opi.vers2.banner_len", FT_UINT8, BASE_DEC,
5556 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5557 { &hf_tns_data_opi_version2_banner, {
5558 "Banner", "tns.data_opi.vers2.banner", FT_STRING, BASE_NONE,
5559 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5560 { &hf_tns_data_opi_version2_vsnum, {
5561 "Version", "tns.data_opi.vers2.version", FT_UINT32, BASE_CUSTOM,
5562 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) }},
5563
5564 { &hf_tns_data_opi_num_of_params, {
5565 "Number of parameters", "tns.data_opi.num_of_params", FT_UINT8, BASE_DEC,
5566 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5567 { &hf_tns_data_opi_param_length, {
5568 "Length", "tns.data_opi.param_length", FT_UINT8, BASE_DEC,
5569 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5570 { &hf_tns_data_opi_param_name, {
5571 "Name", "tns.data_opi.param_name", FT_STRING, BASE_NONE,
5572 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5573 { &hf_tns_data_opi_param_value, {
5574 "Value", "tns.data_opi.param_value", FT_STRING, BASE_NONE,
5575 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5576
5577 { &hf_tns_data_iov_num_binds, {
5578 "Number of Binds", "tns.data_iov.num_binds", FT_UINT32, BASE_DEC,
5579 NULL((void*)0), 0x0, "num_iters * 256 + num_requests", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5580 { &hf_tns_data_iov_bind_dir, {
5581 "Bind Direction", "tns.data_iov.bind_dir", FT_UINT8, BASE_DEC,
5582 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) }},
5583
5584 { &hf_tns_data_bind_retcode, {
5585 "Return Code", "tns.data_bind.retcode", FT_INT32, BASE_DEC,
5586 NULL((void*)0), 0x0, "Non-zero when an OUT value was truncated", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5587 { &hf_tns_data_dcb_num_columns, {
5588 "Number of Columns", "tns.data_dcb.num_columns", FT_UINT32, BASE_DEC,
5589 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5590 { &hf_tns_data_col_type, {
5591 "Data Type", "tns.data_col.type", FT_UINT8, BASE_DEC,
5592 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) }},
5593 { &hf_tns_data_col_precision, {
5594 "Precision", "tns.data_col.precision", FT_UINT8, BASE_DEC,
5595 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5596 { &hf_tns_data_col_scale, {
5597 "Scale", "tns.data_col.scale", FT_INT32, BASE_DEC,
5598 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5599 { &hf_tns_data_col_max_length, {
5600 "Max Data Length", "tns.data_col.max_length", FT_UINT32, BASE_DEC,
5601 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5602 { &hf_tns_data_col_charset, {
5603 "Charset", "tns.data_col.charset", FT_UINT32, BASE_DEC,
5604 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) }},
5605 { &hf_tns_data_col_csform, {
5606 "Charset Form", "tns.data_col.csform", FT_UINT8, BASE_DEC,
5607 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) }},
5608 { &hf_tns_data_col_max_size, {
5609 "Max Size", "tns.data_col.max_size", FT_UINT32, BASE_DEC,
5610 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5611 { &hf_tns_data_col_nulls_ok, {
5612 "Nulls Allowed", "tns.data_col.nulls_ok", FT_UINT8, BASE_DEC,
5613 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5614 { &hf_tns_data_col_name, {
5615 "Column Name", "tns.data_col.name", FT_STRING, BASE_NONE,
5616 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5617
5618 { &hf_tns_data_col_uds_flags, {
5619 "UDS Flags", "tns.data_col.uds_flags", FT_UINT32, BASE_HEX,
5620 NULL((void*)0), 0x0, "Marks a JSON column", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5621 { &hf_tns_data_col_domain_schema, {
5622 "Domain Schema", "tns.data_col.domain_schema", FT_STRING, BASE_NONE,
5623 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5624 { &hf_tns_data_col_domain_name, {
5625 "Domain Name", "tns.data_col.domain_name", FT_STRING, BASE_NONE,
5626 NULL((void*)0), 0x0, "The column's SQL domain", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5627 { &hf_tns_data_col_annotation, {
5628 "Annotation", "tns.data_col.annotation", FT_STRING, BASE_NONE,
5629 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5630 { &hf_tns_data_col_vector_dims, {
5631 "Vector Dimensions", "tns.data_col.vector_dims", FT_UINT32, BASE_DEC,
5632 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5633 { &hf_tns_data_col_vector_format, {
5634 "Vector Format", "tns.data_col.vector_format", FT_UINT8, BASE_DEC,
5635 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5636 { &hf_tns_data_rxh_num_requests, {
5637 "Number of Requests", "tns.data_rxh.num_requests", FT_UINT32, BASE_DEC,
5638 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5639 { &hf_tns_data_rxh_iter_num, {
5640 "Iteration Number", "tns.data_rxh.iter_num", FT_UINT32, BASE_DEC,
5641 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5642 { &hf_tns_data_bit_vector, {
5643 "Bit Vector", "tns.data.bit_vector", FT_BYTES, BASE_NONE,
5644 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) }},
5645 { &hf_tns_data_bvc_num_cols_sent, {
5646 "Columns Sent", "tns.data_bvc.num_cols_sent", FT_UINT16, BASE_DEC,
5647 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5648 { &hf_tns_data_irs_num_results, {
5649 "Number of Result Sets", "tns.data_irs.num_results", FT_UINT32, BASE_DEC,
5650 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5651 { &hf_tns_data_rxh_num_iters, {
5652 "Number of Iterations", "tns.data_rxh.num_iters", FT_UINT32, BASE_DEC,
5653 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5654
5655 { &hf_tns_data_all8_options, {
5656 "Options", "tns.data_all8.options", FT_UINT32, BASE_HEX,
5657 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5658 { &hf_tns_data_all8_opt_parse, {
5659 "Parse", "tns.data_all8.options.parse", FT_BOOLEAN, 32,
5660 NULL((void*)0), 0x00000001, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5661 { &hf_tns_data_all8_opt_bind, {
5662 "Bind Values Present", "tns.data_all8.options.bind", FT_BOOLEAN, 32,
5663 NULL((void*)0), 0x00000008, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5664 { &hf_tns_data_all8_opt_define, {
5665 "Define Columns Present", "tns.data_all8.options.define", FT_BOOLEAN, 32,
5666 NULL((void*)0), 0x00000010, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5667 { &hf_tns_data_all8_opt_execute, {
5668 "Execute", "tns.data_all8.options.execute", FT_BOOLEAN, 32,
5669 NULL((void*)0), 0x00000020, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5670 { &hf_tns_data_all8_opt_commit, {
5671 "Autocommit", "tns.data_all8.options.commit", FT_BOOLEAN, 32,
5672 NULL((void*)0), 0x00000100, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5673 { &hf_tns_data_all8_opt_plsql, {
5674 "PL/SQL Binds", "tns.data_all8.options.plsql", FT_BOOLEAN, 32,
5675 NULL((void*)0), 0x00000400, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5676 { &hf_tns_data_all8_opt_fetch, {
5677 "Fetch", "tns.data_all8.options.fetch", FT_BOOLEAN, 32,
5678 NULL((void*)0), 0x00000040, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5679 { &hf_tns_data_all8_opt_not_plsql, {
5680 "Not PL/SQL", "tns.data_all8.options.not_plsql", FT_BOOLEAN, 32,
5681 NULL((void*)0), 0x00008000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5682 { &hf_tns_data_all8_opt_describe, {
5683 "Describe", "tns.data_all8.options.describe", FT_BOOLEAN, 32,
5684 NULL((void*)0), 0x00020000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5685 { &hf_tns_data_all8_opt_batch_errors, {
5686 "Batch Errors", "tns.data_all8.options.batch_errors", FT_BOOLEAN, 32,
5687 NULL((void*)0), 0x00080000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5688 { &hf_tns_data_all8_fetch_rows, {
5689 "Fetch Rows", "tns.data_all8.fetch_rows", FT_UINT32, BASE_DEC,
5690 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5691 { &hf_tns_data_all8_iterations, {
5692 "Execution Count", "tns.data_all8.iterations", FT_UINT32, BASE_DEC,
5693 NULL((void*)0), 0x0, "Number of times a DML statement runs (array DML)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5694 { &hf_tns_data_all8_prefetch, {
5695 "Prefetch Rows", "tns.data_all8.prefetch", FT_UINT32, BASE_DEC,
5696 NULL((void*)0), 0x0, "Rows a query returns with the execute, before any fetch", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5697 { &hf_tns_data_all8_is_query, {
5698 "Query", "tns.data_all8.is_query", FT_BOOLEAN, BASE_NONE,
5699 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5700 { &hf_tns_data_all8_exec_flags, {
5701 "Execute Flags", "tns.data_all8.exec_flags", FT_UINT32, BASE_HEX,
5702 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5703 { &hf_tns_data_all8_xflag_scrollable, {
5704 "Scrollable", "tns.data_all8.exec_flags.scrollable", FT_BOOLEAN, 32,
5705 NULL((void*)0), 0x00000002, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5706 { &hf_tns_data_all8_xflag_no_cancel_on_eof, {
5707 "No Cancel on EOF", "tns.data_all8.exec_flags.no_cancel_on_eof", FT_BOOLEAN, 32,
5708 NULL((void*)0), 0x00000080, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5709 { &hf_tns_data_all8_xflag_dml_rowcounts, {
5710 "DML Row Counts", "tns.data_all8.exec_flags.dml_rowcounts", FT_BOOLEAN, 32,
5711 NULL((void*)0), 0x00004000, "Return the rows each iteration of an array DML affected", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5712 { &hf_tns_data_all8_xflag_implicit_rs, {
5713 "Implicit Result Sets", "tns.data_all8.exec_flags.implicit_resultset", FT_BOOLEAN, 32,
5714 NULL((void*)0), 0x00008000, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5715 { &hf_tns_data_all8_fetch_orientation, {
5716 "Fetch Orientation", "tns.data_all8.fetch_orientation", FT_UINT32, BASE_HEX,
5717 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) }},
5718 { &hf_tns_data_all8_fetch_pos, {
5719 "Fetch Position", "tns.data_all8.fetch_pos", FT_UINT32, BASE_DEC,
5720 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5721 { &hf_tns_data_reexec_iterations, {
5722 "Execution Count", "tns.data_reexec.iterations", FT_UINT32, BASE_DEC,
5723 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5724 { &hf_tns_data_reexec_options2, {
5725 "Options 2", "tns.data_reexec.options2", FT_UINT32, BASE_HEX,
5726 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5727 { &hf_tns_data_reexec_opt2_commit, {
5728 "Autocommit", "tns.data_reexec.options2.commit", FT_BOOLEAN, 32,
5729 NULL((void*)0), 0x00000001, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5730 { &hf_tns_data_all8_oci_preamble, {
5731 "Preamble", "tns.data_all8.oci_preamble", FT_STRING, BASE_NONE,
5732 NULL((void*)0), 0x0, "The fixed execute preamble of an OCI client", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5733 { &hf_tns_data_all8_define_count, {
5734 "Define Count", "tns.data_all8.define_count", FT_UINT32, BASE_DEC,
5735 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5736 { &hf_tns_data_all8_bind_count, {
5737 "Bind Count", "tns.data_all8.bind_count", FT_UINT32, BASE_DEC,
5738 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5739 { &hf_tns_data_all8_sql, {
5740 "SQL Text", "tns.data_all8.sql", FT_STRING, BASE_NONE,
5741 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5742 { &hf_tns_data_bind_value, {
5743 "Bind Value", "tns.data_bind.value", FT_BYTES, BASE_NONE,
5744 NULL((void*)0), 0x0, "Raw type-encoded bind value", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5745 { &hf_tns_data_fetch_rows, {
5746 "Rows to Fetch", "tns.data_fetch.rows", FT_UINT32, BASE_DEC,
5747 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5748 { &hf_tns_data_lob_op, {
5749 "LOB Operation", "tns.data_lob.op", FT_UINT32, BASE_HEX,
5750 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) }},
5751 { &hf_tns_data_lob_offset, {
5752 "Source Offset", "tns.data_lob.offset", FT_UINT64, BASE_DEC,
5753 NULL((void*)0), 0x0, "1-based offset into the LOB", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5754 { &hf_tns_data_lob_locator, {
5755 "Locator", "tns.data_lob.locator", FT_BYTES, BASE_NONE,
5756 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5757 { &hf_tns_data_lob_charset, {
5758 "Charset", "tns.data_lob.charset", FT_UINT32, BASE_DEC,
5759 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) }},
5760 { &hf_tns_data_lob_data, {
5761 "Data", "tns.data_lob.data", FT_BYTES, BASE_NONE,
5762 NULL((void*)0), 0x0, "LOB content; UTF-16BE for a CLOB", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5763 { &hf_tns_data_lob_total_size, {
5764 "Total Locator Size", "tns.data_lob.total_size", FT_UINT32, BASE_DEC,
5765 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5766 { &hf_tns_data_pgy_schema, {
5767 "Current Schema", "tns.data_piggyback.schema", FT_STRING, BASE_NONE,
5768 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5769 { &hf_tns_data_pgy_session_state, {
5770 "Session State", "tns.data_piggyback.session_state", FT_UINT64, BASE_HEX,
5771 NULL((void*)0), 0x0, "Request boundary: the client begins or ends a request", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5772 { &hf_tns_data_pgy_e2e_flags, {
5773 "Changed Attributes", "tns.data_piggyback.e2e_flags", FT_UINT32, BASE_HEX,
5774 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5775 { &hf_tns_data_pgy_client_id, {
5776 "Client Identifier", "tns.data_piggyback.client_id", FT_STRING, BASE_NONE,
5777 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5778 { &hf_tns_data_pgy_module, {
5779 "Module", "tns.data_piggyback.module", FT_STRING, BASE_NONE,
5780 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5781 { &hf_tns_data_pgy_action, {
5782 "Action", "tns.data_piggyback.action", FT_STRING, BASE_NONE,
5783 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5784 { &hf_tns_data_pgy_client_info, {
5785 "Client Info", "tns.data_piggyback.client_info", FT_STRING, BASE_NONE,
5786 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5787 { &hf_tns_data_pgy_dbop, {
5788 "Database Operation", "tns.data_piggyback.dbop", FT_STRING, BASE_NONE,
5789 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5790 { &hf_tns_data_pgy_error_set_id, {
5791 "Error Set Id", "tns.data_piggyback.error_set_id", FT_UINT16, BASE_DEC,
5792 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5793 { &hf_tns_data_pgy_error_set_mode, {
5794 "Error Set Mode", "tns.data_piggyback.error_set_mode", FT_UINT8, BASE_DEC,
5795 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5796 { &hf_tns_data_pgy_pipeline_mode, {
5797 "Pipeline Mode", "tns.data_piggyback.pipeline_mode", FT_UINT8, BASE_DEC,
5798 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5799 { &hf_tns_data_pgy_sec_flags, {
5800 "Security Context Flags", "tns.data_piggyback.sec_flags", FT_UINT32, BASE_HEX,
5801 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5802 { &hf_tns_data_pgy_sec_key, {
5803 "Security Context Key", "tns.data_piggyback.sec_key", FT_STRING, BASE_NONE,
5804 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5805 { &hf_tns_data_pgy_sec_value, {
5806 "Security Context Value", "tns.data_piggyback.sec_value", FT_BYTES, BASE_NONE,
5807 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5808 { &hf_tns_data_lob_flag, {
5809 "Result", "tns.data_lob.flag", FT_BOOLEAN, BASE_NONE,
5810 NULL((void*)0), 0x0, "Whether the LOB is open, or the file exists", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5811 { &hf_tns_data_lob_amount, {
5812 "Amount", "tns.data_lob.amount", FT_UINT64, BASE_DEC,
5813 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) }},
5814 { &hf_tns_data_col_value, {
5815 "Column Value", "tns.data_col.value", FT_BYTES, BASE_NONE,
5816 NULL((void*)0), 0x0, "Raw type-encoded row column value", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5817
5818 { &hf_tns_data_lob_size, {
5819 "LOB Size", "tns.data_lob.size", FT_UINT64, BASE_DEC,
5820 NULL((void*)0), 0x0, "Characters for a CLOB, bytes for a BLOB", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5821 { &hf_tns_data_lob_chunk_size, {
5822 "LOB Chunk Size", "tns.data_lob.chunk_size", FT_UINT32, BASE_DEC,
5823 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5824 { &hf_tns_data_json_image, {
5825 "OSON Image", "tns.data_json.image", FT_BYTES, BASE_NONE,
5826 NULL((void*)0), 0x0, "Binary JSON (OSON) value", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5827 { &hf_tns_data_vector_image, {
5828 "Vector Image", "tns.data_vector.image", FT_BYTES, BASE_NONE,
5829 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5830 { &hf_tns_data_obj_toid, {
5831 "Type OID", "tns.data_obj.toid", FT_BYTES, BASE_NONE,
5832 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5833 { &hf_tns_data_obj_image, {
5834 "Object Image", "tns.data_obj.image", FT_BYTES, BASE_NONE,
5835 NULL((void*)0), 0x0, "Packed object attributes, or an XMLType document", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5836 { &hf_tns_data_descriptor_row_count, {
5837 "Row Count", "tns.data_descriptor.row_count", FT_UINT32, BASE_DEC,
5838 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5839 { &hf_tns_data_descriptor_row_size, {
5840 "Row Size", "tns.data_descriptor.row_size", FT_UINT32, BASE_DEC,
5841 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5842
5843 { &hf_tns_reserved_byte, {
5844 "Reserved Byte", "tns.reserved_byte", FT_BYTES, BASE_NONE,
5845 NULL((void*)0), 0x0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }},
5846 { &hf_tns_packet_type, {
5847 "Packet Type", "tns.type", FT_UINT8, BASE_DEC,
5848 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) }}
5849
5850 };
5851
5852 static int *ett[] = {
5853 &ett_tns,
5854 &ett_tns_connect,
5855 &ett_tns_accept,
5856 &ett_tns_refuse,
5857 &ett_tns_abort,
5858 &ett_tns_redirect,
5859 &ett_tns_marker,
5860 &ett_tns_attention,
5861 &ett_tns_control,
5862 &ett_tns_data,
5863 &ett_tns_data_flag,
5864 &ett_tns_acc_versions,
5865 &ett_tns_opi_params,
5866 &ett_tns_opi_par,
5867 &ett_tns_sopt_flag,
5868 &ett_tns_ntp_flag,
5869 &ett_tns_conn_flag,
5870 &ett_tns_rows,
5871 &ett_tns_setdt_caphdr,
5872 &ett_tns_setdt_overrides,
5873 &ett_tns_setdt_override,
5874 &ett_tns_oer,
5875 &ett_tns_call_status,
5876 &ett_tns_rpa,
5877 &ett_tns_kv,
5878 &ett_tns_iov,
5879 &ett_tns_dcb_col,
5880 &ett_tns_all8_options,
5881 &ett_tns_all8_i4,
5882 &ett_tns_all8_exec_flags,
5883 &ett_tns_binds,
5884 &ett_tns_bind,
5885 &ett_tns_defines,
5886 &ett_tns_reexec_options2,
5887 &ett_tns_bind_row,
5888 &ett_tns_rxd_row,
5889 &ett_tns_value,
5890 &ett_tns_irs,
5891 &ett_tns_out_binds,
5892 &ett_sql
5893 };
5894
5895 static ei_register_info ei[] = {
5896 { &ei_tns_connect_data_next_packet, { "tns.connect_data.next_packet", PI_REQUEST_CODE0x04000000, PI_CHAT0x00200000, "Long Connect Data (> 221 bytes) carried in subsequent Data packet", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}},
5897 { &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)}}
}},
5898 { &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)}}
}},
5899 { &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)}}
}},
5900 };
5901
5902 module_t *tns_module;
5903 expert_module_t* expert_tns;
5904
5905 proto_tns = proto_register_protocol("Transparent Network Substrate Protocol", "TNS", "tns");
5906 proto_register_field_array(proto_tns, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
5907 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
5908 expert_tns = expert_register_protocol(proto_tns);
5909 expert_register_field_array(expert_tns, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0]));
5910 tns_handle = register_dissector("tns", dissect_tns, proto_tns);
5911
5912 tns_module = prefs_register_protocol(proto_tns, NULL((void*)0));
5913 prefs_register_bool_preference(tns_module, "desegment_tns_messages",
5914 "Reassemble TNS messages spanning multiple TCP segments",
5915 "Whether the TNS dissector should reassemble messages spanning multiple TCP segments. "
5916 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5917 &tns_desegment);
5918}
5919
5920void
5921proto_reg_handoff_tns(void)
5922{
5923 dissector_add_uint_with_preference("tcp.port", TCP_PORT_TNS1521, tns_handle);
5924}
5925
5926/*
5927 * Editor modelines - https://www.wireshark.org/tools/modelines.html
5928 *
5929 * Local variables:
5930 * c-basic-offset: 8
5931 * tab-width: 8
5932 * indent-tabs-mode: t
5933 * End:
5934 *
5935 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
5936 * :indentSize=8:tabSize=8:noTabs=false:
5937 */