Bug Summary

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