Coverage Report

Created: 2026-11-12 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-tns.c
Line
Count
Source
1
/* packet-tns.c
2
 * Routines for Oracle TNS packet dissection
3
 *
4
 * Wireshark - Network traffic analyzer
5
 * By Gerald Combs <gerald@wireshark.org>
6
 * Copyright 1998 Gerald Combs
7
 *
8
 * Copied from packet-tftp.c
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 */
12
13
#include "config.h"
14
15
#include <epan/packet.h>
16
#include "packet-tcp.h"
17
18
#include <epan/prefs.h>
19
#include <epan/expert.h>
20
#include <epan/conversation.h>
21
#include <epan/proto_data.h>
22
#include <epan/unit_strings.h>
23
#include <epan/charsets.h>
24
25
#include <wsutil/array.h>
26
#include <wsutil/pint.h>
27
28
void proto_register_tns(void);
29
30
5
#define TNS_HDR_LEN 8
31
32
/* Packet Types */
33
8
#define TNS_TYPE_CONNECT        1
34
0
#define TNS_TYPE_ACCEPT         2
35
#define TNS_TYPE_ACK            3
36
0
#define TNS_TYPE_REFUSE         4
37
0
#define TNS_TYPE_REDIRECT       5
38
0
#define TNS_TYPE_DATA           6
39
#define TNS_TYPE_NULL           7
40
0
#define TNS_TYPE_ABORT          9
41
#define TNS_TYPE_RESEND         11
42
0
#define TNS_TYPE_MARKER         12
43
0
#define TNS_TYPE_ATTENTION      13
44
0
#define TNS_TYPE_CONTROL        14
45
4
#define TNS_TYPE_DD             15
46
3
#define TNS_TYPE_MAX            19
47
48
/*
49
 * Oracle datatype codes as they appear on the wire and in tns_data_types[].
50
 * python-oracledb lists most of these as its ORA_TYPE_NUM_* constants.
51
 */
52
0
#define TNS_DATATYPE_VARCHAR        1
53
0
#define TNS_DATATYPE_NUMBER         2
54
0
#define TNS_DATATYPE_INTEGER        3    /* BINARY_INTEGER */
55
#define TNS_DATATYPE_FLOAT          4
56
0
#define TNS_DATATYPE_STRING         5
57
#define TNS_DATATYPE_VARNUM         6
58
#define TNS_DATATYPE_DECIMAL        7
59
0
#define TNS_DATATYPE_LONG           8
60
#define TNS_DATATYPE_VCS            9
61
0
#define TNS_DATATYPE_ROWID          11   /* RID */
62
0
#define TNS_DATATYPE_DATE           12
63
#define TNS_DATATYPE_VBI            15
64
0
#define TNS_DATATYPE_RAW            23
65
0
#define TNS_DATATYPE_LONG_RAW       24
66
0
#define TNS_DATATYPE_CHAR           96
67
0
#define TNS_DATATYPE_BINARY_FLOAT   100
68
0
#define TNS_DATATYPE_BINARY_DOUBLE  101
69
0
#define TNS_DATATYPE_REFCURSOR      102
70
#define TNS_DATATYPE_ROWID_EXT      104  /* ROWID */
71
0
#define TNS_DATATYPE_ADT            109  /* object */
72
#define TNS_DATATYPE_REF            111
73
0
#define TNS_DATATYPE_CLOB           112
74
0
#define TNS_DATATYPE_BLOB           113
75
0
#define TNS_DATATYPE_BFILE          114
76
#define TNS_DATATYPE_RSET           116
77
0
#define TNS_DATATYPE_JSON           119  /* OSON */
78
0
#define TNS_DATATYPE_VECTOR         127
79
0
#define TNS_DATATYPE_TIMESTAMP      180
80
0
#define TNS_DATATYPE_TIMESTAMP_TZ   181
81
0
#define TNS_DATATYPE_INTERVAL_YM    182
82
0
#define TNS_DATATYPE_INTERVAL_DS    183
83
0
#define TNS_DATATYPE_UROWID         208
84
0
#define TNS_DATATYPE_TIMESTAMP_LTZ  231
85
0
#define TNS_DATATYPE_BOOLEAN        252
86
87
/* DALC length byte marking a slot with no value (see get_dalc_custom). */
88
0
#define TNS_DALC_ABSENT             0xFD
89
90
/* TTC field versions (compile capability 7), as python-oracledb's
91
 * TNS_CCAP_FIELD_VERSION_* name them. The wire shape of several messages
92
 * depends on the one a connection negotiates. */
93
0
#define TNS_CCAP_FIELD_VERSION  7
94
0
#define TNS_FV_10_2             4   /* older than any python-oracledb names */
95
0
#define TNS_FV_11_2             6
96
0
#define TNS_FV_12_1             7
97
0
#define TNS_FV_12_2             8
98
0
#define TNS_FV_12_2_EXT1        9
99
#define TNS_FV_18_1             10
100
#define TNS_FV_18_1_EXT_1       11
101
#define TNS_FV_19_1             12
102
#define TNS_FV_19_1_EXT_1       13
103
0
#define TNS_FV_20_1             14
104
#define TNS_FV_20_1_EXT_1       15
105
0
#define TNS_FV_21_1             16
106
0
#define TNS_FV_23_1             17
107
0
#define TNS_FV_23_1_EXT_1       18
108
#define TNS_FV_23_1_EXT_2       19
109
0
#define TNS_FV_23_1_EXT_3       20
110
#define TNS_FV_23_1_EXT_4       21
111
#define TNS_FV_23_1_EXT_5       22
112
#define TNS_FV_23_3_EXT_6       23
113
0
#define TNS_FV_23_4             24
114
115
/* Data Packet Functions */
116
0
#define SQLNET_SET_PROTOCOL     1
117
0
#define SQLNET_SET_DATATYPES    2
118
0
#define SQLNET_USER_OCI_FUNC    3
119
0
#define SQLNET_RETURN_STATUS    4
120
#define SQLNET_ACCESS_USR_ADDR  5
121
0
#define SQLNET_ROW_TRANSF_HDR   6
122
0
#define SQLNET_ROW_TRANSF_DATA  7
123
0
#define SQLNET_RETURN_OPI_PARAM 8
124
0
#define SQLNET_FUNCCOMPLETE     9
125
#define SQLNET_NERROR_RET_DEF   10
126
0
#define SQLNET_IOVEC_4FAST_UPI  11
127
#define SQLNET_LONG_4FAST_UPI   12
128
0
#define SQLNET_INVOKE_USER_CB   13
129
0
#define SQLNET_LOB_FILE_DF      14
130
0
#define SQLNET_WARNING          15
131
0
#define SQLNET_DESCRIBE_INFO    16
132
0
#define SQLNET_PIGGYBACK_FUNC   17
133
#define SQLNET_SIG_4UCS         18
134
0
#define SQLNET_FLUSH_BIND_DATA  19
135
0
#define SQLNET_BIT_VECTOR       21
136
0
#define SQLNET_SERVER_PIGGYBACK 23
137
0
#define SQLNET_IMPLICIT_RESULTS 27
138
0
#define SQLNET_END_OF_RESPONSE  29
139
0
#define SQLNET_TOKEN            33
140
0
#define SQLNET_FAST_AUTH        34
141
0
#define SQLNET_SNS              0xdeadbeef
142
#define SQLNET_XTRN_PROCSERV_R1 32
143
#define SQLNET_XTRN_PROCSERV_R2 68
144
145
/* Return OPI Parameter's Type */
146
0
#define OPI_VERSION2            1
147
0
#define OPI_OSESSKEY            2
148
0
#define OPI_OAUTH               3
149
150
/* An OCI client's execute preamble: offsets from the TTI_FUN byte, and
151
 * the 8-byte pointer indicator its fixed slots sit between. */
152
0
#define TNS_OCI_INDICATOR        UINT64_C(0xfeffffffffffffff)
153
0
#define TNS_OCI_ALL8_OPTIONS     3
154
0
#define TNS_OCI_ALL8_CURSOR      7
155
0
#define TNS_OCI_ALL8_IND         11
156
0
#define TNS_OCI_ALL8_SQLLEN3     19
157
0
#define TNS_OCI_ALL8_IND2_NARROW 23
158
0
#define TNS_OCI_ALL8_IND2_WIDE   27
159
/* the al8i4 array's length, after the second indicator */
160
0
#define TNS_OCI_ALL8_AL8I4_NARROW 31
161
0
#define TNS_OCI_ALL8_AL8I4_WIDE   35
162
163
/* The encoding flag of an OCI client's TTI_DTY, which sends no type
164
 * table. */
165
0
#define TNS_DTY_ENCODING_OCI     2
166
167
/* An OCI client's object-type describe (TTI_KOD): the opcodes of its
168
 * request, where the request's name or REF sits from the TTI_FUN byte,
169
 * the kinds of message in its reply, and the last byte of SYS.KOTTD's
170
 * id, the type a type descriptor is an instance of. */
171
0
#define TNS_KOD_BY_NAME          3
172
0
#define TNS_KOD_BY_REF           4
173
0
#define TNS_KOD_FRAME            99
174
0
#define TNS_KOD_RECORD           1
175
0
#define TNS_KOD_HEADER           2
176
0
#define TNS_KOD_KOTTD            1
177
178
/* OCI function ids (TTI_FUN sub-functions). */
179
0
#define TTI_REEXECUTE           4
180
0
#define TTI_FETCH               5
181
0
#define TTI_REEXECUTE_AND_FETCH 78
182
0
#define TTI_KOD                 92
183
0
#define TTI_ALL8                94
184
0
#define TTI_LOBOPS              96
185
0
#define TTI_AQ_ENQUEUE          121
186
0
#define TTI_AQ_DEQUEUE          122
187
0
#define TTI_AQ_ARRAY            145
188
0
#define TTI_TPC_TXN_SWITCH      103
189
0
#define TTI_TPC_TXN_CHANGE_STATE 104
190
0
#define TTI_CLOSE_CURSORS       105
191
0
#define TTI_SET_END_TO_END_ATTR 135
192
0
#define TTI_SET_SCHEMA          152
193
0
#define TTI_APP_CONTEXT         154
194
0
#define TTI_SESSION_RELEASE     163
195
0
#define TTI_SESSION_STATE       176
196
0
#define TTI_PIPELINE_BEGIN      199
197
0
#define TTI_ALTER_SESSION       204
198
0
#define TTI_PIPELINE_END        200
199
0
#define TTI_END_USER_SEC_CTX    205
200
201
/* desegmentation of TNS over TCP */
202
static bool tns_desegment = true;
203
204
static dissector_handle_t tns_handle;
205
206
static int proto_tns;
207
static int hf_tns_request;
208
static int hf_tns_response;
209
static int hf_tns_length;
210
static int hf_tns_packet_checksum;
211
static int hf_tns_header_checksum;
212
static int hf_tns_packet_type;
213
static int hf_tns_reserved_byte;
214
static int hf_tns_version;
215
static int hf_tns_compat_version;
216
217
static int hf_tns_service_options;
218
static int hf_tns_sopt_flag_bconn;
219
static int hf_tns_sopt_flag_pc;
220
static int hf_tns_sopt_flag_hc;
221
static int hf_tns_sopt_flag_fd;
222
static int hf_tns_sopt_flag_hd;
223
static int hf_tns_sopt_flag_dc1;
224
static int hf_tns_sopt_flag_dc2;
225
static int hf_tns_sopt_flag_dio;
226
static int hf_tns_sopt_flag_ap;
227
static int hf_tns_sopt_flag_ra;
228
static int hf_tns_sopt_flag_sa;
229
230
static int hf_tns_sdu_size;
231
static int hf_tns_max_tdu_size;
232
233
static int hf_tns_nt_proto_characteristics;
234
static int hf_tns_ntp_flag_hangon;
235
static int hf_tns_ntp_flag_crel;
236
static int hf_tns_ntp_flag_tduio;
237
static int hf_tns_ntp_flag_srun;
238
static int hf_tns_ntp_flag_dtest;
239
static int hf_tns_ntp_flag_cbio;
240
static int hf_tns_ntp_flag_asio;
241
static int hf_tns_ntp_flag_pio;
242
static int hf_tns_ntp_flag_grant;
243
static int hf_tns_ntp_flag_handoff;
244
static int hf_tns_ntp_flag_sigio;
245
static int hf_tns_ntp_flag_sigpipe;
246
static int hf_tns_ntp_flag_sigurg;
247
static int hf_tns_ntp_flag_urgentio;
248
static int hf_tns_ntp_flag_fdio;
249
static int hf_tns_ntp_flag_testop;
250
251
static int hf_tns_line_turnaround;
252
static int hf_tns_value_of_one;
253
static int hf_tns_connect_data_length;
254
static int hf_tns_connect_data_offset;
255
static int hf_tns_connect_data_max;
256
257
static int hf_tns_connect_flags0;
258
static int hf_tns_connect_flags1;
259
static int hf_tns_conn_flag_nareq;
260
static int hf_tns_conn_flag_nalink;
261
static int hf_tns_conn_flag_enablena;
262
static int hf_tns_conn_flag_ichg;
263
static int hf_tns_conn_flag_wantna;
264
265
static int hf_tns_connect_data;
266
static int hf_tns_trace_cf1;
267
static int hf_tns_trace_cf2;
268
static int hf_tns_trace_cid;
269
270
static int hf_tns_accept_data_length;
271
static int hf_tns_accept_data_offset;
272
static int hf_tns_accept_sdu;
273
static int hf_tns_accept_flags2;
274
static int hf_tns_accept_flags2_check_oob;
275
static int hf_tns_accept_flags2_end_of_response;
276
static int hf_tns_accept_flags2_fast_auth;
277
static int hf_tns_accept_data;
278
279
static int hf_tns_refuse_reason_user;
280
static int hf_tns_refuse_reason_system;
281
static int hf_tns_refuse_data_length;
282
static int hf_tns_refuse_data;
283
284
static int hf_tns_abort_reason_user;
285
static int hf_tns_abort_reason_system;
286
static int hf_tns_abort_data;
287
288
static int hf_tns_marker_type;
289
static int hf_tns_marker_data_byte;
290
static int hf_tns_marker_function;
291
/* static int hf_tns_marker_data; */
292
293
static int hf_tns_redirect_data_length;
294
static int hf_tns_redirect_data;
295
296
static int hf_tns_control_cmd;
297
static int hf_tns_control_data;
298
299
static int hf_tns_data_flag;
300
static int hf_tns_data_flag_send;
301
static int hf_tns_data_flag_rc;
302
static int hf_tns_data_flag_c;
303
static int hf_tns_data_flag_reserved;
304
static int hf_tns_data_flag_more;
305
static int hf_tns_data_flag_eof;
306
static int hf_tns_data_flag_dic;
307
static int hf_tns_data_flag_rts;
308
static int hf_tns_data_flag_sntt;
309
static int hf_tns_data_flag_end_of_request;
310
static int hf_tns_data_flag_begin_pipeline;
311
static int hf_tns_data_flag_end_of_response;
312
313
static int hf_tns_data_id;
314
static int hf_tns_data_length;
315
static int hf_tns_data_oci_id;
316
static int hf_tns_data_tseq;
317
static int hf_tns_data_token;
318
static int hf_tns_data_piggyback_id;
319
static int hf_tns_data_unused;
320
321
static int hf_tns_cursor;
322
323
static int hf_tns_data_opi_version2_banner_len;
324
static int hf_tns_data_opi_version2_banner;
325
static int hf_tns_data_opi_version2_vsnum;
326
327
static int hf_tns_data_opi_num_of_params;
328
static int hf_tns_data_opi_param_length;
329
static int hf_tns_data_opi_param_name;
330
static int hf_tns_data_opi_param_value;
331
static int hf_tns_data_auth_mode;
332
static int hf_tns_data_auth_mode_logon;
333
static int hf_tns_data_auth_mode_change_password;
334
static int hf_tns_data_auth_mode_sysdba;
335
static int hf_tns_data_auth_mode_sysoper;
336
static int hf_tns_data_auth_mode_with_password;
337
static int hf_tns_data_auth_user;
338
339
static int hf_tns_data_setp_acc_version;
340
static int hf_tns_data_setp_cli_plat;
341
static int hf_tns_data_fastauth_version;
342
static int hf_tns_data_setp_version;
343
static int hf_tns_data_setp_banner;
344
static int hf_tns_data_setp_charset;
345
static int hf_tns_data_setp_flags;
346
static int hf_tns_data_setp_ncharset;
347
static int hf_tns_data_setp_compile_caps;
348
static int hf_tns_data_setp_runtime_caps;
349
static int hf_tns_data_setp_field_version;
350
351
static int hf_tns_data_sns_cli_vers;
352
static int hf_tns_data_sns_srv_vers;
353
static int hf_tns_data_sns_srvcnt;
354
static int hf_tns_data_sns_error;
355
static int hf_tns_data_sns_service;
356
static int hf_tns_data_sns_subpackets;
357
static int hf_tns_data_sns_svc_error;
358
static int hf_tns_data_sns_sub_type;
359
static int hf_tns_data_sns_sub_data;
360
static int hf_tns_data_sns_version;
361
static int hf_tns_data_sns_encryption;
362
static int hf_tns_data_sns_integrity;
363
364
static int hf_tns_data_setdt_charset_in;
365
static int hf_tns_data_setdt_charset_out;
366
static int hf_tns_data_setdt_flag;
367
static int hf_tns_data_setdt_tz;
368
static int hf_tns_data_setdt_tz_offset;
369
static int hf_tns_data_setdt_tzfile;
370
static int hf_tns_data_setdt_ncharset;
371
static int hf_tns_data_setdt_caphdr;
372
static int hf_tns_data_setdt_caphdr_version;
373
static int hf_tns_data_setdt_caphdr_flags;
374
static int hf_tns_data_setdt_field_version;
375
static int hf_tns_data_setdt_type;
376
static int hf_tns_data_setdt_conv_type;
377
static int hf_tns_data_setdt_rep;
378
static int hf_tns_data_field_version;
379
static int hf_tns_data_setdt_tblhdr;
380
static int hf_tns_data_setdt_idmap;
381
static int hf_tns_data_setdt_overrides;
382
static int hf_tns_data_setdt_override_client;
383
static int hf_tns_data_setdt_override_repr;
384
static int hf_tns_data_setdt_override_format;
385
386
static int hf_tns_data_oer_call_status;
387
static int hf_tns_data_oer_rowcount;
388
static int hf_tns_data_oer_err_code;
389
static int hf_tns_data_oer_cursor_id;
390
static int hf_tns_data_oer_rowid;
391
static int hf_tns_data_oer_n_batch_errcodes;
392
static int hf_tns_data_oer_n_batch_offsets;
393
static int hf_tns_data_oer_n_batch_messages;
394
static int hf_tns_data_oer_message;
395
static int hf_tns_data_oer_warn_flags;
396
static int hf_tns_data_oer_warn_compile;
397
static int hf_tns_data_oer_err_num_ext;
398
static int hf_tns_data_oer_rowcount_ext;
399
static int hf_tns_data_oer_sql_type;
400
static int hf_tns_data_oer_checksum;
401
402
static int hf_tns_data_rpa_num_al8o4;
403
static int hf_tns_data_rpa_al8o4;
404
static int hf_tns_data_rpa_al8txl;
405
static int hf_tns_data_rpa_num_kv;
406
static int hf_tns_data_rpa_registration;
407
static int hf_tns_data_rpa_num_rowcounts;
408
static int hf_tns_data_rpa_dml_rowcount;
409
static int hf_tns_data_spb_opcode;
410
static int hf_tns_data_spb_ltxid;
411
static int hf_tns_data_spb_os_pid;
412
static int hf_tns_data_spb_num_kv;
413
static int hf_tns_data_spb_flags;
414
static int hf_tns_data_spb_session_id;
415
static int hf_tns_data_spb_serial_num;
416
static int hf_tns_data_kv_text;
417
static int hf_tns_data_kv_binary;
418
static int hf_tns_data_kv_keyword;
419
420
static int hf_tns_data_wrn_code;
421
static int hf_tns_data_wrn_length;
422
static int hf_tns_data_wrn_flags;
423
static int hf_tns_data_wrn_message;
424
425
static int hf_tns_data_oci_oer_status;
426
static int hf_tns_data_oci_oer_seq;
427
static int hf_tns_data_oci_oer_error_pos;
428
static int hf_tns_data_oci_oer_command;
429
static int hf_tns_data_oci_oer_call_seq;
430
431
static int hf_tns_data_sta_call_status;
432
static int hf_tns_data_sta_seq;
433
static int hf_tns_data_call_status_txn;
434
static int hf_tns_data_call_status_sess_release;
435
436
static int hf_tns_data_iov_num_binds;
437
static int hf_tns_data_iov_bind_dir;
438
static int hf_tns_data_bind_actual_len;
439
440
static int hf_tns_data_dcb_num_columns;
441
static int hf_tns_data_col_type;
442
static int hf_tns_data_col_precision;
443
static int hf_tns_data_col_scale;
444
static int hf_tns_data_col_max_length;
445
static int hf_tns_data_col_charset;
446
static int hf_tns_data_col_csform;
447
static int hf_tns_data_col_max_size;
448
static int hf_tns_data_col_max_elements;
449
static int hf_tns_data_bind_num_elements;
450
static int hf_tns_data_bind_cursor_count;
451
static int hf_tns_data_bind_oci_flags;
452
static int hf_tns_data_bind_oci_repeat;
453
static int hf_tns_data_bind_oci_return_code;
454
static int hf_tns_data_col_nulls_ok;
455
static int hf_tns_data_col_name;
456
static int hf_tns_data_col_uds_flags;
457
static int hf_tns_data_col_domain_schema;
458
static int hf_tns_data_col_domain_name;
459
static int hf_tns_data_col_annotation;
460
static int hf_tns_data_col_vector_dims;
461
static int hf_tns_data_col_vector_format;
462
463
static int hf_tns_data_rxh_num_requests;
464
static int hf_tns_data_rxh_iter_num;
465
static int hf_tns_data_rxh_num_iters;
466
static int hf_tns_data_bit_vector;
467
static int hf_tns_data_bvc_num_cols_sent;
468
static int hf_tns_data_irs_num_results;
469
470
static int hf_tns_data_all8_options;
471
static int hf_tns_data_all8_opt_parse;
472
static int hf_tns_data_all8_opt_bind;
473
static int hf_tns_data_all8_opt_define;
474
static int hf_tns_data_all8_opt_execute;
475
static int hf_tns_data_all8_opt_commit;
476
static int hf_tns_data_all8_opt_plsql;
477
static int hf_tns_data_all8_opt_fetch;
478
static int hf_tns_data_all8_opt_not_plsql;
479
static int hf_tns_data_all8_parse_only;
480
static int hf_tns_data_all8_opt_describe;
481
static int hf_tns_data_all8_opt_batch_errors;
482
static int hf_tns_data_all8_iterations;
483
static int hf_tns_data_all8_prefetch;
484
static int hf_tns_data_all8_is_query;
485
static int hf_tns_data_all8_oci_stmt_type;
486
static int hf_tns_data_all8_exec_flags;
487
static int hf_tns_data_all8_xflag_scrollable;
488
static int hf_tns_data_all8_xflag_no_cancel_on_eof;
489
static int hf_tns_data_all8_xflag_dml_rowcounts;
490
static int hf_tns_data_all8_xflag_implicit_rs;
491
static int hf_tns_data_all8_fetch_orientation;
492
static int hf_tns_data_all8_fetch_pos;
493
static int hf_tns_data_all8_fetch_rows;
494
static int hf_tns_data_all8_bind_count;
495
static int hf_tns_data_all8_define_count;
496
static int hf_tns_data_all8_oci_preamble;
497
static int hf_tns_data_all8_sql;
498
static int hf_tns_data_bind_value;
499
static int hf_tns_data_fetch_rows;
500
static int hf_tns_data_kod_opcode;
501
static int hf_tns_data_kod_kind;
502
static int hf_tns_data_kod_schema;
503
static int hf_tns_data_kod_name;
504
static int hf_tns_data_kod_oid;
505
static int hf_tns_data_kod_type_oid;
506
static int hf_tns_data_kod_system_type;
507
static int hf_tns_data_kod_image;
508
static int hf_tns_data_kod_version;
509
static int hf_tns_data_kod_typecode;
510
static int hf_tns_data_reexec_iterations;
511
static int hf_tns_data_reexec_options2;
512
static int hf_tns_data_reexec_opt2_commit;
513
static int hf_tns_data_lob_op;
514
static int hf_tns_data_lob_offset;
515
static int hf_tns_data_lob_locator;
516
static int hf_tns_data_lob_directory;
517
static int hf_tns_data_lob_file_name;
518
static int hf_tns_data_lob_charset;
519
static int hf_tns_data_lob_csform;
520
static int hf_tns_data_lob_type;
521
static int hf_tns_data_lob_data;
522
static int hf_tns_data_lob_amount;
523
static int hf_tns_data_lob_flag;
524
static int hf_tns_data_tpc_switch_op;
525
static int hf_tns_data_aq_queue;
526
static int hf_tns_data_aq_consumer;
527
static int hf_tns_data_aq_correlation;
528
static int hf_tns_data_aq_exception_queue;
529
static int hf_tns_data_aq_condition;
530
static int hf_tns_data_aq_msgid;
531
static int hf_tns_data_aq_toid;
532
static int hf_tns_data_aq_payload;
533
static int hf_tns_data_aq_priority;
534
static int hf_tns_data_aq_delay;
535
static int hf_tns_data_aq_expiration;
536
static int hf_tns_data_aq_attempts;
537
static int hf_tns_data_aq_state;
538
static int hf_tns_data_aq_enq_time;
539
static int hf_tns_data_aq_visibility;
540
static int hf_tns_data_aq_deq_mode;
541
static int hf_tns_data_aq_navigation;
542
static int hf_tns_data_aq_wait;
543
static int hf_tns_data_aq_flags;
544
static int hf_tns_data_aq_delivery_flags;
545
static int hf_tns_data_aq_array_op;
546
static int hf_tns_data_aq_num_messages;
547
static int hf_tns_data_release_tag;
548
static int hf_tns_data_release_mode;
549
static int hf_tns_data_release_mode_deauth;
550
static int hf_tns_data_tpc_change_op;
551
static int hf_tns_data_tpc_format_id;
552
static int hf_tns_data_tpc_gtrid;
553
static int hf_tns_data_tpc_bqual;
554
static int hf_tns_data_tpc_flags;
555
static int hf_tns_data_tpc_timeout;
556
static int hf_tns_data_tpc_state;
557
static int hf_tns_data_tpc_context;
558
static int hf_tns_data_tpc_app_value;
559
static int hf_tns_data_tpc_internal_name;
560
static int hf_tns_data_tpc_external_name;
561
static int hf_tns_data_lob_text;
562
static int hf_tns_data_lob_total_size;
563
static int hf_tns_data_pgy_schema;
564
static int hf_tns_data_pgy_app_ctx_op;
565
static int hf_tns_data_pgy_app_ctx_namespace;
566
static int hf_tns_data_pgy_app_ctx_attr;
567
static int hf_tns_data_pgy_app_ctx_value;
568
static int hf_tns_data_pgy_alter_param;
569
static int hf_tns_data_pgy_alter_value;
570
static int hf_tns_data_pgy_session_state;
571
static int hf_tns_data_pgy_e2e_flags;
572
static int hf_tns_data_pgy_client_id;
573
static int hf_tns_data_pgy_module;
574
static int hf_tns_data_pgy_action;
575
static int hf_tns_data_pgy_client_info;
576
static int hf_tns_data_pgy_dbop;
577
static int hf_tns_data_pgy_error_set_id;
578
static int hf_tns_data_pgy_error_set_mode;
579
static int hf_tns_data_pgy_pipeline_mode;
580
static int hf_tns_data_pgy_sec_flags;
581
static int hf_tns_data_pgy_sec_key;
582
static int hf_tns_data_pgy_sec_value;
583
static int hf_tns_data_col_value;
584
static int hf_tns_data_lob_size;
585
static int hf_tns_data_lob_chunk_size;
586
static int hf_tns_data_json_image;
587
static int hf_tns_data_vector_image;
588
static int hf_tns_data_obj_toid;
589
static int hf_tns_data_obj_image;
590
591
static int hf_tns_data_descriptor_row_count;
592
static int hf_tns_data_descriptor_row_size;
593
594
static int ett_tns;
595
static int ett_tns_connect;
596
static int ett_tns_accept;
597
static int ett_tns_refuse;
598
static int ett_tns_abort;
599
static int ett_tns_redirect;
600
static int ett_tns_marker;
601
static int ett_tns_attention;
602
static int ett_tns_control;
603
static int ett_tns_data;
604
static int ett_tns_data_flag;
605
static int ett_tns_acc_versions;
606
static int ett_tns_opi_params;
607
static int ett_tns_opi_par;
608
static int ett_tns_sopt_flag;
609
static int ett_tns_ntp_flag;
610
static int ett_tns_conn_flag;
611
static int ett_tns_accept_flags2;
612
static int ett_tns_rows;
613
static int ett_tns_setdt_caphdr;
614
static int ett_tns_setdt_overrides;
615
static int ett_tns_setdt_override;
616
static int ett_tns_oer;
617
static int ett_tns_call_status;
618
static int ett_tns_warn_flags;
619
static int ett_tns_auth_mode;
620
static int ett_tns_sns_service;
621
static int ett_tns_sns_subpacket;
622
static int ett_tns_release_mode;
623
static int ett_tns_aq_props;
624
static int ett_tns_rpa;
625
static int ett_tns_kv;
626
static int ett_tns_iov;
627
static int ett_tns_dcb_col;
628
static int ett_tns_all8_options;
629
static int ett_tns_all8_i4;
630
static int ett_tns_all8_exec_flags;
631
static int ett_tns_binds;
632
static int ett_tns_bind;
633
static int ett_tns_defines;
634
static int ett_tns_reexec_options2;
635
static int ett_tns_bind_row;
636
static int ett_tns_bind_oci_flags;
637
static int ett_tns_rxd_row;
638
static int ett_tns_value;
639
static int ett_tns_irs;
640
static int ett_tns_out_binds;
641
static int ett_sql;
642
static int ett_tns_kod;
643
static int ett_tns_app_ctx;
644
static int ett_tns_alter_session;
645
646
static expert_field ei_tns_connect_data_next_packet;
647
static expert_field ei_tns_data_descriptor_size_mismatch;
648
static expert_field ei_tns_data_piggyback_cursors;
649
static expert_field ei_tns_data_count_too_large;
650
static expert_field ei_tns_data_encrypted;
651
static expert_field ei_tns_data_compilation_error;
652
static expert_field ei_tns_data_value_truncated;
653
654
16
#define TCP_PORT_TNS      1521 /* Not IANA registered */
655
656
/* The ACCEPT's flags2 word, what the server offers from version 318. */
657
static int * const tns_accept_flags2[] = {
658
  &hf_tns_accept_flags2_check_oob,
659
  &hf_tns_accept_flags2_end_of_response,
660
  &hf_tns_accept_flags2_fast_auth,
661
  NULL
662
};
663
664
static int * const tns_connect_flags[] = {
665
  &hf_tns_conn_flag_nareq,
666
  &hf_tns_conn_flag_nalink,
667
  &hf_tns_conn_flag_enablena,
668
  &hf_tns_conn_flag_ichg,
669
  &hf_tns_conn_flag_wantna,
670
  NULL
671
};
672
673
static int * const tns_service_options[] = {
674
  &hf_tns_sopt_flag_bconn,
675
  &hf_tns_sopt_flag_pc,
676
  &hf_tns_sopt_flag_hc,
677
  &hf_tns_sopt_flag_fd,
678
  &hf_tns_sopt_flag_hd,
679
  &hf_tns_sopt_flag_dc1,
680
  &hf_tns_sopt_flag_dc2,
681
  &hf_tns_sopt_flag_dio,
682
  &hf_tns_sopt_flag_ap,
683
  &hf_tns_sopt_flag_ra,
684
  &hf_tns_sopt_flag_sa,
685
  NULL
686
};
687
688
/* The flag byte of an OCI client's bind descriptor. */
689
static int * const tns_bind_oci_flags[] = {
690
  &hf_tns_data_bind_oci_repeat,
691
  NULL
692
};
693
694
/* TTI_ALL8 (SQL execute) options bitmask. */
695
static int * const tns_all8_options[] = {
696
  &hf_tns_data_all8_opt_parse,
697
  &hf_tns_data_all8_opt_bind,
698
  &hf_tns_data_all8_opt_define,
699
  &hf_tns_data_all8_opt_execute,
700
  &hf_tns_data_all8_opt_fetch,
701
  &hf_tns_data_all8_opt_commit,
702
  &hf_tns_data_all8_opt_plsql,
703
  &hf_tns_data_all8_opt_not_plsql,
704
  &hf_tns_data_all8_opt_describe,
705
  &hf_tns_data_all8_opt_batch_errors,
706
  NULL
707
};
708
709
static const value_string tns_type_vals[] = {
710
  {TNS_TYPE_CONNECT,   "Connect" },
711
  {TNS_TYPE_ACCEPT,    "Accept" },
712
  {TNS_TYPE_ACK,       "Acknowledge" },
713
  {TNS_TYPE_REFUSE,    "Refuse" },
714
  {TNS_TYPE_REDIRECT,  "Redirect" },
715
  {TNS_TYPE_DATA,      "Data" },
716
  {TNS_TYPE_NULL,      "Null" },
717
  {TNS_TYPE_ABORT,     "Abort" },
718
  {TNS_TYPE_RESEND,    "Resend"},
719
  {TNS_TYPE_MARKER,    "Marker"},
720
  {TNS_TYPE_ATTENTION, "Attention"},
721
  {TNS_TYPE_CONTROL,   "Control"},
722
  {TNS_TYPE_DD,        "Data Descriptor"},
723
  {0, NULL}
724
};
725
726
static const value_string tns_data_funcs[] = {
727
  {SQLNET_SET_PROTOCOL,     "Set Protocol"},
728
  {SQLNET_SET_DATATYPES,    "Set Datatypes"},
729
  {SQLNET_USER_OCI_FUNC,    "User OCI Functions"},
730
  {SQLNET_RETURN_STATUS,    "Return Status"},
731
  {SQLNET_ACCESS_USR_ADDR,  "Access User Address Space"},
732
  {SQLNET_ROW_TRANSF_HDR,   "Row Transfer Header"},
733
  {SQLNET_ROW_TRANSF_DATA,  "Row Transfer Data"},
734
  {SQLNET_RETURN_OPI_PARAM, "Return OPI Parameter"},
735
  {SQLNET_FUNCCOMPLETE,     "Function Complete"},
736
  {SQLNET_NERROR_RET_DEF,   "N Error return definitions follow"},
737
  {SQLNET_IOVEC_4FAST_UPI,  "Sending I/O Vec only for fast UPI"},
738
  {SQLNET_LONG_4FAST_UPI,   "Sending long for fast UPI"},
739
  {SQLNET_INVOKE_USER_CB,   "Invoke user callback"},
740
  {SQLNET_LOB_FILE_DF,      "LOB/FILE data follows"},
741
  {SQLNET_WARNING,          "Warning messages - may be a set of them"},
742
  {SQLNET_DESCRIBE_INFO,    "Describe Information"},
743
  {SQLNET_PIGGYBACK_FUNC,   "Piggy back function follow"},
744
  {SQLNET_SIG_4UCS,         "Signals special action for untrusted callout support"},
745
  {SQLNET_FLUSH_BIND_DATA,  "Flush Out Bind data in DML/w RETURN when error"},
746
  {SQLNET_BIT_VECTOR,       "Bit Vector"},
747
  {SQLNET_SERVER_PIGGYBACK, "Server-side Piggyback"},
748
  {SQLNET_IMPLICIT_RESULTS, "Implicit Result Sets"},
749
  {SQLNET_END_OF_RESPONSE,  "End of Response"},
750
  {SQLNET_TOKEN,            "Token"},
751
  {SQLNET_FAST_AUTH,        "Fast Authentication"},
752
  {SQLNET_XTRN_PROCSERV_R1, "External Procedures and Services Registrations"},
753
  {SQLNET_XTRN_PROCSERV_R2, "External Procedures and Services Registrations"},
754
  {SQLNET_SNS,              "Secure Network Services"},
755
  {0, NULL}
756
};
757
758
/* The authentication mode of an authentication call. */
759
static int * const tns_auth_modes[] = {
760
  &hf_tns_data_auth_mode_logon,
761
  &hf_tns_data_auth_mode_change_password,
762
  &hf_tns_data_auth_mode_sysdba,
763
  &hf_tns_data_auth_mode_sysoper,
764
  &hf_tns_data_auth_mode_with_password,
765
  NULL
766
};
767
768
/* The mode of a DRCP session release. */
769
static int * const tns_release_modes[] = {
770
  &hf_tns_data_release_mode_deauth,
771
  NULL
772
};
773
774
/* The second options word of a re-execute. */
775
static int * const tns_reexec_options2[] = {
776
  &hf_tns_data_reexec_opt2_commit,
777
  NULL
778
};
779
780
/* Execute flags, the al8i4[9] word of a TTI_ALL8 execute. */
781
static int * const tns_all8_exec_flags[] = {
782
  &hf_tns_data_all8_xflag_scrollable,
783
  &hf_tns_data_all8_xflag_no_cancel_on_eof,
784
  &hf_tns_data_all8_xflag_dml_rowcounts,
785
  &hf_tns_data_all8_xflag_implicit_rs,
786
  NULL
787
};
788
789
/* Scrollable-cursor fetch orientation, al8i4[10] of a TTI_ALL8 execute. */
790
static const value_string tns_fetch_orientations[] = {
791
  {0x00, "None"},
792
  {0x01, "Current"},
793
  {0x02, "Next"},
794
  {0x04, "First"},
795
  {0x08, "Last"},
796
  {0x10, "Prior"},
797
  {0x20, "Absolute"},
798
  {0x40, "Relative"},
799
  {0, NULL}
800
};
801
802
/* Server-side piggyback opcodes (python-oracledb's
803
 * TNS_SERVER_PIGGYBACK_*). */
804
0
#define TNS_SPB_QUERY_CACHE_INVALIDATION 1
805
0
#define TNS_SPB_OS_PID_MTS               2
806
0
#define TNS_SPB_TRACE_EVENT              3
807
0
#define TNS_SPB_SESS_RET                 4
808
0
#define TNS_SPB_SYNC                     5
809
0
#define TNS_SPB_LTXID                    7
810
0
#define TNS_SPB_AC_REPLAY_CONTEXT        8
811
0
#define TNS_SPB_EXT_SYNC                 9
812
0
#define TNS_SPB_SESS_SIGNATURE           10
813
814
static const value_string tns_spb_opcodes[] = {
815
  {TNS_SPB_QUERY_CACHE_INVALIDATION, "Query Cache Invalidation"},
816
  {TNS_SPB_OS_PID_MTS,               "OS PID (shared server)"},
817
  {TNS_SPB_TRACE_EVENT,              "Trace Event"},
818
  {TNS_SPB_SESS_RET,                 "Session Return"},
819
  {TNS_SPB_SYNC,                     "Session State Sync"},
820
  {TNS_SPB_LTXID,                    "Logical Transaction Id"},
821
  {TNS_SPB_AC_REPLAY_CONTEXT,        "Application Continuity Replay Context"},
822
  {TNS_SPB_EXT_SYNC,                 "Extended Sync"},
823
  {TNS_SPB_SESS_SIGNATURE,           "Session Signature"},
824
  {0, NULL}
825
};
826
827
/* The statement type an OCI client's execute names in al8i4[7]: OCI's
828
 * statement types, and sqlplus's own for COMMIT and ROLLBACK. */
829
static const value_string tns_oci_stmt_types[] = {
830
  {1,  "SELECT"},
831
  {2,  "UPDATE"},
832
  {3,  "DELETE"},
833
  {4,  "INSERT"},
834
  {5,  "CREATE"},
835
  {6,  "DROP"},
836
  {7,  "ALTER"},
837
  {8,  "BEGIN"},
838
  {9,  "DECLARE"},
839
  {17, "ROLLBACK"},
840
  {21, "COMMIT"},
841
  {0, NULL}
842
};
843
844
/* Status byte of an OCI client's status block. */
845
static const value_string tns_oci_oer_status_vals[] = {
846
  {1, "Success"},
847
  {5, "Error"},
848
  {0, NULL}
849
};
850
851
/* Statement command types, as V$SQL.COMMAND_TYPE numbers them. */
852
static const value_string tns_command_types[] = {
853
  {1,  "CREATE TABLE"},
854
  {2,  "INSERT"},
855
  {3,  "SELECT"},
856
  {6,  "UPDATE"},
857
  {7,  "DELETE"},
858
  {9,  "CREATE INDEX"},
859
  {12, "DROP TABLE"},
860
  {15, "ALTER TABLE"},
861
  {21, "CREATE VIEW"},
862
  {22, "DROP VIEW"},
863
  {44, "COMMIT"},
864
  {45, "ROLLBACK"},
865
  {47, "PL/SQL EXECUTE"},
866
  {85, "TRUNCATE TABLE"},
867
  {0, NULL}
868
};
869
870
static const value_string tns_field_versions[] = {
871
  {TNS_FV_11_2,       "11.2"},
872
  {TNS_FV_12_1,       "12.1"},
873
  {TNS_FV_12_2,       "12.2"},
874
  {TNS_FV_12_2_EXT1,  "12.2 ext 1"},
875
  {TNS_FV_18_1,       "18.1"},
876
  {TNS_FV_18_1_EXT_1, "18.1 ext 1"},
877
  {TNS_FV_19_1,       "19.1"},
878
  {TNS_FV_19_1_EXT_1, "19.1 ext 1"},
879
  {TNS_FV_20_1,       "20.1"},
880
  {TNS_FV_20_1_EXT_1, "20.1 ext 1"},
881
  {TNS_FV_21_1,       "21.1"},
882
  {TNS_FV_23_1,       "23.1"},
883
  {TNS_FV_23_1_EXT_1, "23.1 ext 1"},
884
  {TNS_FV_23_1_EXT_2, "23.1 ext 2"},
885
  {TNS_FV_23_1_EXT_3, "23.1 ext 3"},
886
  {TNS_FV_23_1_EXT_4, "23.1 ext 4"},
887
  {TNS_FV_23_1_EXT_5, "23.1 ext 5"},
888
  {TNS_FV_23_3_EXT_6, "23.3 ext 6"},
889
  {TNS_FV_23_4,       "23.4"},
890
  {0, NULL}
891
};
892
893
/* Advanced Queuing (python-oracledb's TNS_AQ_*). */
894
static const value_string tns_aq_states[] = {
895
  {0, "Ready"},
896
  {1, "Waiting"},
897
  {2, "Processed"},
898
  {3, "Expired"},
899
  {0, NULL}
900
};
901
902
static const value_string tns_aq_visibility[] = {
903
  {1, "Immediate"},
904
  {2, "On commit"},
905
  {0, NULL}
906
};
907
908
static const value_string tns_aq_deq_modes[] = {
909
  {1, "Browse"},
910
  {2, "Locked"},
911
  {3, "Remove"},
912
  {4, "Remove, no data"},
913
  {0, NULL}
914
};
915
916
static const value_string tns_aq_navigation[] = {
917
  {1, "First message"},
918
  {2, "Next transaction"},
919
  {3, "Next message"},
920
  {0, NULL}
921
};
922
923
static const value_string tns_aq_array_ops[] = {
924
  {1, "Enqueue"},
925
  {2, "Dequeue"},
926
  {0, NULL}
927
};
928
929
/* Two-phase commit operations (python-oracledb's TNS_TPC_*). */
930
static const value_string tns_tpc_switch_ops[] = {
931
  {0x01, "Start"},
932
  {0x02, "Detach"},
933
  {0x04, "Post-detach"},
934
  {0, NULL}
935
};
936
937
static const value_string tns_tpc_change_ops[] = {
938
  {0x01, "Commit"},
939
  {0x02, "Abort"},
940
  {0x03, "Prepare"},
941
  {0x04, "Forget"},
942
  {0, NULL}
943
};
944
945
static const value_string tns_tpc_states[] = {
946
  {0, "Prepared"},
947
  {1, "Requires commit"},
948
  {2, "Committed"},
949
  {3, "Aborted"},
950
  {4, "Read only"},
951
  {5, "Forgotten"},
952
  {0, NULL}
953
};
954
955
/* Native network services (ANO) negotiation: services, sub-packet types
956
 * and the encryption and integrity algorithm ids. */
957
#define TNS_ANO_AUTHENTICATION   1
958
0
#define TNS_ANO_ENCRYPTION       2
959
0
#define TNS_ANO_DATA_INTEGRITY   3
960
#define TNS_ANO_SUPERVISOR       4
961
0
#define TNS_ANO_SP_BYTES         1
962
0
#define TNS_ANO_SP_UB1           2
963
0
#define TNS_ANO_SP_VERSION       5
964
965
static const value_string tns_sns_services[] = {
966
  {TNS_ANO_AUTHENTICATION, "Authentication"},
967
  {TNS_ANO_ENCRYPTION,     "Encryption"},
968
  {TNS_ANO_DATA_INTEGRITY, "Data Integrity"},
969
  {TNS_ANO_SUPERVISOR,     "Supervisor"},
970
  {0, NULL}
971
};
972
973
static const value_string tns_sns_subpacket_types[] = {
974
  {0, "String"},
975
  {1, "Bytes"},
976
  {2, "UB1"},
977
  {3, "UB2"},
978
  {4, "UB4"},
979
  {5, "Version"},
980
  {6, "Status"},
981
  {0, NULL}
982
};
983
984
static const value_string tns_sns_encryption_algs[] = {
985
  {0,  "None"},
986
  {1,  "RC4_40"},
987
  {2,  "DES"},
988
  {3,  "DES40"},
989
  {6,  "RC4_256"},
990
  {8,  "RC4_56"},
991
  {10, "RC4_128"},
992
  {11, "3DES112"},
993
  {12, "3DES168"},
994
  {15, "AES128"},
995
  {16, "AES192"},
996
  {17, "AES256"},
997
  {0, NULL}
998
};
999
1000
static const value_string tns_sns_integrity_algs[] = {
1001
  {0, "None"},
1002
  {1, "MD5"},
1003
  {3, "SHA1"},
1004
  {4, "SHA512"},
1005
  {5, "SHA256"},
1006
  {6, "SHA384"},
1007
  {0, NULL}
1008
};
1009
1010
/* Keyword numbers of the key/value pairs a server reports back, for a
1011
 * session attribute a statement changed (python-oracledb's
1012
 * TNS_KEYWORD_NUM_*). */
1013
static const value_string tns_kv_keywords[] = {
1014
  {168, "CURRENT_SCHEMA"},
1015
  {172, "EDITION"},
1016
  {201, "TRANSACTION_ID"},
1017
  {204, "TXN_PRIORITY"},
1018
  {0, NULL}
1019
};
1020
1021
/* Oracle TNS native data-type ids. Used by the Set Datatypes
1022
 * negotiation to label override entries with human names. */
1023
static const value_string tns_data_types[] = {
1024
  {TNS_DATATYPE_VARCHAR,        "VARCHAR"},
1025
  {TNS_DATATYPE_NUMBER,         "NUMBER"},
1026
  {TNS_DATATYPE_INTEGER,        "BINARY_INTEGER"},
1027
  {TNS_DATATYPE_FLOAT,          "FLOAT"},
1028
  {TNS_DATATYPE_STRING,         "STRING"},
1029
  {TNS_DATATYPE_VARNUM,         "VARNUM"},
1030
  {TNS_DATATYPE_DECIMAL,        "DECIMAL"},
1031
  {TNS_DATATYPE_LONG,           "LONG"},
1032
  {TNS_DATATYPE_VCS,            "VCS"},
1033
  {TNS_DATATYPE_ROWID,          "RID"},
1034
  {TNS_DATATYPE_DATE,           "DATE"},
1035
  {TNS_DATATYPE_VBI,            "VBI"},
1036
  {TNS_DATATYPE_RAW,            "RAW"},
1037
  {TNS_DATATYPE_LONG_RAW,       "LONG RAW"},
1038
  {TNS_DATATYPE_CHAR,           "CHAR"},
1039
  {TNS_DATATYPE_BINARY_FLOAT,   "BINARY_FLOAT"},
1040
  {TNS_DATATYPE_BINARY_DOUBLE,  "BINARY_DOUBLE"},
1041
  {TNS_DATATYPE_REFCURSOR,      "REFCURSOR"},
1042
  {TNS_DATATYPE_ROWID_EXT,      "ROWID"},
1043
  {TNS_DATATYPE_ADT,            "ADT"},
1044
  {TNS_DATATYPE_REF,            "REF"},
1045
  {TNS_DATATYPE_CLOB,           "CLOB"},
1046
  {TNS_DATATYPE_BLOB,           "BLOB"},
1047
  {TNS_DATATYPE_BFILE,          "BFILE"},
1048
  {TNS_DATATYPE_RSET,           "RSET"},
1049
  {TNS_DATATYPE_JSON,           "JSON"},
1050
  {TNS_DATATYPE_VECTOR,         "VECTOR"},
1051
  {TNS_DATATYPE_TIMESTAMP,      "TIMESTAMP"},
1052
  {TNS_DATATYPE_TIMESTAMP_TZ,   "TIMESTAMP WITH TIME ZONE"},
1053
  {TNS_DATATYPE_INTERVAL_YM,    "INTERVAL YEAR TO MONTH"},
1054
  {TNS_DATATYPE_INTERVAL_DS,    "INTERVAL DAY TO SECOND"},
1055
  {TNS_DATATYPE_UROWID,         "UROWID"},
1056
  {TNS_DATATYPE_TIMESTAMP_LTZ,  "TIMESTAMP WITH LOCAL TIME ZONE"},
1057
  {TNS_DATATYPE_BOOLEAN,        "BOOLEAN"},
1058
  {0, NULL}
1059
};
1060
1061
/* Oracle NLS character-set ids - the well-known subset, enough to name
1062
 * the charsets seen in a Set Datatypes negotiation. */
1063
static const value_string tns_charsets[] = {
1064
  {1,    "US7ASCII"},
1065
  {31,   "WE8ISO8859P1"},
1066
  {32,   "EE8ISO8859P2"},
1067
  {33,   "SE8ISO8859P3"},
1068
  {34,   "NEE8ISO8859P4"},
1069
  {35,   "CL8ISO8859P5"},
1070
  {36,   "AR8ISO8859P6"},
1071
  {37,   "EL8ISO8859P7"},
1072
  {38,   "IW8ISO8859P8"},
1073
  {39,   "WE8ISO8859P9"},
1074
  {40,   "NE8ISO8859P10"},
1075
  {41,   "TH8TISASCII"},
1076
  {46,   "WE8ISO8859P15"},
1077
  {47,   "BLT8ISO8859P13"},
1078
  {170,  "EE8MSWIN1250"},
1079
  {171,  "CL8MSWIN1251"},
1080
  {172,  "EL8MSWIN1253"},
1081
  {173,  "TR8MSWIN1254"},
1082
  {174,  "IW8MSWIN1255"},
1083
  {175,  "AR8MSWIN1256"},
1084
  {176,  "BLT8MSWIN1257"},
1085
  {177,  "VN8MSWIN1258"},
1086
  {178,  "WE8MSWIN1252"},
1087
  {351,  "WE8PC850"},
1088
  {354,  "US8PC437"},
1089
  {368,  "RU8PC866"},
1090
  {382,  "EE8PC852"},
1091
  {829,  "ZHT16BIG5"},
1092
  {830,  "KO16KSC5601"},
1093
  {831,  "JA16EUC"},
1094
  {832,  "JA16SJIS"},
1095
  {833,  "JA16SJISTILDE"},
1096
  {834,  "JA16EUCTILDE"},
1097
  {846,  "ZHS16GBK"},
1098
  {850,  "ZHT16HKSCS"},
1099
  {852,  "KO16MSWIN949"},
1100
  {854,  "ZHT16MSWIN950"},
1101
  {870,  "ZHS32GB18030"},
1102
  {871,  "UTF8"},
1103
  {873,  "AL32UTF8"},
1104
  {2000, "AL16UTF16"},
1105
  {0, NULL}
1106
};
1107
1108
/* A LOB locator's flag bytes, at these offsets in the locator as a
1109
 * client holds and sends it (python-oracledb's TNS_LOB_LOC_*). Flag 1
1110
 * says what kind of LOB it is; flags 3 and 4 how a CLOB's characters are
1111
 * encoded: UTF-16 with the variable-length charset bit, little-endian
1112
 * with the little-endian bit too, UTF-8 without. An NCLOB is UTF-16. */
1113
0
#define TNS_LOB_LOC_FLAG_1                0x04
1114
#define TNS_LOB_LOC_FLAG_3                0x06
1115
0
#define TNS_LOB_LOC_FLAG_4                0x07
1116
#define TNS_LOB_LOC_FLAGS_BLOB            0x01
1117
0
#define TNS_LOB_LOC_FLAGS_CLOB            0x02
1118
0
#define TNS_LOB_LOC_FLAGS_NCLOB           0x04
1119
0
#define TNS_LOB_LOC_FLAGS_VAR_LENGTH_CHARSET 0x80
1120
0
#define TNS_LOB_LOC_FLAGS_LITTLE_ENDIAN   0x40
1121
1122
/* TTI_LOBOPS operation opcodes. */
1123
0
#define TNS_LOB_OP_FILE_ISOPEN   0x00400
1124
0
#define TNS_LOB_OP_FILE_EXISTS   0x00800
1125
0
#define TNS_LOB_OP_CREATE_TEMP   0x00110
1126
0
#define TNS_LOB_OP_IS_OPEN       0x11000
1127
1128
static const value_string tns_lob_ops[] = {
1129
  {0x00001, "GET_LENGTH"},
1130
  {0x00002, "READ"},
1131
  {0x00020, "TRIM"},
1132
  {0x00040, "WRITE"},
1133
  {0x00100, "FILE_OPEN"},
1134
  {0x00110, "CREATE_TEMP"},
1135
  {0x00111, "FREE_TEMP"},
1136
  {0x00200, "FILE_CLOSE"},
1137
  {0x00400, "FILE_ISOPEN"},
1138
  {0x00800, "FILE_EXISTS"},
1139
  {0x04000, "GET_CHUNK_SIZE"},
1140
  {0x08000, "OPEN"},
1141
  {0x10000, "CLOSE"},
1142
  {0x11000, "IS_OPEN"},
1143
  {0x80000, "ARRAY"},
1144
  {0, NULL}
1145
};
1146
1147
/* Column character-set form (csfrm) in an OAC descriptor: whether char data
1148
 * is in the database charset or the national (AL16UTF16) charset. */
1149
0
#define TNS_CSFORM_NCHAR 2
1150
/* The charset form and type of a temporary LOB a CREATE_TEMP asks for. */
1151
static const val64_string tns_csform_vals64[] = {
1152
  {0, "None (BLOB)"},
1153
  {1, "Implicit (CLOB)"},
1154
  {2, "National (NCLOB)"},
1155
  {0, NULL}
1156
};
1157
1158
static const val64_string tns_lob_types64[] = {
1159
  {TNS_DATATYPE_CLOB, "CLOB"},
1160
  {TNS_DATATYPE_BLOB, "BLOB"},
1161
  {0, NULL}
1162
};
1163
1164
static const value_string tns_csform_vals[] = {
1165
  {1, "Database charset"},
1166
  {2, "National (AL16UTF16)"},
1167
  {0, NULL}
1168
};
1169
1170
/* Bind directions reported per bind in a TTI_IOV vector (TNS_BIND_DIR_*),
1171
 * cross-referenced with python-oracledb's constants. */
1172
0
#define TNS_BIND_DIR_OUTPUT 16
1173
0
#define TNS_BIND_DIR_INPUT 32
1174
1175
/* The length of an Advanced Queuing message id. */
1176
0
#define TNS_AQ_MSGID_LEN   16
1177
0
#define TNS_AQ_TOID_LEN    16
1178
0
#define TNS_AQ_ARRAY_ENQ   1
1179
1180
/* An OAC flag marking a PL/SQL associative-array bind: in the flag byte
1181
 * from 12.2, in the continuation flags before. */
1182
0
#define TNS_BIND_ARRAY     0x40
1183
/* An OCI bind descriptor's flag marking a placeholder whose name came
1184
 * earlier in the statement: the row carries no value for it. */
1185
16
#define TNS_OCI_BIND_REPEAT 0x80
1186
/* The smallest OCI bind descriptor, a scalar's before 12c. */
1187
0
#define TNS_OCI_OAC_MIN_LEN 41
1188
/* The header of the reply to an OCI client's PL/SQL block with OUT binds,
1189
 * from the message id; the bind count is its fifth byte */
1190
0
#define TNS_OCI_IOV_HEADER_LEN 50
1191
0
#define TNS_OCI_IOV_BIND_COUNT 4
1192
static const value_string tns_iov_bind_dirs[] = {
1193
  {16, "OUT"},
1194
  {32, "IN"},
1195
  {48, "IN OUT"},
1196
  {0, NULL}
1197
};
1198
1199
/* What an application-context piggyback does to its namespace. */
1200
static const value_string tns_app_ctx_ops[] = {
1201
  {1, "Set"},
1202
  {2, "Clear"},
1203
  {0, NULL}
1204
};
1205
1206
/* What a TTI_KOD call asks for. */
1207
static const value_string tns_kod_opcodes[] = {
1208
  {TNS_KOD_BY_NAME, "Describe by name"},
1209
  {TNS_KOD_BY_REF,  "Describe by REF"},
1210
  {0, NULL}
1211
};
1212
1213
/* The messages of a TTI_KOD reply. */
1214
static const value_string tns_kod_kinds[] = {
1215
  {TNS_KOD_RECORD, "Type record"},
1216
  {TNS_KOD_HEADER, "Name header"},
1217
  {0, NULL}
1218
};
1219
1220
/* The system types, by the last byte of an id whose first 15 are zero. */
1221
static const value_string tns_kod_system_types[] = {
1222
  {TNS_KOD_KOTTD, "SYS.KOTTD"},
1223
  {0x02, "SYS.KOTTB"},
1224
  {0x03, "SYS.KOTAD"},
1225
  {0x0f, "SYS.NUMBER"},
1226
  {0, NULL}
1227
};
1228
1229
/* The typecodes a type descriptor names. */
1230
static const value_string tns_kod_typecodes[] = {
1231
  {108, "Object"},
1232
  {122, "Named collection"},
1233
  {0, NULL}
1234
};
1235
1236
static const value_string tns_data_oci_subfuncs[] = {
1237
  {1, "Logon to Oracle"},
1238
  {2, "Open Cursor"},
1239
  {3, "Parse a Row"},
1240
  {4, "Execute a Row"},
1241
  {5, "Fetch a Row"},
1242
  {8, "Close Cursor"},
1243
  {9, "Logoff of Oracle"},
1244
  {10, "Describe a select list column"},
1245
  {11, "Define where the column goes"},
1246
  {12, "Auto commit on"},
1247
  {13, "Auto commit off"},
1248
  {14, "Commit"},
1249
  {15, "Rollback"},
1250
  {16, "Set fatal error options"},
1251
  {17, "Resume current operation"},
1252
  {18, "Get Oracle version-date string"},
1253
  {19, "Until we get rid of OASQL"},
1254
  {20, "Cancel the current operation"},
1255
  {21, "Get error message"},
1256
  {22, "Exit Oracle command"},
1257
  {23, "Special function"},
1258
  {24, "Abort"},
1259
  {25, "Dequeue by RowID"},
1260
  {26, "Fetch a long column value"},
1261
  {27, "Create Access Module"},
1262
  {28, "Save Access Module Statement"},
1263
  {29, "Save Access Module"},
1264
  {30, "Parse Access Module Statement"},
1265
  {31, "How many items?"},
1266
  {32, "Initialize Oracle"},
1267
  {33, "Change User ID"},
1268
  {34, "Bind by reference positional"},
1269
  {35, "Get n'th Bind Variable"},
1270
  {36, "Get n'th Into Variable"},
1271
  {37, "Bind by reference"},
1272
  {38, "Bind by reference numeric"},
1273
  {39, "Parse and Execute"},
1274
  {40, "Parse for syntax (only)"},
1275
  {41, "Parse for syntax and SQL Dictionary lookup"},
1276
  {42, "Continue serving after EOF"},
1277
  {43, "Array describe"},
1278
  {44, "Init sys pars command table"},
1279
  {45, "Finalize sys pars command table"},
1280
  {46, "Put sys par in command table"},
1281
  {47, "Get sys pars from command table"},
1282
  {48, "Start Oracle (V6)"},
1283
  {49, "Shutdown Oracle (V6)"},
1284
  {50, "Run Independent Process (V6)"},
1285
  {51, "Test RAM (V6)"},
1286
  {52, "Archive operation (V6)"},
1287
  {53, "Media Recovery - start (V6)"},
1288
  {54, "Media Recovery - record tablespace to recover (V6)"},
1289
  {55, "Media Recovery - get starting log seq # (V6)"},
1290
  {56, "Media Recovery - recover using offline log (V6)"},
1291
  {57, "Media Recovery - cancel media recovery (V6)"},
1292
  {58, "Logon to Oracle (V6)"},
1293
  {59, "Get Oracle version-date string in new format"},
1294
  {60, "Initialize Oracle"},
1295
  {61, "Reserved for MAC; close all cursors"},
1296
  {62, "Bundled execution call"},
1297
  {65, "For direct loader: functions"},
1298
  {66, "For direct loader: buffer transfer"},
1299
  {67, "Distrib. trans. mgr. RPC"},
1300
  {68, "Describe indexes for distributed query"},
1301
  {69, "Session operations"},
1302
  {70, "Execute using synchronized system commit numbers"},
1303
  {71, "Fast UPI calls to OPIAL7"},
1304
  {72, "Long Fetch (V7)"},
1305
  {73, "Call OPIEXE from OPIALL: no two-task access"},
1306
  {74, "Parse Call (V7) to deal with various flavours"},
1307
  {76, "RPC call from PL/SQL"},
1308
  {77, "Do a KGL operation"},
1309
  {78, "Execute and Fetch"},
1310
  {79, "X/Open XA operation"},
1311
  {80, "New KGL operation call"},
1312
  {81, "2nd Half of Logon"},
1313
  {82, "1st Half of Logon"},
1314
  {83, "Do Streaming Operation"},
1315
  {84, "Open Session (71 interface)"},
1316
  {85, "X/Open XA operations (71 interface)"},
1317
  {86, "Debugging operations"},
1318
  {87, "Special debugging operations"},
1319
  {88, "XA Start"},
1320
  {89, "XA Switch and Commit"},
1321
  {90, "Direct copy from db buffers to client address"},
1322
  {91, "OKOD Call (In Oracle <= 7 this used to be Connect"},
1323
  {92, "Describe an object type (KOD)"},
1324
  {93, "RPI Callback with ctxdef"},
1325
  {94, "Bundled execution call (V7)"},
1326
  {95, "Do Streaming Operation without begintxn"},
1327
  {96, "LOB and FILE related calls"},
1328
  {97, "File Create call"},
1329
  {98, "Describe query (V8) call"},
1330
  {99, "Connect (non-blocking attach host)"},
1331
  {100, "Open a recursive cursor"},
1332
  {101, "Bundled KPR Execution"},
1333
  {102, "Bundled PL/SQL execution"},
1334
  {103, "Transaction start, attach, detach"},
1335
  {104, "Transaction commit, rollback, recover"},
1336
  {105, "Cursor close all"},
1337
  {106, "Failover into piggyback"},
1338
  {107, "Session switching piggyback (V8)"},
1339
  {108, "Do Dummy Defines"},
1340
  {109, "Init sys pars (V8)"},
1341
  {110, "Finalize sys pars (V8)"},
1342
  {111, "Put sys par in par space (V8)"},
1343
  {112, "Terminate sys pars (V8)"},
1344
  {114, "Init Untrusted Callbacks"},
1345
  {115, "Generic authentication call"},
1346
  {116, "FailOver Get Instance call"},
1347
  {117, "Oracle Transaction service Commit remote sites"},
1348
  {118, "Get the session key"},
1349
  {119, "Describe any (V8)"},
1350
  {120, "Cancel All"},
1351
  {121, "AQ Enqueue"},
1352
  {122, "AQ Dequeue"},
1353
  {123, "Object transfer"},
1354
  {124, "RFS Call"},
1355
  {125, "Kernel programmatic notification"},
1356
  {126, "Listen"},
1357
  {127, "Oracle Transaction service Commit remote sites (V >= 8.1.3)"},
1358
  {128, "Dir Path Prepare"},
1359
  {129, "Dir Path Load Stream"},
1360
  {130, "Dir Path Misc. Ops"},
1361
  {131, "Memory Stats"},
1362
  {132, "AQ Properties Status"},
1363
  {134, "Remote Fetch Archive Log FAL"},
1364
  {135, "Client ID propagation"},
1365
  {136, "DR Server CNX Process"},
1366
  {138, "SPFILE parameter put"},
1367
  {139, "KPFC exchange"},
1368
  {140, "Object Transfer (V8.2)"},
1369
  {141, "Push Transaction"},
1370
  {142, "Pop Transaction"},
1371
  {143, "KFN Operation"},
1372
  {144, "Dir Path Unload Stream"},
1373
  {145, "AQ batch enqueue dequeue"},
1374
  {146, "File Transfer"},
1375
  {147, "Ping"},
1376
  {148, "TSM"},
1377
  {150, "Begin TSM"},
1378
  {151, "End TSM"},
1379
  {152, "Set schema"},
1380
  {153, "Fetch from suspended result set"},
1381
  {154, "Key/Value pair"},
1382
  {155, "XS Create session Operation"},
1383
  {156, "XS Session Roundtrip Operation"},
1384
  {157, "XS Piggyback Operation"},
1385
  {158, "KSRPC Execution"},
1386
  {159, "Streams combined capture apply"},
1387
  {160, "AQ replay information"},
1388
  {161, "SSCR"},
1389
  {162, "Session Get"},
1390
  {163, "Session RLS"},
1391
  {165, "Workload replay data"},
1392
  {166, "Replay statistic data"},
1393
  {167, "Query Cache Stats"},
1394
  {168, "Query Cache IDs"},
1395
  {169, "RPC Test Stream"},
1396
  {170, "Replay PL/SQL RPC"},
1397
  {171, "XStream Out"},
1398
  {172, "Golden Gate RPC"},
1399
  {176, "Session state"},
1400
  {187, "Notify"},
1401
  {199, "Pipeline begin"},
1402
  {200, "Pipeline end"},
1403
  {204, "Alter session"},
1404
  {205, "End-user security context"},
1405
  {0, NULL}
1406
};
1407
static value_string_ext tns_data_oci_subfuncs_ext = VALUE_STRING_EXT_INIT(tns_data_oci_subfuncs);
1408
1409
/* The final byte of a TNS_MARKER body selects break vs reset:
1410
 * 01 00 01 = break, 01 00 02 = reset. */
1411
static const value_string tns_marker_functions[] = {
1412
  {1, "Break (interrupt call)"},
1413
  {2, "Reset (clear line)"},
1414
  {0, NULL}
1415
};
1416
1417
static const value_string tns_marker_types[] = {
1418
  {0, "Data Marker - 0 Data Bytes"},
1419
  {1, "Data Marker - 1 Data Bytes"},
1420
  {2, "Attention Marker"},
1421
  {0, NULL}
1422
};
1423
1424
static const value_string tns_control_cmds[] = {
1425
  {1, "Oracle Trace Command"},
1426
  {0, NULL}
1427
};
1428
1429
/* What a value decoder needs to know about one column or bind: its
1430
 * datatype, character set form, and the data length (buffer size) the
1431
 * describe gave it. */
1432
typedef struct _tns_column_t {
1433
  uint8_t type;
1434
  uint8_t csform;         /* character set form: 2 = national */
1435
  bool is_array;          /* a PL/SQL associative-array bind */
1436
  uint32_t data_len;
1437
} tns_column_t;
1438
1439
/* Columns from the most recent describe (TTI_DCB), threaded to a later
1440
 * TTI_RXD response so its row values can be split per column. */
1441
typedef struct _tns_describe_t {
1442
  uint32_t num_cols;
1443
  tns_column_t *cols;
1444
} tns_describe_t;
1445
1446
/* The bind types of a cursor, from the execute that opened it. A later
1447
 * execute of the same cursor may send its values with no descriptors. */
1448
typedef struct _tns_binds_t {
1449
  uint32_t count;
1450
  uint32_t num_return;    /* the last num_return are RETURNING ... INTO binds */
1451
  bool plsql;             /* bound to a PL/SQL block */
1452
  tns_column_t *cols;
1453
  /* A PL/SQL block's bind directions, which only the reply to its
1454
   * first execute reports; NULL until then. Its re-executes send no
1455
   * value for an OUT bind and are answered with no directions. */
1456
  uint8_t *dirs;
1457
} tns_binds_t;
1458
1459
/* The call a response answers: some response messages can only be read
1460
 * knowing what was asked. */
1461
typedef struct _tns_call_t {
1462
  uint8_t func;           /* OCI function id */
1463
  uint32_t exec_flags;    /* al8i4[9] of a TTI_ALL8 execute */
1464
  uint32_t num_binds;     /* bind types of an execute */
1465
  uint32_t num_return;    /* ... of which the last are RETURNING ... INTO binds */
1466
  tns_column_t *binds;
1467
  tns_binds_t *bind_rec;  /* ... and the cursor's record of them */
1468
  uint32_t lob_op;        /* TTI_LOBOPS operation */
1469
  uint32_t lob_locator_len; /* ... its source locator length */
1470
  bool lob_amount;        /* ... whether it sent an amount */
1471
  uint8_t lob_flags[4];   /* ... its locator's flag bytes 1 to 4 */
1472
  bool lob_flags_known;
1473
} tns_call_t;
1474
1475
typedef struct _tns_conv_info_t {
1476
  uint32_t pending_connect_data;
1477
  /* The most recent call the client made. */
1478
  tns_call_t *last_call;
1479
  /* The client speaks the OCI dialect: fixed-width little-endian
1480
   * integers and 8-byte pointer indicators, where a thin client uses
1481
   * variable-length integers and 1-byte pointer flags. */
1482
  bool oci_dialect;
1483
  /* ... and at the 12c band, whose status blocks are 144 bytes. */
1484
  bool oci_band_12c;
1485
  /* The TTC field version the client and server settled on, from the
1486
   * client's TTI_DTY; 0 until seen. */
1487
  uint8_t field_version;
1488
  /* The TTC field version the server offered in its TTI_PRO reply,
1489
   * which can be higher; 0 until seen. */
1490
  uint8_t server_field_version;
1491
  /* Native network encryption: the server picked an algorithm, and
1492
   * the frame of the client's last negotiation packet, after which the
1493
   * data packets are encrypted. */
1494
  bool ano_encryption;
1495
  uint32_t ano_active_after;
1496
  tns_describe_t *last_describe;
1497
  /* Bind types of an execute that opened a new cursor, waiting for the
1498
   * status that names the cursor id. */
1499
  tns_binds_t *pending_binds;
1500
  /* Cursor id -> tns_binds_t. */
1501
  wmem_map_t *cursor_binds;
1502
} tns_conv_info_t;
1503
1504
/* p_add_proto_data key for the describe a TTI_RXD response packet uses. */
1505
0
#define TNS_PROTO_DATA_DESCRIBE 1
1506
/* p_add_proto_data key for the remembered binds of a re-execute. */
1507
0
#define TNS_PROTO_DATA_BINDS    2
1508
/* p_add_proto_data key for the call a response packet answers. */
1509
0
#define TNS_PROTO_DATA_CALL     3
1510
/* p_add_proto_data key for whether a packet is in the OCI dialect. */
1511
0
#define TNS_PROTO_DATA_OCI      4
1512
/* p_add_proto_data key for the field version in force for a packet. */
1513
0
#define TNS_PROTO_DATA_FV       5
1514
/* p_add_proto_data key for whether a packet is encrypted. */
1515
0
#define TNS_PROTO_DATA_ENCRYPTED 6
1516
/* p_add_proto_data key for the field version the server offered. */
1517
0
#define TNS_PROTO_DATA_SERVER_FV 7
1518
/* p_add_proto_data key for whether an OCI session is at the 12c band. */
1519
0
#define TNS_PROTO_DATA_OCI_12C  8
1520
1521
/* Execute option set on every SQL statement, clear on a PL/SQL block. */
1522
0
#define TNS_EXEC_OPTION_NOT_PLSQL 0x8000
1523
1524
/* The execute options that ask the server to do something: run the
1525
 * statement, take a set of defines, or return rows. */
1526
0
#define TNS_EXEC_OPTION_DEFINE    0x0010
1527
0
#define TNS_EXEC_OPTION_EXECUTE   0x0020
1528
0
#define TNS_EXEC_OPTION_FETCH     0x0040
1529
1530
/* Execute flag asking for the rows each array DML iteration affected. */
1531
0
#define TNS_EXEC_FLAGS_DML_ROWCOUNTS 0x4000
1532
1533
void proto_reg_handoff_tns(void);
1534
static int dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_);
1535
1536
static tns_conv_info_t*
1537
tns_get_conv_info(packet_info *pinfo)
1538
0
{
1539
0
  conversation_t *conversation = find_or_create_conversation(pinfo);
1540
1541
0
  tns_conv_info_t *tns_info = (tns_conv_info_t *)conversation_get_proto_data(conversation, proto_tns);
1542
0
  if (!tns_info) {
1543
0
    tns_info = wmem_new0(wmem_file_scope(), tns_conv_info_t);
1544
0
    tns_info->cursor_binds = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
1545
0
    conversation_add_proto_data(conversation, proto_tns, tns_info);
1546
0
  }
1547
0
  return tns_info;
1548
0
}
1549
1550
/* The TTC field version negotiated on the packet's connection, or 0 when
1551
 * the negotiation was not seen - which the decoders read as the 11g
1552
 * shape. Stored per packet on the first pass. */
1553
static unsigned tns_field_version(packet_info *pinfo)
1554
0
{
1555
0
  void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_FV);
1556
0
  if ( stored || PINFO_FD_VISITED(pinfo) )
1557
0
    return stored ? GPOINTER_TO_UINT(stored) - 1 : 0;
1558
1559
0
  unsigned fv = tns_get_conv_info(pinfo)->field_version;
1560
0
  p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_FV, GUINT_TO_POINTER(fv + 1));
1561
0
  return fv;
1562
0
}
1563
1564
/* The TTC field version the server offered on the packet's connection -
1565
 * its own release, before the client lowered it - or 0 when the
1566
 * negotiation was not seen. Stored per packet on the first pass. */
1567
static unsigned tns_server_field_version(packet_info *pinfo)
1568
0
{
1569
0
  void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_SERVER_FV);
1570
0
  if ( stored || PINFO_FD_VISITED(pinfo) )
1571
0
    return stored ? GPOINTER_TO_UINT(stored) - 1 : 0;
1572
1573
0
  unsigned fv = tns_get_conv_info(pinfo)->server_field_version;
1574
0
  p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_SERVER_FV, GUINT_TO_POINTER(fv + 1));
1575
0
  return fv;
1576
0
}
1577
1578
/* Whether the connection is known to predate 11g (a 10g server): its
1579
 * describe lacks the fields 11g added. */
1580
static bool tns_before_11g(packet_info *pinfo)
1581
0
{
1582
0
  unsigned fv = tns_field_version(pinfo);
1583
0
  return fv != 0 && fv < TNS_FV_11_2;
1584
0
}
1585
1586
/* Whether a data packet is encrypted by native network encryption.
1587
 * Stored per packet on the first pass. */
1588
static bool tns_is_encrypted(packet_info *pinfo)
1589
0
{
1590
0
  void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_ENCRYPTED);
1591
0
  if ( stored || PINFO_FD_VISITED(pinfo) )
1592
0
    return GPOINTER_TO_UINT(stored) == 2;
1593
1594
0
  tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
1595
0
  bool encrypted = tns_info->ano_active_after && pinfo->num > tns_info->ano_active_after;
1596
0
  p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_ENCRYPTED, GUINT_TO_POINTER(encrypted ? 2 : 1));
1597
0
  return encrypted;
1598
0
}
1599
1600
static unsigned get_data_func_id(tvbuff_t *tvb, int offset)
1601
0
{
1602
  /* Determine Data Function id */
1603
0
  uint8_t first_byte;
1604
1605
0
  first_byte =
1606
0
      tvb_reported_length_remaining(tvb, offset) > 0 ? tvb_get_uint8(tvb, offset) : 0;
1607
1608
0
  if ( tvb_bytes_exist(tvb, offset, 4) && first_byte == 0xDE &&
1609
0
       tvb_get_uint24(tvb, offset+1, ENC_BIG_ENDIAN) == 0xADBEEF )
1610
0
  {
1611
0
    return SQLNET_SNS;
1612
0
  }
1613
0
  else
1614
0
  {
1615
0
    return (unsigned)first_byte;
1616
0
  }
1617
0
}
1618
1619
static int get_strtype_custom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1620
0
{
1621
0
  int ret = 1; // 1st byte contains 254 or length if smaller than 64
1622
0
  int len = 0;
1623
1624
0
  wmem_strbuf_t *strbuf = wmem_strbuf_new(pinfo->pool, "");
1625
1626
0
  len = tvb_get_uint8(tvb, offset);
1627
0
  if (len == 254) {
1628
0
    int actual_len = 0;
1629
0
    do { // walk over the chunks
1630
0
      len = tvb_get_uint8(tvb, offset  + ret);
1631
0
      ret++; // 1st byte with the chunk size
1632
0
      wmem_strbuf_append(strbuf, (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset  + ret, len, ENC_ASCII|ENC_NA));
1633
0
      ret += len; // length of the string's chunk
1634
0
      actual_len += len;
1635
0
    } while (len == 64);
1636
0
    ret++; // has to be null-terminated
1637
0
    len = actual_len;
1638
0
  }
1639
0
  else {
1640
0
    ret += len;
1641
0
    wmem_strbuf_append(strbuf, (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset + 1, len, ENC_ASCII|ENC_NA));
1642
0
  }
1643
1644
0
  proto_tree_add_uint(tree, hf_tns_data_opi_param_length, tvb, offset, 1, len);
1645
0
  proto_tree_add_string(tree, hf_tns_data_opi_param_value, tvb, offset+1, ret-1, wmem_strbuf_get_str(strbuf));
1646
1647
0
  return ret;
1648
0
}
1649
1650
/* Decode an Oracle variable-length integer (ub4 / sb4):
1651
 * a length byte, then that many big-endian magnitude bytes. The low 7 bits
1652
 * of the length byte are the magnitude width (0..4); the high bit flags a
1653
 * negative value in sign-magnitude form (not two's complement) — so -1 is
1654
 * 0x81 0x01 and NUMBER scale -127 is 0x81 0x7f.
1655
 * Returns the number of bytes consumed. */
1656
static int get_sb4_custom(tvbuff_t *tvb, int offset, int *result)
1657
0
{
1658
0
  uint8_t first_byte = tvb_get_uint8(tvb, offset); // Contains length of a value
1659
0
  bool negative = (first_byte & 0x80) != 0;
1660
0
  uint8_t width = first_byte & 0x7f;
1661
0
  int magnitude = 0;
1662
1663
0
  switch(width)
1664
0
  {
1665
0
    case 0:
1666
0
      magnitude = 0;
1667
0
      break;
1668
0
    case 1:
1669
0
      magnitude = tvb_get_uint8(tvb, offset+1);
1670
0
      break;
1671
0
    case 2:
1672
0
      magnitude = tvb_get_ntohs(tvb, offset+1);
1673
0
      break;
1674
0
    case 3:
1675
0
      magnitude = tvb_get_ntoh24(tvb, offset+1);
1676
0
      break;
1677
0
    case 4:
1678
0
      magnitude = tvb_get_ntohl(tvb, offset+1);
1679
0
      break;
1680
0
    default:
1681
      /* Width 5..0x7f is not a valid 1..4-byte integer. In practice
1682
       * only a raw ub2 counter read through this helper reaches here;
1683
       * the historic client behaviour is to consume two bytes and
1684
       * return the negated second byte, which keeps the stream
1685
       * aligned. The value is discarded by such callers. */
1686
0
      if ( tvb_reported_length_remaining(tvb, offset) < 2 )
1687
0
      {
1688
        /* Not even that second byte is present. The width came
1689
         * off the wire, so this is malformed input rather than
1690
         * a bug in the dissector - step over the width alone. */
1691
0
        *result = 0;
1692
0
        return 1;
1693
0
      }
1694
0
      *result = -(int)tvb_get_uint8(tvb, offset+1);
1695
0
      return 2;
1696
0
  }
1697
0
  *result = negative ? -magnitude : magnitude;
1698
0
  return width + 1;
1699
0
}
1700
1701
/* Decode an Oracle variable-length ub8: a width byte (0..8), then that
1702
 * many big-endian bytes. Returns the number of bytes consumed. */
1703
static int get_ub8_custom(tvbuff_t *tvb, int offset, uint64_t *result)
1704
0
{
1705
0
  uint8_t width = tvb_get_uint8(tvb, offset);
1706
0
  uint64_t value = 0;
1707
1708
0
  if ( width > 8 )
1709
0
  {
1710
    /* Not a valid width; the value came off the wire, so step over
1711
     * the width byte alone rather than claim bytes. */
1712
0
    *result = 0;
1713
0
    return 1;
1714
0
  }
1715
0
  for ( int i = 0; i < width; i++ )
1716
0
    value = (value << 8) | tvb_get_uint8(tvb, offset + 1 + i);
1717
0
  *result = value;
1718
0
  return 1 + width;
1719
0
}
1720
1721
/* Walk the chunks of a chunked (0xFE) value, starting after the 0xFE:
1722
 * (length, bytes) pairs until a zero length. A length is one byte below
1723
 * field version 12.1 and a variable-length ub4 from 12.1 on. The data is
1724
 * appended to strbuf as UTF-8 when strbuf is not NULL. Returns the bytes
1725
 * consumed, the terminating zero included. */
1726
static int tns_chunks_len(tvbuff_t *tvb, packet_info *pinfo, int offset, wmem_strbuf_t *strbuf)
1727
0
{
1728
0
  bool ub4_lengths = tns_field_version(pinfo) >= TNS_FV_12_1;
1729
0
  int o = offset;
1730
1731
0
  while ( tvb_reported_length_remaining(tvb, o) > 0 )
1732
0
  {
1733
0
    int chunk_len;
1734
0
    if ( ub4_lengths )
1735
0
      o += get_sb4_custom(tvb, o, &chunk_len);
1736
0
    else
1737
0
    {
1738
0
      chunk_len = tvb_get_uint8(tvb, o);
1739
0
      o += 1;
1740
0
    }
1741
0
    if ( chunk_len <= 0 )
1742
0
      break;
1743
0
    if ( strbuf )
1744
0
      wmem_strbuf_append(strbuf, (const char *)tvb_get_string_enc(pinfo->pool, tvb, o, chunk_len, ENC_UTF_8|ENC_NA));
1745
0
    o += chunk_len;
1746
0
  }
1747
0
  return o - offset;
1748
0
}
1749
1750
/* The data of a DALC value at offset, chunks joined, in pinfo->pool;
1751
 * *len receives its length. NULL for an empty, NULL or absent value. */
1752
static const uint8_t *tns_dalc_bytes(tvbuff_t *tvb, packet_info *pinfo, int offset, int *len)
1753
0
{
1754
0
  uint8_t first = tvb_get_uint8(tvb, offset);
1755
0
  bool ub4_lengths = tns_field_version(pinfo) >= TNS_FV_12_1;
1756
0
  wmem_array_t *out;
1757
0
  int o;
1758
1759
0
  *len = 0;
1760
0
  if ( first == 0 || first >= TNS_DALC_ABSENT )
1761
0
  {
1762
0
    if ( first != 0xfe )
1763
0
      return NULL;
1764
0
  }
1765
0
  else
1766
0
  {
1767
0
    *len = first;
1768
0
    return tvb_memdup(pinfo->pool, tvb, offset + 1, first);
1769
0
  }
1770
1771
0
  out = wmem_array_new(pinfo->pool, 1);
1772
0
  o = offset + 1;
1773
0
  while ( tvb_reported_length_remaining(tvb, o) > 0 )
1774
0
  {
1775
0
    int chunk_len;
1776
0
    if ( ub4_lengths )
1777
0
      o += get_sb4_custom(tvb, o, &chunk_len);
1778
0
    else
1779
0
    {
1780
0
      chunk_len = tvb_get_uint8(tvb, o);
1781
0
      o += 1;
1782
0
    }
1783
0
    if ( chunk_len <= 0 )
1784
0
      break;
1785
0
    wmem_array_append(out, tvb_get_ptr(tvb, o, chunk_len), chunk_len);
1786
0
    o += chunk_len;
1787
0
  }
1788
0
  *len = (int)wmem_array_get_count(out);
1789
0
  return (const uint8_t *)wmem_array_get_raw(out);
1790
0
}
1791
1792
/* Decode a DALC (Data-Length-And-Content) blob. The leading byte is a
1793
 * length only in the middle of its range:
1794
 *
1795
 *   0x00        empty
1796
 *   0x01..0xFC  that many data bytes follow (252 is the longest)
1797
 *   0xFD        absent value: the two-byte placeholder FD 01, no data
1798
 *   0xFE        chunked: (len, bytes) pairs until a 0-length chunk
1799
 *   0xFF        null - a marker only, no data follows
1800
 *
1801
 * The top three bytes are markers, not lengths. The null marker consumes
1802
 * just itself. The absent-value placeholder fills a bind slot that has no
1803
 * inline value - a pure OUT bind, or a NULL of a type with no inline form
1804
 * such as BOOLEAN - and consumes itself plus the 0x01 after it. Reading
1805
 * either as a length would claim bytes that are not there and misalign
1806
 * every field after it, so they have to be spelled out rather than left
1807
 * to the default.
1808
 *
1809
 * The chunk lengths in the 0xFE form are plain counts, a single byte (up
1810
 * to 255) below field version 12.1 and a variable-length ub4 from 12.1 on.
1811
 *
1812
 * Returns the number of bytes consumed from the tvb and, when content
1813
 * is non-empty, a UTF-8 string allocated from pinfo->pool. */
1814
static int get_dalc_custom(tvbuff_t *tvb, packet_info *pinfo, int offset, const char **out_str)
1815
0
{
1816
0
  uint8_t first = tvb_get_uint8(tvb, offset);
1817
0
  if ( first == 0 || first == 255 )
1818
0
  {
1819
0
    if ( out_str )
1820
0
      *out_str = NULL;
1821
0
    return 1;
1822
0
  }
1823
0
  if ( first == TNS_DALC_ABSENT )
1824
0
  {
1825
0
    if ( out_str )
1826
0
      *out_str = NULL;
1827
0
    return 2;
1828
0
  }
1829
0
  if ( first != 254 )
1830
0
  {
1831
0
    if ( out_str )
1832
0
      *out_str = (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset + 1, first, ENC_UTF_8|ENC_NA);
1833
0
    return 1 + first;
1834
0
  }
1835
1836
  /* Chunked form: (len, bytes)+ until a zero-length chunk. */
1837
0
  wmem_strbuf_t *strbuf = wmem_strbuf_new(pinfo->pool, "");
1838
0
  int used = 1 + tns_chunks_len(tvb, pinfo, offset + 1, strbuf);
1839
0
  if ( out_str )
1840
0
    *out_str = wmem_strbuf_get_str(strbuf);
1841
0
  return used;
1842
0
}
1843
1844
/* A server's message text carries a trailing newline; a client strips it
1845
 * before showing the error. Returns a pinfo->pool string, or NULL. */
1846
static const char *tns_trim_message(packet_info *pinfo, const char *msg)
1847
0
{
1848
0
  size_t len;
1849
1850
0
  if ( !msg )
1851
0
    return NULL;
1852
0
  len = strlen(msg);
1853
0
  while ( len > 0 && (msg[len - 1] == '\n' || msg[len - 1] == '\r' || msg[len - 1] == ' ') )
1854
0
    len--;
1855
0
  return wmem_strndup(pinfo->pool, msg, len);
1856
0
}
1857
1858
/* Decode a bytes_with_length / str_with_length field: a ub4 count, and
1859
 * a DALC carrying the value only when that count is non-zero. The count
1860
 * is not simply a byte to step over - an empty field is the count
1861
 * alone, so reading a DALC anyway consumes whatever follows it.
1862
 * Returns bytes consumed; *out_str (when non-NULL) gets the string, or
1863
 * NULL when the field is empty. */
1864
static int get_field_with_length(tvbuff_t *tvb, packet_info *pinfo, int offset, const char **out_str)
1865
0
{
1866
0
  int count = 0;
1867
0
  int used = get_sb4_custom(tvb, offset, &count);
1868
0
  if ( out_str )
1869
0
    *out_str = NULL;
1870
0
  if ( count > 0 )
1871
0
    used += get_dalc_custom(tvb, pinfo, offset + used, out_str);
1872
0
  return used;
1873
0
}
1874
1875
/* Render an Oracle NUMBER value as a decimal string.
1876
 * Base-100 float: byte 0 is the biased exponent (top bit = sign, inverted
1877
 * for negatives); the rest are base-100 mantissa groups, with a trailing
1878
 * 0x66 terminator on negatives.
1879
 * Returns a pinfo->pool string, or NULL if the value is not renderable. */
1880
static const char *tns_format_number(packet_info *pinfo, const uint8_t *data, int len)
1881
0
{
1882
0
  if ( len <= 0 )
1883
0
    return NULL;
1884
0
  if ( len == 1 )
1885
0
    return (data[0] == 0x80) ? "0" : NULL; /* 0x80 = zero; sentinels skipped */
1886
1887
0
  uint8_t exp_byte = data[0];
1888
0
  bool is_pos = (exp_byte & 0x80) != 0;
1889
0
  int exponent = is_pos ? (exp_byte & 0x7f) - 65 : ((~exp_byte) & 0x7f) - 65;
1890
1891
0
  int mant_len = len - 1;
1892
0
  if ( !is_pos && mant_len > 0 && data[len - 1] == 0x66 )
1893
0
    mant_len--; /* drop the negative terminator */
1894
1895
  /* Build the base-100 digit string (two decimal digits per group). */
1896
0
  wmem_strbuf_t *digits = wmem_strbuf_new(pinfo->pool, "");
1897
0
  for ( int i = 0; i < mant_len; i++ )
1898
0
  {
1899
0
    int pair = is_pos ? (data[1 + i] - 1) : (101 - data[1 + i]);
1900
0
    if ( pair < 0 || pair > 99 )
1901
0
      return NULL; /* malformed */
1902
0
    wmem_strbuf_append_printf(digits, "%02d", pair);
1903
0
  }
1904
0
  const char *ds = wmem_strbuf_get_str(digits);
1905
0
  int dlen = (int)wmem_strbuf_get_len(digits);
1906
0
  int int_digits = (exponent + 1) * 2;
1907
1908
0
  wmem_strbuf_t *ip = wmem_strbuf_new(pinfo->pool, "");
1909
0
  wmem_strbuf_t *fp = wmem_strbuf_new(pinfo->pool, "");
1910
0
  if ( int_digits >= dlen )
1911
0
  {
1912
0
    wmem_strbuf_append(ip, ds);
1913
0
    for ( int i = 0; i < int_digits - dlen; i++ )
1914
0
      wmem_strbuf_append_c(ip, '0');
1915
0
  }
1916
0
  else if ( int_digits <= 0 )
1917
0
  {
1918
0
    wmem_strbuf_append_c(ip, '0');
1919
0
    for ( int i = 0; i < -int_digits; i++ )
1920
0
      wmem_strbuf_append_c(fp, '0');
1921
0
    wmem_strbuf_append(fp, ds);
1922
0
  }
1923
0
  else
1924
0
  {
1925
0
    wmem_strbuf_append(ip, wmem_strndup(pinfo->pool, ds, int_digits));
1926
0
    wmem_strbuf_append(fp, ds + int_digits);
1927
0
  }
1928
1929
  /* Trim leading zeros on the integer part, trailing zeros on the fraction. */
1930
0
  const char *ips = wmem_strbuf_get_str(ip);
1931
0
  while ( ips[0] == '0' && ips[1] != '\0' )
1932
0
    ips++;
1933
0
  char *fps = wmem_strdup(pinfo->pool, wmem_strbuf_get_str(fp));
1934
0
  int flen = (int)strlen(fps);
1935
0
  while ( flen > 0 && fps[flen - 1] == '0' )
1936
0
    fps[--flen] = '\0';
1937
1938
0
  const char *sign = is_pos ? "" : "-";
1939
0
  if ( flen > 0 )
1940
0
    return wmem_strdup_printf(pinfo->pool, "%s%s.%s", sign, ips, fps);
1941
0
  return wmem_strdup_printf(pinfo->pool, "%s%s", sign, ips);
1942
0
}
1943
1944
/* Render an Oracle DATE / TIMESTAMP value as an
1945
 * ISO-ish string. 7 bytes: century+100, year+100, month, day, hour+1,
1946
 * minute+1, second+1; 11 bytes add 4-byte big-endian nanoseconds.
1947
 * A year before 1 - a DATE reaches back to 4712 BC, with no year 0 -
1948
 * counts down from the same bias, so the same sum gives it negative,
1949
 * and it is shown as the BC year it is. Returns a pinfo->pool string, or
1950
 * NULL. */
1951
static const char *tns_format_date(packet_info *pinfo, const uint8_t *data, int len)
1952
0
{
1953
0
  if ( len < 7 )
1954
0
    return NULL;
1955
0
  int year = (data[0] - 100) * 100 + (data[1] - 100);
1956
0
  const char *era = "";
1957
0
  if ( year < 0 )
1958
0
  {
1959
0
    year = -year;
1960
0
    era = " BC";
1961
0
  }
1962
0
  int month = data[2], day = data[3];
1963
0
  int hour = data[4] - 1, minute = data[5] - 1, second = data[6] - 1;
1964
0
  if ( month < 1 || month > 12 || day < 1 || day > 31 ||
1965
0
       hour < 0 || hour > 23 || minute < 0 || minute > 59 || second < 0 || second > 59 )
1966
0
    return NULL;
1967
0
  if ( len >= 11 )
1968
0
  {
1969
0
    uint32_t nsec = ((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) |
1970
0
        ((uint32_t)data[9] << 8) | data[10];
1971
0
    if ( nsec > 0 )
1972
0
      return wmem_strdup_printf(pinfo->pool, "%04d-%02d-%02d %02d:%02d:%02d.%09u%s",
1973
0
        year, month, day, hour, minute, second, nsec, era);
1974
0
  }
1975
0
  return wmem_strdup_printf(pinfo->pool, "%04d-%02d-%02d %02d:%02d:%02d%s",
1976
0
    year, month, day, hour, minute, second, era);
1977
0
}
1978
1979
/* Days since 1970-01-01 of a proleptic Gregorian date, and back. */
1980
static int64_t tns_days_from_civil(int64_t y, unsigned m, unsigned d)
1981
0
{
1982
0
  y -= m <= 2;
1983
0
  int64_t era = (y >= 0 ? y : y - 399) / 400;
1984
0
  unsigned yoe = (unsigned)(y - era * 400);
1985
0
  unsigned doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
1986
0
  unsigned doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
1987
0
  return era * 146097 + (int64_t)doe - 719468;
1988
0
}
1989
1990
static void tns_civil_from_days(int64_t z, int64_t *y, unsigned *m, unsigned *d)
1991
0
{
1992
0
  z += 719468;
1993
0
  int64_t era = (z >= 0 ? z : z - 146096) / 146097;
1994
0
  unsigned doe = (unsigned)(z - era * 146097);
1995
0
  unsigned yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
1996
0
  unsigned doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
1997
0
  unsigned mp = (5 * doy + 2) / 153;
1998
0
  *d = doy - (153 * mp + 2) / 5 + 1;
1999
0
  *m = mp < 10 ? mp + 3 : mp - 9;
2000
0
  *y = (int64_t)yoe + era * 400 + (*m <= 2);
2001
0
}
2002
2003
/* Render an Oracle TIMESTAMP WITH TIME ZONE value: 13 bytes, the
2004
 * 11-byte TIMESTAMP form holding the instant in UTC, then two zone
2005
 * bytes. With the top bit of the first clear they are an offset, hour
2006
 * + 20 and minute + 60, and the value is shown in local time with that
2007
 * offset; with it set they hold a named zone's region id,
2008
 * ((b0 & 0x7f) << 6) + (b1 >> 2), and the value is shown in UTC. A
2009
 * server sends an OCI client the wall clock at the offset instead, and
2010
 * says so with bit 0x40 of the hour byte.
2011
 * Returns a pinfo->pool string, or NULL. */
2012
static const char *tns_format_timestamp_tz(packet_info *pinfo, const uint8_t *data, int len)
2013
0
{
2014
0
  const char *utc;
2015
0
  uint32_t nsec;
2016
0
  int64_t minutes, days, year;
2017
0
  unsigned month, day;
2018
0
  int tz_hour, tz_min, minute_of_day;
2019
0
  char sign;
2020
2021
0
  if ( len != 13 )
2022
0
    return tns_format_date(pinfo, data, len);
2023
0
  utc = tns_format_date(pinfo, data, 11);
2024
0
  if ( !utc )
2025
0
    return NULL;
2026
0
  if ( data[11] & 0x80 )
2027
0
    return wmem_strdup_printf(pinfo->pool, "%s UTC (time zone region %u)", utc,
2028
0
      ((unsigned)(data[11] & 0x7f) << 6) + (data[12] >> 2));
2029
2030
  /* Shift the UTC wall clock by the offset, in whole minutes, unless
2031
   * it is the local one already. */
2032
0
  tz_hour = (data[11] & 0x3f) - 20;
2033
0
  tz_min = data[12] - 60;
2034
0
  days = tns_days_from_civil((data[0] - 100) * 100 + (data[1] - 100), data[2], data[3]);
2035
0
  minutes = days * 1440 + (data[4] - 1) * 60 + (data[5] - 1);
2036
0
  if ( !(data[11] & 0x40) )
2037
0
    minutes += tz_hour * 60 + tz_min;
2038
0
  days = minutes >= 0 ? minutes / 1440 : -((-minutes + 1439) / 1440);
2039
0
  minute_of_day = (int)(minutes - days * 1440);
2040
0
  tns_civil_from_days(days, &year, &month, &day);
2041
2042
0
  nsec = ((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) | ((uint32_t)data[9] << 8) | data[10];
2043
  /* The sign goes on the whole offset: -03:30 is hour -3, minute -30. */
2044
0
  sign = (tz_hour < 0 || tz_min < 0) ? '-' : '+';
2045
0
  if ( nsec )
2046
0
    return wmem_strdup_printf(pinfo->pool, "%04" PRId64 "-%02u-%02u %02d:%02d:%02d.%09u %c%02d:%02d",
2047
0
      year, month, day, minute_of_day / 60, minute_of_day % 60, data[6] - 1, nsec,
2048
0
      sign, abs(tz_hour), abs(tz_min));
2049
0
  return wmem_strdup_printf(pinfo->pool, "%04" PRId64 "-%02u-%02u %02d:%02d:%02d %c%02d:%02d",
2050
0
    year, month, day, minute_of_day / 60, minute_of_day % 60, data[6] - 1,
2051
0
    sign, abs(tz_hour), abs(tz_min));
2052
0
}
2053
2054
/* Render an Oracle INTERVAL YEAR TO MONTH (5 bytes: years as a
2055
 * big-endian ub4 biased by 2^31, months biased by 60) or INTERVAL DAY TO
2056
 * SECOND (11 bytes: days as a ub4 biased by 2^31, hours, minutes and
2057
 * seconds each biased by 60, nanoseconds as a ub4 biased by 2^31). All
2058
 * fields carry the interval's sign. Rendered as Oracle writes an
2059
 * interval literal: [-]Y-MM, or [-]D HH:MM:SS[.fffffffff].
2060
 * Returns a pinfo->pool string, or NULL. */
2061
static const char *tns_format_interval(packet_info *pinfo, uint8_t dtype, const uint8_t *data, int len)
2062
0
{
2063
0
  int32_t lead = (int32_t)((((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) |
2064
0
    ((uint32_t)data[2] << 8) | data[3]) - 0x80000000u);
2065
2066
0
  if ( dtype == TNS_DATATYPE_INTERVAL_YM && len == 5 )
2067
0
  {
2068
0
    int months = data[4] - 60;
2069
0
    bool neg = lead < 0 || months < 0;
2070
0
    return wmem_strdup_printf(pinfo->pool, "%s%d-%02d", neg ? "-" : "",
2071
0
      abs(lead), abs(months));
2072
0
  }
2073
0
  if ( dtype == TNS_DATATYPE_INTERVAL_DS && len == 11 )
2074
0
  {
2075
0
    int hours = data[4] - 60, minutes = data[5] - 60, seconds = data[6] - 60;
2076
0
    int32_t nsec = (int32_t)((((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) |
2077
0
      ((uint32_t)data[9] << 8) | data[10]) - 0x80000000u);
2078
0
    bool neg = lead < 0 || hours < 0 || minutes < 0 || seconds < 0 || nsec < 0;
2079
0
    if ( nsec )
2080
0
      return wmem_strdup_printf(pinfo->pool, "%s%d %02d:%02d:%02d.%09d", neg ? "-" : "",
2081
0
        abs(lead), abs(hours), abs(minutes), abs(seconds), abs(nsec));
2082
0
    return wmem_strdup_printf(pinfo->pool, "%s%d %02d:%02d:%02d", neg ? "-" : "",
2083
0
      abs(lead), abs(hours), abs(minutes), abs(seconds));
2084
0
  }
2085
0
  return NULL;
2086
0
}
2087
2088
/* Render an Oracle BINARY_FLOAT (4 bytes) / BINARY_DOUBLE (8 bytes) value
2089
 * Stored in an order-preserving IEEE-754 form: if the
2090
 * high bit is set the value was positive (clear it), else it was negative
2091
 * (invert all bits); then read as big-endian IEEE-754. Returns a
2092
 * pinfo->pool string, or NULL. */
2093
static const char *tns_format_binary_float(packet_info *pinfo, const uint8_t *data, int len)
2094
0
{
2095
0
  char buf[G_ASCII_DTOSTR_BUF_SIZE];
2096
2097
0
  if ( len == 4 )
2098
0
  {
2099
0
    uint32_t u = ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) |
2100
0
           ((uint32_t)data[2] << 8) | data[3];
2101
0
    u = (u & 0x80000000u) ? (u & 0x7fffffffu) : ~u;
2102
0
    float f;
2103
0
    memcpy(&f, &u, 4);
2104
    /* Locale-independent '.' decimal separator. */
2105
0
    g_ascii_formatd(buf, sizeof(buf), "%g", (double)f);
2106
0
    return wmem_strdup(pinfo->pool, buf);
2107
0
  }
2108
0
  if ( len == 8 )
2109
0
  {
2110
0
    uint64_t u = 0;
2111
0
    for ( int i = 0; i < 8; i++ )
2112
0
      u = (u << 8) | data[i];
2113
0
    u = (u & UINT64_C(0x8000000000000000)) ? (u & UINT64_C(0x7fffffffffffffff)) : ~u;
2114
0
    double d;
2115
0
    memcpy(&d, &u, 8);
2116
0
    g_ascii_formatd(buf, sizeof(buf), "%g", d);
2117
0
    return wmem_strdup(pinfo->pool, buf);
2118
0
  }
2119
0
  return NULL;
2120
0
}
2121
2122
/* The base-64 alphabet of Oracle's printable rowids. */
2123
static const char tns_rowid_alphabet[] =
2124
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2125
2126
/* Append value to buf as `digits` base-64 characters, most significant
2127
 * first. */
2128
static void tns_rowid_append(wmem_strbuf_t *buf, uint32_t value, int digits)
2129
0
{
2130
0
  char chars[6];
2131
2132
0
  for ( int i = digits - 1; i >= 0; i-- )
2133
0
  {
2134
0
    chars[i] = tns_rowid_alphabet[value & 0x3f];
2135
0
    value >>= 6;
2136
0
  }
2137
0
  wmem_strbuf_append_len(buf, chars, digits);
2138
0
}
2139
2140
/* Render a physical rowid as the 18-character extended rowid ROWIDTOCHAR
2141
 * prints: object, file, block and slot in 6, 3, 6 and 3 base-64 digits.
2142
 * Returns a pinfo->pool string. */
2143
static const char *tns_format_rowid(packet_info *pinfo, uint32_t rba, uint32_t part, uint32_t block, uint32_t slot)
2144
0
{
2145
0
  wmem_strbuf_t *buf = wmem_strbuf_new(pinfo->pool, "");
2146
2147
0
  tns_rowid_append(buf, rba, 6);
2148
0
  tns_rowid_append(buf, part, 3);
2149
0
  tns_rowid_append(buf, block, 6);
2150
0
  tns_rowid_append(buf, slot, 3);
2151
0
  return wmem_strbuf_get_str(buf);
2152
0
}
2153
2154
/* Render a universal rowid. A leading type byte of 1 marks a physical
2155
 * rowid, printed as above; anything else is a logical one - an
2156
 * index-organized table's, carrying its primary key - printed as "*" and
2157
 * the base-64 of the bytes after the type byte, unpadded. Returns a
2158
 * pinfo->pool string, or NULL. */
2159
static const char *tns_format_urowid(packet_info *pinfo, const uint8_t *data, int len)
2160
0
{
2161
0
  if ( len >= 13 && data[0] == 1 )
2162
0
    return tns_format_rowid(pinfo,
2163
0
      ((uint32_t)data[1] << 24) | ((uint32_t)data[2] << 16) | ((uint32_t)data[3] << 8) | data[4],
2164
0
      ((uint32_t)data[5] << 8) | data[6],
2165
0
      ((uint32_t)data[7] << 24) | ((uint32_t)data[8] << 16) | ((uint32_t)data[9] << 8) | data[10],
2166
0
      ((uint32_t)data[11] << 8) | data[12]);
2167
0
  if ( len < 2 )
2168
0
    return NULL;
2169
2170
0
  wmem_strbuf_t *buf = wmem_strbuf_new(pinfo->pool, "*");
2171
0
  for ( int i = 1; i < len; i += 3 )
2172
0
  {
2173
0
    int n = MIN(3, len - i);
2174
0
    uint32_t group = (uint32_t)data[i] << 16;
2175
0
    if ( n > 1 )
2176
0
      group |= (uint32_t)data[i + 1] << 8;
2177
0
    if ( n > 2 )
2178
0
      group |= data[i + 2];
2179
    /* n bytes give n + 1 characters */
2180
0
    for ( int k = 0; k <= n; k++ )
2181
0
      wmem_strbuf_append_c(buf, tns_rowid_alphabet[(group >> (18 - 6 * k)) & 0x3f]);
2182
0
  }
2183
0
  return wmem_strbuf_get_str(buf);
2184
0
}
2185
2186
/* Render a VECTOR image:
2187
 *   0xDB | version (ub1) | flags (be16) | format (ub1) | elements (be32) |
2188
 *   [norm, 8 bytes, with flag 0x02 or 0x10] |
2189
 *   [sparse (flag 0x20): count (be16), count x be32 index] | values
2190
 * FLOAT32 / FLOAT64 values use the order-preserving BINARY_FLOAT /
2191
 * BINARY_DOUBLE encoding, INT8 plain bytes, BINARY bits packed eight to a
2192
 * byte (the element count is then a bit count). The first few values are
2193
 * shown. Returns a pinfo->pool string, or NULL. */
2194
static const char *tns_format_vector(packet_info *pinfo, const uint8_t *data, int len)
2195
0
{
2196
0
  static const char *formats[] = { NULL, NULL, "FLOAT32", "FLOAT64", "INT8", "BINARY" };
2197
0
  const int shown = 16;
2198
0
  uint16_t flags;
2199
0
  uint8_t format;
2200
0
  uint32_t count, dims;
2201
0
  int pos = 9, size;
2202
0
  const uint8_t *indices = NULL;
2203
0
  wmem_strbuf_t *buf;
2204
2205
0
  if ( len < 9 || data[0] != 0xdb )
2206
0
    return NULL;
2207
0
  flags = (uint16_t)((data[2] << 8) | data[3]);
2208
0
  format = data[4];
2209
0
  dims = count = ((uint32_t)data[5] << 24) | ((uint32_t)data[6] << 16) | ((uint32_t)data[7] << 8) | data[8];
2210
0
  if ( format < 2 || format > 5 )
2211
0
    return NULL;
2212
0
  if ( flags & 0x0012 )
2213
0
    pos += 8;
2214
0
  if ( flags & 0x0020 )
2215
0
  {
2216
0
    if ( pos + 2 > len )
2217
0
      return NULL;
2218
0
    count = (uint32_t)((data[pos] << 8) | data[pos + 1]);
2219
0
    pos += 2;
2220
0
    indices = data + pos;
2221
0
    if ( (uint64_t)count * 4 > (uint64_t)(len - pos) )
2222
0
      return NULL;
2223
0
    pos += count * 4;
2224
0
  }
2225
0
  else if ( format == 5 )
2226
0
    count = (count + 7) / 8;
2227
0
  size = format == 2 ? 4 : format == 3 ? 8 : 1;
2228
0
  if ( (uint64_t)count * size > (uint64_t)(len - pos) )
2229
0
    return NULL;
2230
2231
0
  buf = wmem_strbuf_new(pinfo->pool, "");
2232
0
  if ( indices )
2233
0
    wmem_strbuf_append_printf(buf, "sparse %s of %u dimensions: {", formats[format], dims);
2234
0
  else
2235
0
    wmem_strbuf_append_printf(buf, "%s[%u]: [", formats[format], dims);
2236
0
  for ( uint32_t i = 0; i < count && i < (uint32_t)shown; i++ )
2237
0
  {
2238
0
    const uint8_t *e = data + pos + i * size;
2239
0
    if ( i )
2240
0
      wmem_strbuf_append(buf, ", ");
2241
0
    if ( indices )
2242
0
      wmem_strbuf_append_printf(buf, "%u: ", ((uint32_t)indices[4 * i] << 24)
2243
0
        | ((uint32_t)indices[4 * i + 1] << 16) | ((uint32_t)indices[4 * i + 2] << 8) | indices[4 * i + 3]);
2244
0
    if ( size > 1 )
2245
0
      wmem_strbuf_append(buf, tns_format_binary_float(pinfo, e, size));
2246
0
    else if ( format == 4 )
2247
0
      wmem_strbuf_append_printf(buf, "%d", (int8_t)e[0]);
2248
0
    else
2249
0
      wmem_strbuf_append_printf(buf, "%u", e[0]);
2250
0
  }
2251
0
  if ( count > (uint32_t)shown )
2252
0
    wmem_strbuf_append(buf, ", ...");
2253
0
  wmem_strbuf_append_c(buf, indices ? '}' : ']');
2254
0
  return wmem_strbuf_get_str(buf);
2255
0
}
2256
2257
0
#define TNS_OSON_MAX_DEPTH   32
2258
0
#define TNS_OSON_MAX_NODES   4096
2259
0
#define TNS_OSON_MAX_TEXT    2048
2260
2261
/* A reader over an OSON image; every access is bounds checked, and a
2262
 * failed one marks the reader bad instead of throwing. */
2263
typedef struct _tns_oson_t {
2264
  const uint8_t *data;
2265
  uint32_t len;
2266
  bool bad;
2267
  uint32_t tree;          /* start of the tree segment */
2268
  uint8_t field_id_len;   /* 1, 2 or 4 */
2269
  bool relative;          /* container children count from the container */
2270
  uint32_t num_names;
2271
  const uint8_t **names;
2272
  uint32_t *name_lens;
2273
} tns_oson_t;
2274
2275
typedef struct _tns_oson_frame_t {
2276
  bool is_object;
2277
  uint8_t node_type;
2278
  uint32_t count, next;
2279
  uint32_t ids_pos, offsets_pos, container;
2280
} tns_oson_frame_t;
2281
2282
static uint32_t tns_oson_uint(tns_oson_t *o, uint32_t pos, int width)
2283
0
{
2284
0
  uint32_t v = 0;
2285
2286
0
  if ( o->bad || pos > o->len || (uint32_t)width > o->len - pos )
2287
0
  {
2288
0
    o->bad = true;
2289
0
    return 0;
2290
0
  }
2291
0
  for ( int i = 0; i < width; i++ )
2292
0
    v = (v << 8) | o->data[pos + i];
2293
0
  return v;
2294
0
}
2295
2296
/* Read the field names of one segment: a hash array (hash_size bytes a
2297
 * name), an offsets array, then the names, each behind a length of
2298
 * len_size bytes. */
2299
static uint32_t tns_oson_names(tns_oson_t *o, uint32_t pos, uint32_t first, uint32_t num,
2300
  int hash_size, int off_size, uint32_t seg_size, int len_size)
2301
0
{
2302
0
  uint32_t offsets, seg, prod, end;
2303
2304
  /* The names live in [seg, seg + seg_size); require that whole range to
2305
   * lie within the buffer. Check for overflow; these inputs are 32-bit
2306
   * from packet data and so are their sums and products, but pointer
2307
   * widths might be 64-bit. */
2308
0
  if ( ckd_mul(&prod, num, hash_size) || ckd_add(&offsets, pos, prod)
2309
0
    || ckd_mul(&prod, num, off_size) || ckd_add(&seg, offsets, prod)
2310
0
    || ckd_add(&end, seg, seg_size) || end > o->len )
2311
0
  {
2312
0
    o->bad = true;
2313
0
    return o->len;
2314
0
  }
2315
0
  for ( uint32_t i = 0; i < num && !o->bad; i++ )
2316
0
  {
2317
    /* offsets + i*off_size <= seg and seg + at + len_size + n <= end
2318
     * <= o->len, so none of these overflow or leave the buffer. */
2319
0
    uint32_t at = tns_oson_uint(o, offsets + i * off_size, off_size);
2320
0
    uint32_t n;
2321
0
    if ( at > seg_size || (uint32_t)len_size > seg_size - at )
2322
0
    {
2323
0
      o->bad = true;
2324
0
      break;
2325
0
    }
2326
0
    n = tns_oson_uint(o, seg + at, len_size);
2327
0
    if ( n > seg_size - at - len_size )
2328
0
      o->bad = true;
2329
0
    else
2330
0
    {
2331
0
      o->names[first + i] = o->data + seg + at + len_size;
2332
0
      o->name_lens[first + i] = n;
2333
0
    }
2334
0
  }
2335
0
  return end;
2336
0
}
2337
2338
static void tns_oson_append_string(wmem_strbuf_t *buf, const uint8_t *s, uint32_t len)
2339
0
{
2340
0
  wmem_strbuf_append_c(buf, '"');
2341
0
  for ( uint32_t i = 0; i < len; i++ )
2342
0
  {
2343
0
    if ( s[i] == '"' || s[i] == '\\' )
2344
0
      wmem_strbuf_append_printf(buf, "\\%c", s[i]);
2345
0
    else if ( s[i] < 0x20 )
2346
0
      wmem_strbuf_append_printf(buf, "\\u%04x", s[i]);
2347
0
    else
2348
0
      wmem_strbuf_append_c(buf, s[i]);
2349
0
  }
2350
0
  wmem_strbuf_append_c(buf, '"');
2351
0
}
2352
2353
/* How an OSON scalar's payload is rendered. */
2354
typedef enum {
2355
  TNS_OSON_STRING,
2356
  TNS_OSON_NUMBER,
2357
  TNS_OSON_DATETIME,
2358
  TNS_OSON_FLOAT,
2359
  TNS_OSON_INTERVAL,
2360
  TNS_OSON_BYTES
2361
} tns_oson_kind_t;
2362
2363
/* Render the scalar node at pos; returns false on a malformed or unknown
2364
 * node. The tag selects the type and says where its length is: in a byte,
2365
 * a be16 or a be32 after the tag, fixed by the type, or in the tag's low
2366
 * bits. */
2367
static bool tns_oson_scalar(packet_info *pinfo, tns_oson_t *o, uint32_t pos, wmem_strbuf_t *buf)
2368
0
{
2369
0
  uint8_t t = (uint8_t)tns_oson_uint(o, pos, 1);
2370
0
  uint32_t n = 0, at = pos + 1;
2371
0
  tns_oson_kind_t kind;
2372
0
  const char *text = NULL;
2373
2374
0
  if ( o->bad )
2375
0
    return false;
2376
0
  switch ( t )
2377
0
  {
2378
0
    case 0x30: wmem_strbuf_append(buf, "null"); return true;
2379
0
    case 0x31: wmem_strbuf_append(buf, "true"); return true;
2380
0
    case 0x32: wmem_strbuf_append(buf, "false"); return true;
2381
0
    case 0x33: kind = TNS_OSON_STRING; n = tns_oson_uint(o, at, 1); at += 1; break;
2382
0
    case 0x37: kind = TNS_OSON_STRING; n = tns_oson_uint(o, at, 2); at += 2; break;
2383
0
    case 0x38: kind = TNS_OSON_STRING; n = tns_oson_uint(o, at, 4); at += 4; break;
2384
0
    case 0x34: kind = TNS_OSON_NUMBER; n = tns_oson_uint(o, at, 1); at += 1; break;
2385
0
    case 0x3c: case 0x7d: kind = TNS_OSON_DATETIME; n = 7; break;
2386
0
    case 0x39: kind = TNS_OSON_DATETIME; n = 11; break;
2387
0
    case 0x7c: kind = TNS_OSON_DATETIME; n = 13; break;
2388
0
    case 0x7f: kind = TNS_OSON_FLOAT; n = 4; break;
2389
0
    case 0x36: kind = TNS_OSON_FLOAT; n = 8; break;
2390
0
    case 0x3d: kind = TNS_OSON_INTERVAL; n = 5; break;
2391
0
    case 0x3e: kind = TNS_OSON_INTERVAL; n = 11; break;
2392
0
    case 0x7e: kind = TNS_OSON_BYTES; n = tns_oson_uint(o, at, 1); at += 1; break;
2393
0
    case 0x3a: kind = TNS_OSON_BYTES; n = tns_oson_uint(o, at, 2); at += 2; break;
2394
0
    case 0x3b: kind = TNS_OSON_BYTES; n = tns_oson_uint(o, at, 4); at += 4; break;
2395
0
    case 0x7b:
2396
      /* extended type: a vector, with a be32 image length */
2397
0
      if ( tns_oson_uint(o, at, 1) != 0x01 )
2398
0
        return false;
2399
0
      n = tns_oson_uint(o, at + 1, 4);
2400
0
      at += 5;
2401
0
      if ( o->bad || n > o->len - at )
2402
0
        return false;
2403
0
      text = tns_format_vector(pinfo, o->data + at, n);
2404
0
      if ( !text )
2405
0
        return false;
2406
0
      tns_oson_append_string(buf, (const uint8_t *)text, (uint32_t)strlen(text));
2407
0
      return true;
2408
0
    default:
2409
0
      if ( (t & 0xf0) == 0x20 || (t & 0xf0) == 0x60 )
2410
0
      {
2411
0
        kind = TNS_OSON_NUMBER;
2412
0
        n = (t & 0x0f) + 1u;
2413
0
      }
2414
0
      else if ( (t & 0xf0) == 0x40 || (t & 0xf0) == 0x50 )
2415
0
      {
2416
0
        kind = TNS_OSON_NUMBER;
2417
0
        n = t & 0x0f;
2418
0
      }
2419
0
      else if ( (t & 0xe0) == 0 )
2420
0
      {
2421
0
        kind = TNS_OSON_STRING;
2422
0
        n = t;
2423
0
      }
2424
0
      else
2425
0
        return false;
2426
0
      break;
2427
0
  }
2428
0
  if ( o->bad || n > o->len - at )
2429
0
    return false;
2430
2431
0
  switch ( kind )
2432
0
  {
2433
0
    case TNS_OSON_STRING:
2434
0
      tns_oson_append_string(buf, o->data + at, n);
2435
0
      return true;
2436
0
    case TNS_OSON_BYTES:
2437
0
      wmem_strbuf_append_c(buf, '"');
2438
0
      for ( uint32_t i = 0; i < n; i++ )
2439
0
        wmem_strbuf_append_printf(buf, "%02x", o->data[at + i]);
2440
0
      wmem_strbuf_append_c(buf, '"');
2441
0
      return true;
2442
0
    case TNS_OSON_NUMBER:
2443
0
      text = n ? tns_format_number(pinfo, o->data + at, (int)n) : "0";
2444
0
      break;
2445
0
    case TNS_OSON_FLOAT:
2446
0
      text = tns_format_binary_float(pinfo, o->data + at, (int)n);
2447
0
      break;
2448
0
    case TNS_OSON_DATETIME:
2449
0
      text = t == 0x7c ? tns_format_timestamp_tz(pinfo, o->data + at, (int)n)
2450
0
        : tns_format_date(pinfo, o->data + at, (int)n);
2451
0
      break;
2452
0
    case TNS_OSON_INTERVAL:
2453
0
      text = tns_format_interval(pinfo, t == 0x3d ? TNS_DATATYPE_INTERVAL_YM : TNS_DATATYPE_INTERVAL_DS,
2454
0
        o->data + at, (int)n);
2455
0
      break;
2456
0
  }
2457
0
  if ( !text )
2458
0
    return false;
2459
  /* numbers stand bare; dates and intervals are strings in JSON */
2460
0
  if ( kind == TNS_OSON_NUMBER || kind == TNS_OSON_FLOAT )
2461
0
    wmem_strbuf_append(buf, text);
2462
0
  else
2463
0
    tns_oson_append_string(buf, (const uint8_t *)text, (uint32_t)strlen(text));
2464
0
  return true;
2465
0
}
2466
2467
/* Open the container node at pos into frame f. A container's tag says
2468
 * whether it is an object or an array (0x40), how wide its child count is
2469
 * (bits 0x18: one, two or four bytes), and how wide its offsets are
2470
 * (0x20). With both count bits set, an object shares another object's
2471
 * field ids: the donor's offset - absolute even in relative mode - takes
2472
 * the count's place, and the donor supplies the count and ids. */
2473
static bool tns_oson_open(tns_oson_t *o, uint32_t pos, tns_oson_frame_t *f)
2474
0
{
2475
0
  uint8_t t = (uint8_t)tns_oson_uint(o, pos, 1);
2476
0
  int off_size = (t & 0x20) ? 4 : 2;
2477
0
  uint32_t at = pos + 1;
2478
2479
0
  f->node_type = t;
2480
0
  f->is_object = (t & 0x40) == 0;
2481
0
  f->next = 0;
2482
0
  f->container = pos - o->tree;
2483
0
  switch ( t & 0x18 )
2484
0
  {
2485
0
    case 0x00: f->count = tns_oson_uint(o, at, 1); at += 1; break;
2486
0
    case 0x08: f->count = tns_oson_uint(o, at, 2); at += 2; break;
2487
0
    case 0x10: f->count = tns_oson_uint(o, at, 4); at += 4; break;
2488
0
    default:
2489
0
    {
2490
0
      uint32_t donor = o->tree + tns_oson_uint(o, at, off_size);
2491
0
      uint8_t dt = (uint8_t)tns_oson_uint(o, donor, 1);
2492
0
      at += off_size;
2493
0
      f->offsets_pos = at;
2494
0
      switch ( dt & 0x18 )
2495
0
      {
2496
0
        case 0x00: f->count = tns_oson_uint(o, donor + 1, 1); f->ids_pos = donor + 2; break;
2497
0
        case 0x08: f->count = tns_oson_uint(o, donor + 1, 2); f->ids_pos = donor + 3; break;
2498
0
        case 0x10: f->count = tns_oson_uint(o, donor + 1, 4); f->ids_pos = donor + 5; break;
2499
0
        default: return false;
2500
0
      }
2501
0
      return !o->bad;
2502
0
    }
2503
0
  }
2504
0
  if ( f->is_object )
2505
0
  {
2506
0
    f->ids_pos = at;
2507
0
    f->offsets_pos = at + o->field_id_len * f->count;
2508
0
  }
2509
0
  else
2510
0
    f->offsets_pos = at;
2511
0
  return !o->bad;
2512
0
}
2513
2514
/* Render an OSON image as JSON text, or NULL when it is not one this
2515
 * decoder understands. Containers are walked with an explicit stack, not
2516
 * recursion, and the depth, the nodes visited and the text are bounded:
2517
 * the offsets come off the wire and may point anywhere. */
2518
static const char *tns_format_oson(packet_info *pinfo, const uint8_t *data, int len)
2519
0
{
2520
0
  tns_oson_t o = { data, (uint32_t)len, false, 0, 1, false, 0, NULL, NULL };
2521
0
  tns_oson_frame_t stack[TNS_OSON_MAX_DEPTH];
2522
0
  int depth = 0, nodes = 0;
2523
0
  wmem_strbuf_t *buf;
2524
0
  uint32_t pos, num_short, short_seg, num_long = 0, long_seg = 0;
2525
0
  int short_off = 2, long_off = 4;
2526
0
  uint16_t flags;
2527
0
  uint8_t version;
2528
2529
0
  if ( len < 6 || data[0] != 0xff || data[1] != 0x4a || data[2] != 0x5a )
2530
0
    return NULL;
2531
0
  version = data[3];
2532
0
  if ( version != 1 && version != 3 )
2533
0
    return NULL;
2534
0
  flags = (uint16_t)tns_oson_uint(&o, 4, 2);
2535
0
  o.relative = (flags & 0x01) != 0;
2536
0
  pos = 6;
2537
0
  buf = wmem_strbuf_new(pinfo->pool, "");
2538
2539
0
  if ( flags & 0x10 )
2540
0
  {
2541
    /* a scalar document: the tree segment size, then the value */
2542
0
    pos += (flags & 0x1000) ? 4 : 2;
2543
0
    return tns_oson_scalar(pinfo, &o, pos, buf) ? wmem_strbuf_get_str(buf) : NULL;
2544
0
  }
2545
2546
0
  if ( flags & 0x08 )
2547
0
  {
2548
0
    num_short = tns_oson_uint(&o, pos, 4);
2549
0
    pos += 4;
2550
0
    o.field_id_len = 4;
2551
0
  }
2552
0
  else if ( flags & 0x0400 )
2553
0
  {
2554
0
    num_short = tns_oson_uint(&o, pos, 2);
2555
0
    pos += 2;
2556
0
    o.field_id_len = 2;
2557
0
  }
2558
0
  else
2559
0
  {
2560
0
    num_short = tns_oson_uint(&o, pos, 1);
2561
0
    pos += 1;
2562
0
  }
2563
0
  if ( flags & 0x0800 )
2564
0
  {
2565
0
    short_off = 4;
2566
0
    short_seg = tns_oson_uint(&o, pos, 4);
2567
0
    pos += 4;
2568
0
  }
2569
0
  else
2570
0
  {
2571
0
    short_seg = tns_oson_uint(&o, pos, 2);
2572
0
    pos += 2;
2573
0
  }
2574
  /* version 3 adds a segment of field names over 255 bytes */
2575
0
  if ( version == 3 )
2576
0
  {
2577
0
    if ( tns_oson_uint(&o, pos, 2) & 0x0100 )
2578
0
      long_off = 2;
2579
0
    num_long = tns_oson_uint(&o, pos + 2, 4);
2580
0
    long_seg = tns_oson_uint(&o, pos + 6, 4);
2581
0
    pos += 10;
2582
0
  }
2583
0
  pos += (flags & 0x1000) ? 4 : 2;   /* tree segment size */
2584
0
  pos += 2;                          /* number of tiny nodes */
2585
0
  if ( o.bad || num_short > o.len || num_long > o.len )
2586
0
    return NULL;
2587
2588
0
  o.num_names = num_short + num_long;
2589
0
  o.names = wmem_alloc0_array(pinfo->pool, const uint8_t *, o.num_names + 1);
2590
0
  o.name_lens = wmem_alloc0_array(pinfo->pool, uint32_t, o.num_names + 1);
2591
0
  if ( num_short )
2592
0
    pos = tns_oson_names(&o, pos, 0, num_short, 1, short_off, short_seg, 1);
2593
0
  if ( num_long )
2594
0
    pos = tns_oson_names(&o, pos, num_short, num_long, 2, long_off, long_seg, 2);
2595
0
  if ( o.bad )
2596
0
    return NULL;
2597
0
  o.tree = pos;
2598
2599
  /* the root node */
2600
0
  if ( !(tns_oson_uint(&o, pos, 1) & 0x80) )
2601
0
    return tns_oson_scalar(pinfo, &o, pos, buf) ? wmem_strbuf_get_str(buf) : NULL;
2602
0
  if ( !tns_oson_open(&o, pos, &stack[0]) )
2603
0
    return NULL;
2604
0
  wmem_strbuf_append_c(buf, stack[0].is_object ? '{' : '[');
2605
0
  depth = 1;
2606
2607
0
  while ( depth > 0 )
2608
0
  {
2609
0
    tns_oson_frame_t *f = &stack[depth - 1];
2610
0
    uint32_t child, off;
2611
2612
0
    if ( f->next == f->count )
2613
0
    {
2614
0
      wmem_strbuf_append_c(buf, f->is_object ? '}' : ']');
2615
0
      depth--;
2616
0
      continue;
2617
0
    }
2618
0
    if ( ++nodes > TNS_OSON_MAX_NODES || wmem_strbuf_get_len(buf) > TNS_OSON_MAX_TEXT )
2619
0
    {
2620
0
      wmem_strbuf_append(buf, "...");
2621
0
      return wmem_strbuf_get_str(buf);
2622
0
    }
2623
0
    if ( f->next > 0 )
2624
0
      wmem_strbuf_append(buf, ", ");
2625
0
    if ( f->is_object )
2626
0
    {
2627
0
      uint32_t id = tns_oson_uint(&o, f->ids_pos + f->next * o.field_id_len, o.field_id_len);
2628
0
      if ( o.bad || id == 0 || id > o.num_names )
2629
0
        return NULL;
2630
0
      tns_oson_append_string(buf, o.names[id - 1], o.name_lens[id - 1]);
2631
0
      wmem_strbuf_append(buf, ": ");
2632
0
    }
2633
0
    off = tns_oson_uint(&o, f->offsets_pos + f->next * ((f->node_type & 0x20) ? 4 : 2),
2634
0
      (f->node_type & 0x20) ? 4 : 2);
2635
0
    if ( o.relative )
2636
0
      off += f->container;
2637
0
    child = o.tree + off;
2638
0
    f->next++;
2639
0
    if ( o.bad )
2640
0
      return NULL;
2641
2642
0
    if ( tns_oson_uint(&o, child, 1) & 0x80 )
2643
0
    {
2644
0
      if ( depth == TNS_OSON_MAX_DEPTH || !tns_oson_open(&o, child, &stack[depth]) )
2645
0
        return NULL;
2646
0
      wmem_strbuf_append_c(buf, stack[depth].is_object ? '{' : '[');
2647
0
      depth++;
2648
0
    }
2649
0
    else if ( !tns_oson_scalar(pinfo, &o, child, buf) )
2650
0
      return NULL;
2651
0
  }
2652
0
  return wmem_strbuf_get_str(buf);
2653
0
}
2654
2655
static void vsnum_to_vstext_basecustom(char *result, uint32_t vsnum)
2656
0
{
2657
  /*
2658
   * Translate hex value to human readable version value, described at
2659
   * http://docs.oracle.com/cd/B28359_01/server.111/b28310/dba004.htm
2660
   * From 18c the word holds a release update's fields instead: major,
2661
   * update, revision, increment and extension, as python-oracledb
2662
   * reads them.
2663
   */
2664
0
  if ( (vsnum >> 24) >= 18 )
2665
0
  {
2666
0
    snprintf(result, ITEM_LABEL_LENGTH, "%u.%u.%u.%u.%u",
2667
0
       vsnum >> 24,
2668
0
      (vsnum >> 16) & 0xff,
2669
0
      (vsnum >> 12) & 0xf,
2670
0
      (vsnum >>  4) & 0xff,
2671
0
       vsnum & 0xf);
2672
0
    return;
2673
0
  }
2674
0
  snprintf(result, ITEM_LABEL_LENGTH, "%d.%d.%d.%d.%d",
2675
0
     vsnum >> 24,
2676
0
    (vsnum >> 20) & 0xf,
2677
0
    (vsnum >> 12) & 0xf,
2678
0
    (vsnum >>  8) & 0xf,
2679
0
     vsnum & 0xff);
2680
0
}
2681
2682
/* The warning-flags byte of an error block: a PL/SQL object was created
2683
 * with compilation errors, though the call itself succeeded. */
2684
16
#define TNS_WARN_COMPILATION_ERROR  0x20
2685
2686
/* End-of-call status flags, carried by both TTI_OER and TTI_STA. */
2687
16
#define TNS_CALL_STATUS_TXN_IN_PROGRESS  0x00000002
2688
16
#define TNS_CALL_STATUS_SESS_RELEASE     0x00008000
2689
2690
/* Show the warning flags of an error block, and say so when the
2691
 * compilation-warning bit is set. */
2692
static void tns_add_warn_flags(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
2693
0
{
2694
0
  proto_item *ti = proto_tree_add_item(tree, hf_tns_data_oer_warn_flags, tvb, offset, 1, ENC_NA);
2695
0
  proto_tree *wt = proto_item_add_subtree(ti, ett_tns_warn_flags);
2696
2697
0
  proto_tree_add_item(wt, hf_tns_data_oer_warn_compile, tvb, offset, 1, ENC_NA);
2698
0
  if ( tvb_get_uint8(tvb, offset) & TNS_WARN_COMPILATION_ERROR )
2699
0
  {
2700
0
    expert_add_info(pinfo, ti, &ei_tns_data_compilation_error);
2701
0
    col_append_str(pinfo->cinfo, COL_INFO, " [created with compilation errors]");
2702
0
  }
2703
0
}
2704
2705
/* Break out the flag bits of a call status item. A client reads the
2706
 * transaction bit to decide whether closing or releasing the connection
2707
 * owes a rollback. */
2708
static void tns_add_call_status_flags(proto_item *ti, tvbuff_t *tvb, int start, int len, uint32_t status)
2709
0
{
2710
0
  proto_tree *st = proto_item_add_subtree(ti, ett_tns_call_status);
2711
0
  proto_tree_add_boolean(st, hf_tns_data_call_status_txn, tvb, start, len, status);
2712
0
  proto_tree_add_boolean(st, hf_tns_data_call_status_sess_release, tvb, start, len, status);
2713
0
}
2714
2715
/* Decode an OAC (Oracle Access Column) descriptor — the type/format core
2716
 * shared by describe columns and bind descriptors. Fields
2717
 * use the Oracle variable-length form (get_sb4_custom). From field version
2718
 * 12.1 the scale is a single signed byte, where 11g sends a variable-length
2719
 * sb4 (NUMBER's default -127 as 0x81 0x7f), and the flag byte marks an
2720
 * array bind; from 12.2 a ub4 oaccolid also follows the max size.
2721
 * When col is not NULL it receives the type and data length.
2722
 * Returns the new offset. */
2723
static int dissect_tns_oac(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, tns_column_t *col)
2724
0
{
2725
0
  int v = 0, start;
2726
0
  uint64_t u = 0;
2727
0
  unsigned fv = tns_field_version(pinfo);
2728
0
  bool fv_12_1 = fv >= TNS_FV_12_1, fv_12_2 = fv >= TNS_FV_12_2;
2729
2730
0
  if ( col )
2731
0
    col->type = tvb_get_uint8(tvb, offset);
2732
  /* type (ub1) */
2733
0
  proto_tree_add_item(tree, hf_tns_data_col_type, tvb, offset, 1, ENC_BIG_ENDIAN);
2734
0
  offset += 1;
2735
  /* flag (ub1); from 12.1 it marks an array bind */
2736
0
  if ( col && fv_12_1 )
2737
0
    col->is_array = (tvb_get_uint8(tvb, offset) & TNS_BIND_ARRAY) != 0;
2738
0
  offset += 1;
2739
  /* precision (sb1) */
2740
0
  proto_tree_add_item(tree, hf_tns_data_col_precision, tvb, offset, 1, ENC_BIG_ENDIAN);
2741
0
  offset += 1;
2742
  /* scale (may be negative — NUMBER default is -127) */
2743
0
  start = offset;
2744
0
  if ( fv_12_1 )
2745
0
  {
2746
0
    v = (int8_t)tvb_get_uint8(tvb, offset);
2747
0
    offset += 1;
2748
0
  }
2749
0
  else
2750
0
    offset += get_sb4_custom(tvb, offset, &v);
2751
0
  proto_tree_add_int(tree, hf_tns_data_col_scale, tvb, start, offset - start, v);
2752
  /* max data length / buffer size (ub4) */
2753
0
  start = offset;
2754
0
  offset += get_sb4_custom(tvb, offset, &v);
2755
0
  proto_tree_add_uint(tree, hf_tns_data_col_max_length, tvb, start, offset - start, v);
2756
0
  if ( col )
2757
0
    col->data_len = (uint32_t)v;
2758
  /* max array elements (ub4) */
2759
0
  start = offset;
2760
0
  offset += get_sb4_custom(tvb, offset, &v);
2761
0
  if ( v > 0 )
2762
0
    proto_tree_add_uint(tree, hf_tns_data_col_max_elements, tvb, start, offset - start, v);
2763
  /* cont flags (ub8); below 12.1 they mark an array bind */
2764
0
  offset += get_ub8_custom(tvb, offset, &u);
2765
0
  if ( col && !fv_12_1 )
2766
0
    col->is_array = (u & TNS_BIND_ARRAY) != 0;
2767
  /* type OID (bytes_with_length, skip) */
2768
0
  offset += get_field_with_length(tvb, pinfo, offset, NULL);
2769
  /* version (ub4, skip) */
2770
0
  offset += get_sb4_custom(tvb, offset, &v);
2771
  /* charset id (ub4) */
2772
0
  start = offset;
2773
0
  offset += get_sb4_custom(tvb, offset, &v);
2774
0
  proto_tree_add_uint(tree, hf_tns_data_col_charset, tvb, start, offset - start, v);
2775
  /* charset form (ub1) */
2776
0
  proto_tree_add_item(tree, hf_tns_data_col_csform, tvb, offset, 1, ENC_BIG_ENDIAN);
2777
0
  if ( col )
2778
0
    col->csform = tvb_get_uint8(tvb, offset);
2779
0
  offset += 1;
2780
  /* max size (ub4) */
2781
0
  start = offset;
2782
0
  offset += get_sb4_custom(tvb, offset, &v);
2783
0
  proto_tree_add_uint(tree, hf_tns_data_col_max_size, tvb, start, offset - start, v);
2784
  /* oaccolid (ub4, skip) */
2785
0
  if ( fv_12_2 )
2786
0
    offset += get_sb4_custom(tvb, offset, &v);
2787
2788
0
  return offset;
2789
0
}
2790
2791
/* Decode one per-column metadata block of a TTI_DCB describe (11g
2792
 * shape): an OAC descriptor plus the nullability and naming fields.
2793
 * When col is not NULL it receives what a row decoder needs.
2794
 * Returns the new offset. */
2795
static int dissect_tns_dcb_column(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int idx, tns_column_t *col)
2796
0
{
2797
0
  unsigned fv = tns_field_version(pinfo);
2798
0
  int start;
2799
0
  proto_tree *col_tree;
2800
0
  proto_item *col_item;
2801
0
  int col_start = offset, v = 0;
2802
0
  uint8_t col_type = tvb_get_uint8(tvb, offset);
2803
0
  const char *name = NULL;
2804
2805
0
  col_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
2806
0
    ett_tns_dcb_col, &col_item, "Column %d", idx);
2807
2808
0
  offset = dissect_tns_oac(tvb, pinfo, col_tree, offset, col);
2809
2810
  /* nulls allowed (ub1) */
2811
0
  proto_tree_add_item(col_tree, hf_tns_data_col_nulls_ok, tvb, offset, 1, ENC_BIG_ENDIAN);
2812
0
  offset += 1;
2813
  /* v7 name length (ub1, skip) */
2814
0
  offset += 1;
2815
  /* column name (str_with_length) */
2816
0
  int name_start = offset;
2817
0
  offset += get_field_with_length(tvb, pinfo, offset, &name);
2818
0
  if ( name )
2819
0
    proto_tree_add_string(col_tree, hf_tns_data_col_name, tvb, name_start, offset - name_start, name);
2820
  /* schema name, type name (str_with_length, skip) */
2821
0
  offset += get_field_with_length(tvb, pinfo, offset, NULL);
2822
0
  offset += get_field_with_length(tvb, pinfo, offset, NULL);
2823
  /* column position (ub4, skip) */
2824
0
  offset += get_sb4_custom(tvb, offset, &v);
2825
  /* uds flags (ub4) — an 11g addition; it marks a JSON column */
2826
0
  if ( !tns_before_11g(pinfo) )
2827
0
  {
2828
0
    start = offset;
2829
0
    offset += get_sb4_custom(tvb, offset, &v);
2830
0
    proto_tree_add_uint(col_tree, hf_tns_data_col_uds_flags, tvb, start, offset - start, v);
2831
0
  }
2832
  /* 23ai: the column's SQL domain, its annotations, and a vector
2833
   * column's dimensions and format */
2834
0
  if ( fv >= TNS_FV_23_1 )
2835
0
  {
2836
0
    const char *str = NULL;
2837
0
    start = offset;
2838
0
    offset += get_field_with_length(tvb, pinfo, offset, &str);
2839
0
    if ( str )
2840
0
      proto_tree_add_string(col_tree, hf_tns_data_col_domain_schema, tvb, start, offset - start, str);
2841
0
    start = offset;
2842
0
    offset += get_field_with_length(tvb, pinfo, offset, &str);
2843
0
    if ( str )
2844
0
      proto_tree_add_string(col_tree, hf_tns_data_col_domain_name, tvb, start, offset - start, str);
2845
0
  }
2846
0
  if ( fv >= TNS_FV_23_1_EXT_3 )
2847
0
  {
2848
0
    int num = 0;
2849
0
    offset += get_sb4_custom(tvb, offset, &num);
2850
0
    if ( num > 0 )
2851
0
    {
2852
0
      offset += 1;
2853
0
      offset += get_sb4_custom(tvb, offset, &num);
2854
0
      offset += 1;
2855
0
      for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
2856
0
      {
2857
0
        const char *key = NULL, *value = NULL;
2858
0
        start = offset;
2859
0
        offset += get_field_with_length(tvb, pinfo, offset, &key);
2860
0
        offset += get_field_with_length(tvb, pinfo, offset, &value);
2861
0
        proto_tree_add_string_format_value(col_tree, hf_tns_data_col_annotation, tvb,
2862
0
          start, offset - start, key ? key : "", "%s = %s",
2863
0
          key ? key : "", value ? value : "");
2864
0
        offset += get_sb4_custom(tvb, offset, &v); /* flags */
2865
0
      }
2866
0
      offset += get_sb4_custom(tvb, offset, &v);     /* flags */
2867
0
    }
2868
0
  }
2869
0
  if ( fv >= TNS_FV_23_4 )
2870
0
  {
2871
0
    start = offset;
2872
0
    offset += get_sb4_custom(tvb, offset, &v);
2873
0
    proto_tree_add_uint(col_tree, hf_tns_data_col_vector_dims, tvb, start, offset - start, v);
2874
0
    proto_tree_add_item(col_tree, hf_tns_data_col_vector_format, tvb, offset, 1, ENC_NA);
2875
0
    offset += 1;
2876
0
    offset += 1;                                         /* vector flags */
2877
0
  }
2878
2879
0
  if ( name )
2880
0
    proto_item_append_text(col_item, ": %s (%s)", name,
2881
0
      val_to_str_const(col_type, tns_data_types, "unknown"));
2882
0
  proto_item_set_len(col_item, offset - col_start);
2883
0
  return offset;
2884
0
}
2885
2886
/* Decode a describe body - the column metadata of a result set - as a
2887
 * TTI_DCB carries it after its preamble: a ub4 max row size, a ub4 column
2888
 * count, a reserved byte when there are columns, the columns, and a
2889
 * trailer. When out is not NULL it receives the columns, allocated in
2890
 * file scope. Returns the new offset. */
2891
static int dissect_tns_describe_body(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, tns_describe_t **out)
2892
0
{
2893
0
  int v = 0, num_cols = 0, nc_start;
2894
0
  tns_column_t *cols = NULL;
2895
2896
  /* max row size (ub4, skip) */
2897
0
  offset += get_sb4_custom(tvb, offset, &v);
2898
  /* number of columns */
2899
0
  nc_start = offset;
2900
0
  offset += get_sb4_custom(tvb, offset, &num_cols);
2901
0
  proto_tree_add_uint(tree, hf_tns_data_dcb_num_columns, tvb, nc_start, offset - nc_start, num_cols);
2902
  /* The count comes off the wire and sizes the allocation below, so a
2903
   * count larger than the data left cannot be real - report it and
2904
   * decode no columns. */
2905
0
  if ( num_cols < 0 ||
2906
0
       (unsigned)num_cols > tvb_reported_length_remaining(tvb, offset) )
2907
0
  {
2908
0
    proto_tree_add_expert(tree, pinfo, &ei_tns_data_count_too_large,
2909
0
      tvb, nc_start, offset - nc_start);
2910
0
    num_cols = 0;
2911
0
  }
2912
0
  if ( num_cols > 0 )
2913
0
    offset += 1; /* reserved byte */
2914
2915
0
  if ( out && num_cols > 0 )
2916
0
    cols = wmem_alloc0_array(wmem_file_scope(), tns_column_t, num_cols);
2917
0
  for ( int i = 0; i < num_cols && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
2918
0
    offset = dissect_tns_dcb_column(tvb, pinfo, tree, offset, i + 1,
2919
0
      cols ? &cols[i] : NULL);
2920
0
  if ( cols )
2921
0
  {
2922
0
    tns_describe_t *desc = wmem_new0(wmem_file_scope(), tns_describe_t);
2923
0
    desc->num_cols = num_cols;
2924
0
    desc->cols = cols;
2925
0
    *out = desc;
2926
0
  }
2927
2928
  /* Trailer: current date (bytes_with_length), four ub4 flags,
2929
   * and the query-cache key (bytes_with_length) — all skipped. The key
2930
   * came with the 11g result cache: a 10g describe ends after the
2931
   * flags. */
2932
0
  offset += get_field_with_length(tvb, pinfo, offset, NULL);
2933
0
  for ( int i = 0; i < 4; i++ )
2934
0
    offset += get_sb4_custom(tvb, offset, &v);
2935
0
  if ( !tns_before_11g(pinfo) )
2936
0
    offset += get_field_with_length(tvb, pinfo, offset, NULL);
2937
0
  return offset;
2938
0
}
2939
2940
static tns_call_t *tns_answered_call(packet_info *pinfo);
2941
2942
/* A BFILE's locator names its file: a big-endian ub2 length and the
2943
 * directory object's name, then a ub2 length and the file name, which end
2944
 * the locator. They start 16 bytes into the locator as a value carries it,
2945
 * behind its own ub2 length, and 14 bytes in in a LOB operation, which
2946
 * sends it without that length. Finds the names in the len bytes at
2947
 * offset, or returns false. */
2948
static bool tns_bfile_names(tvbuff_t *tvb, int offset, int len,
2949
    int *dir_off, int *dir_len, int *file_off, int *file_len)
2950
0
{
2951
0
  static const int bases[] = { 16, 14 };
2952
2953
0
  for ( unsigned i = 0; i < array_length(bases); i++ )
2954
0
  {
2955
0
    int b = bases[i], dl, fl;
2956
2957
0
    if ( len < b + 4 )
2958
0
      continue;
2959
0
    dl = tvb_get_ntohs(tvb, offset + b);
2960
0
    if ( dl == 0 || b + 2 + dl + 2 > len )
2961
0
      continue;
2962
0
    fl = tvb_get_ntohs(tvb, offset + b + 2 + dl);
2963
0
    if ( fl == 0 || b + 2 + dl + 2 + fl != len )
2964
0
      continue;
2965
0
    if ( !tvb_utf_8_isprint(tvb, offset + b + 2, dl)
2966
0
      || !tvb_utf_8_isprint(tvb, offset + b + 2 + dl + 2, fl) )
2967
0
      continue;
2968
0
    *dir_off = offset + b + 2;
2969
0
    *dir_len = dl;
2970
0
    *file_off = offset + b + 2 + dl + 2;
2971
0
    *file_len = fl;
2972
0
    return true;
2973
0
  }
2974
0
  return false;
2975
0
}
2976
2977
/* Where a value is being carried, which decides the framing some types
2978
 * use: a fetched row column, a value a client binds, or a value a server
2979
 * returns for a bind - an OUT or IN OUT bind, or a RETURNING one. */
2980
typedef enum {
2981
  TNS_VALUE_FETCH,
2982
  TNS_VALUE_BIND,
2983
  TNS_VALUE_OUT
2984
} tns_value_kind_t;
2985
2986
/* Decode one row/bind value by its data type, and add it as a
2987
 * "<prefix> N (TYPE)" item under `hf`. Ordinary values are a
2988
 * DALC blob; ROWID / UROWID / LONG / LOB / JSON / VECTOR / object carry
2989
 * their own framings - though out of a fetch (fetch false: a bind or OUT
2990
 * value) a ROWID or UROWID is its string and a LONG has no trailing
2991
 * indicators. Returns the new offset. */
2992
static int dissect_tns_value(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint8_t dtype, uint8_t csform, tns_value_kind_t kind, int idx, int hf, const char *prefix)
2993
0
{
2994
0
  int v_start = offset, disp_start = offset, v = 0;
2995
0
  int is_null = 0, is_absent = 0;
2996
0
  uint8_t first;
2997
0
  const char *rendered = NULL;
2998
  /* LOB metadata: size and chunk size, with where they sit */
2999
0
  bool lob_meta = false;
3000
0
  uint64_t lob_size = 0;
3001
0
  int lob_chunk = 0, size_start = 0, size_len = 0, lchunk_start = 0, lchunk_len = 0;
3002
0
  int image_start = 0, image_len = 0, obj_toid_start = 0, obj_toid_len = 0;
3003
0
  proto_item *ti;
3004
0
  uint8_t frame = dtype;
3005
3006
0
  if ( kind != TNS_VALUE_FETCH && (dtype == TNS_DATATYPE_ROWID || dtype == TNS_DATATYPE_UROWID
3007
0
    || dtype == TNS_DATATYPE_LONG) )
3008
0
    frame = TNS_DATATYPE_VARCHAR;
3009
0
  else if ( kind != TNS_VALUE_FETCH && dtype == TNS_DATATYPE_LONG_RAW )
3010
0
    frame = TNS_DATATYPE_RAW;
3011
3012
0
  switch ( frame )
3013
0
  {
3014
0
    case TNS_DATATYPE_REFCURSOR:
3015
0
    {
3016
      /* A cursor - a CURSOR(...) column, or a REF CURSOR OUT
3017
       * bind: a ub1 length (a fixed value, ignored), the describe
3018
       * of the cursor's result set inline, and the ub2 id the
3019
       * client drains it with. The value's length is known only
3020
       * once the describe is read, so read it once to size the
3021
       * item and again to show it. */
3022
0
      proto_item *ci;
3023
0
      proto_tree *ct;
3024
0
      int end, cursor = 0, start;
3025
0
      const tns_call_t *call = tns_answered_call(pinfo);
3026
3027
0
      if ( kind == TNS_VALUE_BIND )
3028
0
      {
3029
        /* A client's REF CURSOR bind carries no DALC but a ub4
3030
         * count, then that many ub4 cursor ids: none for an
3031
         * OUT bind, which asks the server to open one, and the
3032
         * id of the cursor an IN bind passes. */
3033
0
        wmem_strbuf_t *ids = wmem_strbuf_new(pinfo->pool, "");
3034
0
        int count = 0;
3035
3036
0
        end = offset + get_sb4_custom(tvb, offset, &count);
3037
0
        for ( int i = 0; i < count; i++ )
3038
0
        {
3039
0
          end += get_sb4_custom(tvb, end, &cursor);
3040
0
          wmem_strbuf_append_printf(ids, "%s%d", i ? ", " : "", cursor);
3041
0
        }
3042
0
        ci = proto_tree_add_bytes_format(tree, hf, tvb, offset, end - offset, NULL,
3043
0
          "%s %d (%s): %s%s", prefix, idx,
3044
0
          val_to_str_const(dtype, tns_data_types, "unknown"),
3045
0
          count == 0 ? "a new cursor" : count == 1 ? "cursor " : "cursors ",
3046
0
          wmem_strbuf_get_str(ids));
3047
0
        ct = proto_item_add_subtree(ci, ett_tns_value);
3048
0
        start = offset;
3049
0
        offset += get_sb4_custom(tvb, offset, &count);
3050
0
        proto_tree_add_uint(ct, hf_tns_data_bind_cursor_count, tvb, start, offset - start, count);
3051
0
        for ( int i = 0; i < count; i++ )
3052
0
        {
3053
0
          start = offset;
3054
0
          offset += get_sb4_custom(tvb, offset, &cursor);
3055
0
          proto_tree_add_uint(ct, hf_tns_cursor, tvb, start, offset - start, cursor);
3056
0
        }
3057
0
        return offset;
3058
0
      }
3059
3060
      /* Rows a TTI_FETCH returns carry a cursor cut short before
3061
       * 23ai: the length byte and the id, with no describe. An
3062
       * execute's reply, and a fetch-only execute's, carry it
3063
       * whole. */
3064
0
      if ( call && call->func == TTI_FETCH && tns_field_version(pinfo) < TNS_FV_23_1 )
3065
0
      {
3066
0
        start = offset;
3067
0
        end = offset + 1;
3068
0
        end += get_sb4_custom(tvb, end, &cursor);
3069
0
        ci = proto_tree_add_bytes_format(tree, hf, tvb, start, end - start, NULL,
3070
0
          "%s %d (%s): cursor %d", prefix, idx,
3071
0
          val_to_str_const(dtype, tns_data_types, "unknown"), cursor);
3072
0
        ct = proto_item_add_subtree(ci, ett_tns_value);
3073
0
        proto_tree_add_uint(ct, hf_tns_cursor, tvb, offset + 1, end - offset - 1, cursor);
3074
0
        return end;
3075
0
      }
3076
3077
0
      end = dissect_tns_describe_body(tvb, pinfo, NULL, offset + 1, NULL);
3078
0
      end += get_sb4_custom(tvb, end, &cursor);
3079
0
      ci = proto_tree_add_bytes_format(tree, hf, tvb, offset, end - offset, NULL,
3080
0
        "%s %d (%s): cursor %d", prefix, idx,
3081
0
        val_to_str_const(dtype, tns_data_types, "unknown"), cursor);
3082
0
      ct = proto_item_add_subtree(ci, ett_tns_value);
3083
0
      offset = dissect_tns_describe_body(tvb, pinfo, ct, offset + 1, NULL);
3084
0
      start = offset;
3085
0
      offset += get_sb4_custom(tvb, offset, &cursor);
3086
0
      proto_tree_add_uint(ct, hf_tns_cursor, tvb, start, offset - start, cursor);
3087
0
      return offset;
3088
0
    }
3089
3090
0
    case TNS_DATATYPE_ADT:
3091
0
    {
3092
      /* An object - or an XMLType, which is an ADT by describe - is
3093
       * framed the same way whether it is NULL or not:
3094
       *   bytes_with_length type OID | bytes_with_length OID |
3095
       *   bytes_with_length snapshot | ub2 version |
3096
       *   ub4 image length | ub2 flags | [DALC image]
3097
       * A NULL object has an image length of 0 and no image. */
3098
0
      int toid_start = offset, img_len = 0;
3099
0
      offset += get_field_with_length(tvb, pinfo, offset, NULL);
3100
0
      obj_toid_start = toid_start;
3101
0
      obj_toid_len = offset - toid_start;
3102
0
      offset += get_field_with_length(tvb, pinfo, offset, NULL); /* OID */
3103
0
      offset += get_field_with_length(tvb, pinfo, offset, NULL); /* snapshot */
3104
0
      offset += get_sb4_custom(tvb, offset, &v);                  /* version */
3105
0
      offset += get_sb4_custom(tvb, offset, &img_len);
3106
0
      offset += get_sb4_custom(tvb, offset, &v);                  /* flags */
3107
0
      if ( img_len > 0 )
3108
0
      {
3109
0
        image_start = offset;
3110
0
        offset += get_dalc_custom(tvb, pinfo, offset, NULL);
3111
0
        image_len = offset - image_start;
3112
0
        rendered = wmem_strdup_printf(pinfo->pool, "object, %d-byte image", img_len);
3113
0
      }
3114
0
      else
3115
0
        rendered = "NULL object";
3116
0
      break;
3117
0
    }
3118
3119
0
    case TNS_DATATYPE_JSON:   /* OSON */
3120
0
    case TNS_DATATYPE_VECTOR:
3121
      /* LOB-class, but the value itself rides in the row: the LOB
3122
       * metadata framing with the image spliced in ahead of the
3123
       * locator,
3124
       *   ub4 locator length | ub8 image size | ub4 chunk size |
3125
       *   DALC image | DALC locator
3126
       * The locator is a placeholder. A 0x00 is NULL. A server may
3127
       * instead send a bare locator, as for a CLOB, and leave the
3128
       * image to a LOB read; that is told apart as for a CLOB.
3129
       *
3130
       * A bind sends the locator and the image behind it, and a
3131
       * value a server returns for a bind is the LOB block alone,
3132
       * as for a CLOB. */
3133
0
      first = tvb_get_uint8(tvb, offset);
3134
0
      if ( first == 0 )
3135
0
      {
3136
0
        offset += 1;
3137
0
        is_null = 1;
3138
0
        break;
3139
0
      }
3140
0
      offset += get_sb4_custom(tvb, offset, &v);
3141
0
      if ( kind == TNS_VALUE_OUT )
3142
0
      {
3143
0
        lob_meta = true;
3144
0
        size_start = offset;
3145
0
        offset += get_ub8_custom(tvb, offset, &lob_size);
3146
0
        size_len = offset - size_start;
3147
0
        lchunk_start = offset;
3148
0
        offset += get_sb4_custom(tvb, offset, &lob_chunk);
3149
0
        lchunk_len = offset - lchunk_start;
3150
0
        offset += get_dalc_custom(tvb, pinfo, offset, NULL);
3151
0
        rendered = wmem_strdup_printf(pinfo->pool, "locator, size %" PRIu64, lob_size);
3152
0
        break;
3153
0
      }
3154
0
      if ( kind == TNS_VALUE_BIND )
3155
0
      {
3156
        /* the locator the value rides under, then the image */
3157
0
        offset += get_dalc_custom(tvb, pinfo, offset, NULL);
3158
0
        image_start = offset;
3159
0
        offset += get_dalc_custom(tvb, pinfo, offset, NULL);
3160
0
        image_len = offset - image_start;
3161
0
      }
3162
0
      else if ( v > 8 && tvb_get_uint8(tvb, offset) == v )
3163
0
      {
3164
        /* bare locator */
3165
0
        offset += get_dalc_custom(tvb, pinfo, offset, NULL);
3166
0
        rendered = "locator only";
3167
0
        break;
3168
0
      }
3169
0
      else
3170
0
      {
3171
0
        lob_meta = true;
3172
0
        size_start = offset;
3173
0
        offset += get_ub8_custom(tvb, offset, &lob_size);
3174
0
        size_len = offset - size_start;
3175
0
        lchunk_start = offset;
3176
0
        offset += get_sb4_custom(tvb, offset, &lob_chunk);
3177
0
        lchunk_len = offset - lchunk_start;
3178
0
        image_start = offset;
3179
0
        offset += get_dalc_custom(tvb, pinfo, offset, NULL);
3180
0
        image_len = offset - image_start;
3181
0
        offset += get_dalc_custom(tvb, pinfo, offset, NULL);
3182
0
      }
3183
0
      if ( image_len > 1 )
3184
0
      {
3185
0
        int img_len = 0;
3186
0
        const uint8_t *img = tns_dalc_bytes(tvb, pinfo, image_start, &img_len);
3187
0
        if ( img )
3188
0
          rendered = dtype == TNS_DATATYPE_VECTOR ? tns_format_vector(pinfo, img, img_len)
3189
0
            : tns_format_oson(pinfo, img, img_len);
3190
0
      }
3191
0
      if ( !rendered )
3192
0
        rendered = wmem_strdup_printf(pinfo->pool, "%s image, %d bytes",
3193
0
          dtype == TNS_DATATYPE_JSON ? "OSON" : "vector",
3194
0
          lob_meta ? (int)lob_size : image_len - 1);
3195
0
      break;
3196
3197
0
    case TNS_DATATYPE_ROWID:
3198
0
    {
3199
      /* a present indicator (0 / 0xff = NULL), then the object id
3200
       * (ub4), file number (ub2), an unused byte, block number
3201
       * (ub4) and slot number (ub2) */
3202
0
      int rba = 0, part = 0, block = 0, slot = 0;
3203
0
      first = tvb_get_uint8(tvb, offset);
3204
0
      offset += 1;
3205
0
      if ( first == 0 || first == 0xff )
3206
0
      {
3207
0
        is_null = 1;
3208
0
        break;
3209
0
      }
3210
0
      offset += get_sb4_custom(tvb, offset, &rba);
3211
0
      offset += get_sb4_custom(tvb, offset, &part);
3212
0
      offset += 1;
3213
0
      offset += get_sb4_custom(tvb, offset, &block);
3214
0
      offset += get_sb4_custom(tvb, offset, &slot);
3215
0
      rendered = tns_format_rowid(pinfo, (uint32_t)rba, (uint32_t)part, (uint32_t)block, (uint32_t)slot);
3216
0
      break;
3217
0
    }
3218
3219
0
    case TNS_DATATYPE_UROWID: /* ub4 num_bytes, a length echo byte, then the bytes */
3220
0
      offset += get_sb4_custom(tvb, offset, &v);
3221
0
      if ( v > 0 )
3222
0
      {
3223
0
        offset += 1;
3224
0
        rendered = tns_format_urowid(pinfo, tvb_get_ptr(tvb, offset, v), v);
3225
0
        offset += v;
3226
0
      }
3227
0
      else
3228
0
        is_null = 1;
3229
0
      break;
3230
3231
0
    case TNS_DATATYPE_LONG:
3232
0
    case TNS_DATATYPE_LONG_RAW: /* value then two trailing ub4 length indicators */
3233
0
      first = tvb_get_uint8(tvb, offset);
3234
0
      if ( first == 0 )
3235
0
      {
3236
0
        offset += 1;
3237
0
        is_null = 1;
3238
0
      }
3239
0
      else if ( first == 0xfe ) /* chunked */
3240
0
        offset += 1 + tns_chunks_len(tvb, pinfo, offset + 1, NULL);
3241
0
      else
3242
0
        offset += 1 + first;
3243
0
      offset += get_sb4_custom(tvb, offset, &v);
3244
0
      offset += get_sb4_custom(tvb, offset, &v);
3245
0
      break;
3246
3247
0
    case TNS_DATATYPE_CLOB:
3248
0
    case TNS_DATATYPE_BLOB:
3249
0
    case TNS_DATATYPE_BFILE:
3250
      /* 0x00 NULL, else a ub4 locator length and the locator. A
3251
       * server sends CLOB / BLOB in one of two forms: with the LOB's
3252
       * size (ub8) and chunk size (ub4) between the two, or bare -
3253
       * and which one it picks for a client is not known. They are
3254
       * told apart by the byte after the length: the bare form's is
3255
       * the locator's own length prefix (or 0xFE when chunked), the
3256
       * metadata form's is the size's width, at most 8. A real
3257
       * locator is far longer than 8 bytes, so the two cannot meet.
3258
       * A BFILE is always bare, as is the locator a client binds;
3259
       * a value a server returns for a bind always carries the
3260
       * size and chunk size. */
3261
0
      first = tvb_get_uint8(tvb, offset);
3262
0
      if ( first == 0 )
3263
0
      {
3264
0
        offset += 1;
3265
0
        is_null = 1;
3266
0
      }
3267
0
      else
3268
0
      {
3269
0
        offset += get_sb4_custom(tvb, offset, &v);
3270
0
        if ( dtype != TNS_DATATYPE_BFILE && v > 8 && kind != TNS_VALUE_BIND )
3271
0
        {
3272
0
          uint8_t next = tvb_get_uint8(tvb, offset);
3273
0
          if ( kind == TNS_VALUE_OUT || (next <= 8 && next != v) )
3274
0
          {
3275
0
            lob_meta = true;
3276
0
            size_start = offset;
3277
0
            offset += get_ub8_custom(tvb, offset, &lob_size);
3278
0
            size_len = offset - size_start;
3279
0
            lchunk_start = offset;
3280
0
            offset += get_sb4_custom(tvb, offset, &lob_chunk);
3281
0
            lchunk_len = offset - lchunk_start;
3282
0
            rendered = wmem_strdup_printf(pinfo->pool, "locator, size %" PRIu64, lob_size);
3283
0
          }
3284
0
        }
3285
0
        int loc_start = offset, dir_off, dir_len, file_off, file_len;
3286
0
        uint8_t loc_len = tvb_get_uint8(tvb, offset);
3287
0
        offset += get_dalc_custom(tvb, pinfo, offset, NULL);
3288
0
        if ( dtype == TNS_DATATYPE_BFILE && loc_len <= 0xfc
3289
0
          && tns_bfile_names(tvb, loc_start + 1, loc_len, &dir_off, &dir_len, &file_off, &file_len) )
3290
0
          rendered = wmem_strdup_printf(pinfo->pool, "BFILENAME('%s', '%s')",
3291
0
            tvb_get_string_enc(pinfo->pool, tvb, dir_off, dir_len, ENC_UTF_8),
3292
0
            tvb_get_string_enc(pinfo->pool, tvb, file_off, file_len, ENC_UTF_8));
3293
0
        if ( !rendered )
3294
0
          rendered = "locator";
3295
0
      }
3296
0
      break;
3297
3298
0
    default: /* ordinary: a single DALC value */
3299
0
      first = tvb_get_uint8(tvb, offset);
3300
0
      offset += get_dalc_custom(tvb, pinfo, offset, NULL);
3301
0
      if ( first == 0 )
3302
0
        is_null = 1;
3303
0
      else if ( first == TNS_DALC_ABSENT )
3304
0
        is_absent = 1;
3305
0
      else
3306
0
      {
3307
0
        disp_start = v_start + 1; /* show the value bytes, not the length */
3308
        /* Render common scalar types (never chunked): NUMBER as
3309
         * decimal, DATE / TIMESTAMP / TIMESTAMP LTZ as a datetime. */
3310
0
        if ( first != 254 && offset > disp_start )
3311
0
        {
3312
0
          const uint8_t *vb = tvb_get_ptr(tvb, disp_start, offset - disp_start);
3313
0
          int vlen = offset - disp_start;
3314
          /* A BINARY_INTEGER carries NUMBER bytes, not a native
3315
           * integer. */
3316
0
          if ( dtype == TNS_DATATYPE_NUMBER || dtype == TNS_DATATYPE_INTEGER )
3317
0
            rendered = tns_format_number(pinfo, vb, vlen);
3318
0
          else if ( dtype == TNS_DATATYPE_DATE || dtype == TNS_DATATYPE_TIMESTAMP || dtype == TNS_DATATYPE_TIMESTAMP_LTZ )
3319
0
            rendered = tns_format_date(pinfo, vb, vlen);
3320
0
          else if ( dtype == TNS_DATATYPE_TIMESTAMP_TZ )
3321
0
            rendered = tns_format_timestamp_tz(pinfo, vb, vlen);
3322
0
          else if ( (dtype == TNS_DATATYPE_INTERVAL_YM || dtype == TNS_DATATYPE_INTERVAL_DS) && vlen >= 5 )
3323
0
            rendered = tns_format_interval(pinfo, dtype, vb, vlen);
3324
0
          else if ( dtype == TNS_DATATYPE_BOOLEAN )
3325
            /* an encoded integer: 00 false, 01 01 true */
3326
0
            rendered = vb[0] == 1 ? "TRUE" : "FALSE";
3327
0
          else if ( dtype == TNS_DATATYPE_BINARY_FLOAT || dtype == TNS_DATATYPE_BINARY_DOUBLE )
3328
0
            rendered = tns_format_binary_float(pinfo, vb, vlen);
3329
0
          else if ( frame == TNS_DATATYPE_VARCHAR || dtype == TNS_DATATYPE_STRING || dtype == TNS_DATATYPE_CHAR )
3330
            /* VARCHAR / STRING / CHAR: character data, in the
3331
             * session charset (ordinarily UTF-8), or UTF-16BE
3332
             * for the national charset form (NCHAR,
3333
             * NVARCHAR2) - in a column and an OUT bind alike. */
3334
0
            rendered = (const char *)tvb_get_string_enc(pinfo->pool,
3335
0
              tvb, disp_start, vlen,
3336
0
              csform == TNS_CSFORM_NCHAR ? ENC_UTF_16|ENC_BIG_ENDIAN : ENC_UTF_8|ENC_NA);
3337
0
        }
3338
0
        else if ( first == 254 && (frame == TNS_DATATYPE_VARCHAR || dtype == TNS_DATATYPE_STRING
3339
0
          || dtype == TNS_DATATYPE_CHAR) )
3340
0
        {
3341
          /* Chunked character data: the chunks joined. A chunk
3342
           * can end inside a UTF-16 character. */
3343
0
          int clen;
3344
0
          const uint8_t *cb = tns_dalc_bytes(tvb, pinfo, v_start, &clen);
3345
0
          if ( cb && clen > 0 )
3346
0
          {
3347
0
            tvbuff_t *ctvb = tvb_new_real_data(cb, clen, clen);
3348
0
            rendered = (const char *)tvb_get_string_enc(pinfo->pool, ctvb, 0, clen,
3349
0
              csform == TNS_CSFORM_NCHAR ? ENC_UTF_16|ENC_BIG_ENDIAN : ENC_UTF_8|ENC_NA);
3350
0
            tvb_free(ctvb);
3351
0
          }
3352
0
        }
3353
0
      }
3354
0
      break;
3355
0
  }
3356
3357
0
  if ( is_null )
3358
0
    proto_tree_add_bytes_format(tree, hf, tvb,
3359
0
      v_start, offset - v_start, NULL, "%s %d (%s): NULL", prefix, idx,
3360
0
      val_to_str_const(dtype, tns_data_types, "unknown"));
3361
0
  else if ( is_absent )
3362
0
    proto_tree_add_bytes_format(tree, hf, tvb,
3363
0
      v_start, offset - v_start, NULL, "%s %d (%s): no value", prefix, idx,
3364
0
      val_to_str_const(dtype, tns_data_types, "unknown"));
3365
0
  else if ( rendered )
3366
0
  {
3367
0
    ti = proto_tree_add_bytes_format(tree, hf, tvb,
3368
0
      disp_start, offset - disp_start, NULL, "%s %d (%s): %s", prefix, idx,
3369
0
      val_to_str_const(dtype, tns_data_types, "unknown"), rendered);
3370
0
    if ( dtype == TNS_DATATYPE_ADT )
3371
0
    {
3372
0
      proto_tree *vt = proto_item_add_subtree(ti, ett_tns_value);
3373
      /* the type OID, without its ub4 count and DALC length */
3374
0
      if ( obj_toid_len > 2 )
3375
0
      {
3376
0
        int w = 1 + (tvb_get_uint8(tvb, obj_toid_start) & 0x7f);
3377
0
        proto_tree_add_item(vt, hf_tns_data_obj_toid, tvb,
3378
0
          obj_toid_start + w + 1, obj_toid_len - w - 1, ENC_NA);
3379
0
      }
3380
0
      if ( image_len > 1 )
3381
0
      {
3382
0
        bool chunked = tvb_get_uint8(tvb, image_start) == 0xfe;
3383
0
        proto_tree_add_item(vt, hf_tns_data_obj_image, tvb,
3384
0
          chunked ? image_start : image_start + 1, chunked ? image_len : image_len - 1, ENC_NA);
3385
0
      }
3386
0
    }
3387
0
    if ( lob_meta )
3388
0
    {
3389
0
      proto_tree *vt = proto_item_add_subtree(ti, ett_tns_value);
3390
0
      proto_tree_add_uint64(vt, hf_tns_data_lob_size, tvb, size_start, size_len, lob_size);
3391
0
      proto_tree_add_uint(vt, hf_tns_data_lob_chunk_size, tvb, lchunk_start, lchunk_len, lob_chunk);
3392
      /* the image of a prefetched JSON / VECTOR value, without its
3393
       * DALC length byte (chunked images are shown whole) */
3394
0
      if ( image_len > 1 )
3395
0
      {
3396
0
        bool chunked = tvb_get_uint8(tvb, image_start) == 0xfe;
3397
0
        proto_tree_add_item(vt, dtype == TNS_DATATYPE_JSON ? hf_tns_data_json_image : hf_tns_data_vector_image,
3398
0
          tvb, chunked ? image_start : image_start + 1, chunked ? image_len : image_len - 1, ENC_NA);
3399
0
      }
3400
0
    }
3401
0
  }
3402
0
  else
3403
0
    proto_tree_add_bytes_format(tree, hf, tvb,
3404
0
      disp_start, offset - disp_start, NULL, "%s %d (%s)", prefix, idx,
3405
0
      val_to_str_const(dtype, tns_data_types, "unknown"));
3406
0
  return offset;
3407
0
}
3408
3409
/* The describe a row-data message is split by: the conversation's most
3410
 * recent one, stored per packet on the first pass so a later pass uses
3411
 * the same. */
3412
static tns_describe_t *tns_current_describe(packet_info *pinfo)
3413
0
{
3414
0
  tns_describe_t *desc;
3415
3416
0
  if ( PINFO_FD_VISITED(pinfo) )
3417
0
    return (tns_describe_t *)p_get_proto_data(wmem_file_scope(), pinfo,
3418
0
      proto_tns, TNS_PROTO_DATA_DESCRIBE);
3419
3420
0
  desc = tns_get_conv_info(pinfo)->last_describe;
3421
0
  if ( desc && !p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_DESCRIBE) )
3422
0
    p_add_proto_data(wmem_file_scope(), pinfo, proto_tns,
3423
0
      TNS_PROTO_DATA_DESCRIBE, desc);
3424
0
  return desc;
3425
0
}
3426
3427
/* Count the RETURNING ... INTO binds of a statement: the placeholders
3428
 * after INTO, in a DML statement that has RETURNING ... INTO. Each
3429
 * placeholder is a bind of its own, and those after INTO come last. A
3430
 * PL/SQL block is never this form - a RETURNING INTO inside one is its
3431
 * own PL/SQL, and its target an ordinary OUT bind. String literals and
3432
 * comments are skipped. */
3433
static unsigned tns_count_return_binds(const char *sql)
3434
0
{
3435
0
  const char *p = sql;
3436
0
  bool first_word = true, returning = false, into = false;
3437
0
  unsigned n = 0;
3438
3439
0
  while ( *p )
3440
0
  {
3441
0
    if ( *p == '\'' )
3442
0
    {
3443
0
      for ( p++; *p && *p != '\''; p++ )
3444
0
        ;
3445
0
      if ( *p )
3446
0
        p++;
3447
0
    }
3448
0
    else if ( p[0] == '-' && p[1] == '-' )
3449
0
    {
3450
0
      while ( *p && *p != '\n' )
3451
0
        p++;
3452
0
    }
3453
0
    else if ( p[0] == '/' && p[1] == '*' )
3454
0
    {
3455
0
      const char *end = strstr(p + 2, "*/");
3456
0
      p = end ? end + 2 : p + strlen(p);
3457
0
    }
3458
0
    else if ( g_ascii_isalpha(*p) )
3459
0
    {
3460
0
      const char *w = p;
3461
0
      size_t len;
3462
0
      while ( g_ascii_isalnum(*p) || *p == '_' || *p == '$' || *p == '#' )
3463
0
        p++;
3464
0
      len = p - w;
3465
0
      if ( first_word )
3466
0
      {
3467
0
        first_word = false;
3468
0
        if ( !((len == 6 && (g_ascii_strncasecmp(w, "INSERT", 6) == 0
3469
0
            || g_ascii_strncasecmp(w, "UPDATE", 6) == 0
3470
0
            || g_ascii_strncasecmp(w, "DELETE", 6) == 0))
3471
0
          || (len == 5 && g_ascii_strncasecmp(w, "MERGE", 5) == 0)) )
3472
0
          return 0;
3473
0
      }
3474
0
      else if ( !returning && len == 9 && g_ascii_strncasecmp(w, "RETURNING", 9) == 0 )
3475
0
        returning = true;
3476
0
      else if ( returning && !into && len == 4 && g_ascii_strncasecmp(w, "INTO", 4) == 0 )
3477
0
        into = true;
3478
0
    }
3479
0
    else if ( *p == ':' && into && (g_ascii_isalnum(p[1]) || p[1] == '_' || p[1] == '"') )
3480
0
    {
3481
0
      n++;
3482
0
      for ( p++; g_ascii_isalnum(*p) || *p == '_' || *p == '"'; p++ )
3483
0
        ;
3484
0
    }
3485
0
    else
3486
0
      p++;
3487
0
  }
3488
0
  return n;
3489
0
}
3490
3491
/* Look up the bind types remembered for a cursor, for an execute that
3492
 * sends its values without descriptors. Stashed per packet on the first
3493
 * pass, so a later pass gets the same answer. */
3494
static tns_binds_t *tns_lookup_cursor_binds(packet_info *pinfo, uint32_t cursor)
3495
0
{
3496
0
  if ( PINFO_FD_VISITED(pinfo) )
3497
0
    return (tns_binds_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_BINDS);
3498
3499
0
  tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
3500
0
  tns_binds_t *binds = (tns_binds_t *)wmem_map_lookup(tns_info->cursor_binds, GUINT_TO_POINTER(cursor));
3501
0
  if ( binds )
3502
0
    p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_BINDS, binds);
3503
0
  return binds;
3504
0
}
3505
3506
/* Whether a bind is LONG-class: a LONG or LONG RAW whose buffer exceeds
3507
 * the longest string a server takes in place. */
3508
static bool tns_is_long_bind(const tns_column_t *col)
3509
0
{
3510
0
  return (col->type == TNS_DATATYPE_LONG || col->type == TNS_DATATYPE_LONG_RAW)
3511
0
    && col->data_len > 4000;
3512
0
}
3513
3514
/* Decode one bind's value in a bind row or an OUT reply, framed as out of
3515
 * a fetch. An array bind's value is a ub4 element count and that many
3516
 * elements. In an OUT reply each value - each element of an array - is
3517
 * followed by its sb4 return code. Returns the new offset. */
3518
/* After each value a server returns for a bind - an OUT bind or a
3519
 * RETURNING one, never a fetched column - comes an sb4 with the value's
3520
 * actual length: 0 when it fitted, -1 when it is NULL, and otherwise the
3521
 * length the value had before the server cut it to the size the client
3522
 * declared. Only a value that arrived as plain bytes can have been cut -
3523
 * VARCHAR2, CHAR or RAW; the others are fixed width or carry framing of
3524
 * their own. value_start is where the value began. Returns the new
3525
 * offset. */
3526
static int dissect_tns_actual_length(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3527
    int value_start, uint8_t dtype)
3528
0
{
3529
0
  int actual = 0, start = offset, got = 0;
3530
0
  proto_item *ti;
3531
3532
0
  offset += get_sb4_custom(tvb, offset, &actual);
3533
0
  ti = proto_tree_add_int(tree, hf_tns_data_bind_actual_len, tvb, start, offset - start, actual);
3534
0
  if ( actual == -1 )
3535
0
    proto_item_append_text(ti, " (NULL)");
3536
0
  else if ( actual > 0 && (dtype == TNS_DATATYPE_VARCHAR || dtype == TNS_DATATYPE_CHAR
3537
0
    || dtype == TNS_DATATYPE_RAW || dtype == TNS_DATATYPE_LONG || dtype == TNS_DATATYPE_LONG_RAW) )
3538
0
  {
3539
    /* A server may echo the length of a value that fitted, so the
3540
     * value is cut only when it had more than arrived. */
3541
0
    tns_dalc_bytes(tvb, pinfo, value_start, &got);
3542
0
    if ( actual > got )
3543
0
    {
3544
0
      proto_item_append_text(ti, " (truncated to %d)", got);
3545
0
      expert_add_info_format(pinfo, ti, &ei_tns_data_value_truncated,
3546
0
        "The value was cut to %d of its %d", got, actual);
3547
0
      col_append_str(pinfo->cinfo, COL_INFO, " [truncated]");
3548
0
    }
3549
0
  }
3550
0
  return offset;
3551
0
}
3552
3553
static int dissect_tns_bind_value(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, const tns_column_t *col, int idx, bool out)
3554
0
{
3555
0
  int num = 1, start;
3556
3557
0
  if ( col->is_array )
3558
0
  {
3559
0
    start = offset;
3560
0
    offset += get_sb4_custom(tvb, offset, &num);
3561
0
    proto_tree_add_uint(tree, hf_tns_data_bind_num_elements, tvb, start, offset - start, num);
3562
0
  }
3563
0
  for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3564
0
  {
3565
0
    start = offset;
3566
0
    offset = dissect_tns_value(tvb, pinfo, tree, offset, col->type, col->csform,
3567
0
      out ? TNS_VALUE_OUT : TNS_VALUE_BIND, idx, hf_tns_data_bind_value, "Bind");
3568
0
    if ( out )
3569
0
      offset = dissect_tns_actual_length(tvb, pinfo, tree, offset, start, col->type);
3570
0
  }
3571
0
  return offset;
3572
0
}
3573
3574
/* Decode the TTI_RXD value rows of a bind section - one row per
3575
 * execution - with each value typed by cols[]. Returns the new offset. */
3576
static int dissect_tns_bind_rows(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, const tns_column_t *cols, uint32_t count, bool plsql, const uint8_t *dirs)
3577
0
{
3578
0
  int rownum = 0;
3579
3580
0
  while ( tvb_reported_length_remaining(tvb, offset) > 0
3581
0
    && tvb_get_uint8(tvb, offset) == SQLNET_ROW_TRANSF_DATA )
3582
0
  {
3583
0
    proto_tree *row_tree;
3584
0
    proto_item *row_item;
3585
0
    int r_start = offset;
3586
3587
0
    offset += 1; /* TTI_RXD token */
3588
0
    row_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
3589
0
      ett_tns_bind_row, &row_item, "Row %d", ++rownum);
3590
    /* In a SQL statement a LONG-class value - one too long for a
3591
     * string, sent as LONG or LONG RAW - rides after all the others;
3592
     * a PL/SQL block takes its values in bind order. */
3593
0
    for ( int pass = 0; pass < 2; pass++ )
3594
0
      for ( uint32_t i = 0; i < count
3595
0
        && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3596
0
      {
3597
0
        bool late = !plsql && tns_is_long_bind(&cols[i]);
3598
        /* a re-executed block sends no value for an OUT bind */
3599
0
        if ( dirs && dirs[i] == TNS_BIND_DIR_OUTPUT )
3600
0
          continue;
3601
0
        if ( late == (pass == 1) )
3602
0
          offset = dissect_tns_bind_value(tvb, pinfo, row_tree, offset, &cols[i], i + 1, false);
3603
0
      }
3604
0
    proto_item_set_len(row_item, offset - r_start);
3605
0
  }
3606
0
  return offset;
3607
0
}
3608
3609
/* Whether an OCI client sends a bind's value behind the others in the
3610
 * value row: a char or RAW bind whose buffer is wider than 4000 bytes, as
3611
 * a thin client sends a LONG-class one. */
3612
static bool tns_oci_bind_rides_last(const tns_column_t *col)
3613
0
{
3614
0
  return (col->type == TNS_DATATYPE_VARCHAR || col->type == TNS_DATATYPE_CHAR
3615
0
    || col->type == TNS_DATATYPE_RAW) && col->data_len > 4000;
3616
0
}
3617
3618
/* Whether an OCI client sends a bind's value as the value decoder reads
3619
 * it. A LOB's, an object's and a REF CURSOR's come in forms of their
3620
 * own. */
3621
static bool tns_oci_bind_is_plain(uint8_t type)
3622
0
{
3623
0
  switch ( type )
3624
0
  {
3625
0
    case TNS_DATATYPE_VARCHAR:
3626
0
    case TNS_DATATYPE_NUMBER:
3627
0
    case TNS_DATATYPE_DATE:
3628
0
    case TNS_DATATYPE_RAW:
3629
0
    case TNS_DATATYPE_CHAR:
3630
0
    case TNS_DATATYPE_BINARY_FLOAT:
3631
0
    case TNS_DATATYPE_BINARY_DOUBLE:
3632
0
    case TNS_DATATYPE_TIMESTAMP:
3633
0
    case TNS_DATATYPE_TIMESTAMP_TZ:
3634
0
      return true;
3635
0
    default:
3636
0
      return false;
3637
0
  }
3638
0
}
3639
3640
/* Decode an OCI client's bind descriptor: the thin OAC's fields at fixed
3641
 * width, little-endian, with OCI's own parts - a lead byte (01 for a
3642
 * scalar, 00 for an object), from 12c four zero bytes before the
3643
 * continuation flags and four before the charset, and for a scalar six
3644
 * zero bytes after the version, one after the form and a ub4 column id
3645
 * after the max characters. A scalar's descriptor is 41 bytes before 12c
3646
 * and 49 from it. The lengths are the client's buffer: three bytes a
3647
 * character for the database charset, two for NCHAR. *repeat is set when
3648
 * the flags mark a name that occurs again. A describe column carries the
3649
 * same fields, whose flags mean other things; it passes a NULL repeat.
3650
 * Returns the new offset. */
3651
static int dissect_tns_oci_oac(tvbuff_t *tvb, proto_tree *tree, int offset, bool band_12c, tns_column_t *col, bool *repeat)
3652
0
{
3653
0
  uint32_t v;
3654
0
  bool plain;
3655
3656
  /* lead byte */
3657
0
  offset += 1;
3658
0
  col->type = tvb_get_uint8(tvb, offset);
3659
0
  plain = col->type != TNS_DATATYPE_ADT;
3660
0
  proto_tree_add_item(tree, hf_tns_data_col_type, tvb, offset, 1, ENC_NA);
3661
0
  offset += 1;
3662
0
  if ( repeat )
3663
0
  {
3664
0
    *repeat = (tvb_get_uint8(tvb, offset) & TNS_OCI_BIND_REPEAT) != 0;
3665
0
    proto_tree_add_bitmask(tree, tvb, offset, hf_tns_data_bind_oci_flags,
3666
0
      ett_tns_bind_oci_flags, tns_bind_oci_flags, ENC_NA);
3667
0
  }
3668
0
  offset += 1;
3669
0
  proto_tree_add_item(tree, hf_tns_data_col_precision, tvb, offset, 1, ENC_NA);
3670
0
  offset += 1;
3671
0
  proto_tree_add_int(tree, hf_tns_data_col_scale, tvb, offset, 1, (int8_t)tvb_get_uint8(tvb, offset));
3672
0
  offset += 1;
3673
0
  proto_tree_add_item_ret_uint(tree, hf_tns_data_col_max_length, tvb, offset, 4, ENC_LITTLE_ENDIAN, &col->data_len);
3674
0
  offset += 4;
3675
0
  v = tvb_get_letohl(tvb, offset);
3676
0
  if ( v > 0 )
3677
0
    proto_tree_add_uint(tree, hf_tns_data_col_max_elements, tvb, offset, 4, v);
3678
0
  offset += 4;
3679
0
  if ( band_12c )
3680
0
    offset += 4;
3681
  /* continuation flags */
3682
0
  offset += 4;
3683
  /* the type OID: a ub4 length, then, when not empty, a ub1 length
3684
   * and the id */
3685
0
  v = tvb_get_letohl(tvb, offset);
3686
0
  offset += 4;
3687
0
  if ( v > 0 )
3688
0
    offset += 1 + tvb_get_uint8(tvb, offset);
3689
  /* version */
3690
0
  offset += 2;
3691
0
  if ( plain )
3692
0
    offset += 6;
3693
0
  if ( band_12c )
3694
0
    offset += 4;
3695
0
  proto_tree_add_item(tree, hf_tns_data_col_charset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
3696
0
  offset += 2;
3697
0
  col->csform = tvb_get_uint8(tvb, offset);
3698
0
  proto_tree_add_item(tree, hf_tns_data_col_csform, tvb, offset, 1, ENC_NA);
3699
0
  offset += 1;
3700
0
  if ( plain )
3701
0
    offset += 1;
3702
  /* max characters */
3703
0
  proto_tree_add_item(tree, hf_tns_data_col_max_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3704
0
  offset += 4;
3705
  /* column id */
3706
0
  if ( plain )
3707
0
    offset += 4;
3708
0
  return offset;
3709
0
}
3710
3711
/* Decode a describe body as a server sends it to an OCI client, as a
3712
 * REF CURSOR OUT value and an implicit result carry it: thin's fields at
3713
 * fixed width, little-endian. A ub4 max row size and column count, then
3714
 * per column a marker byte (nonzero on the first, as thin's reserved
3715
 * byte), a bind descriptor's fields - at the 12c band when band_12c - the
3716
 * nullability, the name's lengths and the name, the type's schema and
3717
 * name - each a ub4 length and, when not empty, a ub1 length and the
3718
 * text - from 11.2 the uds flags, and a reserved byte. The trailer: a
3719
 * byte, the describe time as a ub4 length and a ub1-length value, four
3720
 * flag words and, from 11.2, the query key's length. Returns the new
3721
 * offset. */
3722
static int dissect_tns_oci_describe_body(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3723
    bool band_12c, bool fv_11_2)
3724
0
{
3725
0
  uint32_t num_cols, v;
3726
3727
  /* max row size */
3728
0
  offset += 4;
3729
0
  proto_tree_add_item_ret_uint(tree, hf_tns_data_dcb_num_columns, tvb, offset, 4, ENC_LITTLE_ENDIAN, &num_cols);
3730
0
  offset += 4;
3731
0
  for ( uint32_t i = 0; i < num_cols && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3732
0
  {
3733
0
    proto_tree *col_tree;
3734
0
    proto_item *col_item;
3735
0
    tns_column_t col = { 0 };
3736
0
    int col_start = offset;
3737
0
    const char *name;
3738
0
    uint8_t len;
3739
3740
0
    col_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1,
3741
0
      ett_tns_dcb_col, &col_item, "Column %u", i + 1);
3742
    /* marker */
3743
0
    offset += 1;
3744
0
    offset = dissect_tns_oci_oac(tvb, col_tree, offset, band_12c, &col, NULL);
3745
0
    proto_tree_add_item(col_tree, hf_tns_data_col_nulls_ok, tvb, offset, 1, ENC_NA);
3746
0
    offset += 1;
3747
    /* the name's v7 length and its length in characters */
3748
0
    offset += 1 + 4;
3749
0
    len = tvb_get_uint8(tvb, offset);
3750
0
    name = (const char *)tvb_get_string_enc(pinfo->pool, tvb, offset + 1, len, ENC_UTF_8|ENC_NA);
3751
0
    proto_tree_add_string(col_tree, hf_tns_data_col_name, tvb, offset, 1 + len, name);
3752
0
    offset += 1 + len;
3753
0
    for ( int k = 0; k < 2; k++ )
3754
0
    {
3755
0
      v = tvb_get_letohl(tvb, offset);
3756
0
      offset += 4;
3757
0
      if ( v > 0 )
3758
0
        offset += 1 + tvb_get_uint8(tvb, offset);
3759
0
    }
3760
0
    if ( fv_11_2 )
3761
0
    {
3762
0
      proto_tree_add_item(col_tree, hf_tns_data_col_uds_flags, tvb, offset, 4, ENC_LITTLE_ENDIAN);
3763
0
      offset += 4;
3764
0
    }
3765
    /* reserved */
3766
0
    offset += 1;
3767
0
    proto_item_append_text(col_item, ": %s (%s)", name,
3768
0
      val_to_str_const(col.type, tns_data_types, "unknown"));
3769
0
    proto_item_set_len(col_item, offset - col_start);
3770
0
  }
3771
  /* The trailer: a byte that closes the column array, so a cursor
3772
   * left unopened or closed, with no columns, has none; then the
3773
   * describe time as a ub4 length and the value. */
3774
0
  if ( num_cols > 0 )
3775
0
    offset += 1;
3776
0
  offset += 4;
3777
0
  offset += 1 + tvb_get_uint8(tvb, offset);
3778
0
  offset += 4 * 4;
3779
0
  if ( fv_11_2 )
3780
0
    offset += 4;
3781
0
  return offset;
3782
0
}
3783
3784
/* Show the al8i4 array of an OCI client's execute: count ub4 LE words.
3785
 * Slot 1 is the execution count, or for a query the rows to fetch with
3786
 * the execute; slot 7 the statement type; slots 9 to 11 the execute
3787
 * flags and, for a scrollable cursor, the fetch orientation and the row
3788
 * it asks for. */
3789
static void dissect_tns_oci_al8i4(tvbuff_t *tvb, proto_tree *tree, int offset, uint32_t count)
3790
0
{
3791
0
  proto_tree *i4_tree;
3792
0
  uint32_t stmt_type;
3793
3794
0
  if ( count < 12 || !tvb_bytes_exist(tvb, offset, 4 * count) )
3795
0
    return;
3796
0
  i4_tree = proto_tree_add_subtree(tree, tvb, offset, 4 * count, ett_tns_all8_i4, NULL,
3797
0
    "Execute Arguments (al8i4)");
3798
0
  stmt_type = tvb_get_letohl(tvb, offset + 4 * 7);
3799
0
  proto_tree_add_item(i4_tree, stmt_type == 1 ? hf_tns_data_all8_prefetch : hf_tns_data_all8_iterations,
3800
0
    tvb, offset + 4 * 1, 4, ENC_LITTLE_ENDIAN);
3801
0
  proto_tree_add_item(i4_tree, hf_tns_data_all8_oci_stmt_type, tvb, offset + 4 * 7, 4, ENC_LITTLE_ENDIAN);
3802
0
  proto_tree_add_bitmask(i4_tree, tvb, offset + 4 * 9, hf_tns_data_all8_exec_flags,
3803
0
    ett_tns_all8_exec_flags, tns_all8_exec_flags, ENC_LITTLE_ENDIAN);
3804
0
  proto_tree_add_item(i4_tree, hf_tns_data_all8_fetch_orientation, tvb, offset + 4 * 10, 4, ENC_LITTLE_ENDIAN);
3805
0
  proto_tree_add_item(i4_tree, hf_tns_data_all8_fetch_pos, tvb, offset + 4 * 11, 4, ENC_LITTLE_ENDIAN);
3806
0
}
3807
3808
/* Decode the TTI_RXD value row of an OCI client's execute. The values
3809
 * ride in descriptor order, except that a repeated name sends none and a
3810
 * wide char or RAW bind rides last. A chunked value's chunk lengths are
3811
 * one byte to a server before 12.1; past that their width follows a
3812
 * capability, not the field version, so the row stops being read there.
3813
 * Returns the new offset. */
3814
static int dissect_tns_oci_bind_row(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3815
    const tns_column_t *cols, const bool *repeat, uint32_t count)
3816
0
{
3817
0
  proto_tree *row_tree;
3818
0
  proto_item *row_item;
3819
0
  int r_start = offset;
3820
0
  bool stop = false;
3821
3822
0
  offset += 1; /* TTI_RXD token */
3823
0
  row_tree = proto_tree_add_subtree(tree, tvb, r_start, -1, ett_tns_bind_row, &row_item, "Row 1");
3824
0
  for ( int pass = 0; pass < 2 && !stop; pass++ )
3825
0
    for ( uint32_t i = 0; i < count && !stop; i++ )
3826
0
    {
3827
0
      if ( repeat[i] || tns_oci_bind_rides_last(&cols[i]) != (pass == 1) )
3828
0
        continue;
3829
0
      if ( tvb_reported_length_remaining(tvb, offset) <= 0
3830
0
        || (tvb_get_uint8(tvb, offset) == 0xfe && tns_field_version(pinfo) >= TNS_FV_12_1) )
3831
0
        stop = true;
3832
0
      else if ( cols[i].type == TNS_DATATYPE_REFCURSOR )
3833
0
      {
3834
        /* a REF CURSOR: a ub1 length and the ub4 id of the
3835
         * cursor; 0 asks the server to open one */
3836
0
        proto_item *ci;
3837
0
        uint32_t cursor;
3838
3839
0
        if ( tvb_get_uint8(tvb, offset) != 4 || !tvb_bytes_exist(tvb, offset, 5) )
3840
0
        {
3841
0
          stop = true;
3842
0
          continue;
3843
0
        }
3844
0
        cursor = tvb_get_letohl(tvb, offset + 1);
3845
0
        if ( cursor )
3846
0
          ci = proto_tree_add_bytes_format(row_tree, hf_tns_data_bind_value, tvb, offset, 5, NULL,
3847
0
            "Bind %u (REFCURSOR): cursor %u", i + 1, cursor);
3848
0
        else
3849
0
          ci = proto_tree_add_bytes_format(row_tree, hf_tns_data_bind_value, tvb, offset, 5, NULL,
3850
0
            "Bind %u (REFCURSOR): a new cursor", i + 1);
3851
0
        proto_tree_add_item(proto_item_add_subtree(ci, ett_tns_value), hf_tns_cursor, tvb,
3852
0
          offset + 1, 4, ENC_LITTLE_ENDIAN);
3853
0
        offset += 5;
3854
0
      }
3855
0
      else
3856
0
        offset = dissect_tns_bind_value(tvb, pinfo, row_tree, offset, &cols[i], i + 1, false);
3857
0
    }
3858
0
  proto_item_set_len(row_item, offset - r_start);
3859
0
  return offset;
3860
0
}
3861
3862
/* Remember the call a request makes, so the response can be read in its
3863
 * light. Returns the record to fill in, or NULL on a later pass. */
3864
static tns_call_t *tns_remember_call(packet_info *pinfo, uint8_t func)
3865
0
{
3866
0
  if ( PINFO_FD_VISITED(pinfo) )
3867
0
    return NULL;
3868
3869
0
  tns_call_t *call = wmem_new0(wmem_file_scope(), tns_call_t);
3870
0
  call->func = func;
3871
0
  tns_get_conv_info(pinfo)->last_call = call;
3872
0
  return call;
3873
0
}
3874
3875
/* The call a response packet answers, or NULL if none was seen. */
3876
static tns_call_t *tns_answered_call(packet_info *pinfo)
3877
0
{
3878
0
  if ( PINFO_FD_VISITED(pinfo) )
3879
0
    return (tns_call_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_CALL);
3880
3881
0
  tns_call_t *call = tns_get_conv_info(pinfo)->last_call;
3882
0
  if ( call )
3883
0
    p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_CALL, call);
3884
0
  return call;
3885
0
}
3886
3887
/* Decode num key/value pairs: each a ub2 text length and text, a ub2
3888
 * binary length and bytes, and a ub2 keyword number saying which session
3889
 * attribute the value is for. Returns the new offset. */
3890
static int dissect_tns_kv_pairs(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int num)
3891
0
{
3892
0
  for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3893
0
  {
3894
0
    proto_tree *kv_tree;
3895
0
    proto_item *kv_item;
3896
0
    const char *text = NULL;
3897
0
    int kv_start = offset, len = 0, keyword = 0, start;
3898
3899
0
    kv_tree = proto_tree_add_subtree_format(tree, tvb, offset, -1, ett_tns_kv,
3900
0
      &kv_item, "Key/Value Pair %d", i + 1);
3901
0
    offset += get_sb4_custom(tvb, offset, &len);
3902
0
    if ( len > 0 )
3903
0
    {
3904
0
      start = offset;
3905
0
      offset += get_dalc_custom(tvb, pinfo, offset, &text);
3906
0
      proto_tree_add_string(kv_tree, hf_tns_data_kv_text, tvb, start, offset - start, text);
3907
0
    }
3908
0
    offset += get_sb4_custom(tvb, offset, &len);
3909
0
    if ( len > 0 )
3910
0
    {
3911
0
      start = offset;
3912
0
      offset += get_dalc_custom(tvb, pinfo, offset, NULL);
3913
0
      proto_tree_add_item(kv_tree, hf_tns_data_kv_binary, tvb, start + 1, offset - start - 1, ENC_NA);
3914
0
    }
3915
0
    start = offset;
3916
0
    offset += get_sb4_custom(tvb, offset, &keyword);
3917
0
    proto_tree_add_uint(kv_tree, hf_tns_data_kv_keyword, tvb, start, offset - start, keyword);
3918
0
    proto_item_append_text(kv_item, ": %s", val_to_str(pinfo->pool, keyword, tns_kv_keywords, "keyword %u"));
3919
0
    if ( text )
3920
0
      proto_item_append_text(kv_item, " = %s", text);
3921
0
    proto_item_set_len(kv_item, offset - kv_start);
3922
0
  }
3923
0
  return offset;
3924
0
}
3925
3926
/* Decode the return-parameters block (TTI_RPA) that answers an execute,
3927
 * ahead of its closing status. With DML_ROWCOUNTS requested it ends with
3928
 * the rows each iteration of an array DML affected. Returns the new
3929
 * offset. */
3930
static int dissect_tns_return_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, bool rowcounts)
3931
0
{
3932
0
  proto_tree *rpa_tree;
3933
0
  proto_item *rpa_item;
3934
0
  int rpa_start = offset, num = 0, len = 0, start;
3935
3936
0
  rpa_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_tns_rpa, &rpa_item, "Return Parameters");
3937
3938
  /* al8o4l: a count of ub4 words */
3939
0
  start = offset;
3940
0
  offset += get_sb4_custom(tvb, offset, &num);
3941
0
  proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_num_al8o4, tvb, start, offset - start, num);
3942
0
  for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3943
0
  {
3944
0
    int v = 0;
3945
0
    start = offset;
3946
0
    offset += get_sb4_custom(tvb, offset, &v);
3947
0
    proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_al8o4, tvb, start, offset - start, v);
3948
0
  }
3949
  /* al8txl: a byte count and the bytes */
3950
0
  offset += get_sb4_custom(tvb, offset, &len);
3951
0
  if ( len > 0 )
3952
0
  {
3953
0
    proto_tree_add_item(rpa_tree, hf_tns_data_rpa_al8txl, tvb, offset, len, ENC_NA);
3954
0
    offset += len;
3955
0
  }
3956
  /* key/value pairs: a changed session attribute is reported here */
3957
0
  start = offset;
3958
0
  offset += get_sb4_custom(tvb, offset, &num);
3959
0
  proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_num_kv, tvb, start, offset - start, num);
3960
0
  offset = dissect_tns_kv_pairs(tvb, pinfo, rpa_tree, offset, num);
3961
  /* registration: a byte count and the bytes */
3962
0
  offset += get_sb4_custom(tvb, offset, &len);
3963
0
  if ( len > 0 )
3964
0
  {
3965
0
    proto_tree_add_item(rpa_tree, hf_tns_data_rpa_registration, tvb, offset, len, ENC_NA);
3966
0
    offset += len;
3967
0
  }
3968
  /* per-iteration row counts, when the execute asked for them */
3969
0
  if ( rowcounts )
3970
0
  {
3971
0
    start = offset;
3972
0
    offset += get_sb4_custom(tvb, offset, &num);
3973
0
    proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_num_rowcounts, tvb, start, offset - start, num);
3974
0
    for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
3975
0
    {
3976
0
      uint64_t rows = 0;
3977
0
      start = offset;
3978
0
      offset += get_ub8_custom(tvb, offset, &rows);
3979
0
      proto_tree_add_uint64(rpa_tree, hf_tns_data_rpa_dml_rowcount, tvb, start, offset - start, rows);
3980
0
    }
3981
0
  }
3982
0
  proto_item_set_len(rpa_item, offset - rpa_start);
3983
0
  return offset;
3984
0
}
3985
3986
/* Decode the return parameters a server sends an OCI client ahead of an
3987
 * execute's status: thin's block at fixed widths. A ub2 count of ub4
3988
 * words, the third the statement's cursor; a ub2 length and the
3989
 * transaction id; a ub2 count of the session settings the statement
3990
 * changed, each a ub4 length and the key, a ub4 length and the value,
3991
 * and a ub2 keyword number; then a ub4 registration. Returns the new
3992
 * offset, or -1 when the block does not fit. */
3993
static int dissect_tns_oci_return_params(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
3994
0
{
3995
0
  proto_tree *rpa_tree;
3996
0
  proto_item *rpa_item;
3997
0
  int rpa_start = offset;
3998
0
  uint32_t num, len;
3999
4000
0
  if ( !tvb_bytes_exist(tvb, offset, 2) )
4001
0
    return -1;
4002
0
  num = tvb_get_letohs(tvb, offset);
4003
0
  if ( !tvb_bytes_exist(tvb, offset + 2, num * 4 + 2) )
4004
0
    return -1;
4005
0
  rpa_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_tns_rpa, &rpa_item, "Return Parameters");
4006
0
  proto_tree_add_uint(rpa_tree, hf_tns_data_rpa_num_al8o4, tvb, offset, 2, num);
4007
0
  offset += 2;
4008
0
  for ( uint32_t i = 0; i < num; i++ )
4009
0
  {
4010
0
    proto_tree_add_item(rpa_tree, i == 2 ? hf_tns_cursor : hf_tns_data_rpa_al8o4, tvb, offset, 4, ENC_LITTLE_ENDIAN);
4011
0
    offset += 4;
4012
0
  }
4013
0
  len = tvb_get_letohs(tvb, offset);
4014
0
  offset += 2;
4015
0
  if ( len > 0 )
4016
0
  {
4017
0
    proto_tree_add_item(rpa_tree, hf_tns_data_rpa_al8txl, tvb, offset, len, ENC_NA);
4018
0
    offset += len;
4019
0
  }
4020
0
  proto_tree_add_item_ret_uint(rpa_tree, hf_tns_data_rpa_num_kv, tvb, offset, 2, ENC_LITTLE_ENDIAN, &num);
4021
0
  offset += 2;
4022
0
  for ( uint32_t i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4023
0
  {
4024
0
    proto_tree *kv_tree;
4025
0
    proto_item *kv_item;
4026
0
    const char *text = NULL;
4027
0
    int kv_start = offset, start;
4028
0
    uint32_t keyword;
4029
4030
0
    kv_tree = proto_tree_add_subtree_format(rpa_tree, tvb, offset, -1, ett_tns_kv,
4031
0
      &kv_item, "Key/Value Pair %u", i + 1);
4032
0
    len = tvb_get_letohl(tvb, offset);
4033
0
    offset += 4;
4034
0
    if ( len > 0 )
4035
0
    {
4036
0
      start = offset;
4037
0
      offset += get_dalc_custom(tvb, pinfo, offset, NULL);
4038
0
      proto_tree_add_item(kv_tree, hf_tns_data_kv_binary, tvb, start + 1, offset - start - 1, ENC_NA);
4039
0
    }
4040
0
    len = tvb_get_letohl(tvb, offset);
4041
0
    offset += 4;
4042
0
    if ( len > 0 )
4043
0
    {
4044
0
      start = offset;
4045
0
      offset += get_dalc_custom(tvb, pinfo, offset, &text);
4046
0
      proto_tree_add_string(kv_tree, hf_tns_data_kv_text, tvb, start, offset - start, text);
4047
0
    }
4048
0
    proto_tree_add_item_ret_uint(kv_tree, hf_tns_data_kv_keyword, tvb, offset, 2, ENC_LITTLE_ENDIAN, &keyword);
4049
0
    offset += 2;
4050
0
    proto_item_append_text(kv_item, ": %s", val_to_str(pinfo->pool, keyword, tns_kv_keywords, "keyword %u"));
4051
0
    if ( text )
4052
0
      proto_item_append_text(kv_item, " = %s", text);
4053
0
    proto_item_set_len(kv_item, offset - kv_start);
4054
0
  }
4055
  /* the registration */
4056
0
  offset += 4;
4057
0
  proto_item_set_len(rpa_item, offset - rpa_start);
4058
0
  return offset;
4059
0
}
4060
4061
/* From field version 23.1 ext 1 a call or piggyback header carries a ub8
4062
 * token after its sequence number, which the reply echoes in a TOKEN
4063
 * message. Returns the new offset. */
4064
static int dissect_tns_call_token(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
4065
0
{
4066
0
  uint64_t token = 0;
4067
0
  int start = offset;
4068
4069
0
  if ( tns_field_version(pinfo) < TNS_FV_23_1_EXT_1 )
4070
0
    return offset;
4071
0
  offset += get_ub8_custom(tvb, offset, &token);
4072
0
  proto_tree_add_uint64(tree, hf_tns_data_token, tvb, start, offset - start, token);
4073
0
  return offset;
4074
0
}
4075
4076
/* The message properties of an Advanced Queuing message, as the enqueue
4077
 * request writes them and a dequeue reply returns them: the priority,
4078
 * delay and expiration, the correlation, the number of delivery
4079
 * attempts, the exception queue, the state, the enqueue time and
4080
 * transaction id, extensions as key/value pairs, and flags.
4081
 * Returns the new offset. */
4082
static int dissect_tns_aq_msg_props(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, bool reply)
4083
0
{
4084
0
  proto_tree *props_tree;
4085
0
  proto_item *props_item;
4086
0
  const char *text = NULL;
4087
0
  int start, props_start = offset, v = 0, num = 0;
4088
4089
0
  props_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_tns_aq_props, &props_item,
4090
0
    "Message Properties");
4091
0
  start = offset;
4092
0
  offset += get_sb4_custom(tvb, offset, &v);
4093
0
  proto_tree_add_uint(props_tree, hf_tns_data_aq_priority, tvb, start, offset - start, v);
4094
0
  start = offset;
4095
0
  offset += get_sb4_custom(tvb, offset, &v);
4096
0
  proto_tree_add_uint(props_tree, hf_tns_data_aq_delay, tvb, start, offset - start, v);
4097
0
  start = offset;
4098
0
  offset += get_sb4_custom(tvb, offset, &v);
4099
0
  proto_tree_add_int(props_tree, hf_tns_data_aq_expiration, tvb, start, offset - start, v);
4100
0
  start = offset;
4101
0
  offset += get_field_with_length(tvb, pinfo, offset, &text);
4102
0
  if ( text )
4103
0
    proto_tree_add_string(props_tree, hf_tns_data_aq_correlation, tvb, start, offset - start, text);
4104
0
  start = offset;
4105
0
  offset += get_sb4_custom(tvb, offset, &v);
4106
0
  proto_tree_add_uint(props_tree, hf_tns_data_aq_attempts, tvb, start, offset - start, v);
4107
0
  start = offset;
4108
0
  offset += get_field_with_length(tvb, pinfo, offset, &text);
4109
0
  if ( text )
4110
0
    proto_tree_add_string(props_tree, hf_tns_data_aq_exception_queue, tvb, start, offset - start, text);
4111
0
  start = offset;
4112
0
  offset += get_sb4_custom(tvb, offset, &v);
4113
0
  proto_tree_add_uint(props_tree, hf_tns_data_aq_state, tvb, start, offset - start, v);
4114
  /* the enqueue time: a length and, in a reply, a date */
4115
0
  start = offset;
4116
0
  offset += get_sb4_custom(tvb, offset, &v);
4117
0
  if ( reply && v > 0 )
4118
0
  {
4119
0
    int date_start = offset;
4120
0
    offset += get_dalc_custom(tvb, pinfo, offset, NULL);
4121
0
    if ( offset - date_start > 1 )
4122
0
    {
4123
0
      const uint8_t *d = tvb_get_ptr(tvb, date_start + 1, offset - date_start - 1);
4124
0
      const char *when = tns_format_date(pinfo, d, offset - date_start - 1);
4125
0
      if ( when )
4126
0
        proto_tree_add_string(props_tree, hf_tns_data_aq_enq_time, tvb, start, offset - start, when);
4127
0
    }
4128
0
  }
4129
0
  offset += get_field_with_length(tvb, pinfo, offset, NULL);   /* transaction id */
4130
0
  offset += get_sb4_custom(tvb, offset, &num);                 /* extensions */
4131
0
  if ( num > 0 )
4132
0
  {
4133
0
    offset += 1;
4134
0
    offset = dissect_tns_kv_pairs(tvb, pinfo, props_tree, offset, num);
4135
0
  }
4136
0
  offset += get_sb4_custom(tvb, offset, &v);                   /* user properties */
4137
0
  offset += get_sb4_custom(tvb, offset, &v);                   /* change SCN */
4138
0
  offset += get_sb4_custom(tvb, offset, &v);                   /* dependency SCN */
4139
0
  start = offset;
4140
0
  offset += get_sb4_custom(tvb, offset, &v);
4141
0
  proto_tree_add_uint(props_tree, hf_tns_data_aq_delivery_flags, tvb, start, offset - start, v);
4142
0
  if ( tns_field_version(pinfo) >= TNS_FV_21_1 )
4143
0
    offset += get_sb4_custom(tvb, offset, &v);               /* shard */
4144
0
  proto_item_set_len(props_item, offset - props_start);
4145
0
  return offset;
4146
0
}
4147
4148
/* Decode an Advanced Queuing enqueue (121) or dequeue (122) call. Each
4149
 * opens with a header of pointers and lengths - the queue name, the
4150
 * options, the payload type's OID and, for an enqueue, the message
4151
 * properties - and ends with the values those lengths describe.
4152
 * Returns the new offset. */
4153
static int dissect_tns_aq_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint32_t func)
4154
0
{
4155
0
  const char *text = NULL;
4156
0
  int start, v = 0, qname_len = 0, consumer_len = 0, correlation_len = 0;
4157
0
  int condition_len = 0, toid_len = 0, raw_len = 0, num_recipients = 0;
4158
0
  uint8_t msgid_ptr = 0, toid_ptr, raw_ptr = 0;
4159
0
  unsigned fv = tns_field_version(pinfo);
4160
4161
0
  offset += 1;                                        /* queue name pointer */
4162
0
  offset += get_sb4_custom(tvb, offset, &qname_len);
4163
0
  if ( func == TTI_AQ_ENQUEUE )
4164
0
  {
4165
0
    offset = dissect_tns_aq_msg_props(tvb, pinfo, tree, offset, false);
4166
0
    offset += 1;                                    /* recipients pointer */
4167
0
    offset += get_sb4_custom(tvb, offset, &num_recipients);
4168
0
    start = offset;
4169
0
    offset += get_sb4_custom(tvb, offset, &v);
4170
0
    proto_tree_add_uint(tree, hf_tns_data_aq_visibility, tvb, start, offset - start, v);
4171
0
    offset += 1;                                    /* relative message id */
4172
0
    offset += get_sb4_custom(tvb, offset, &v);
4173
0
    offset += get_sb4_custom(tvb, offset, &v);      /* sequence deviation */
4174
0
    toid_ptr = tvb_get_uint8(tvb, offset);
4175
0
    offset += 1;
4176
0
    offset += get_sb4_custom(tvb, offset, &toid_len);
4177
0
    offset += get_sb4_custom(tvb, offset, &v);      /* message version */
4178
0
    offset += 1;                                    /* payload pointer */
4179
0
    raw_ptr = tvb_get_uint8(tvb, offset);
4180
0
    offset += 1;
4181
0
    offset += get_sb4_custom(tvb, offset, &raw_len);
4182
0
    offset += 1;                                    /* return message id */
4183
0
    offset += get_sb4_custom(tvb, offset, &v);
4184
0
    start = offset;
4185
0
    offset += get_sb4_custom(tvb, offset, &v);
4186
0
    proto_tree_add_uint(tree, hf_tns_data_aq_flags, tvb, start, offset - start, v);
4187
0
    for ( int i = 0; i < 2; i++ )                   /* two extension lists */
4188
0
    {
4189
0
      offset += 1;
4190
0
      offset += get_sb4_custom(tvb, offset, &v);
4191
0
    }
4192
0
    for ( int i = 0; i < 2; i++ )                   /* sequence numbers */
4193
0
    {
4194
0
      offset += 1;
4195
0
      offset += get_sb4_custom(tvb, offset, &v);
4196
0
    }
4197
0
    offset += 1;                                    /* output ack length */
4198
0
    for ( int i = 0; i < 3; i++ )                   /* correlation, sender name and address */
4199
0
    {
4200
0
      offset += 1;
4201
0
      offset += get_sb4_custom(tvb, offset, &v);
4202
0
    }
4203
0
    offset += 2;                                    /* sender charsets */
4204
0
    if ( fv >= TNS_FV_20_1 )
4205
0
      offset += 1;                                /* JSON payload pointer */
4206
0
  }
4207
0
  else
4208
0
  {
4209
0
    offset += 4;                                    /* message properties and
4210
                 * recipient list pointers */
4211
0
    offset += 1;                                    /* consumer name pointer */
4212
0
    offset += get_sb4_custom(tvb, offset, &consumer_len);
4213
0
    start = offset;
4214
0
    offset += get_sb4_custom(tvb, offset, &v);
4215
0
    proto_tree_add_uint(tree, hf_tns_data_aq_deq_mode, tvb, start, offset - start, v);
4216
0
    start = offset;
4217
0
    offset += get_sb4_custom(tvb, offset, &v);
4218
0
    proto_tree_add_uint(tree, hf_tns_data_aq_navigation, tvb, start, offset - start, v);
4219
0
    start = offset;
4220
0
    offset += get_sb4_custom(tvb, offset, &v);
4221
0
    proto_tree_add_uint(tree, hf_tns_data_aq_visibility, tvb, start, offset - start, v);
4222
0
    start = offset;
4223
0
    offset += get_sb4_custom(tvb, offset, &v);
4224
0
    proto_tree_add_int(tree, hf_tns_data_aq_wait, tvb, start, offset - start, v);
4225
0
    msgid_ptr = tvb_get_uint8(tvb, offset);
4226
0
    offset += 1;
4227
0
    offset += get_sb4_custom(tvb, offset, &v);
4228
0
    offset += 1;                                    /* correlation pointer */
4229
0
    offset += get_sb4_custom(tvb, offset, &correlation_len);
4230
0
    toid_ptr = tvb_get_uint8(tvb, offset);
4231
0
    offset += 1;
4232
0
    offset += get_sb4_custom(tvb, offset, &toid_len);
4233
0
    offset += get_sb4_custom(tvb, offset, &v);      /* message version */
4234
0
    offset += 2;                                    /* payload, message id */
4235
0
    offset += get_sb4_custom(tvb, offset, &v);
4236
0
    start = offset;
4237
0
    offset += get_sb4_custom(tvb, offset, &v);
4238
0
    proto_tree_add_uint(tree, hf_tns_data_aq_flags, tvb, start, offset - start, v);
4239
0
    offset += 1;                                    /* condition pointer */
4240
0
    offset += get_sb4_custom(tvb, offset, &condition_len);
4241
0
    offset += 1;                                    /* extensions pointer */
4242
0
    offset += get_sb4_custom(tvb, offset, &v);
4243
0
    if ( fv >= TNS_FV_20_1 )
4244
0
      offset += 1;                                /* JSON payload pointer */
4245
0
    if ( fv >= TNS_FV_21_1 )
4246
0
      offset += get_sb4_custom(tvb, offset, &v);  /* shard id */
4247
0
  }
4248
4249
  /* the values the header's lengths describe */
4250
0
  if ( qname_len > 0 )
4251
0
  {
4252
0
    start = offset;
4253
0
    offset += get_dalc_custom(tvb, pinfo, offset, &text);
4254
0
    if ( text )
4255
0
    {
4256
0
      proto_tree_add_string(tree, hf_tns_data_aq_queue, tvb, start, offset - start, text);
4257
0
      col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", text);
4258
0
    }
4259
0
  }
4260
0
  if ( func == TTI_AQ_ENQUEUE && num_recipients > 0 )
4261
0
    offset = dissect_tns_kv_pairs(tvb, pinfo, tree, offset, num_recipients);
4262
0
  if ( consumer_len > 0 )
4263
0
  {
4264
0
    start = offset;
4265
0
    offset += get_dalc_custom(tvb, pinfo, offset, &text);
4266
0
    if ( text )
4267
0
      proto_tree_add_string(tree, hf_tns_data_aq_consumer, tvb, start, offset - start, text);
4268
0
  }
4269
0
  if ( msgid_ptr )
4270
0
  {
4271
0
    proto_tree_add_item(tree, hf_tns_data_aq_msgid, tvb, offset, TNS_AQ_MSGID_LEN, ENC_NA);
4272
0
    offset += TNS_AQ_MSGID_LEN;
4273
0
  }
4274
0
  if ( correlation_len > 0 )
4275
0
  {
4276
0
    start = offset;
4277
0
    offset += get_dalc_custom(tvb, pinfo, offset, &text);
4278
0
    if ( text )
4279
0
      proto_tree_add_string(tree, hf_tns_data_aq_correlation, tvb, start, offset - start, text);
4280
0
  }
4281
0
  if ( toid_ptr && toid_len > 0 )
4282
0
  {
4283
0
    proto_tree_add_item(tree, hf_tns_data_aq_toid, tvb, offset, toid_len, ENC_NA);
4284
0
    offset += toid_len;
4285
0
  }
4286
0
  if ( condition_len > 0 )
4287
0
  {
4288
0
    start = offset;
4289
0
    offset += get_dalc_custom(tvb, pinfo, offset, &text);
4290
0
    if ( text )
4291
0
      proto_tree_add_string(tree, hf_tns_data_aq_condition, tvb, start, offset - start, text);
4292
0
  }
4293
0
  if ( func == TTI_AQ_ENQUEUE )
4294
0
  {
4295
    /* the payload: raw bytes of the length the header gave, else an
4296
     * object or a JSON image in the object framing */
4297
0
    if ( raw_ptr && raw_len > 0 )
4298
0
    {
4299
0
      proto_tree_add_item(tree, hf_tns_data_aq_payload, tvb, offset, raw_len, ENC_NA);
4300
0
      offset += raw_len;
4301
0
    }
4302
0
    else if ( tvb_reported_length_remaining(tvb, offset) > 0 )
4303
0
      offset = dissect_tns_value(tvb, pinfo, tree, offset, TNS_DATATYPE_ADT, 0,
4304
0
        TNS_VALUE_BIND, 1, hf_tns_data_aq_payload, "Payload");
4305
0
  }
4306
0
  return offset;
4307
0
}
4308
4309
/* Decode an array Advanced Queuing call (145), which enqueues or
4310
 * dequeues several messages at once. Its header says which operation and
4311
 * how many messages; an array enqueue then carries a row header with the
4312
 * queue name, the payload type's OID and the flags, and one row per
4313
 * message, closing with a status byte, while an array dequeue repeats
4314
 * the queue name and the dequeue options for each message it asks for.
4315
 * Returns the new offset. */
4316
static int dissect_tns_aq_array_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
4317
0
{
4318
0
  const char *text = NULL;
4319
0
  int start, v = 0, op = 0, num_iters = 0;
4320
0
  bool enqueue;
4321
4322
0
  offset += 1;                                        /* input parameters */
4323
0
  offset += get_sb4_custom(tvb, offset, &num_iters);
4324
0
  offset += get_sb4_custom(tvb, offset, &v);          /* array flags */
4325
0
  offset += 2;                                        /* output parameters */
4326
0
  start = offset;
4327
0
  offset += get_sb4_custom(tvb, offset, &op);
4328
0
  proto_tree_add_uint(tree, hf_tns_data_aq_array_op, tvb, start, offset - start, op);
4329
0
  enqueue = op == TNS_AQ_ARRAY_ENQ;
4330
0
  offset += 1;                                        /* iterations pointer */
4331
0
  if ( tns_field_version(pinfo) >= TNS_FV_21_1 )
4332
0
    offset += get_sb4_custom(tvb, offset, &v);      /* shard id */
4333
0
  if ( enqueue )
4334
0
    offset += get_sb4_custom(tvb, offset, &num_iters);
4335
0
  proto_tree_add_uint(tree, hf_tns_data_aq_num_messages, tvb, offset, 0, num_iters);
4336
4337
0
  if ( enqueue )
4338
0
  {
4339
0
    offset += get_sb4_custom(tvb, offset, &v);      /* relative message id */
4340
0
    offset += 1;                                    /* row header */
4341
0
    start = offset;
4342
0
    offset += get_field_with_length(tvb, pinfo, offset, &text);
4343
0
    if ( text )
4344
0
    {
4345
0
      proto_tree_add_string(tree, hf_tns_data_aq_queue, tvb, start, offset - start, text);
4346
0
      col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", text);
4347
0
    }
4348
0
    proto_tree_add_item(tree, hf_tns_data_aq_toid, tvb, offset, TNS_AQ_TOID_LEN, ENC_NA);
4349
0
    offset += TNS_AQ_TOID_LEN;
4350
0
    offset += get_sb4_custom(tvb, offset, &v);      /* message version */
4351
0
    offset += get_sb4_custom(tvb, offset, &v);      /* flags */
4352
0
    for ( int i = 0; i < num_iters && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4353
0
    {
4354
0
      int num_recipients = 0, payload_len = 0;
4355
0
      offset += 1;                                /* row data */
4356
0
      offset += get_sb4_custom(tvb, offset, &v);  /* flags */
4357
0
      offset = dissect_tns_aq_msg_props(tvb, pinfo, tree, offset, false);
4358
0
      offset += get_sb4_custom(tvb, offset, &num_recipients);
4359
0
      if ( num_recipients > 0 )
4360
0
        offset = dissect_tns_kv_pairs(tvb, pinfo, tree, offset, num_recipients);
4361
0
      offset += get_sb4_custom(tvb, offset, &v);  /* visibility */
4362
0
      offset += get_sb4_custom(tvb, offset, &v);  /* relative message id */
4363
0
      offset += get_sb4_custom(tvb, offset, &v);  /* sequence deviation */
4364
0
      offset += get_sb4_custom(tvb, offset, &payload_len);
4365
0
      if ( payload_len > 0 )
4366
0
      {
4367
0
        proto_tree_add_item(tree, hf_tns_data_aq_payload, tvb, offset, payload_len, ENC_NA);
4368
0
        offset += payload_len;
4369
0
      }
4370
0
    }
4371
0
    offset += 1;                                    /* the closing status */
4372
0
    return offset;
4373
0
  }
4374
4375
0
  for ( int i = 0; i < num_iters && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4376
0
  {
4377
0
    start = offset;
4378
0
    offset += get_field_with_length(tvb, pinfo, offset, &text);
4379
0
    if ( text && i == 0 )
4380
0
    {
4381
0
      proto_tree_add_string(tree, hf_tns_data_aq_queue, tvb, start, offset - start, text);
4382
0
      col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", text);
4383
0
    }
4384
0
    offset = dissect_tns_aq_msg_props(tvb, pinfo, tree, offset, false);
4385
0
    offset += get_sb4_custom(tvb, offset, &v);      /* recipients */
4386
0
    start = offset;
4387
0
    offset += get_field_with_length(tvb, pinfo, offset, &text);
4388
0
    if ( text )
4389
0
      proto_tree_add_string(tree, hf_tns_data_aq_consumer, tvb, start, offset - start, text);
4390
0
    start = offset;
4391
0
    offset += get_sb4_custom(tvb, offset, &v);
4392
0
    proto_tree_add_uint(tree, hf_tns_data_aq_deq_mode, tvb, start, offset - start, v);
4393
0
    start = offset;
4394
0
    offset += get_sb4_custom(tvb, offset, &v);
4395
0
    proto_tree_add_uint(tree, hf_tns_data_aq_navigation, tvb, start, offset - start, v);
4396
0
    start = offset;
4397
0
    offset += get_sb4_custom(tvb, offset, &v);
4398
0
    proto_tree_add_uint(tree, hf_tns_data_aq_visibility, tvb, start, offset - start, v);
4399
0
    start = offset;
4400
0
    offset += get_sb4_custom(tvb, offset, &v);
4401
0
    proto_tree_add_int(tree, hf_tns_data_aq_wait, tvb, start, offset - start, v);
4402
0
    offset += get_field_with_length(tvb, pinfo, offset, NULL);  /* message id */
4403
0
    start = offset;
4404
0
    offset += get_field_with_length(tvb, pinfo, offset, &text);
4405
0
    if ( text )
4406
0
      proto_tree_add_string(tree, hf_tns_data_aq_correlation, tvb, start, offset - start, text);
4407
0
    start = offset;
4408
0
    offset += get_field_with_length(tvb, pinfo, offset, &text);
4409
0
    if ( text )
4410
0
      proto_tree_add_string(tree, hf_tns_data_aq_condition, tvb, start, offset - start, text);
4411
0
    offset += get_sb4_custom(tvb, offset, &v);      /* extensions */
4412
0
    offset += get_sb4_custom(tvb, offset, &v);      /* relative message id */
4413
0
    offset += get_sb4_custom(tvb, offset, &v);      /* sequence deviation */
4414
0
    start = offset;
4415
0
    offset += get_field_with_length(tvb, pinfo, offset, NULL);
4416
0
    if ( offset - start > 2 )
4417
0
      proto_tree_add_item(tree, hf_tns_data_aq_toid, tvb, offset - TNS_AQ_TOID_LEN,
4418
0
        TNS_AQ_TOID_LEN, ENC_NA);
4419
0
  }
4420
0
  return offset;
4421
0
}
4422
4423
/* Decode a two-phase commit call: a transaction switch (103) - start,
4424
 * detach - or a state change (104) - prepare, commit, abort, forget. The
4425
 * header gives an operation, the lengths of a transaction context and of
4426
 * the XID's parts, and for a switch the names; the context, the XID and
4427
 * the rest follow. The XID is padded to 128 bytes. Returns the new
4428
 * offset. */
4429
static int dissect_tns_tpc_call(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint32_t func)
4430
0
{
4431
0
  int v = 0, ctx_len = 0, gtrid_len = 0, bqual_len = 0, xid_len = 0;
4432
0
  int int_len = 0, ext_len = 0, start;
4433
0
  uint8_t ctx_ptr, xid_ptr, int_ptr = 0, ext_ptr = 0;
4434
4435
0
  start = offset;
4436
0
  offset += get_sb4_custom(tvb, offset, &v);
4437
0
  proto_tree_add_uint(tree, func == TTI_TPC_TXN_SWITCH ? hf_tns_data_tpc_switch_op : hf_tns_data_tpc_change_op,
4438
0
    tvb, start, offset - start, v);
4439
0
  col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", val_to_str_const(v,
4440
0
    func == TTI_TPC_TXN_SWITCH ? tns_tpc_switch_ops : tns_tpc_change_ops, "unknown"));
4441
0
  ctx_ptr = tvb_get_uint8(tvb, offset);
4442
0
  offset += 1;
4443
0
  offset += get_sb4_custom(tvb, offset, &ctx_len);
4444
0
  start = offset;
4445
0
  offset += get_sb4_custom(tvb, offset, &v);
4446
0
  proto_tree_add_uint(tree, hf_tns_data_tpc_format_id, tvb, start, offset - start, v);
4447
0
  offset += get_sb4_custom(tvb, offset, &gtrid_len);
4448
0
  offset += get_sb4_custom(tvb, offset, &bqual_len);
4449
0
  xid_ptr = tvb_get_uint8(tvb, offset);
4450
0
  offset += 1;
4451
0
  offset += get_sb4_custom(tvb, offset, &xid_len);
4452
0
  if ( func == TTI_TPC_TXN_SWITCH )
4453
0
  {
4454
0
    start = offset;
4455
0
    offset += get_sb4_custom(tvb, offset, &v);
4456
0
    proto_tree_add_uint(tree, hf_tns_data_tpc_flags, tvb, start, offset - start, v);
4457
0
    start = offset;
4458
0
    offset += get_sb4_custom(tvb, offset, &v);
4459
0
    proto_tree_add_uint(tree, hf_tns_data_tpc_timeout, tvb, start, offset - start, v);
4460
0
    offset += 3; /* application value, return context and its length pointers */
4461
0
    int_ptr = tvb_get_uint8(tvb, offset);
4462
0
    offset += 1;
4463
0
    offset += get_sb4_custom(tvb, offset, &int_len);
4464
0
    ext_ptr = tvb_get_uint8(tvb, offset);
4465
0
    offset += 1;
4466
0
    offset += get_sb4_custom(tvb, offset, &ext_len);
4467
0
  }
4468
0
  else
4469
0
  {
4470
0
    start = offset;
4471
0
    offset += get_sb4_custom(tvb, offset, &v);
4472
0
    proto_tree_add_uint(tree, hf_tns_data_tpc_timeout, tvb, start, offset - start, v);
4473
0
    start = offset;
4474
0
    offset += get_sb4_custom(tvb, offset, &v);
4475
0
    proto_tree_add_uint(tree, hf_tns_data_tpc_state, tvb, start, offset - start, v);
4476
0
    offset += 1; /* out state pointer */
4477
0
    start = offset;
4478
0
    offset += get_sb4_custom(tvb, offset, &v);
4479
0
    proto_tree_add_uint(tree, hf_tns_data_tpc_flags, tvb, start, offset - start, v);
4480
0
  }
4481
0
  if ( ctx_ptr && ctx_len > 0 )
4482
0
  {
4483
0
    proto_tree_add_item(tree, hf_tns_data_tpc_context, tvb, offset, ctx_len, ENC_NA);
4484
0
    offset += ctx_len;
4485
0
  }
4486
0
  if ( xid_ptr && xid_len > 0 )
4487
0
  {
4488
0
    if ( gtrid_len >= 0 && bqual_len >= 0 && gtrid_len + bqual_len <= xid_len )
4489
0
    {
4490
0
      proto_tree_add_item(tree, hf_tns_data_tpc_gtrid, tvb, offset, gtrid_len, ENC_NA);
4491
0
      proto_tree_add_item(tree, hf_tns_data_tpc_bqual, tvb, offset + gtrid_len, bqual_len, ENC_NA);
4492
0
    }
4493
0
    offset += xid_len;
4494
0
  }
4495
0
  if ( func == TTI_TPC_TXN_SWITCH )
4496
0
  {
4497
0
    start = offset;
4498
0
    offset += get_sb4_custom(tvb, offset, &v);
4499
0
    proto_tree_add_uint(tree, hf_tns_data_tpc_app_value, tvb, start, offset - start, v);
4500
0
    if ( int_ptr && int_len > 0 )
4501
0
    {
4502
0
      proto_tree_add_item(tree, hf_tns_data_tpc_internal_name, tvb, offset, int_len, ENC_UTF_8);
4503
0
      offset += int_len;
4504
0
    }
4505
0
    if ( ext_ptr && ext_len > 0 )
4506
0
    {
4507
0
      proto_tree_add_item(tree, hf_tns_data_tpc_external_name, tvb, offset, ext_len, ENC_UTF_8);
4508
0
      offset += ext_len;
4509
0
    }
4510
0
  }
4511
0
  return offset;
4512
0
}
4513
4514
/* Decode the body of a piggyback other than close-cursors. Layouts
4515
 * follow python-oracledb's _write_*_piggyback. Sets *walk when the body
4516
 * was understood, so the call behind it can be decoded. Returns the new
4517
 * offset. */
4518
static int dissect_tns_piggyback_body(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint8_t piggyback_id, bool *walk)
4519
0
{
4520
0
  int v = 0, start;
4521
0
  uint64_t u = 0;
4522
4523
0
  switch ( piggyback_id )
4524
0
  {
4525
0
    case TTI_LOBOPS:
4526
0
    {
4527
      /* close temporary LOBs: a FREE_TEMP | ARRAY LOB operation
4528
       * whose locators, each with its own ub2 length prefix, follow
4529
       * back to back - as many bytes as the total says. */
4530
0
      int total = 0, op = 0;
4531
0
      offset += 1;                                   /* pointer */
4532
0
      start = offset;
4533
0
      offset += get_sb4_custom(tvb, offset, &total);
4534
0
      proto_tree_add_uint(tree, hf_tns_data_lob_total_size, tvb, start, offset - start, total);
4535
0
      offset += 1;                                   /* dest locator pointer */
4536
0
      offset += get_sb4_custom(tvb, offset, &v);     /* dest locator length */
4537
0
      offset += get_sb4_custom(tvb, offset, &v);     /* source locator */
4538
0
      offset += get_sb4_custom(tvb, offset, &v);
4539
0
      offset += 3;                                   /* offsets, charset */
4540
0
      start = offset;
4541
0
      offset += get_sb4_custom(tvb, offset, &op);
4542
0
      proto_tree_add_uint(tree, hf_tns_data_lob_op, tvb, start, offset - start, op);
4543
0
      offset += 1;                                   /* scn */
4544
0
      offset += get_sb4_custom(tvb, offset, &v);     /* losbscn */
4545
0
      offset += get_ub8_custom(tvb, offset, &u);     /* lobscnl */
4546
0
      offset += get_ub8_custom(tvb, offset, &u);
4547
0
      offset += 1;
4548
0
      for ( int i = 0; i < 3; i++ )                   /* array LOB fields */
4549
0
      {
4550
0
        offset += 1;
4551
0
        offset += get_sb4_custom(tvb, offset, &v);
4552
0
      }
4553
0
      if ( total < 0 || (unsigned)total > tvb_reported_length_remaining(tvb, offset) )
4554
0
      {
4555
0
        proto_tree_add_expert(tree, pinfo, &ei_tns_data_count_too_large, tvb, offset, 0);
4556
0
        return offset;
4557
0
      }
4558
0
      for ( int end = offset + total; offset + 2 <= end; )
4559
0
      {
4560
0
        int len = 2 + tvb_get_ntohs(tvb, offset);
4561
0
        if ( offset + len > end )
4562
0
          len = end - offset;
4563
0
        proto_tree_add_item(tree, hf_tns_data_lob_locator, tvb, offset, len, ENC_NA);
4564
0
        offset += len;
4565
0
      }
4566
0
      break;
4567
0
    }
4568
4569
0
    case TTI_SET_SCHEMA:
4570
0
    {
4571
0
      const char *schema = NULL;
4572
0
      offset += 1;                                   /* pointer */
4573
0
      start = offset;
4574
0
      offset += get_field_with_length(tvb, pinfo, offset, &schema);
4575
0
      if ( schema )
4576
0
        proto_tree_add_string(tree, hf_tns_data_pgy_schema, tvb, start, offset - start, schema);
4577
0
      break;
4578
0
    }
4579
4580
0
    case TTI_APP_CONTEXT:
4581
0
    {
4582
      /* Set or clear an application context namespace, as
4583
       * DBMS_SESSION.SET_CONTEXT or CLEAR_CONTEXT would, without a
4584
       * round trip of its own: a pointer and the namespace's ub4
4585
       * length, a pointer and the ub4 number of attributes, a ub2
4586
       * operation (1 set, 2 clear), a zero byte from field
4587
       * version 12.1 on, the namespace, and then each attribute
4588
       * and its value in the bytes_with_length form, followed by
4589
       * a ub4 0. */
4590
0
      const char *ns = NULL;
4591
0
      unsigned fv = tns_field_version(pinfo);
4592
0
      int num = 0;
4593
0
      uint32_t op;
4594
4595
0
      offset += 1;                                   /* pointer */
4596
0
      offset += get_sb4_custom(tvb, offset, &v);     /* namespace length */
4597
0
      offset += 1;                                   /* pointer */
4598
0
      offset += get_sb4_custom(tvb, offset, &num);
4599
0
      start = offset;
4600
0
      offset += get_sb4_custom(tvb, offset, &v);
4601
0
      op = (uint32_t)v;
4602
0
      proto_tree_add_uint(tree, hf_tns_data_pgy_app_ctx_op, tvb, start, offset - start, op);
4603
      /* Without a negotiated field version, the namespace's length
4604
       * byte, never zero, tells whether the zero byte is there. */
4605
0
      if ( fv ? fv >= TNS_FV_12_1 : tvb_get_uint8(tvb, offset) == 0 )
4606
0
        offset += 1;
4607
0
      start = offset;
4608
0
      offset += get_dalc_custom(tvb, pinfo, offset, &ns);
4609
0
      if ( ns )
4610
0
      {
4611
0
        proto_tree_add_string(tree, hf_tns_data_pgy_app_ctx_namespace, tvb, start, offset - start, ns);
4612
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " [%s %s]",
4613
0
          val_to_str_const(op, tns_app_ctx_ops, "Change"), ns);
4614
0
      }
4615
0
      for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4616
0
      {
4617
0
        proto_tree *attr_tree;
4618
0
        proto_item *attr_item;
4619
0
        const char *attr = NULL, *value = NULL;
4620
0
        int attr_start = offset;
4621
4622
0
        attr_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_tns_app_ctx, &attr_item, "Context Attribute");
4623
0
        start = offset;
4624
0
        offset += get_field_with_length(tvb, pinfo, offset, &attr);
4625
0
        if ( attr )
4626
0
          proto_tree_add_string(attr_tree, hf_tns_data_pgy_app_ctx_attr, tvb, start, offset - start, attr);
4627
0
        start = offset;
4628
0
        offset += get_field_with_length(tvb, pinfo, offset, &value);
4629
0
        if ( value )
4630
0
          proto_tree_add_string(attr_tree, hf_tns_data_pgy_app_ctx_value, tvb, start, offset - start, value);
4631
0
        offset += get_sb4_custom(tvb, offset, &v);
4632
0
        proto_item_append_text(attr_item, ": %s = %s", attr ? attr : "", value ? value : "");
4633
0
        proto_item_set_len(attr_item, offset - attr_start);
4634
0
      }
4635
0
      break;
4636
0
    }
4637
4638
0
    case TTI_ALTER_SESSION:
4639
0
    {
4640
      /* Change session parameters, as ALTER SESSION would, without
4641
       * a round trip of its own - a 23ai client sets its
4642
       * transaction priority (TXN_PRIORITY) this way: a ub4 of
4643
       * flags, a pointer and the ub4 number of parameters, then
4644
       * each parameter and its value in the bytes_with_length form
4645
       * and a ub4 flag, 1 when the value is empty to restore the
4646
       * database default. */
4647
0
      int num = 0;
4648
4649
0
      offset += get_sb4_custom(tvb, offset, &v);     /* flags */
4650
0
      offset += 1;                                   /* pointer */
4651
0
      offset += get_sb4_custom(tvb, offset, &num);
4652
0
      for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4653
0
      {
4654
0
        proto_tree *par_tree;
4655
0
        proto_item *par_item;
4656
0
        const char *param = NULL, *value = NULL;
4657
0
        int par_start = offset;
4658
4659
0
        par_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_tns_alter_session, &par_item, "Session Parameter");
4660
0
        start = offset;
4661
0
        offset += get_field_with_length(tvb, pinfo, offset, &param);
4662
0
        if ( param )
4663
0
          proto_tree_add_string(par_tree, hf_tns_data_pgy_alter_param, tvb, start, offset - start, param);
4664
0
        start = offset;
4665
0
        offset += get_field_with_length(tvb, pinfo, offset, &value);
4666
0
        proto_tree_add_string(par_tree, hf_tns_data_pgy_alter_value, tvb, start, offset - start, value ? value : "");
4667
0
        offset += get_sb4_custom(tvb, offset, &v);
4668
0
        proto_item_append_text(par_item, ": %s = %s", param ? param : "", value ? value : "(default)");
4669
0
        proto_item_set_len(par_item, offset - par_start);
4670
0
        if ( param )
4671
0
          col_append_fstr(pinfo->cinfo, COL_INFO, " [%s=%s]", param, value ? value : "default");
4672
0
      }
4673
0
      break;
4674
0
    }
4675
4676
0
    case TTI_SESSION_STATE:
4677
0
      start = offset;
4678
0
      offset += get_ub8_custom(tvb, offset, &u);
4679
0
      proto_tree_add_uint64(tree, hf_tns_data_pgy_session_state, tvb, start, offset - start, u);
4680
0
      break;
4681
4682
0
    case TTI_PIPELINE_BEGIN:
4683
0
      start = offset;
4684
0
      offset += get_sb4_custom(tvb, offset, &v);
4685
0
      proto_tree_add_uint(tree, hf_tns_data_pgy_error_set_id, tvb, start, offset - start, v);
4686
0
      proto_tree_add_item(tree, hf_tns_data_pgy_error_set_mode, tvb, offset, 1, ENC_NA);
4687
0
      offset += 1;
4688
0
      proto_tree_add_item(tree, hf_tns_data_pgy_pipeline_mode, tvb, offset, 1, ENC_NA);
4689
0
      offset += 1;
4690
0
      break;
4691
4692
0
    case TTI_SET_END_TO_END_ATTR:
4693
0
    {
4694
      /* End-to-end attributes: a flags word saying which changed,
4695
       * then a (pointer, length) header for each attribute - some
4696
       * never used - and finally the strings of those that have a
4697
       * value, in the same order. */
4698
0
      static int * const hfs[] = { &hf_tns_data_pgy_client_id, &hf_tns_data_pgy_module,
4699
0
        &hf_tns_data_pgy_action, NULL, &hf_tns_data_pgy_client_info, NULL, NULL,
4700
0
        &hf_tns_data_pgy_dbop };
4701
0
      int lens[array_length(hfs)];
4702
4703
0
      offset += 2;                                   /* cidnam, cidser pointers */
4704
0
      start = offset;
4705
0
      offset += get_sb4_custom(tvb, offset, &v);
4706
0
      proto_tree_add_uint(tree, hf_tns_data_pgy_e2e_flags, tvb, start, offset - start, v);
4707
0
      for ( unsigned i = 0; i < array_length(hfs); i++ )
4708
0
      {
4709
0
        uint8_t ptr = tvb_get_uint8(tvb, offset);
4710
0
        offset += 1;
4711
0
        offset += get_sb4_custom(tvb, offset, &lens[i]);
4712
0
        if ( !ptr || !hfs[i] )
4713
0
          lens[i] = 0;
4714
0
        if ( i == 3 )                                /* cideci is followed by cidcct, cidecs */
4715
0
        {
4716
0
          offset += 1;
4717
0
          offset += get_sb4_custom(tvb, offset, &v);
4718
0
        }
4719
0
      }
4720
0
      for ( unsigned i = 0; i < array_length(hfs); i++ )
4721
0
      {
4722
0
        const char *str = NULL;
4723
0
        if ( lens[i] <= 0 )
4724
0
          continue;
4725
0
        start = offset;
4726
0
        offset += get_dalc_custom(tvb, pinfo, offset, &str);
4727
0
        if ( str )
4728
0
          proto_tree_add_string(tree, *hfs[i], tvb, start, offset - start, str);
4729
0
      }
4730
0
      break;
4731
0
    }
4732
4733
0
    case TTI_END_USER_SEC_CTX:
4734
0
    {
4735
      /* End-user security context: flags, then key/value pairs, each
4736
       * a flags word and a key, a text and a value in the
4737
       * bytes_with_length form. */
4738
0
      int num = 0;
4739
0
      start = offset;
4740
0
      offset += get_sb4_custom(tvb, offset, &v);
4741
0
      proto_tree_add_uint(tree, hf_tns_data_pgy_sec_flags, tvb, start, offset - start, v);
4742
0
      offset += 1;                                   /* pointer */
4743
0
      offset += get_sb4_custom(tvb, offset, &num);
4744
0
      for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
4745
0
      {
4746
0
        const char *key = NULL;
4747
0
        offset += get_sb4_custom(tvb, offset, &v); /* flags */
4748
0
        start = offset;
4749
0
        offset += get_field_with_length(tvb, pinfo, offset, &key);
4750
0
        if ( key )
4751
0
          proto_tree_add_string(tree, hf_tns_data_pgy_sec_key, tvb, start, offset - start, key);
4752
0
        offset += get_field_with_length(tvb, pinfo, offset, NULL); /* text */
4753
0
        start = offset;
4754
0
        offset += get_field_with_length(tvb, pinfo, offset, NULL);
4755
0
        proto_tree_add_item(tree, hf_tns_data_pgy_sec_value, tvb, start, offset - start, ENC_NA);
4756
0
      }
4757
0
      break;
4758
0
    }
4759
4760
0
    default:
4761
      /* An unknown body has an unknown length. */
4762
0
      return offset;
4763
0
  }
4764
0
  *walk = true;
4765
0
  return offset;
4766
0
}
4767
4768
static void dissect_tns_data_descriptor(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tns_tree, uint32_t length)
4769
1
{
4770
  /* This is used by Oracle 12c for at least sending LOB/FILE data. */
4771
1
  proto_tree *dd_tree, *row_tree;
4772
1
  proto_item *ti;
4773
1
  uint32_t data_len, row_count, row_size, total_row_size = 0;
4774
1
  int orig_offset = offset;
4775
4776
  /* We only get here after tcp_dissect_pdus(), length is guaranteed. */
4777
1
  DISSECTOR_ASSERT_CMPINT(length, >=, TNS_HDR_LEN);
4778
4779
1
  dd_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL, "Data Descriptor");
4780
4781
  /* No idea what this is. Usually 0x0003. */
4782
1
  offset += 4;
4783
1
  proto_tree_add_item_ret_uint(dd_tree, hf_tns_data_length, tvb,
4784
1
      offset, 4, ENC_BIG_ENDIAN, &data_len);
4785
1
  offset += 4;
4786
4787
  /* This next parameter looks like: number of big endian shorts that follow,
4788
   * the sum of the shorts equals the file length above - each short maxes
4789
   * out at 0x1f7c = 8060, presumably related to the page size / max table
4790
   * row size in Microsoft SQL Server? Something about how many rows it
4791
   * would take to store this in-table?
4792
   */
4793
1
  proto_tree_add_item_ret_uint(dd_tree, hf_tns_data_descriptor_row_count, tvb,
4794
1
      offset, 4, ENC_BIG_ENDIAN, &row_count);
4795
1
  offset += 4;
4796
1
  row_tree = proto_tree_add_subtree(dd_tree, tvb, offset, row_count * 2,
4797
1
    ett_tns_rows, &ti, "Rows");
4798
44
  for (uint32_t i = 0; i < row_count; i++) {
4799
43
    proto_tree_add_item_ret_uint(row_tree, hf_tns_data_descriptor_row_size, tvb,
4800
43
        offset, 2, ENC_BIG_ENDIAN, &row_size);
4801
43
    total_row_size += row_size;
4802
43
    offset += 2;
4803
43
  }
4804
1
  proto_item_append_text(ti, " (%u bytes)", total_row_size);
4805
1
  if (total_row_size != data_len) {
4806
0
    expert_add_info(pinfo, ti, &ei_tns_data_descriptor_size_mismatch);
4807
0
  }
4808
4809
1
  offset = orig_offset + (length - TNS_HDR_LEN);
4810
4811
1
  call_data_dissector(tvb_new_subset_length(tvb, offset, data_len), pinfo,
4812
1
      dd_tree);
4813
1
}
4814
4815
/* State carried from one TTC message to the next within a packet. */
4816
typedef struct _tns_msg_ctx_t {
4817
  /* The decoder ended exactly on its message's last byte. */
4818
  bool walk;
4819
  /* Which columns the next row sends, from a row header or a TTI_BVC:
4820
   * a clear bit means the value repeats the previous row's. NULL when
4821
   * every column is sent. */
4822
  const uint8_t *bit_vector;
4823
  unsigned bit_vector_len;
4824
  /* After a TTI_IOV: the call it answers and each bind's direction, so
4825
   * the TTI_RXD after it can be read as the OUT bind values. */
4826
  const tns_call_t *out_call;
4827
  const uint8_t *bind_dirs;
4828
  /* The call inside a fast-authentication bundle carries no token,
4829
   * whatever field version the connection ends up with. */
4830
  bool no_token;
4831
} tns_msg_ctx_t;
4832
4833
static int dissect_tns_message(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *data_tree, bool is_request, unsigned data_func_id, tns_msg_ctx_t *ctx);
4834
4835
static bool tns_is_oci(packet_info *pinfo);
4836
4837
/* Whether a message that follows another in the same packet is one we
4838
 * step into. A response is a run of messages back to back - a describe,
4839
 * a row header, the rows, a status - and a request may put piggybacks in
4840
 * front of its call. */
4841
static bool tns_is_next_message(packet_info *pinfo, unsigned data_func_id, bool is_request)
4842
0
{
4843
0
  if ( is_request )
4844
0
    return data_func_id == SQLNET_USER_OCI_FUNC || data_func_id == SQLNET_PIGGYBACK_FUNC
4845
0
      || data_func_id == SQLNET_SET_DATATYPES;
4846
4847
0
  switch ( data_func_id )
4848
0
  {
4849
0
    case SQLNET_RETURN_STATUS:
4850
0
    case SQLNET_SET_DATATYPES:
4851
0
    case SQLNET_FLUSH_BIND_DATA:
4852
0
    case SQLNET_FUNCCOMPLETE:
4853
0
    case SQLNET_WARNING:
4854
0
    case SQLNET_LOB_FILE_DF:
4855
0
    case SQLNET_BIT_VECTOR:
4856
0
    case SQLNET_SERVER_PIGGYBACK:
4857
0
    case SQLNET_IMPLICIT_RESULTS:
4858
0
    case SQLNET_TOKEN:
4859
0
    case SQLNET_END_OF_RESPONSE:
4860
0
    case SQLNET_ROW_TRANSF_HDR:
4861
0
    case SQLNET_ROW_TRANSF_DATA:
4862
0
    case SQLNET_RETURN_OPI_PARAM:
4863
0
    case SQLNET_IOVEC_4FAST_UPI:
4864
0
    case SQLNET_DESCRIBE_INFO:
4865
0
      return true;
4866
0
    case SQLNET_INVOKE_USER_CB:
4867
      /* a record of an OCI client's TTI_KOD reply */
4868
0
      return tns_is_oci(pinfo);
4869
0
    default:
4870
0
      return false;
4871
0
  }
4872
0
}
4873
4874
static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tns_tree)
4875
0
{
4876
0
  proto_tree *data_tree;
4877
0
  unsigned data_func_id;
4878
0
  bool is_request;
4879
0
  static int * const flags[] = {
4880
0
    &hf_tns_data_flag_send,
4881
0
    &hf_tns_data_flag_rc,
4882
0
    &hf_tns_data_flag_c,
4883
0
    &hf_tns_data_flag_reserved,
4884
0
    &hf_tns_data_flag_more,
4885
0
    &hf_tns_data_flag_eof,
4886
0
    &hf_tns_data_flag_dic,
4887
0
    &hf_tns_data_flag_rts,
4888
0
    &hf_tns_data_flag_sntt,
4889
0
    &hf_tns_data_flag_end_of_request,
4890
0
    &hf_tns_data_flag_begin_pipeline,
4891
0
    &hf_tns_data_flag_end_of_response,
4892
0
    NULL
4893
0
  };
4894
4895
0
  is_request = pinfo->match_uint == pinfo->destport;
4896
0
  data_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1, ett_tns_data, NULL, "Data");
4897
4898
0
  proto_tree_add_bitmask(data_tree, tvb, offset, hf_tns_data_flag, ett_tns_data_flag, flags, ENC_BIG_ENDIAN);
4899
0
  offset += 2;
4900
0
  data_func_id = get_data_func_id(tvb, offset);
4901
4902
  /* Once native network encryption is on, a data packet is ciphertext
4903
   * followed by a padding and a key-fold byte; nothing in it can be
4904
   * decoded without the session key. */
4905
0
  if ( tns_is_encrypted(pinfo) && data_func_id != SQLNET_SNS )
4906
0
  {
4907
0
    col_append_str(pinfo->cinfo, COL_INFO, ", Encrypted Data");
4908
0
    proto_tree_add_expert(data_tree, pinfo, &ei_tns_data_encrypted, tvb, offset, tvb_reported_length_remaining(tvb, offset));
4909
0
    call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, data_tree);
4910
0
    return;
4911
0
  }
4912
4913
  /* The field version the connection negotiated decides the shape of
4914
   * several messages; show the one in force. */
4915
0
  unsigned fv = tns_field_version(pinfo);
4916
0
  if ( fv )
4917
0
    proto_item_set_generated(proto_tree_add_uint(data_tree, hf_tns_data_field_version, tvb, 0, 0, fv));
4918
4919
  /* Do this only if the Data message have a body. Otherwise, there are only Data flags. */
4920
0
  int remaining = tvb_reported_length_remaining(tvb, offset);
4921
0
  if ( remaining > 0 )
4922
0
  {
4923
0
    if (is_request) {
4924
0
      if (!PINFO_FD_VISITED(pinfo)) {
4925
0
        tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
4926
0
        if ((uint32_t)remaining == tns_info->pending_connect_data) {
4927
0
          col_append_str(pinfo->cinfo, COL_INFO, ", Connect Data");
4928
0
          proto_tree_add_item(data_tree, hf_tns_connect_data, tvb,
4929
0
            offset, -1, ENC_ASCII);
4930
0
          p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, 0,
4931
0
            GUINT_TO_POINTER(tns_info->pending_connect_data));
4932
0
          tns_info->pending_connect_data = 0;
4933
0
          return;
4934
0
        }
4935
0
      } else {
4936
0
        if (p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, 0) != NULL) {
4937
0
          col_append_str(pinfo->cinfo, COL_INFO, ", Connect Data");
4938
0
          proto_tree_add_item(data_tree, hf_tns_connect_data, tvb,
4939
0
            offset, -1, ENC_ASCII);
4940
0
          return;
4941
0
        }
4942
0
      }
4943
0
    }
4944
0
    col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(data_func_id, tns_data_funcs, "unknown"));
4945
4946
0
    if ( (data_func_id != SQLNET_SNS) && (try_val_to_str(data_func_id, tns_data_funcs) != NULL) )
4947
0
    {
4948
0
      proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 1, ENC_BIG_ENDIAN);
4949
0
      offset += 1;
4950
0
    }
4951
0
  }
4952
4953
  /* Decode the first message, then step into each one after it for as
4954
   * long as the previous decoder ended exactly on its last byte. */
4955
0
  tns_msg_ctx_t ctx = { 0 };
4956
0
  offset = dissect_tns_message(tvb, offset, pinfo, data_tree, is_request, data_func_id, &ctx);
4957
0
  while ( ctx.walk && tvb_reported_length_remaining(tvb, offset) > 0 )
4958
0
  {
4959
0
    data_func_id = tvb_get_uint8(tvb, offset);
4960
0
    if ( !tns_is_next_message(pinfo, data_func_id, is_request) )
4961
0
      break;
4962
0
    col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str_const(data_func_id, tns_data_funcs, "unknown"));
4963
0
    proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 1, ENC_BIG_ENDIAN);
4964
0
    offset += 1;
4965
0
    ctx.walk = false;
4966
0
    offset = dissect_tns_message(tvb, offset, pinfo, data_tree, is_request, data_func_id, &ctx);
4967
0
  }
4968
4969
0
  if ( tvb_reported_length_remaining(tvb, offset) > 0 )
4970
0
    call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo, data_tree);
4971
0
}
4972
4973
/* Whether the length byte in front of an OCI execute's SQL agrees with
4974
 * the SQL length its preamble declares. A client in AL32UTF8, the
4975
 * database's own character set, declares the SQL's byte length; one in
4976
 * any other set declares three times it, a conversion buffer's worth.
4977
 * The length byte is the byte length either way, or 0xFE for chunked
4978
 * text. */
4979
static bool tns_oci_sql_length_matches(uint8_t prefix, uint32_t declared)
4980
0
{
4981
0
  return prefix == 0xfe || prefix == declared || (uint32_t)prefix * 3 == declared;
4982
0
}
4983
4984
/* Whether a packet belongs to a conversation whose client speaks the OCI
4985
 * dialect. Stored per packet on the first pass. */
4986
static bool tns_is_oci(packet_info *pinfo)
4987
0
{
4988
0
  void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_OCI);
4989
0
  if ( stored || PINFO_FD_VISITED(pinfo) )
4990
0
    return GPOINTER_TO_UINT(stored) == 2;
4991
4992
0
  bool oci = tns_get_conv_info(pinfo)->oci_dialect;
4993
0
  p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_OCI, GUINT_TO_POINTER(oci ? 2 : 1));
4994
0
  return oci;
4995
0
}
4996
4997
/* Whether an OCI client's session has been seen at the 12c band. Stored
4998
 * per packet on the first pass. */
4999
static bool tns_is_oci_12c(packet_info *pinfo)
5000
0
{
5001
0
  void *stored = p_get_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_OCI_12C);
5002
0
  if ( stored || PINFO_FD_VISITED(pinfo) )
5003
0
    return GPOINTER_TO_UINT(stored) == 2;
5004
5005
0
  bool band = tns_get_conv_info(pinfo)->oci_band_12c;
5006
0
  p_add_proto_data(wmem_file_scope(), pinfo, proto_tns, TNS_PROTO_DATA_OCI_12C, GUINT_TO_POINTER(band ? 2 : 1));
5007
0
  return band;
5008
0
}
5009
5010
/* A REF in a TTI_KOD message: a ub4 LE length, then the REF itself - a
5011
 * ub2 LE length, three flag bytes, the 16-byte object id and 15 bytes
5012
 * more. Adds the object id as hf. An id of 15 zero bytes and one more is
5013
 * a system type's; *sys_type, when not NULL, gets that last byte, or 0.
5014
 * Returns the offset past the REF. */
5015
static int dissect_tns_kod_ref(tvbuff_t *tvb, proto_tree *tree, int offset, int hf, int *sys_type)
5016
0
{
5017
0
  uint32_t len = tvb_get_letohl(tvb, offset);
5018
5019
0
  if ( sys_type )
5020
0
    *sys_type = 0;
5021
0
  tvb_ensure_bytes_exist(tvb, offset + 4, (int)MIN(len, INT_MAX));
5022
0
  if ( len < 21 )
5023
0
    return offset + 4 + len;
5024
0
  proto_tree_add_item(tree, hf, tvb, offset + 9, 16, ENC_NA);
5025
0
  if ( sys_type && tvb_skip_uint8(tvb, offset + 9, 15, 0) == (unsigned)(offset + 24) )
5026
0
  {
5027
0
    *sys_type = tvb_get_uint8(tvb, offset + 24);
5028
0
    proto_item_set_generated(proto_tree_add_uint(tree, hf_tns_data_kod_system_type, tvb, offset + 24, 1, *sys_type));
5029
0
  }
5030
0
  return offset + 4 + len;
5031
0
}
5032
5033
/* A TEXT in a TTI_KOD reply: a ub4 LE count, then, unless it is zero, a
5034
 * length byte and the text. Returns the offset past it. */
5035
static int dissect_tns_kod_text(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int hf, const char **out)
5036
0
{
5037
0
  uint8_t len;
5038
5039
0
  *out = NULL;
5040
0
  if ( tvb_get_letohl(tvb, offset) == 0 )
5041
0
    return offset + 4;
5042
0
  len = tvb_get_uint8(tvb, offset + 4);
5043
0
  proto_tree_add_item_ret_string(tree, hf, tvb, offset + 5, len, ENC_UTF_8, pinfo->pool, (const uint8_t **)out);
5044
0
  return offset + 5 + len;
5045
0
}
5046
5047
/* The image of a type descriptor in a TTI_KOD record: a DALC, chunked in
5048
 * single-byte lengths when long. The image is a pickled object - 85 01
5049
 * fe and a ub4 BE length, then one value per attribute: a length byte,
5050
 * fe and a ub4 BE length, or ff for NULL. An instance of SYS.KOTTD
5051
 * describes a type, and its attributes 1 to 4 are the type's schema,
5052
 * name, version and a ub2 BE typecode. Returns the offset past the
5053
 * image. */
5054
static int dissect_tns_kod_image(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int sys_type)
5055
0
{
5056
0
  wmem_array_t *buf = wmem_array_new(pinfo->pool, 1);
5057
0
  uint8_t first = tvb_get_uint8(tvb, offset);
5058
0
  const char *schema = NULL, *name = NULL;
5059
0
  const uint8_t *img;
5060
0
  int start = offset, base = -1, len, pos;
5061
5062
0
  if ( first == 0xfe )
5063
0
  {
5064
0
    offset += 1;
5065
0
    for ( uint8_t n = tvb_get_uint8(tvb, offset++); n > 0; n = tvb_get_uint8(tvb, offset++) )
5066
0
    {
5067
0
      wmem_array_append(buf, tvb_get_ptr(tvb, offset, n), n);
5068
0
      offset += n;
5069
0
    }
5070
0
  }
5071
0
  else if ( first < TNS_DALC_ABSENT )
5072
0
  {
5073
    /* in place: an attribute's bytes can be pointed at */
5074
0
    base = offset + 1;
5075
0
    wmem_array_append(buf, tvb_get_ptr(tvb, base, first), first);
5076
0
    offset = base + first;
5077
0
  }
5078
0
  else
5079
0
    return offset + get_dalc_custom(tvb, pinfo, offset, NULL);
5080
5081
0
  img = (const uint8_t *)wmem_array_get_raw(buf);
5082
0
  len = (int)wmem_array_get_count(buf);
5083
0
  proto_tree_add_bytes_with_length(tree, hf_tns_data_kod_image, tvb, start, offset - start, img, len);
5084
0
  if ( sys_type != TNS_KOD_KOTTD || len < 7 || img[0] != 0x85 || img[2] != 0xfe )
5085
0
    return offset;
5086
5087
0
  pos = 7;
5088
0
  for ( int attr = 0; attr <= 4 && pos < len; attr++ )
5089
0
  {
5090
0
    uint32_t alen = img[pos++];
5091
0
    int item_start = start, item_len = offset - start;
5092
5093
0
    if ( alen == 0xff )
5094
0
      continue;
5095
0
    if ( alen == 0xfe )
5096
0
    {
5097
0
      if ( len - pos < 4 )
5098
0
        break;
5099
0
      alen = pntohu32(img + pos);
5100
0
      pos += 4;
5101
0
    }
5102
0
    if ( alen > (uint32_t)(len - pos) )
5103
0
      break;
5104
0
    if ( base >= 0 )
5105
0
    {
5106
0
      item_start = base + pos;
5107
0
      item_len = (int)alen;
5108
0
    }
5109
0
    switch ( attr )
5110
0
    {
5111
0
      case 1:
5112
0
        schema = (const char *)get_utf_8_string(pinfo->pool, img + pos, (int)alen);
5113
0
        proto_tree_add_string(tree, hf_tns_data_kod_schema, tvb, item_start, item_len, schema);
5114
0
        break;
5115
0
      case 2:
5116
0
        name = (const char *)get_utf_8_string(pinfo->pool, img + pos, (int)alen);
5117
0
        proto_tree_add_string(tree, hf_tns_data_kod_name, tvb, item_start, item_len, name);
5118
0
        break;
5119
0
      case 3:
5120
0
        proto_tree_add_string(tree, hf_tns_data_kod_version, tvb, item_start, item_len,
5121
0
          (const char *)get_utf_8_string(pinfo->pool, img + pos, (int)alen));
5122
0
        break;
5123
0
      case 4:
5124
0
        if ( alen == 2 )
5125
0
          proto_tree_add_uint(tree, hf_tns_data_kod_typecode, tvb, item_start, item_len, pntohu16(img + pos));
5126
0
        break;
5127
0
      default:
5128
0
        break;
5129
0
    }
5130
0
    pos += (int)alen;
5131
0
  }
5132
0
  if ( name )
5133
0
    col_append_fstr(pinfo->cinfo, COL_INFO, " [%s%s%s]", schema ? schema : "", schema ? "." : "", name);
5134
0
  return offset;
5135
0
}
5136
5137
/* The 11-byte time zone block of an OCI client's data-type round, in the
5138
 * request and the reply alike: the hours, minutes and seconds of the
5139
 * offset from UTC at bytes 4 to 6, each biased by 60. Returns the offset
5140
 * past it. */
5141
static int dissect_tns_dty_tz(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
5142
0
{
5143
0
  int h, m, sec;
5144
0
  bool negative;
5145
5146
0
  proto_tree_add_item(tree, hf_tns_data_setdt_tz, tvb, offset, 11, ENC_NA);
5147
0
  h = tvb_get_uint8(tvb, offset + 4) - 60;
5148
0
  m = tvb_get_uint8(tvb, offset + 5) - 60;
5149
0
  sec = tvb_get_uint8(tvb, offset + 6) - 60;
5150
0
  negative = h < 0 || m < 0 || sec < 0;
5151
0
  proto_item_set_generated(proto_tree_add_string(tree, hf_tns_data_setdt_tz_offset, tvb, offset + 4, 3,
5152
0
    wmem_strdup_printf(pinfo->pool, "%c%02d:%02d:%02d", negative ? '-' : '+', abs(h), abs(m), abs(sec))));
5153
0
  return offset + 11;
5154
0
}
5155
5156
/* Read the error text after an OCI status block: a length byte for up to
5157
 * 252 bytes, else 0xFE and chunks until a zero length. The chunk lengths
5158
 * are single bytes from an 11g server and ub4 LE from an 18c one, and
5159
 * which a server sends is not its field version but a capability not yet
5160
 * identified. The text holds no zero bytes and a message never runs to
5161
 * 64K, so the two zero high bytes of a ub4 LE length tell it from a ub1
5162
 * length followed by text. Returns the bytes consumed; *out_str gets the
5163
 * text, or NULL. */
5164
static int tns_oci_error_text(tvbuff_t *tvb, packet_info *pinfo, int offset, const char **out_str)
5165
0
{
5166
0
  wmem_strbuf_t *strbuf;
5167
0
  bool ub4_lengths;
5168
0
  int o;
5169
5170
0
  if ( tvb_get_uint8(tvb, offset) != 0xfe )
5171
0
    return get_dalc_custom(tvb, pinfo, offset, out_str);
5172
5173
0
  ub4_lengths = tvb_bytes_exist(tvb, offset + 1, 4) && tvb_get_letohs(tvb, offset + 3) == 0;
5174
0
  strbuf = wmem_strbuf_new(pinfo->pool, "");
5175
0
  o = offset + 1;
5176
0
  while ( tvb_reported_length_remaining(tvb, o) > 0 )
5177
0
  {
5178
0
    int chunk_len;
5179
0
    if ( ub4_lengths )
5180
0
    {
5181
0
      chunk_len = (int)MIN(tvb_get_letohl(tvb, o), INT_MAX);
5182
0
      o += 4;
5183
0
    }
5184
0
    else
5185
0
    {
5186
0
      chunk_len = tvb_get_uint8(tvb, o);
5187
0
      o += 1;
5188
0
    }
5189
0
    if ( chunk_len == 0 )
5190
0
      break;
5191
0
    wmem_strbuf_append(strbuf, (const char *)tvb_get_string_enc(pinfo->pool, tvb, o, chunk_len, ENC_UTF_8|ENC_NA));
5192
0
    o += chunk_len;
5193
0
  }
5194
0
  *out_str = wmem_strbuf_get_str(strbuf);
5195
0
  return o - offset;
5196
0
}
5197
5198
/* Decode a REF CURSOR OUT value as a server sends it to an OCI client: a
5199
 * lead byte (0x4c, from a 10g server 0x3c), the describe of the cursor's
5200
 * result set and its trailer, the ub4 cursor id the client then executes
5201
 * to fetch the rows, and the ub2 return code. The describe is read once to
5202
 * size the item and again to show it. Returns the new offset. */
5203
static int dissect_tns_oci_refcursor_out(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, uint32_t idx)
5204
0
{
5205
0
  unsigned fv = tns_field_version(pinfo);
5206
0
  bool band_12c = fv ? fv >= TNS_FV_12_1 : tns_is_oci_12c(pinfo);
5207
0
  bool fv_11_2 = !fv || fv >= TNS_FV_11_2;
5208
0
  proto_item *ci;
5209
0
  proto_tree *ct;
5210
0
  uint32_t cursor;
5211
0
  int end;
5212
5213
0
  end = dissect_tns_oci_describe_body(tvb, pinfo, NULL, offset + 1, band_12c, fv_11_2);
5214
0
  cursor = tvb_get_letohl(tvb, end);
5215
0
  end += 4 + 2;
5216
  /* a cursor the block left unopened, or closed, has no columns */
5217
0
  if ( tvb_get_letohl(tvb, offset + 1 + 4) == 0 )
5218
0
    ci = proto_tree_add_bytes_format(tree, hf_tns_data_bind_value, tvb, offset, end - offset, NULL,
5219
0
      "Bind %u (REFCURSOR): not open", idx);
5220
0
  else
5221
0
    ci = proto_tree_add_bytes_format(tree, hf_tns_data_bind_value, tvb, offset, end - offset, NULL,
5222
0
      "Bind %u (REFCURSOR): cursor %u", idx, cursor);
5223
0
  ct = proto_item_add_subtree(ci, ett_tns_value);
5224
0
  offset = dissect_tns_oci_describe_body(tvb, pinfo, ct, offset + 1, band_12c, fv_11_2);
5225
0
  proto_tree_add_item(ct, hf_tns_cursor, tvb, offset, 4, ENC_LITTLE_ENDIAN);
5226
0
  offset += 4;
5227
0
  proto_tree_add_item(ct, hf_tns_data_bind_oci_return_code, tvb, offset, 2, ENC_LITTLE_ENDIAN);
5228
0
  return offset + 2;
5229
0
}
5230
5231
/* Decode a server message to an OCI client. Its integers are fixed-width
5232
 * little-endian, so only the status messages, whose layout is known, are
5233
 * decoded; the rest is left to the data dissector. Returns the new
5234
 * offset. */
5235
static int dissect_tns_oci_message(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *data_tree, unsigned data_func_id, tns_msg_ctx_t *ctx)
5236
0
{
5237
0
  switch ( data_func_id )
5238
0
  {
5239
0
    case SQLNET_SET_DATATYPES:
5240
      /* The answer to an OCI client's data-type round: the
5241
       * database's time zone block and, when the client sent one,
5242
       * the timezone file version as a ub4 BE. */
5243
0
      if ( !tvb_bytes_exist(tvb, offset, 11) )
5244
0
        return offset;
5245
0
      offset = dissect_tns_dty_tz(tvb, pinfo, data_tree, offset);
5246
0
      if ( tvb_bytes_exist(tvb, offset, 4) )
5247
0
      {
5248
0
        proto_tree_add_item(data_tree, hf_tns_data_setdt_tzfile, tvb, offset, 4, ENC_BIG_ENDIAN);
5249
0
        offset += 4;
5250
0
      }
5251
0
      return offset;
5252
5253
0
    case SQLNET_INVOKE_USER_CB:
5254
0
    {
5255
      /* A message of a TTI_KOD reply: a by-name reply's header,
5256
       * then a record per type descriptor, then the status. A
5257
       * TEXT is a ub4 count, a length byte and the text. The
5258
       * header: a ub4 2, the schema (the connected user's, even
5259
       * for a SYS type), a ub4 0, the name, a byte, the REF of the
5260
       * type and 01 00, with four zero bytes more at the 12c band.
5261
       * A record: the REF of the system type the descriptor is an
5262
       * instance of, a byte, the REF of the type described, a
5263
       * byte, a 24-byte descriptor behind a ub4 length (a bare 35
5264
       * bytes at the 12c band), 00 01 00, the image's ub4 length,
5265
       * 09 00, and the image. */
5266
0
      tns_call_t *call = tns_answered_call(pinfo);
5267
0
      proto_tree *kod_tree;
5268
0
      proto_item *kod_item;
5269
0
      const char *schema, *name;
5270
0
      int start = offset - 1, sys_type;
5271
0
      uint8_t kind;
5272
5273
0
      if ( !call || call->func != TTI_KOD )
5274
0
        return offset;
5275
0
      kind = tvb_get_uint8(tvb, offset);
5276
0
      kod_tree = proto_tree_add_subtree(data_tree, tvb, start, -1, ett_tns_kod, &kod_item,
5277
0
        kind == TNS_KOD_HEADER ? "Object Type Header" : "Object Type Record");
5278
0
      proto_tree_add_item(kod_tree, hf_tns_data_kod_kind, tvb, offset, 1, ENC_NA);
5279
0
      col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str_const(kind, tns_kod_kinds, "unknown"));
5280
0
      offset += 1;
5281
0
      if ( kind == TNS_KOD_HEADER )
5282
0
      {
5283
0
        offset += 4;
5284
0
        offset = dissect_tns_kod_text(tvb, pinfo, kod_tree, offset, hf_tns_data_kod_schema, &schema);
5285
0
        offset += 4;
5286
0
        offset = dissect_tns_kod_text(tvb, pinfo, kod_tree, offset, hf_tns_data_kod_name, &name);
5287
0
        offset += 1;
5288
0
        offset = dissect_tns_kod_ref(tvb, kod_tree, offset, hf_tns_data_kod_oid, NULL);
5289
0
        offset += tvb_bytes_exist(tvb, offset + 2, 1) && tvb_get_uint8(tvb, offset + 2) == 0 ? 6 : 2;
5290
0
        if ( name )
5291
0
          col_append_fstr(pinfo->cinfo, COL_INFO, " [%s%s%s]", schema ? schema : "", schema ? "." : "", name);
5292
0
      }
5293
0
      else if ( kind == TNS_KOD_RECORD )
5294
0
      {
5295
0
        offset = dissect_tns_kod_ref(tvb, kod_tree, offset, hf_tns_data_kod_type_oid, &sys_type);
5296
0
        offset += 1;
5297
0
        offset = dissect_tns_kod_ref(tvb, kod_tree, offset, hf_tns_data_kod_oid, NULL);
5298
0
        offset += 1;
5299
0
        offset += tvb_get_letohl(tvb, offset) == 24 ? 4 + 24 : 35;
5300
0
        offset += 3 + 4 + 2;
5301
0
        offset = dissect_tns_kod_image(tvb, pinfo, kod_tree, offset, sys_type);
5302
0
      }
5303
0
      else
5304
0
        return offset;
5305
0
      proto_item_set_len(kod_item, offset - start);
5306
0
      ctx->walk = true;
5307
0
      return offset;
5308
0
    }
5309
5310
0
    case SQLNET_IOVEC_4FAST_UPI:
5311
0
    {
5312
      /* TTI_IOV, answering a PL/SQL block with OUT binds: a
5313
       * 50-byte header, counting the message id, with the bind
5314
       * count in its fifth byte and the rest constants and the
5315
       * instance's state; one direction byte per bind, as thin
5316
       * has them; then a TTI_RXD row of the OUT and IN OUT values
5317
       * in bind order, typed by the execute this answers: an IN
5318
       * bind has none. A scalar is a value as
5319
       * the client binds it, then a ub2 return code; a REF CURSOR
5320
       * comes in its own form. A LOB's and an object's are not
5321
       * decoded, and the row stops there. */
5322
0
      const tns_call_t *call = tns_answered_call(pinfo);
5323
0
      proto_tree *dir_tree, *ob_tree;
5324
0
      proto_item *ob_item;
5325
0
      int dirs = offset - 1 + TNS_OCI_IOV_HEADER_LEN, start;
5326
0
      uint32_t num_binds;
5327
0
      bool stop = false;
5328
5329
0
      if ( !tvb_bytes_exist(tvb, offset - 1 + TNS_OCI_IOV_BIND_COUNT, 1) )
5330
0
        return offset;
5331
0
      proto_tree_add_item_ret_uint(data_tree, hf_tns_data_iov_num_binds, tvb,
5332
0
        offset - 1 + TNS_OCI_IOV_BIND_COUNT, 1, ENC_NA, &num_binds);
5333
0
      if ( !tvb_bytes_exist(tvb, dirs, num_binds + 1)
5334
0
        || tvb_get_uint8(tvb, dirs + num_binds) != SQLNET_ROW_TRANSF_DATA )
5335
0
        return offset;
5336
0
      offset = dirs;
5337
0
      dir_tree = proto_tree_add_subtree(data_tree, tvb, offset, num_binds, ett_tns_iov, NULL, "Bind Directions");
5338
0
      for ( uint32_t i = 0; i < num_binds; i++ )
5339
0
        proto_tree_add_item(dir_tree, hf_tns_data_iov_bind_dir, tvb, offset + i, 1, ENC_NA);
5340
0
      offset += num_binds;
5341
0
      if ( !call || !call->binds || call->num_binds != num_binds )
5342
0
        return offset;
5343
5344
0
      start = offset;
5345
0
      offset += 1; /* TTI_RXD token */
5346
0
      ob_tree = proto_tree_add_subtree(data_tree, tvb, start, -1, ett_tns_out_binds, &ob_item, "Out Binds");
5347
0
      for ( uint32_t i = 0; i < num_binds && !stop; i++ )
5348
0
      {
5349
0
        const tns_column_t *col = &call->binds[i];
5350
0
        int v_start = offset;
5351
5352
0
        if ( tvb_get_uint8(tvb, dirs + i) == TNS_BIND_DIR_INPUT )
5353
0
          continue;
5354
0
        if ( tvb_reported_length_remaining(tvb, offset) <= 0 )
5355
0
          stop = true;
5356
0
        else if ( col->type == TNS_DATATYPE_REFCURSOR )
5357
0
          offset = dissect_tns_oci_refcursor_out(tvb, pinfo, ob_tree, offset, i + 1);
5358
0
        else if ( tns_oci_bind_is_plain(col->type) && !col->is_array
5359
0
          && !(tvb_get_uint8(tvb, offset) == 0xfe && tns_field_version(pinfo) >= TNS_FV_12_1) )
5360
0
        {
5361
0
          offset = dissect_tns_value(tvb, pinfo, ob_tree, offset, col->type, col->csform,
5362
0
            TNS_VALUE_OUT, i + 1, hf_tns_data_bind_value, "Bind");
5363
0
          proto_tree_add_item(ob_tree, hf_tns_data_bind_oci_return_code, tvb, offset, 2, ENC_LITTLE_ENDIAN);
5364
0
          offset += 2;
5365
0
        }
5366
0
        else
5367
0
          stop = true;
5368
0
        if ( offset <= v_start )
5369
0
          stop = true;
5370
0
      }
5371
0
      proto_item_set_len(ob_item, offset - start);
5372
0
      ctx->walk = !stop;
5373
0
      return offset;
5374
0
    }
5375
5376
0
    case SQLNET_IMPLICIT_RESULTS:
5377
0
    {
5378
      /* The result sets a PL/SQL block returned with
5379
       * DBMS_SQL.RETURN_RESULT, as an OCI client gets them: thin's
5380
       * block at fixed widths. A ub4 count, then per result a
5381
       * length-prefixed preamble, a zero byte where a REF CURSOR
5382
       * OUT value has its lead byte, the describe and the ub4
5383
       * cursor id, which sqlplus then executes by id to fetch the
5384
       * rows. Implicit results came with 12.1, so the describe is
5385
       * at the 12c band. */
5386
0
      uint32_t num;
5387
5388
0
      proto_tree_add_item_ret_uint(data_tree, hf_tns_data_irs_num_results, tvb, offset, 4,
5389
0
        ENC_LITTLE_ENDIAN, &num);
5390
0
      offset += 4;
5391
0
      for ( uint32_t i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
5392
0
      {
5393
0
        proto_tree *rs_tree;
5394
0
        proto_item *rs_item;
5395
0
        int rs_start = offset;
5396
0
        uint32_t cursor;
5397
5398
0
        rs_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, -1,
5399
0
          ett_tns_irs, &rs_item, "Result Set %u", i + 1);
5400
0
        offset += 1 + tvb_get_uint8(tvb, offset);
5401
0
        offset += 1;
5402
0
        offset = dissect_tns_oci_describe_body(tvb, pinfo, rs_tree, offset, true, true);
5403
0
        proto_tree_add_item_ret_uint(rs_tree, hf_tns_cursor, tvb, offset, 4, ENC_LITTLE_ENDIAN, &cursor);
5404
0
        offset += 4;
5405
0
        proto_item_append_text(rs_item, ": cursor %u", cursor);
5406
0
        proto_item_set_len(rs_item, offset - rs_start);
5407
0
      }
5408
0
      ctx->walk = true;
5409
0
      return offset;
5410
0
    }
5411
5412
0
    case SQLNET_RETURN_STATUS:
5413
0
    {
5414
      /* The OCI status block: 136 bytes, or a compact 24 for a
5415
       * query's execute status, the end of a fetch and a no-row
5416
       * status. Offsets count from the message id byte; a field
5417
       * this decoder skips is a constant or not understood. The
5418
       * error message follows the full form. At the 12c band the
5419
       * full form is 144 bytes: the error number again at 132 and
5420
       * a ub8 row count, the one sqlplus reports for a DML. */
5421
0
      proto_tree *oer_tree;
5422
0
      proto_item *oer_item;
5423
0
      int base = offset - 1, remaining = tvb_reported_length_remaining(tvb, base);
5424
0
      bool full = remaining >= 136, wide = false;
5425
0
      uint32_t err_code;
5426
5427
0
      if ( remaining < 24 )
5428
0
        return offset;
5429
0
      err_code = tvb_get_letohl(tvb, base + 12);
5430
0
      if ( remaining >= 144 )
5431
0
        wide = tns_is_oci_12c(pinfo)
5432
0
          || (err_code != 0 && tvb_get_letohl(tvb, base + 132) == err_code)
5433
0
          || (err_code == 0 && remaining == 144);
5434
0
      oer_tree = proto_tree_add_subtree(data_tree, tvb, base, wide ? 144 : full ? 136 : 24, ett_tns_oer, &oer_item,
5435
0
        wide ? "Oracle Error Return (OCI, 12c band)" : full ? "Oracle Error Return (OCI)"
5436
0
        : "Oracle Error Return (OCI, compact)");
5437
      /* the call status, with the transaction bit set after a
5438
       * DML */
5439
0
      tns_add_call_status_flags(
5440
0
        proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_status, tvb, base + 1, 1, ENC_NA),
5441
0
        tvb, base + 1, 1, tvb_get_uint8(tvb, base + 1));
5442
0
      proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_seq, tvb, base + 5, 2, ENC_LITTLE_ENDIAN);
5443
0
      proto_tree_add_int(oer_tree, hf_tns_data_oer_rowcount, tvb, base + 8, 4, (int32_t)tvb_get_letohl(tvb, base + 8));
5444
0
      proto_tree_add_int(oer_tree, hf_tns_data_oer_err_code, tvb, base + 12, 4, (int32_t)err_code);
5445
      /* the statement's cursor, which the return parameters
5446
       * ahead of the status carry too */
5447
0
      proto_tree_add_item(oer_tree, hf_tns_cursor, tvb, base + 18, 2, ENC_LITTLE_ENDIAN);
5448
0
      proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_error_pos, tvb, base + 20, 1, ENC_NA);
5449
0
      proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_command, tvb, base + 22, 1, ENC_NA);
5450
0
      if ( !full )
5451
0
        return base + 24;
5452
      /* The warning flags of the thin error block, at 27 where a
5453
       * DML's status has the rowid of the row it touched instead:
5454
       * the DML command types are INSERT, UPDATE, DELETE and
5455
       * UPSERT. */
5456
0
      switch ( tvb_get_uint8(tvb, base + 22) )
5457
0
      {
5458
0
        case 2: case 6: case 7: case 189:
5459
0
          break;
5460
0
        default:
5461
0
          tns_add_warn_flags(tvb, pinfo, oer_tree, base + 27);
5462
0
          break;
5463
0
      }
5464
      /* the sequence number of the call this answers - the client's
5465
       * own, not the counter at offset 5 */
5466
0
      proto_tree_add_item(oer_tree, hf_tns_data_oci_oer_call_seq, tvb, base + 49, 2, ENC_LITTLE_ENDIAN);
5467
0
      offset = base + 136;
5468
0
      if ( wide )
5469
0
      {
5470
0
        proto_tree_add_item(oer_tree, hf_tns_data_oer_err_num_ext, tvb, base + 132, 4, ENC_LITTLE_ENDIAN);
5471
0
        proto_tree_add_item(oer_tree, hf_tns_data_oer_rowcount_ext, tvb, base + 136, 8, ENC_LITTLE_ENDIAN);
5472
0
        offset = base + 144;
5473
0
      }
5474
0
      if ( err_code != 0 && tvb_reported_length_remaining(tvb, offset) > 0 )
5475
0
      {
5476
0
        const char *msg = NULL;
5477
0
        int msg_start = offset;
5478
0
        offset += tns_oci_error_text(tvb, pinfo, offset, &msg);
5479
0
        msg = tns_trim_message(pinfo, msg);
5480
0
        if ( msg )
5481
0
        {
5482
0
          proto_tree_add_string(oer_tree, hf_tns_data_oer_message, tvb, msg_start, offset - msg_start, msg);
5483
0
          col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", msg);
5484
0
        }
5485
0
        proto_item_set_len(oer_item, offset - base);
5486
0
      }
5487
0
      return offset;
5488
0
    }
5489
5490
0
    case SQLNET_FUNCCOMPLETE:
5491
      /* TTI_STA, answering a commit, a rollback or a logoff: a
5492
       * ub4 LE call status and a ub2 LE end-to-end sequence */
5493
0
      if ( !tvb_bytes_exist(tvb, offset, 6) )
5494
0
        return offset;
5495
0
      tns_add_call_status_flags(
5496
0
        proto_tree_add_item(data_tree, hf_tns_data_sta_call_status, tvb, offset, 4, ENC_LITTLE_ENDIAN),
5497
0
        tvb, offset, 4, tvb_get_letohl(tvb, offset));
5498
0
      proto_tree_add_item(data_tree, hf_tns_data_sta_seq, tvb, offset + 4, 2, ENC_LITTLE_ENDIAN);
5499
0
      return offset + 6;
5500
5501
0
    default:
5502
0
      return offset;
5503
0
  }
5504
0
}
5505
5506
/* Decode the body of one TTC message, whose id byte has already been
5507
 * consumed. Sets ctx->walk when the decoder ended exactly on the
5508
 * message's last byte, so the caller can step into whatever follows it.
5509
 * Returns the new offset. */
5510
static int dissect_tns_message(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *data_tree, bool is_request, unsigned data_func_id, tns_msg_ctx_t *ctx)
5511
0
{
5512
  /* The thin decoders below would misread the fixed-width integers of
5513
   * a server talking to an OCI client. */
5514
0
  if ( !is_request && data_func_id != SQLNET_SNS && data_func_id != SQLNET_RETURN_OPI_PARAM
5515
0
    && tns_is_oci(pinfo) )
5516
0
    return dissect_tns_oci_message(tvb, offset, pinfo, data_tree, data_func_id, ctx);
5517
5518
  /* Handle data functions that have more than just ID */
5519
0
  switch (data_func_id)
5520
0
  {
5521
0
    case SQLNET_SET_PROTOCOL:
5522
0
    {
5523
0
      proto_tree *versions_tree;
5524
0
      proto_item *ti;
5525
0
      char sep;
5526
0
      if ( is_request )
5527
0
      {
5528
0
        versions_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_acc_versions, &ti, "Accepted Versions");
5529
0
        sep = ':';
5530
0
        for (;;) {
5531
          /*
5532
           * Add each accepted version as a
5533
           * separate item.
5534
           */
5535
0
          uint8_t vers;
5536
5537
0
          vers = tvb_get_uint8(tvb, offset);
5538
0
          if (vers == 0) {
5539
            /*
5540
             * A version of 0 terminates
5541
             * the list.
5542
             */
5543
0
            break;
5544
0
          }
5545
0
          proto_item_append_text(ti, "%c %u", sep, vers);
5546
0
          sep = ',';
5547
0
          proto_tree_add_uint(versions_tree, hf_tns_data_setp_acc_version, tvb, offset, 1, vers);
5548
0
          offset += 1;
5549
0
        }
5550
0
        offset += 1; /* skip the 0 terminator */
5551
0
        proto_item_set_end(ti, tvb, offset);
5552
0
        proto_tree_add_item(data_tree, hf_tns_data_setp_cli_plat, tvb, offset, -1, ENC_ASCII);
5553
5554
0
        return tvb_reported_length(tvb); /* skip call_data_dissector */
5555
0
      }
5556
0
      else
5557
0
      {
5558
0
        unsigned len;
5559
0
        versions_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_acc_versions, &ti, "Versions");
5560
0
        sep = ':';
5561
0
        for (;;) {
5562
          /*
5563
           * Add each version as a separate item.
5564
           */
5565
0
          uint8_t vers;
5566
5567
0
          vers = tvb_get_uint8(tvb, offset);
5568
0
          if (vers == 0) {
5569
            /*
5570
             * A version of 0 terminates
5571
             * the list.
5572
             */
5573
0
            break;
5574
0
          }
5575
0
          proto_item_append_text(ti, "%c %u", sep, vers);
5576
0
          sep = ',';
5577
0
          proto_tree_add_uint(versions_tree, hf_tns_data_setp_version, tvb, offset, 1, vers);
5578
0
          offset += 1;
5579
0
        }
5580
0
        offset += 1; /* skip the 0 terminator */
5581
0
        proto_item_set_end(ti, tvb, offset);
5582
0
        proto_tree_add_item_ret_length(data_tree, hf_tns_data_setp_banner, tvb, offset, -1, ENC_ASCII|ENC_NA, &len);
5583
0
        offset += len;
5584
5585
        /* After the banner: the server's charset (LE), flags, a
5586
         * count of 5-byte elements (LE), the "fdo" block (a BE
5587
         * length) whose tail names the national charset, and the
5588
         * server's compile and runtime capabilities, each behind a
5589
         * length byte. Capability 7 is the highest TTC field
5590
         * version the server offers. */
5591
0
        if ( tvb_reported_length_remaining(tvb, offset) < 5 )
5592
0
          break;
5593
0
        proto_tree_add_item(data_tree, hf_tns_data_setp_charset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
5594
0
        offset += 2;
5595
0
        proto_tree_add_item(data_tree, hf_tns_data_setp_flags, tvb, offset, 1, ENC_NA);
5596
0
        offset += 1;
5597
0
        unsigned num_elem = tvb_get_letohs(tvb, offset);
5598
0
        offset += 2 + 5 * num_elem;
5599
0
        unsigned fdo_len = tvb_get_ntohs(tvb, offset);
5600
0
        offset += 2;
5601
0
        if ( fdo_len >= 7 )
5602
0
        {
5603
0
          unsigned ix = 6 + tvb_get_uint8(tvb, offset + 5) + tvb_get_uint8(tvb, offset + 6);
5604
0
          if ( ix + 5 <= fdo_len )
5605
0
            proto_tree_add_item(data_tree, hf_tns_data_setp_ncharset, tvb, offset + ix + 3, 2, ENC_BIG_ENDIAN);
5606
0
        }
5607
0
        offset += fdo_len;
5608
0
        uint8_t caps_len = tvb_get_uint8(tvb, offset);
5609
0
        proto_tree_add_item(data_tree, hf_tns_data_setp_compile_caps, tvb, offset, 1 + caps_len, ENC_NA);
5610
0
        if ( caps_len > TNS_CCAP_FIELD_VERSION )
5611
0
        {
5612
0
          proto_tree_add_item(data_tree, hf_tns_data_setp_field_version, tvb,
5613
0
            offset + 1 + TNS_CCAP_FIELD_VERSION, 1, ENC_NA);
5614
0
          if ( !PINFO_FD_VISITED(pinfo) )
5615
0
            tns_get_conv_info(pinfo)->server_field_version =
5616
0
              tvb_get_uint8(tvb, offset + 1 + TNS_CCAP_FIELD_VERSION);
5617
0
        }
5618
0
        offset += 1 + caps_len;
5619
0
        caps_len = tvb_get_uint8(tvb, offset);
5620
0
        proto_tree_add_item(data_tree, hf_tns_data_setp_runtime_caps, tvb, offset, 1 + caps_len, ENC_NA);
5621
0
        offset += 1 + caps_len;
5622
0
        ctx->walk = true;
5623
0
      }
5624
0
      break;
5625
0
    }
5626
5627
0
    case SQLNET_SET_DATATYPES:
5628
0
    {
5629
      /* TTI_DTY: Data Type Negotiation, sent right after TTI_PRO
5630
       * during the TTC handshake. The client tells the server its
5631
       * capabilities and, for each native Oracle data type it
5632
       * understands, the wire representation it wants. Layout
5633
       * cross-referenced with python-oracledb.
5634
       *
5635
       *   charset_in        2 bytes LE   NLS_LANGUAGE charset id
5636
       *   charset_out       2 bytes LE   NLS_NCHAR   charset id
5637
       *   flag              1 byte       capability flag (1 = std)
5638
       *   compile caps      a length byte and the capabilities
5639
       *   runtime caps      a length byte and the capabilities
5640
       *   type entries      until a 0 type
5641
       *
5642
       * The entries are single bytes from an 11g client - (type,
5643
       * conversion type, representation, 0), or just (type, 0) - and
5644
       * big-endian 16-bit fields (type, conversion type,
5645
       * representation, 0) from a 12c+ one; a table of 16-bit
5646
       * entries opens with a zero byte. The single-byte table opens
5647
       * with an identity map - (N, N, 1, 0) for each type N - that
5648
       * is shown whole. */
5649
0
      proto_tree *caphdr_tree, *ov_tree;
5650
0
      proto_item *caphdr_item, *ov_item;
5651
0
      uint32_t dty_flag;
5652
0
      uint8_t caps_len;
5653
5654
0
      if ( !is_request )
5655
0
      {
5656
        /* The server's reply, from 12.1: 16-bit (type, conversion
5657
         * type) pairs - with four more bytes when the conversion
5658
         * type is not 0 - up to a 0 type. */
5659
0
        if ( tns_field_version(pinfo) < TNS_FV_12_1 )
5660
0
          break;
5661
0
        while ( tvb_reported_length_remaining(tvb, offset) >= 2 )
5662
0
        {
5663
0
          uint16_t type = tvb_get_ntohs(tvb, offset);
5664
0
          uint16_t conv;
5665
0
          if ( type == 0 )
5666
0
          {
5667
0
            offset += 2;
5668
0
            ctx->walk = true;
5669
0
            break;
5670
0
          }
5671
0
          conv = tvb_get_ntohs(tvb, offset + 2);
5672
0
          proto_tree *e_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, conv ? 8 : 4,
5673
0
            ett_tns_setdt_override, NULL, "Type %u (%s)",
5674
0
            type, val_to_str_const(type, tns_data_types, "unknown"));
5675
0
          proto_tree_add_item(e_tree, hf_tns_data_setdt_type, tvb, offset, 2, ENC_BIG_ENDIAN);
5676
0
          proto_tree_add_item(e_tree, hf_tns_data_setdt_conv_type, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
5677
0
          if ( conv )
5678
0
            proto_tree_add_item(e_tree, hf_tns_data_setdt_rep, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
5679
0
          offset += conv ? 8 : 4;
5680
0
        }
5681
0
        break;
5682
0
      }
5683
5684
0
      proto_tree_add_item(data_tree, hf_tns_data_setdt_charset_in, tvb, offset, 2, ENC_LITTLE_ENDIAN);
5685
0
      offset += 2;
5686
0
      proto_tree_add_item(data_tree, hf_tns_data_setdt_charset_out, tvb, offset, 2, ENC_LITTLE_ENDIAN);
5687
0
      offset += 2;
5688
0
      proto_tree_add_item_ret_uint(data_tree, hf_tns_data_setdt_flag, tvb, offset, 1, ENC_BIG_ENDIAN, &dty_flag);
5689
0
      offset += 1;
5690
5691
0
      caps_len = tvb_get_uint8(tvb, offset);
5692
0
      caphdr_item = proto_tree_add_item(data_tree, hf_tns_data_setdt_caphdr, tvb, offset, 1 + caps_len, ENC_NA);
5693
0
      caphdr_tree = proto_item_add_subtree(caphdr_item, ett_tns_setdt_caphdr);
5694
0
      if ( caps_len >= 2 )
5695
0
      {
5696
0
        proto_tree_add_item(caphdr_tree, hf_tns_data_setdt_caphdr_version, tvb, offset, 3, ENC_BIG_ENDIAN);
5697
0
        proto_tree_add_item(caphdr_tree, hf_tns_data_setdt_caphdr_flags, tvb, offset + 3, caps_len - 2, ENC_NA);
5698
0
      }
5699
      /* The header opens with the length of the client's compile
5700
       * capabilities, and capability 7 is the TTC field version.
5701
       * The client has already lowered it to the server's, so it
5702
       * is the one the connection uses. */
5703
0
      if ( caps_len > TNS_CCAP_FIELD_VERSION )
5704
0
      {
5705
0
        uint8_t fv = tvb_get_uint8(tvb, offset + 1 + TNS_CCAP_FIELD_VERSION);
5706
0
        proto_tree_add_item(caphdr_tree, hf_tns_data_setdt_field_version, tvb,
5707
0
          offset + 1 + TNS_CCAP_FIELD_VERSION, 1, ENC_NA);
5708
0
        if ( !PINFO_FD_VISITED(pinfo) )
5709
0
          tns_get_conv_info(pinfo)->field_version = fv;
5710
0
      }
5711
0
      offset += 1 + caps_len;
5712
5713
      /* runtime capabilities */
5714
0
      caps_len = tvb_get_uint8(tvb, offset);
5715
0
      proto_tree_add_item(data_tree, hf_tns_data_setdt_tblhdr, tvb, offset, 1 + caps_len, ENC_NA);
5716
0
      offset += 1 + caps_len;
5717
5718
0
      if ( dty_flag == TNS_DTY_ENCODING_OCI )
5719
0
      {
5720
        /* An OCI client - sqlplus, thick python-oracledb - sends
5721
         * no type table: the server keeps its own representations,
5722
         * the fixed-width integers of the OCI dialect, which this
5723
         * flag is the first sign of. In the table's place come the
5724
         * session's time zone block, from 11.2 on a ub4 BE
5725
         * timezone file version, and the national charset as a
5726
         * little-endian ub2. */
5727
0
        if ( !PINFO_FD_VISITED(pinfo) )
5728
0
          tns_get_conv_info(pinfo)->oci_dialect = true;
5729
0
        offset = dissect_tns_dty_tz(tvb, pinfo, data_tree, offset);
5730
0
        if ( tvb_reported_length_remaining(tvb, offset) >= 6 )
5731
0
        {
5732
0
          proto_tree_add_item(data_tree, hf_tns_data_setdt_tzfile, tvb, offset, 4, ENC_BIG_ENDIAN);
5733
0
          offset += 4;
5734
0
        }
5735
0
        proto_tree_add_item(data_tree, hf_tns_data_setdt_ncharset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
5736
0
        offset += 2;
5737
0
        break;
5738
0
      }
5739
5740
0
      ov_item = proto_tree_add_item(data_tree, hf_tns_data_setdt_overrides, tvb, offset, -1, ENC_NA);
5741
0
      ov_tree = proto_item_add_subtree(ov_item, ett_tns_setdt_overrides);
5742
0
      int ov_start = offset;
5743
0
      if ( tvb_reported_length_remaining(tvb, offset) > 0 && tvb_get_uint8(tvb, offset) == 0 )
5744
0
      {
5745
        /* 16-bit entries */
5746
0
        while ( tvb_reported_length_remaining(tvb, offset) >= 2 )
5747
0
        {
5748
0
          uint16_t type = tvb_get_ntohs(tvb, offset);
5749
0
          if ( type == 0 )
5750
0
          {
5751
0
            offset += 2;
5752
0
            break;
5753
0
          }
5754
0
          proto_tree *e_tree = proto_tree_add_subtree_format(ov_tree, tvb, offset, 8,
5755
0
            ett_tns_setdt_override, NULL, "Type %u (%s)",
5756
0
            type, val_to_str_const(type, tns_data_types, "unknown"));
5757
0
          proto_tree_add_item(e_tree, hf_tns_data_setdt_type, tvb, offset, 2, ENC_BIG_ENDIAN);
5758
0
          proto_tree_add_item(e_tree, hf_tns_data_setdt_conv_type, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
5759
0
          proto_tree_add_item(e_tree, hf_tns_data_setdt_rep, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
5760
0
          offset += 8;
5761
0
        }
5762
0
        proto_item_set_len(ov_item, offset - ov_start);
5763
      /* in a fast-authentication bundle the session key request
5764
       * follows */
5765
0
      ctx->walk = true;
5766
0
        break;
5767
0
      }
5768
5769
      /* the identity run of the single-byte table */
5770
0
      int id_start = offset;
5771
0
      while ( tvb_bytes_exist(tvb, offset, 4) && tvb_get_uint8(tvb, offset) != 0
5772
0
        && tvb_get_uint8(tvb, offset) == tvb_get_uint8(tvb, offset + 1)
5773
0
        && tvb_get_uint8(tvb, offset + 2) == 1 && tvb_get_uint8(tvb, offset + 3) == 0 )
5774
0
        offset += 4;
5775
0
      if ( offset > id_start )
5776
0
        proto_tree_add_item(data_tree, hf_tns_data_setdt_idmap, tvb, id_start, offset - id_start, ENC_NA);
5777
0
      ov_start = offset;
5778
5779
      /* Walk type-override entries until the 0 terminator. Each
5780
       * entry is (client_type, server_repr[, format]); a 0 in the
5781
       * server_repr slot marks a short "client knows the id but
5782
       * has no override" entry. */
5783
0
      while ( tvb_reported_length_remaining(tvb, offset) > 0 )
5784
0
      {
5785
0
        uint8_t client_type = tvb_get_uint8(tvb, offset);
5786
0
        if ( client_type == 0 )
5787
0
        {
5788
0
          proto_tree_add_item(ov_tree, hf_tns_data_setdt_override_client, tvb, offset, 1, ENC_BIG_ENDIAN);
5789
0
          offset += 1;
5790
0
          break;
5791
0
        }
5792
0
        uint8_t repr = tvb_get_uint8(tvb, offset + 1);
5793
0
        int entry_len = (repr == 0) ? 2 : 4;
5794
0
        proto_tree *e_tree = proto_tree_add_subtree_format(ov_tree, tvb, offset, entry_len,
5795
0
          ett_tns_setdt_override, NULL, "Type %u (%s)",
5796
0
          client_type, val_to_str_const(client_type, tns_data_types, "unknown"));
5797
0
        proto_tree_add_item(e_tree, hf_tns_data_setdt_override_client, tvb, offset, 1, ENC_BIG_ENDIAN);
5798
0
        if ( entry_len == 4 )
5799
0
        {
5800
0
          proto_tree_add_item(e_tree, hf_tns_data_setdt_override_repr, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
5801
0
          proto_tree_add_item(e_tree, hf_tns_data_setdt_override_format, tvb, offset + 2, 1, ENC_BIG_ENDIAN);
5802
0
        }
5803
0
        offset += entry_len;
5804
0
      }
5805
0
      proto_item_set_len(ov_item, offset - ov_start);
5806
0
      break;
5807
0
    }
5808
5809
0
    case SQLNET_RETURN_STATUS:
5810
0
    {
5811
      /* TTI_OER: server-side end-of-call status block. Emitted at
5812
       * the end of every response — success or failure. Layout
5813
       * cross-referenced with python-oracledb's
5814
       * _process_error_info, in the Oracle 11g shape (no extended
5815
       * ub4 error number / ub8 rowcount that 12c+ adds).
5816
       *
5817
       * All multi-byte integers are stored in the ub4 variable-
5818
       * length form (see get_sb4_custom): first byte holds the
5819
       * value's width (0..4), followed by that many big-endian
5820
       * data bytes. */
5821
0
      proto_tree *oer_tree;
5822
0
      proto_item *oer_item;
5823
0
      int oer_start = offset;
5824
0
      int v;
5825
5826
0
      oer_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_oer, &oer_item, "Oracle Error Return");
5827
5828
      /* call_status */
5829
0
      offset += get_sb4_custom(tvb, offset, &v);
5830
0
      tns_add_call_status_flags(
5831
0
        proto_tree_add_int(oer_tree, hf_tns_data_oer_call_status, tvb, oer_start, offset - oer_start, v),
5832
0
        tvb, oer_start, offset - oer_start, (uint32_t)v);
5833
      /* end-to-end seq# (skipped) */
5834
0
      offset += get_sb4_custom(tvb, offset, &v);
5835
      /* rowcount: the rows the call applied, whether it went on
5836
       * to fail or not */
5837
0
      int rc_start = offset;
5838
0
      uint64_t rows_done;
5839
0
      offset += get_sb4_custom(tvb, offset, &v);
5840
0
      proto_tree_add_int(oer_tree, hf_tns_data_oer_rowcount, tvb, rc_start, offset - rc_start, v);
5841
0
      rows_done = (uint64_t)(uint32_t)v;
5842
      /* err_code (ORA-NNNNN, 0 on success) */
5843
0
      int ec_start = offset;
5844
0
      int err_code = 0;
5845
0
      offset += get_sb4_custom(tvb, offset, &err_code);
5846
0
      proto_tree_add_int(oer_tree, hf_tns_data_oer_err_code, tvb, ec_start, offset - ec_start, err_code);
5847
      /* array elem error #1, #2 (skipped) */
5848
0
      offset += get_sb4_custom(tvb, offset, &v);
5849
0
      offset += get_sb4_custom(tvb, offset, &v);
5850
      /* cursor_id */
5851
0
      int ci_start = offset;
5852
0
      offset += get_sb4_custom(tvb, offset, &v);
5853
0
      proto_tree_add_int(oer_tree, hf_tns_data_oer_cursor_id, tvb, ci_start, offset - ci_start, v);
5854
      /* The status of an execute that opened a new cursor names it:
5855
       * its bind types now belong to that cursor id. */
5856
0
      if ( !PINFO_FD_VISITED(pinfo) && v != 0 )
5857
0
      {
5858
0
        tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
5859
0
        if ( tns_info->pending_binds )
5860
0
        {
5861
0
          wmem_map_insert(tns_info->cursor_binds, GUINT_TO_POINTER(v), tns_info->pending_binds);
5862
0
          tns_info->pending_binds = NULL;
5863
0
        }
5864
0
      }
5865
      /* error position (skipped) */
5866
0
      offset += get_sb4_custom(tvb, offset, &v);
5867
      /* 6 fields: sql_type, fatal, flags, user_cursor_opts,
5868
       * upi_param, warn_flags. All are single bytes except flags
5869
       * below 12.1, a variable-length ub2: 00 when zero, but two
5870
       * bytes once a warning (an aggregate that skipped NULLs)
5871
       * sets it. With no field version known, a byte that cannot
5872
       * be a ub2's width is the single-byte form. Five are
5873
       * diagnostic; the last is not. Its bit 0x20 says the
5874
       * statement created a PL/SQL object that compiled with
5875
       * errors - the call succeeded, the error code is 0 and the
5876
       * reply is otherwise indistinguishable from a clean one, so
5877
       * this bit is the only sign the object is invalid. */
5878
0
      offset += 2;
5879
0
      if ( tns_field_version(pinfo) < TNS_FV_12_1 && tvb_get_uint8(tvb, offset) <= 2 )
5880
0
        offset += get_sb4_custom(tvb, offset, &v);
5881
0
      else
5882
0
        offset += 1;
5883
0
      offset += 2;
5884
0
      tns_add_warn_flags(tvb, pinfo, oer_tree, offset);
5885
0
      offset += 1;
5886
      /* The rowid of the last row the statement touched: ub4
5887
       * data object, ub2 relative file, a reserved byte, ub4
5888
       * block, ub2 slot. A zero block means there is none - a
5889
       * query, DDL, or a DML that touched no row. In a bigfile
5890
       * tablespace the file is 1024 here where a fetched ROWID
5891
       * says 0; both name the same row. */
5892
0
      {
5893
0
        int rid_start = offset, rba = 0, part = 0, block = 0, slot = 0;
5894
0
        offset += get_sb4_custom(tvb, offset, &rba);
5895
0
        offset += get_sb4_custom(tvb, offset, &part);
5896
0
        offset += 1;
5897
0
        offset += get_sb4_custom(tvb, offset, &block);
5898
0
        offset += get_sb4_custom(tvb, offset, &slot);
5899
0
        if ( block != 0 )
5900
0
          proto_tree_add_string(oer_tree, hf_tns_data_oer_rowid, tvb, rid_start, offset - rid_start,
5901
0
            tns_format_rowid(pinfo, (uint32_t)rba, (uint32_t)part, (uint32_t)block, (uint32_t)slot));
5902
0
      }
5903
      /* os error (skipped) */
5904
0
      offset += get_sb4_custom(tvb, offset, &v);
5905
      /* statement #, call # (1 byte each) */
5906
0
      offset += 2;
5907
      /* padding ub2 + successful iterations ub4 */
5908
0
      offset += get_sb4_custom(tvb, offset, &v);
5909
0
      offset += get_sb4_custom(tvb, offset, &v);
5910
      /* oerrdd (logical rowid), a bytes_with_length — skipped */
5911
0
      offset += get_field_with_length(tvb, pinfo, offset, NULL);
5912
5913
      /* Batch error arrays (array DML). The code and offset arrays
5914
       * are each a ub4 count followed by one DALC packing that many
5915
       * ub4 values back to back; the message array is a ub4 count,
5916
       * an indicator byte, and then that many str_with_length
5917
       * entries each with a 2-byte trailer. All three counts are
5918
       * zero for an ordinary statement. */
5919
0
      int n_codes = 0, n_offs = 0, n_msgs = 0;
5920
0
      int nb_start = offset;
5921
0
      offset += get_sb4_custom(tvb, offset, &n_codes);
5922
0
      proto_tree_add_int(oer_tree, hf_tns_data_oer_n_batch_errcodes, tvb, nb_start, offset - nb_start, n_codes);
5923
0
      if ( n_codes > 0 )
5924
0
        offset += get_dalc_custom(tvb, pinfo, offset, NULL);
5925
0
      nb_start = offset;
5926
0
      offset += get_sb4_custom(tvb, offset, &n_offs);
5927
0
      proto_tree_add_int(oer_tree, hf_tns_data_oer_n_batch_offsets, tvb, nb_start, offset - nb_start, n_offs);
5928
0
      if ( n_offs > 0 )
5929
0
        offset += get_dalc_custom(tvb, pinfo, offset, NULL);
5930
0
      nb_start = offset;
5931
0
      offset += get_sb4_custom(tvb, offset, &n_msgs);
5932
0
      proto_tree_add_int(oer_tree, hf_tns_data_oer_n_batch_messages, tvb, nb_start, offset - nb_start, n_msgs);
5933
0
      if ( n_msgs > 0 )
5934
0
      {
5935
0
        offset += 1;
5936
0
        for ( int i = 0; i < n_msgs; i++ )
5937
0
        {
5938
0
          offset += get_field_with_length(tvb, pinfo, offset, NULL);
5939
0
          offset += 2;
5940
0
        }
5941
0
      }
5942
5943
      /* From 12.1 the block goes on with the error number and row
5944
       * count at their full widths (a ub4 and a ub8), and from 20.1
5945
       * with the SQL type and a server checksum. The extended error
5946
       * number is the one that says whether a message follows.
5947
       * The first pair follows the negotiated field version, the
5948
       * second the server's own release: a 21c or later server
5949
       * sends it even to a session that settled on 12.1 or 19c. */
5950
0
      unsigned fv = tns_field_version(pinfo);
5951
0
      unsigned server_fv = tns_server_field_version(pinfo);
5952
0
      if ( fv >= TNS_FV_12_1 )
5953
0
      {
5954
0
        uint64_t rows = 0;
5955
0
        int start = offset;
5956
0
        offset += get_sb4_custom(tvb, offset, &err_code);
5957
0
        proto_tree_add_uint(oer_tree, hf_tns_data_oer_err_num_ext, tvb, start, offset - start, err_code);
5958
0
        start = offset;
5959
0
        offset += get_ub8_custom(tvb, offset, &rows);
5960
0
        proto_tree_add_uint64(oer_tree, hf_tns_data_oer_rowcount_ext, tvb, start, offset - start, rows);
5961
0
        rows_done = rows;
5962
0
      }
5963
0
      if ( fv >= TNS_FV_12_1 && (server_fv ? server_fv : fv) >= TNS_FV_20_1 )
5964
0
      {
5965
0
        int start = offset;
5966
0
        offset += get_sb4_custom(tvb, offset, &v);
5967
0
        proto_tree_add_uint(oer_tree, hf_tns_data_oer_sql_type, tvb, start, offset - start, v);
5968
0
        start = offset;
5969
0
        offset += get_sb4_custom(tvb, offset, &v);
5970
0
        proto_tree_add_uint(oer_tree, hf_tns_data_oer_checksum, tvb, start, offset - start, v);
5971
0
      }
5972
5973
      /* Trailing message DALC — present (and meaningful) only when
5974
       * err_code is non-zero. */
5975
0
      if ( err_code != 0 && tvb_reported_length_remaining(tvb, offset) > 0 )
5976
0
      {
5977
0
        const char *msg = NULL;
5978
0
        int msg_start = offset;
5979
0
        offset += get_dalc_custom(tvb, pinfo, offset, &msg);
5980
0
        msg = tns_trim_message(pinfo, msg);
5981
0
        if ( msg )
5982
0
        {
5983
0
          proto_tree_add_string(oer_tree, hf_tns_data_oer_message, tvb, msg_start, offset - msg_start, msg);
5984
0
          col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", msg);
5985
0
        }
5986
0
      }
5987
      /* A call that failed part-way through - an array DML whose
5988
       * later iteration raised - still applied the rows before the
5989
       * one that raised, and this is where it says how many. */
5990
0
      if ( err_code != 0 && rows_done != 0 )
5991
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " [%" PRIu64 " rows applied]", rows_done);
5992
0
      proto_item_set_len(oer_item, offset - oer_start);
5993
      /* With the field version known the block ends where it
5994
       * should, so an end-of-response marker after it can be read. */
5995
0
      ctx->walk = fv != 0;
5996
0
      break;
5997
0
    }
5998
5999
0
    case SQLNET_FUNCCOMPLETE:
6000
0
    {
6001
      /* TTI_STA: a bare status, with no error block. It answers a
6002
       * commit, a rollback or a logoff: a ub4 call status and the
6003
       * ub2 end-to-end sequence number. */
6004
0
      int v = 0, start;
6005
6006
0
      if ( is_request )
6007
0
        break;
6008
6009
0
      start = offset;
6010
0
      offset += get_sb4_custom(tvb, offset, &v);
6011
0
      tns_add_call_status_flags(
6012
0
        proto_tree_add_uint(data_tree, hf_tns_data_sta_call_status, tvb, start, offset - start, v),
6013
0
        tvb, start, offset - start, (uint32_t)v);
6014
0
      start = offset;
6015
0
      offset += get_sb4_custom(tvb, offset, &v);
6016
0
      proto_tree_add_uint(data_tree, hf_tns_data_sta_seq, tvb, start, offset - start, v);
6017
0
      ctx->walk = true;
6018
0
      break;
6019
0
    }
6020
6021
0
    case SQLNET_LOB_FILE_DF:
6022
0
    {
6023
      /* LOB content: what a TTI_LOBOPS READ returns, ahead of the
6024
       * return parameters. Raw bytes for a BLOB or BFILE, the LOB's
6025
       * character set (usually UTF-16BE) for a CLOB. */
6026
0
      int start = offset;
6027
6028
0
      if ( is_request )
6029
0
        break;
6030
6031
0
      offset += get_dalc_custom(tvb, pinfo, offset, NULL);
6032
0
      if ( tvb_get_uint8(tvb, start) == 0xfe ) /* chunked: shown whole */
6033
0
        proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start, offset - start, ENC_NA);
6034
0
      else if ( offset - start > 1 )
6035
0
        proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start + 1, offset - start - 1, ENC_NA);
6036
6037
      /* A CLOB's content is text; the locator the read named says
6038
       * how it is encoded. */
6039
0
      const tns_call_t *call = tns_answered_call(pinfo);
6040
0
      if ( call && call->func == TTI_LOBOPS && call->lob_flags_known
6041
0
        && (call->lob_flags[0] & (TNS_LOB_LOC_FLAGS_CLOB | TNS_LOB_LOC_FLAGS_NCLOB)) )
6042
0
      {
6043
0
        int len = 0;
6044
0
        const uint8_t *data = tns_dalc_bytes(tvb, pinfo, start, &len);
6045
0
        const uint8_t *text = NULL;
6046
6047
0
        if ( data && (call->lob_flags[0] & TNS_LOB_LOC_FLAGS_NCLOB) )
6048
0
          text = get_utf_16_string(pinfo->pool, data, len, ENC_BIG_ENDIAN);
6049
0
        else if ( data && (call->lob_flags[2] & TNS_LOB_LOC_FLAGS_VAR_LENGTH_CHARSET) )
6050
0
          text = get_utf_16_string(pinfo->pool, data, len,
6051
0
            (call->lob_flags[3] & TNS_LOB_LOC_FLAGS_LITTLE_ENDIAN) ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN);
6052
0
        else if ( data )
6053
0
          text = get_utf_8_string(pinfo->pool, data, len);
6054
0
        if ( text )
6055
0
          proto_item_set_generated(proto_tree_add_string(data_tree, hf_tns_data_lob_text, tvb,
6056
0
            start, offset - start, (const char *)text));
6057
0
      }
6058
0
      ctx->walk = true;
6059
0
      break;
6060
0
    }
6061
6062
0
    case SQLNET_WARNING:
6063
0
    {
6064
      /* TTI_WRN: a warning that does not fail the call - PL/SQL
6065
       * compiled with errors, say. A ub2 warning number, a ub2
6066
       * message length and ub2 flags, then the message itself when
6067
       * both are non-zero. */
6068
0
      int code = 0, len = 0, v = 0, start;
6069
6070
0
      if ( is_request )
6071
0
        break;
6072
6073
0
      start = offset;
6074
0
      offset += get_sb4_custom(tvb, offset, &code);
6075
0
      proto_tree_add_uint(data_tree, hf_tns_data_wrn_code, tvb, start, offset - start, code);
6076
0
      start = offset;
6077
0
      offset += get_sb4_custom(tvb, offset, &len);
6078
0
      proto_tree_add_uint(data_tree, hf_tns_data_wrn_length, tvb, start, offset - start, len);
6079
0
      start = offset;
6080
0
      offset += get_sb4_custom(tvb, offset, &v);
6081
0
      proto_tree_add_uint(data_tree, hf_tns_data_wrn_flags, tvb, start, offset - start, v);
6082
0
      if ( code != 0 && len > 0 )
6083
0
      {
6084
0
        const char *msg = NULL;
6085
0
        start = offset;
6086
0
        offset += get_dalc_custom(tvb, pinfo, offset, &msg);
6087
0
        msg = tns_trim_message(pinfo, msg);
6088
0
        if ( msg )
6089
0
        {
6090
0
          proto_tree_add_string(data_tree, hf_tns_data_wrn_message, tvb, start, offset - start, msg);
6091
0
          col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", msg);
6092
0
        }
6093
0
      }
6094
0
      ctx->walk = true;
6095
0
      break;
6096
0
    }
6097
6098
0
    case SQLNET_SERVER_PIGGYBACK:
6099
0
    {
6100
      /* A piggyback from the server: state it pushes to the client
6101
       * alongside a reply, selected by an opcode. Layouts follow
6102
       * python-oracledb's _process_server_side_piggyback. */
6103
0
      int v = 0, num = 0, start;
6104
0
      uint8_t opcode;
6105
6106
0
      if ( is_request )
6107
0
        break;
6108
6109
0
      proto_tree_add_item_ret_uint8(data_tree, hf_tns_data_spb_opcode, tvb, offset, 1, ENC_BIG_ENDIAN, &opcode);
6110
0
      col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
6111
0
        val_to_str_const(opcode, tns_spb_opcodes, "unknown"));
6112
0
      offset += 1;
6113
0
      switch ( opcode )
6114
0
      {
6115
0
        case TNS_SPB_QUERY_CACHE_INVALIDATION:
6116
0
        case TNS_SPB_TRACE_EVENT:
6117
0
          break;
6118
0
        case TNS_SPB_LTXID:
6119
0
          offset += get_sb4_custom(tvb, offset, &v);
6120
0
          if ( v > 0 )
6121
0
          {
6122
0
            start = offset;
6123
0
            offset += get_dalc_custom(tvb, pinfo, offset, NULL);
6124
0
            proto_tree_add_item(data_tree, hf_tns_data_spb_ltxid, tvb, start + 1, offset - start - 1, ENC_NA);
6125
0
          }
6126
0
          break;
6127
0
        case TNS_SPB_OS_PID_MTS:
6128
0
        {
6129
0
          const char *pid = NULL;
6130
0
          offset += get_sb4_custom(tvb, offset, &v);
6131
0
          start = offset;
6132
0
          offset += get_dalc_custom(tvb, pinfo, offset, &pid);
6133
0
          if ( pid )
6134
0
            proto_tree_add_string(data_tree, hf_tns_data_spb_os_pid, tvb, start, offset - start, pid);
6135
0
          break;
6136
0
        }
6137
0
        case TNS_SPB_SYNC:
6138
          /* Session state the statement changed - a new current
6139
           * schema, edition or NLS setting - as key/value pairs. */
6140
0
          offset += get_sb4_custom(tvb, offset, &v);  /* number of DTYs */
6141
0
          offset += 1;                               /* length of DTYs */
6142
0
          start = offset;
6143
0
          offset += get_sb4_custom(tvb, offset, &num);
6144
0
          proto_tree_add_uint(data_tree, hf_tns_data_spb_num_kv, tvb, start, offset - start, num);
6145
0
          offset += 1;                               /* length */
6146
0
          offset = dissect_tns_kv_pairs(tvb, pinfo, data_tree, offset, num);
6147
0
          start = offset;
6148
0
          offset += get_sb4_custom(tvb, offset, &v);
6149
0
          proto_tree_add_uint(data_tree, hf_tns_data_spb_flags, tvb, start, offset - start, v);
6150
0
          break;
6151
0
        case TNS_SPB_EXT_SYNC:
6152
0
          offset += get_sb4_custom(tvb, offset, &v);  /* number of DTYs */
6153
0
          offset += 1;                               /* length of DTYs */
6154
0
          break;
6155
0
        case TNS_SPB_AC_REPLAY_CONTEXT:
6156
0
          offset += get_sb4_custom(tvb, offset, &v);  /* number of DTYs */
6157
0
          offset += 1;                               /* length of DTYs */
6158
0
          offset += get_sb4_custom(tvb, offset, &v);  /* flags */
6159
0
          offset += get_sb4_custom(tvb, offset, &v);  /* error code */
6160
0
          offset += 1;                               /* queue */
6161
0
          offset += get_field_with_length(tvb, pinfo, offset, NULL); /* replay context */
6162
0
          break;
6163
0
        case TNS_SPB_SESS_RET:
6164
0
          offset += get_sb4_custom(tvb, offset, &v);  /* number of DTYs */
6165
0
          offset += 1;                               /* length of DTYs */
6166
0
          offset += get_sb4_custom(tvb, offset, &num);
6167
0
          if ( num > 0 )
6168
0
          {
6169
0
            offset += 1;
6170
0
            for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
6171
0
            {
6172
0
              offset += get_sb4_custom(tvb, offset, &v);   /* key */
6173
0
              if ( v > 0 )
6174
0
                offset += get_dalc_custom(tvb, pinfo, offset, NULL);
6175
0
              offset += get_sb4_custom(tvb, offset, &v);   /* value */
6176
0
              if ( v > 0 )
6177
0
                offset += get_dalc_custom(tvb, pinfo, offset, NULL);
6178
0
              offset += get_sb4_custom(tvb, offset, &v);   /* flags */
6179
0
            }
6180
0
          }
6181
0
          start = offset;
6182
0
          offset += get_sb4_custom(tvb, offset, &v);
6183
0
          proto_tree_add_uint(data_tree, hf_tns_data_spb_flags, tvb, start, offset - start, v);
6184
0
          start = offset;
6185
0
          offset += get_sb4_custom(tvb, offset, &v);
6186
0
          proto_tree_add_uint(data_tree, hf_tns_data_spb_session_id, tvb, start, offset - start, v);
6187
0
          start = offset;
6188
0
          offset += get_sb4_custom(tvb, offset, &v);
6189
0
          proto_tree_add_uint(data_tree, hf_tns_data_spb_serial_num, tvb, start, offset - start, v);
6190
0
          break;
6191
0
        case TNS_SPB_SESS_SIGNATURE:
6192
0
        {
6193
0
          uint64_t u = 0;
6194
0
          offset += get_sb4_custom(tvb, offset, &v);  /* number of DTYs */
6195
0
          offset += 1;                               /* length of DTYs */
6196
0
          offset += get_ub8_custom(tvb, offset, &u);  /* signature flags */
6197
0
          offset += get_ub8_custom(tvb, offset, &u);  /* client signature */
6198
0
          offset += get_ub8_custom(tvb, offset, &u);  /* server signature */
6199
0
          break;
6200
0
        }
6201
0
        default:
6202
          /* Unknown opcode: its length is unknown too. */
6203
0
          return offset;
6204
0
      }
6205
0
      ctx->walk = true;
6206
0
      break;
6207
0
    }
6208
6209
0
    case SQLNET_IMPLICIT_RESULTS:
6210
0
    {
6211
      /* The result sets a PL/SQL block returned with
6212
       * DBMS_SQL.RETURN_RESULT: a ub4 count, then per result a
6213
       * length-prefixed opaque blob, the describe of its columns,
6214
       * and the ub2 cursor id the client fetches it with. */
6215
0
      int num = 0, start;
6216
6217
0
      if ( is_request )
6218
0
        break;
6219
6220
0
      start = offset;
6221
0
      offset += get_sb4_custom(tvb, offset, &num);
6222
0
      proto_tree_add_uint(data_tree, hf_tns_data_irs_num_results, tvb, start, offset - start, num);
6223
0
      for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
6224
0
      {
6225
0
        proto_tree *rs_tree;
6226
0
        proto_item *rs_item;
6227
0
        int rs_start = offset, cursor = 0;
6228
6229
0
        rs_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, -1,
6230
0
          ett_tns_irs, &rs_item, "Result Set %d", i + 1);
6231
0
        offset += 1 + tvb_get_uint8(tvb, offset);
6232
0
        offset = dissect_tns_describe_body(tvb, pinfo, rs_tree, offset, NULL);
6233
0
        start = offset;
6234
0
        offset += get_sb4_custom(tvb, offset, &cursor);
6235
0
        proto_tree_add_uint(rs_tree, hf_tns_cursor, tvb, start, offset - start, cursor);
6236
0
        proto_item_append_text(rs_item, ": cursor %d", cursor);
6237
0
        proto_item_set_len(rs_item, offset - rs_start);
6238
0
      }
6239
0
      ctx->walk = true;
6240
0
      break;
6241
0
    }
6242
6243
0
    case SQLNET_TOKEN:
6244
0
    {
6245
      /* the token of the call this answers */
6246
0
      uint64_t token = 0;
6247
0
      int start = offset;
6248
6249
0
      if ( is_request )
6250
0
        break;
6251
0
      offset += get_ub8_custom(tvb, offset, &token);
6252
0
      proto_tree_add_uint64(data_tree, hf_tns_data_token, tvb, start, offset - start, token);
6253
0
      ctx->walk = true;
6254
0
      break;
6255
0
    }
6256
6257
0
    case SQLNET_FLUSH_BIND_DATA:
6258
      /* Sent when a DML with a RETURNING clause fails: the client
6259
       * drops the out-bind data it was collecting. There is no
6260
       * body, and the error follows. */
6261
0
      if ( !is_request )
6262
0
        ctx->walk = true;
6263
0
      break;
6264
6265
0
    case SQLNET_END_OF_RESPONSE:
6266
      /* Marks the end of a response for a client that negotiated
6267
       * it; there is no body. */
6268
0
      ctx->walk = true;
6269
0
      break;
6270
6271
0
    case SQLNET_IOVEC_4FAST_UPI:
6272
0
    {
6273
      /* TTI_IOV: the server's I/O vector for an executed anonymous
6274
       * PL/SQL block that carried bind variables. It lists each
6275
       * bind's direction (IN / OUT / IN OUT); when any bind is
6276
       * OUT / IN OUT the returned values follow as a TTI_RXD row.
6277
       * Layout cross-referenced with python-oracledb's
6278
       * _process_io_vector, and
6279
       * verified against XE 11g.
6280
       *
6281
       * All the leading counters are stored in the ub4 variable-
6282
       * length form (see get_sb4_custom). The per-bind directions
6283
       * are one raw byte each. The trailing RXD values need each
6284
       * bind's declared type to decode, so they are read only when
6285
       * the execute this answers was seen. */
6286
0
      int num_requests = 0, num_iters = 0, v = 0, bv_len = 0, rid_len = 0;
6287
6288
0
      if ( !is_request )
6289
0
      {
6290
        /* flag (ub1, skip) */
6291
0
        offset += 1;
6292
0
        offset += get_sb4_custom(tvb, offset, &num_requests);
6293
0
        offset += get_sb4_custom(tvb, offset, &num_iters);
6294
0
        int num_binds = num_iters * 256 + num_requests;
6295
0
        proto_tree_add_uint(data_tree, hf_tns_data_iov_num_binds, tvb, offset, 0, num_binds);
6296
        /* num iters this time (skip) */
6297
0
        offset += get_sb4_custom(tvb, offset, &v);
6298
        /* uac buffer length (skip) */
6299
0
        offset += get_sb4_custom(tvb, offset, &v);
6300
        /* fast-fetch bit-vector: length + bytes (skip) */
6301
0
        offset += get_sb4_custom(tvb, offset, &bv_len);
6302
0
        if ( bv_len > 0 )
6303
0
          offset += bv_len;
6304
        /* rowid: length + bytes (skip) */
6305
0
        offset += get_sb4_custom(tvb, offset, &rid_len);
6306
0
        if ( rid_len > 0 )
6307
0
          offset += rid_len;
6308
6309
        /* Per-bind direction bytes, in bind order. Bound by both
6310
         * the reported count and the bytes actually present so a
6311
         * malformed vector cannot run away. */
6312
0
        proto_tree *iov_tree;
6313
0
        proto_item *iov_item;
6314
0
        int iov_start = offset;
6315
0
        iov_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_iov, &iov_item, "Bind Directions");
6316
0
        for ( int i = 0; i < num_binds && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
6317
0
        {
6318
0
          proto_tree_add_item(iov_tree, hf_tns_data_iov_bind_dir, tvb, offset, 1, ENC_BIG_ENDIAN);
6319
0
          offset += 1;
6320
0
        }
6321
0
        proto_item_set_len(iov_item, offset - iov_start);
6322
6323
        /* The OUT and IN OUT values follow as a TTI_RXD, typed by
6324
         * the binds of the execute this answers - readable only
6325
         * when that execute was seen and bound as many. */
6326
0
        const tns_call_t *call = tns_answered_call(pinfo);
6327
0
        if ( call && call->binds && call->num_binds == (uint32_t)num_binds
6328
0
          && offset - iov_start == num_binds )
6329
0
        {
6330
0
          ctx->out_call = call;
6331
0
          ctx->bind_dirs = tvb_memdup(pinfo->pool, tvb, iov_start, num_binds);
6332
0
          ctx->walk = true;
6333
          /* Only this reply says which of a block's binds are
6334
           * OUT; its re-executes need to know. */
6335
0
          if ( !PINFO_FD_VISITED(pinfo) && call->bind_rec && call->bind_rec->plsql )
6336
0
            call->bind_rec->dirs = (uint8_t *)tvb_memdup(wmem_file_scope(), tvb, iov_start, num_binds);
6337
0
        }
6338
0
      }
6339
0
      break;
6340
0
    }
6341
6342
0
    case SQLNET_DESCRIBE_INFO:
6343
0
    {
6344
      /* TTI_DCB: describe (column metadata) for a SELECT result set,
6345
       * in the Oracle 11g shape: a preamble, then the describe body.
6346
       * The columns are remembered, once, so a later TTI_RXD can
6347
       * split its row values. */
6348
0
      tns_describe_t *desc = NULL;
6349
6350
0
      if ( is_request )
6351
0
        break;
6352
6353
      /* describe-info preamble (chunked bytes: cursor uuid + date) */
6354
0
      offset += get_dalc_custom(tvb, pinfo, offset, NULL);
6355
0
      offset = dissect_tns_describe_body(tvb, pinfo, data_tree, offset,
6356
0
        PINFO_FD_VISITED(pinfo) ? NULL : &desc);
6357
0
      if ( desc )
6358
0
        tns_get_conv_info(pinfo)->last_describe = desc;
6359
0
      ctx->walk = true;
6360
0
      break;
6361
0
    }
6362
6363
0
    case SQLNET_ROW_TRANSF_HDR:
6364
0
    {
6365
      /* TTI_RXH: row transfer header, precedes the row data in a
6366
       * SELECT response. All numeric fields use the ub4 variable-
6367
       * length form. Layout cross-referenced with
6368
       * python-oracledb's _process_row_header. */
6369
0
      int v = 0, bv_len = 0, start;
6370
6371
0
      if ( is_request )
6372
0
        break;
6373
6374
      /* flag (ub1, skip) */
6375
0
      offset += 1;
6376
      /* number of requests */
6377
0
      start = offset;
6378
0
      offset += get_sb4_custom(tvb, offset, &v);
6379
0
      proto_tree_add_uint(data_tree, hf_tns_data_rxh_num_requests, tvb, start, offset - start, v);
6380
      /* iteration number */
6381
0
      start = offset;
6382
0
      offset += get_sb4_custom(tvb, offset, &v);
6383
0
      proto_tree_add_uint(data_tree, hf_tns_data_rxh_iter_num, tvb, start, offset - start, v);
6384
      /* number of iterations */
6385
0
      start = offset;
6386
0
      offset += get_sb4_custom(tvb, offset, &v);
6387
0
      proto_tree_add_uint(data_tree, hf_tns_data_rxh_num_iters, tvb, start, offset - start, v);
6388
      /* buffer length (ub4, skip) */
6389
0
      offset += get_sb4_custom(tvb, offset, &v);
6390
      /* bit vector: length + [repeated length byte + vector bytes],
6391
       * saying which columns the first row sends */
6392
0
      offset += get_sb4_custom(tvb, offset, &bv_len);
6393
0
      if ( bv_len > 0 )
6394
0
      {
6395
0
        offset += 1;       /* repeated length byte */
6396
0
        proto_tree_add_item(data_tree, hf_tns_data_bit_vector, tvb, offset, bv_len, ENC_NA);
6397
0
        ctx->bit_vector = tvb_memdup(pinfo->pool, tvb, offset, bv_len);
6398
0
        ctx->bit_vector_len = bv_len;
6399
0
        offset += bv_len;  /* bit vector */
6400
0
      }
6401
      /* rxhrid (bytes_with_length, skip) */
6402
0
      offset += get_field_with_length(tvb, pinfo, offset, NULL);
6403
0
      ctx->walk = true;
6404
0
      break;
6405
0
    }
6406
6407
0
    case SQLNET_BIT_VECTOR:
6408
0
    {
6409
      /* TTI_BVC: which columns the next row sends. A row that
6410
       * repeats values from the row before sends only the ones that
6411
       * changed, and the clear bits name those it left out. A ub2
6412
       * count of columns sent, then one bit per described column. */
6413
0
      tns_describe_t *desc;
6414
0
      int v = 0, start;
6415
6416
0
      if ( is_request )
6417
0
        break;
6418
6419
0
      start = offset;
6420
0
      offset += get_sb4_custom(tvb, offset, &v);
6421
0
      proto_tree_add_uint(data_tree, hf_tns_data_bvc_num_cols_sent, tvb, start, offset - start, v);
6422
0
      desc = tns_current_describe(pinfo);
6423
0
      if ( !desc )
6424
0
        break;
6425
0
      unsigned bv_len = (desc->num_cols + 7) / 8;
6426
0
      proto_tree_add_item(data_tree, hf_tns_data_bit_vector, tvb, offset, bv_len, ENC_NA);
6427
0
      ctx->bit_vector = tvb_memdup(pinfo->pool, tvb, offset, bv_len);
6428
0
      ctx->bit_vector_len = bv_len;
6429
0
      offset += bv_len;
6430
0
      ctx->walk = true;
6431
0
      break;
6432
0
    }
6433
6434
0
    case SQLNET_ROW_TRANSF_DATA:
6435
0
    {
6436
      /* TTI_RXD: row data for a SELECT result set — typically a
6437
       * TTI_FETCH continuation, where the describe (TTI_DCB) arrived
6438
       * in an earlier packet. Split each row into columns using the
6439
       * types remembered from that describe (threaded through
6440
       * conversation state); ordinary values are shown raw.
6441
       *
6442
       * The leading RXD token was already consumed above, so offset
6443
       * sits on the first row's first value. A row that follows a
6444
       * bit vector sends only the columns whose bit is set. */
6445
0
      tns_describe_t *desc;
6446
6447
0
      if ( is_request )
6448
0
        break;
6449
6450
0
      if ( !ctx->bind_dirs )
6451
0
      {
6452
        /* A PL/SQL block's re-execute is answered with no IOV:
6453
         * each iteration's OUT values come as a TTI_RXD of their
6454
         * own, read by the directions its first execute got. */
6455
0
        const tns_call_t *rc = tns_answered_call(pinfo);
6456
0
        if ( rc && (rc->func == TTI_REEXECUTE || rc->func == TTI_REEXECUTE_AND_FETCH)
6457
0
          && rc->binds && rc->bind_rec && rc->bind_rec->plsql && rc->bind_rec->dirs )
6458
0
        {
6459
0
          ctx->out_call = rc;
6460
0
          ctx->bind_dirs = rc->bind_rec->dirs;
6461
0
        }
6462
0
      }
6463
6464
0
      if ( ctx->bind_dirs )
6465
0
      {
6466
        /* The OUT and IN OUT bind values of a PL/SQL execute, in
6467
         * bind order, each followed by its sb4 return code. Out of
6468
         * a fetch, ROWID and UROWID come as strings and a LONG has
6469
         * no trailing indicators. */
6470
0
        proto_tree *ob_tree;
6471
0
        proto_item *ob_item;
6472
0
        int ob_start = offset;
6473
6474
0
        ob_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
6475
0
          ett_tns_out_binds, &ob_item, "Out Binds");
6476
0
        for ( uint32_t i = 0; i < ctx->out_call->num_binds
6477
0
          && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
6478
0
        {
6479
0
          if ( ctx->bind_dirs[i] == TNS_BIND_DIR_INPUT )
6480
0
            continue;
6481
0
          offset = dissect_tns_bind_value(tvb, pinfo, ob_tree, offset,
6482
0
            &ctx->out_call->binds[i], i + 1, true);
6483
0
        }
6484
0
        proto_item_set_len(ob_item, offset - ob_start);
6485
0
        ctx->bind_dirs = NULL;
6486
0
        ctx->walk = true;
6487
0
        break;
6488
0
      }
6489
6490
0
      const tns_call_t *rcall = tns_answered_call(pinfo);
6491
0
      if ( rcall && rcall->num_return > 0 && rcall->binds )
6492
0
      {
6493
        /* The values a DML RETURNING ... INTO returned: for each
6494
         * return bind a ub4 row count - every row the statement
6495
         * touched - then that many values, each followed by its
6496
         * sb4 actual length. */
6497
0
        proto_tree *rv_tree;
6498
0
        proto_item *rv_item;
6499
0
        int rv_start = offset, start;
6500
6501
0
        rv_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
6502
0
          ett_tns_out_binds, &rv_item, "Returned Values");
6503
0
        for ( uint32_t i = rcall->num_binds - rcall->num_return; i < rcall->num_binds
6504
0
          && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
6505
0
        {
6506
0
          int rows = 0;
6507
0
          offset += get_sb4_custom(tvb, offset, &rows);
6508
0
          for ( int j = 0; j < rows && tvb_reported_length_remaining(tvb, offset) > 0; j++ )
6509
0
          {
6510
0
            start = offset;
6511
0
            offset = dissect_tns_value(tvb, pinfo, rv_tree, offset, rcall->binds[i].type,
6512
0
              rcall->binds[i].csform, TNS_VALUE_OUT, i + 1, hf_tns_data_bind_value, "Bind");
6513
0
            offset = dissect_tns_actual_length(tvb, pinfo, rv_tree, offset, start,
6514
0
              rcall->binds[i].type);
6515
0
          }
6516
0
        }
6517
0
        proto_item_set_len(rv_item, offset - rv_start);
6518
0
        ctx->walk = true;
6519
0
        break;
6520
0
      }
6521
6522
0
      desc = tns_current_describe(pinfo);
6523
6524
0
      if ( desc && desc->num_cols > 0 )
6525
0
      {
6526
0
        int rownum = 0, first_row = 1;
6527
0
        while ( tvb_reported_length_remaining(tvb, offset) > 0 )
6528
0
        {
6529
0
          proto_tree *row_tree;
6530
0
          proto_item *row_item;
6531
0
          int r_start;
6532
6533
0
          if ( !first_row )
6534
0
          {
6535
0
            if ( tvb_get_uint8(tvb, offset) != SQLNET_ROW_TRANSF_DATA )
6536
0
              break;
6537
0
            offset += 1; /* RXD token for subsequent rows */
6538
0
          }
6539
0
          first_row = 0;
6540
6541
0
          r_start = offset;
6542
0
          row_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, -1,
6543
0
            ett_tns_rxd_row, &row_item, "Row %d", ++rownum);
6544
0
          for ( uint32_t c = 0; c < desc->num_cols
6545
0
            && tvb_reported_length_remaining(tvb, offset) > 0; c++ )
6546
0
          {
6547
0
            const tns_column_t *col = &desc->cols[c];
6548
0
            if ( ctx->bit_vector && c / 8 < ctx->bit_vector_len
6549
0
              && !(ctx->bit_vector[c / 8] & (1 << (c % 8))) )
6550
0
            {
6551
0
              proto_tree_add_bytes_format(row_tree, hf_tns_data_col_value,
6552
0
                tvb, offset, 0, NULL, "Column %u (%s): same as previous row",
6553
0
                c + 1, val_to_str_const(col->type, tns_data_types, "unknown"));
6554
0
              continue;
6555
0
            }
6556
            /* A column the describe gives no data length is
6557
             * NULL by definition (SELECT NULL, SELECT '')
6558
             * and sends no bytes at all - not even an empty
6559
             * DALC. LONG, LONG RAW and UROWID are the
6560
             * exceptions: they always carry their value. */
6561
0
            if ( col->data_len == 0 && col->type != TNS_DATATYPE_LONG
6562
0
              && col->type != TNS_DATATYPE_LONG_RAW
6563
0
              && col->type != TNS_DATATYPE_UROWID )
6564
0
            {
6565
0
              proto_tree_add_bytes_format(row_tree, hf_tns_data_col_value,
6566
0
                tvb, offset, 0, NULL, "Column %u (%s): NULL (no data length)",
6567
0
                c + 1, val_to_str_const(col->type, tns_data_types, "unknown"));
6568
0
              continue;
6569
0
            }
6570
0
            offset = dissect_tns_value(tvb, pinfo, row_tree, offset,
6571
0
              col->type, col->csform, TNS_VALUE_FETCH, c + 1, hf_tns_data_col_value, "Column");
6572
0
          }
6573
0
          proto_item_set_len(row_item, offset - r_start);
6574
          /* A bit vector covers one row only. */
6575
0
          ctx->bit_vector = NULL;
6576
0
        }
6577
0
        ctx->walk = true;
6578
0
      }
6579
0
      break;
6580
0
    }
6581
6582
0
    case SQLNET_USER_OCI_FUNC:
6583
0
    {
6584
0
      guint32 oci_id = 0;
6585
0
      tns_call_t *call;
6586
0
      int fun_start = offset - 1; /* the TTI_FUN byte */
6587
0
      proto_tree_add_item_ret_uint(data_tree, hf_tns_data_oci_id, tvb, offset, 1, ENC_BIG_ENDIAN, &oci_id);
6588
0
      offset += 1;
6589
0
      call = is_request ? tns_remember_call(pinfo, (uint8_t)oci_id) : NULL;
6590
      /* Name the specific OCI call in the Info column — otherwise every
6591
       * function call reads only as the generic "User OCI Functions". */
6592
0
      col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
6593
0
        val_to_str_ext_const(oci_id, &tns_data_oci_subfuncs_ext, "unknown"));
6594
0
      proto_tree_add_item(data_tree, hf_tns_data_tseq, tvb, offset, 1, ENC_BIG_ENDIAN);
6595
0
      offset += 1;
6596
0
      if ( !ctx->no_token )
6597
0
        offset = dissect_tns_call_token(tvb, pinfo, data_tree, offset);
6598
0
      if((oci_id == 115) || (oci_id == 118)){
6599
        /* The two authentication calls: the session key request
6600
         * (118) and the authentication itself (115). A pointer
6601
         * and a ub4 user name length, the ub4 mode, a pointer, the
6602
         * ub4 number of key/value pairs, two pointers, the user
6603
         * name, and the pairs - each a key and a value with two
6604
         * lengths and a ub4 flags word. The first call's pairs
6605
         * carry the client's identity (program, machine, terminal,
6606
         * process id, OS user), which is what the server records
6607
         * for the session; the second's the proof, the driver name
6608
         * and the session settings. */
6609
0
        int user_len = 0, mode = 0, num = 0, start;
6610
0
        proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 1, ENC_NA);
6611
0
        offset += 1;
6612
0
        offset += get_sb4_custom(tvb, offset, &user_len);
6613
0
        start = offset;
6614
0
        offset += get_sb4_custom(tvb, offset, &mode);
6615
0
        proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_auth_mode,
6616
0
          ett_tns_auth_mode, tns_auth_modes, (uint64_t)(uint32_t)mode);
6617
0
        offset += 1; /* pointer */
6618
0
        start = offset;
6619
0
        offset += get_sb4_custom(tvb, offset, &num);
6620
0
        proto_tree_add_uint(data_tree, hf_tns_data_opi_num_of_params, tvb, start, offset - start, num);
6621
0
        offset += 2; /* pointers */
6622
0
        if ( user_len > 0 )
6623
0
        {
6624
0
          const char *user = NULL;
6625
0
          start = offset;
6626
0
          offset += get_dalc_custom(tvb, pinfo, offset, &user);
6627
0
          if ( user )
6628
0
          {
6629
0
            proto_tree_add_string(data_tree, hf_tns_data_auth_user, tvb, start, offset - start, user);
6630
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", user);
6631
0
          }
6632
0
        }
6633
0
        for ( int i = 0; i < num && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
6634
0
        {
6635
0
          proto_tree *par_tree;
6636
0
          proto_item *par_ti;
6637
0
          const char *key = NULL, *value = NULL;
6638
0
          int v = 0, par_start = offset;
6639
6640
0
          par_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, -1,
6641
0
            ett_tns_opi_par, &par_ti, "Parameter %d", i + 1);
6642
0
          start = offset;
6643
0
          offset += get_field_with_length(tvb, pinfo, offset, &key);
6644
0
          if ( key )
6645
0
            proto_tree_add_string(par_tree, hf_tns_data_opi_param_name, tvb, start, offset - start, key);
6646
0
          start = offset;
6647
0
          offset += get_field_with_length(tvb, pinfo, offset, &value);
6648
0
          if ( value )
6649
0
            proto_tree_add_string(par_tree, hf_tns_data_opi_param_value, tvb, start, offset - start, value);
6650
0
          offset += get_sb4_custom(tvb, offset, &v); /* flags */
6651
0
          if ( key )
6652
0
            proto_item_append_text(par_ti, ": %s = %s", key, value ? value : "");
6653
0
          proto_item_set_len(par_ti, offset - par_start);
6654
0
        }
6655
0
      }
6656
0
      else if ( oci_id == TTI_KOD && tvb_bytes_exist(tvb, fun_start + TNS_KOD_FRAME, 4) )
6657
0
      {
6658
        /* An object-type describe, sent only by an OCI client: a
6659
         * ub4 LE opcode and a frame of zeros, then by name a ub4
6660
         * 2, the schema's buffer length (three times its
6661
         * characters, 0 for none) and, when there is one, the
6662
         * schema behind a length byte, a ub4 0, the name's buffer
6663
         * length and the name behind a length byte; by REF the
6664
         * REF of the type wanted. The bytes after them are not
6665
         * understood. */
6666
0
        uint32_t opcode;
6667
0
        int o = fun_start + TNS_KOD_FRAME, sys_type;
6668
6669
0
        if ( !PINFO_FD_VISITED(pinfo) )
6670
0
          tns_get_conv_info(pinfo)->oci_dialect = true;
6671
0
        proto_tree_add_item_ret_uint(data_tree, hf_tns_data_kod_opcode, tvb, fun_start + 3, 4, ENC_LITTLE_ENDIAN, &opcode);
6672
0
        if ( opcode == TNS_KOD_BY_NAME && tvb_bytes_exist(tvb, o, 8) )
6673
0
        {
6674
0
          const char *schema = NULL, *name;
6675
0
          int p = o + 8;
6676
0
          uint8_t len;
6677
6678
0
          if ( tvb_get_letohl(tvb, o + 4) != 0 )
6679
0
          {
6680
0
            len = tvb_get_uint8(tvb, p);
6681
0
            proto_tree_add_item_ret_string(data_tree, hf_tns_data_kod_schema, tvb, p + 1, len, ENC_UTF_8, pinfo->pool, (const uint8_t **)&schema);
6682
0
            p += 1 + len;
6683
0
          }
6684
0
          len = tvb_get_uint8(tvb, p + 8);
6685
0
          proto_tree_add_item_ret_string(data_tree, hf_tns_data_kod_name, tvb, p + 9, len, ENC_UTF_8, pinfo->pool, (const uint8_t **)&name);
6686
0
          if ( schema )
6687
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " [%s.%s]", schema, name);
6688
0
          else
6689
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", name);
6690
0
        }
6691
0
        else if ( opcode == TNS_KOD_BY_REF )
6692
0
          dissect_tns_kod_ref(tvb, data_tree, o, hf_tns_data_kod_oid, &sys_type);
6693
0
        offset = tvb_reported_length(tvb);
6694
0
      }
6695
0
      else if ( oci_id == TTI_FETCH && tns_is_oci(pinfo) && tvb_bytes_exist(tvb, fun_start + 3, 8) )
6696
0
      {
6697
        /* An OCI client's fetch: the cursor id and the row count
6698
         * as fixed-width little-endian ub4s, right after the
6699
         * sequence number. The count is a hard limit - the
6700
         * client sizes its fetch buffer to it. */
6701
0
        proto_tree_add_item(data_tree, hf_tns_cursor, tvb, fun_start + 3, 4, ENC_LITTLE_ENDIAN);
6702
0
        proto_tree_add_item(data_tree, hf_tns_data_fetch_rows, tvb, fun_start + 7, 4, ENC_LITTLE_ENDIAN);
6703
0
        offset = fun_start + 11;
6704
0
      }
6705
0
      else if ( oci_id == TTI_FETCH )
6706
0
      {
6707
        /* TTI_FETCH: fetch more rows from an open cursor.
6708
         * [TTI_FUN, TTI_FETCH, seq] then cursor id and the row
6709
         * count, both ub4. */
6710
0
        int v = 0, start;
6711
6712
0
        start = offset;
6713
0
        offset += get_sb4_custom(tvb, offset, &v);
6714
0
        proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, start, offset - start, v);
6715
0
        start = offset;
6716
0
        offset += get_sb4_custom(tvb, offset, &v);
6717
0
        proto_tree_add_uint(data_tree, hf_tns_data_fetch_rows, tvb, start, offset - start, v);
6718
0
      }
6719
0
      else if ( oci_id == TTI_PIPELINE_END )
6720
0
      {
6721
        /* ends a pipeline begun by the pipeline-begin piggyback: a
6722
         * ub4 id, unused */
6723
0
        int v = 0;
6724
0
        offset += get_sb4_custom(tvb, offset, &v);
6725
0
      }
6726
0
      else if ( oci_id == TTI_SESSION_RELEASE )
6727
0
      {
6728
        /* DRCP: hand the session back to the pool - a tag name
6729
         * (a pointer and a length byte) and the release mode */
6730
0
        int v = 0, start;
6731
0
        uint8_t tag_ptr = tvb_get_uint8(tvb, offset);
6732
0
        uint8_t tag_len = tvb_get_uint8(tvb, offset + 1);
6733
0
        offset += 2;
6734
0
        if ( tag_ptr && tag_len > 0 )
6735
0
        {
6736
0
          proto_tree_add_item(data_tree, hf_tns_data_release_tag, tvb, offset, tag_len, ENC_UTF_8);
6737
0
          offset += tag_len;
6738
0
        }
6739
0
        start = offset;
6740
0
        offset += get_sb4_custom(tvb, offset, &v);
6741
0
        proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_release_mode,
6742
0
          ett_tns_release_mode, tns_release_modes, (uint64_t)(uint32_t)v);
6743
0
      }
6744
0
      else if ( oci_id == TTI_AQ_ARRAY )
6745
0
        offset = dissect_tns_aq_array_call(tvb, pinfo, data_tree, offset);
6746
0
      else if ( oci_id == TTI_AQ_ENQUEUE || oci_id == TTI_AQ_DEQUEUE )
6747
0
        offset = dissect_tns_aq_call(tvb, pinfo, data_tree, offset, oci_id);
6748
0
      else if ( oci_id == TTI_TPC_TXN_SWITCH || oci_id == TTI_TPC_TXN_CHANGE_STATE )
6749
0
        offset = dissect_tns_tpc_call(tvb, pinfo, data_tree, offset, oci_id);
6750
0
      else if ( oci_id == TTI_REEXECUTE && tns_is_oci(pinfo) && tvb_bytes_exist(tvb, fun_start + 3, 8) )
6751
0
      {
6752
        /* An OCI client's re-execute, as sqlplus runs a block
6753
         * again for each SERVEROUTPUT batch after the first: the
6754
         * cursor id and the execution count as fixed-width
6755
         * little-endian ub4s, eight zero bytes, then a TTI_RXD
6756
         * row of the values of the binds that send one. */
6757
0
        proto_tree_add_item(data_tree, hf_tns_cursor, tvb, fun_start + 3, 4, ENC_LITTLE_ENDIAN);
6758
0
        proto_tree_add_item(data_tree, hf_tns_data_reexec_iterations, tvb, fun_start + 7, 4, ENC_LITTLE_ENDIAN);
6759
0
        offset = fun_start + 11;
6760
0
      }
6761
0
      else if ( oci_id == TTI_ALL8 && tns_is_oci(pinfo) && tvb_bytes_exist(tvb, fun_start + TNS_OCI_ALL8_IND, 8)
6762
0
        && tvb_get_ntoh64(tvb, fun_start + TNS_OCI_ALL8_IND) == 0 )
6763
0
      {
6764
        /* An OCI client's execute of an open cursor by its id,
6765
         * as sqlplus prints a REF CURSOR variable: no SQL, so no
6766
         * pointer where the first indicator goes. The options and
6767
         * the cursor id sit where every other OCI execute has
6768
         * them, and the al8i4 array where the SQL's length byte
6769
         * would be. */
6770
0
        bool wide = tvb_bytes_exist(tvb, fun_start + TNS_OCI_ALL8_IND2_WIDE, 8)
6771
0
          && tvb_get_ntoh64(tvb, fun_start + TNS_OCI_ALL8_IND2_WIDE) == TNS_OCI_INDICATOR;
6772
0
        bool narrow = !wide && tvb_bytes_exist(tvb, fun_start + TNS_OCI_ALL8_IND2_NARROW, 8)
6773
0
          && tvb_get_ntoh64(tvb, fun_start + TNS_OCI_ALL8_IND2_NARROW) == TNS_OCI_INDICATOR;
6774
6775
0
        proto_tree_add_string(data_tree, hf_tns_data_all8_oci_preamble, tvb, fun_start, 0, "OCI, by cursor id");
6776
0
        proto_tree_add_bitmask(data_tree, tvb, fun_start + TNS_OCI_ALL8_OPTIONS, hf_tns_data_all8_options,
6777
0
          ett_tns_all8_options, tns_all8_options, ENC_LITTLE_ENDIAN);
6778
0
        proto_tree_add_item(data_tree, hf_tns_cursor, tvb, fun_start + TNS_OCI_ALL8_CURSOR, 4, ENC_LITTLE_ENDIAN);
6779
0
        if ( wide )
6780
0
          dissect_tns_oci_al8i4(tvb, data_tree, fun_start + 195,
6781
0
            tvb_get_letohl(tvb, fun_start + TNS_OCI_ALL8_AL8I4_WIDE));
6782
0
        else if ( narrow && tns_field_version(pinfo) != TNS_FV_10_2 )
6783
0
          dissect_tns_oci_al8i4(tvb, data_tree, fun_start + (tns_is_oci_12c(pinfo) ? 239 : 175),
6784
0
            tvb_get_letohl(tvb, fun_start + TNS_OCI_ALL8_AL8I4_NARROW));
6785
0
        offset = fun_start + TNS_OCI_ALL8_IND;
6786
0
      }
6787
0
      else if ( oci_id == TTI_REEXECUTE || oci_id == TTI_REEXECUTE_AND_FETCH )
6788
0
      {
6789
        /* Re-execute of a cursor whose statement already ran and
6790
         * whose bind types did not change: the cursor id, the
6791
         * iteration count (the prefetch size for 78, the number
6792
         * of executions for 4) and two options words, then one
6793
         * TTI_RXD row of values per iteration with no bind
6794
         * descriptors - the values are typed by the execute that
6795
         * opened the cursor. */
6796
0
        int v = 0, cursor = 0, start;
6797
6798
0
        start = offset;
6799
0
        offset += get_sb4_custom(tvb, offset, &cursor);
6800
0
        proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, start, offset - start, cursor);
6801
0
        start = offset;
6802
0
        offset += get_sb4_custom(tvb, offset, &v);
6803
0
        proto_tree_add_uint(data_tree, oci_id == TTI_REEXECUTE_AND_FETCH ?
6804
0
          hf_tns_data_all8_prefetch : hf_tns_data_reexec_iterations,
6805
0
          tvb, start, offset - start, v);
6806
0
        start = offset;
6807
0
        offset += get_sb4_custom(tvb, offset, &v);
6808
0
        proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_all8_options,
6809
0
          ett_tns_all8_options, tns_all8_options, (uint64_t)(uint32_t)v);
6810
0
        start = offset;
6811
0
        offset += get_sb4_custom(tvb, offset, &v);
6812
0
        proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_reexec_options2,
6813
0
          ett_tns_reexec_options2, tns_reexec_options2, (uint64_t)(uint32_t)v);
6814
6815
0
        tns_binds_t *binds = tns_lookup_cursor_binds(pinfo, cursor);
6816
0
        if ( binds && tvb_reported_length_remaining(tvb, offset) > 0 )
6817
0
        {
6818
0
          proto_item *binds_item;
6819
0
          proto_tree *binds_tree;
6820
0
          int binds_start = offset;
6821
6822
0
          binds_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
6823
0
            ett_tns_binds, &binds_item, "Binds");
6824
          /* RETURNING ... INTO binds send no value, nor does a
6825
           * block's OUT bind */
6826
0
          offset = dissect_tns_bind_rows(tvb, pinfo, binds_tree, offset, binds->cols,
6827
0
            binds->count - binds->num_return, binds->plsql,
6828
0
            binds->plsql ? binds->dirs : NULL);
6829
0
          proto_item_set_len(binds_item, offset - binds_start);
6830
0
        }
6831
0
        if ( call && binds )
6832
0
        {
6833
0
          call->num_binds = binds->count;
6834
0
          call->num_return = binds->num_return;
6835
0
          call->binds = binds->cols;
6836
0
          call->bind_rec = binds;
6837
0
        }
6838
0
      }
6839
0
      else if ( oci_id == TTI_ALL8 && ((tvb_bytes_exist(tvb, fun_start + TNS_OCI_ALL8_IND, 8)
6840
0
        && tvb_get_ntoh64(tvb, fun_start + TNS_OCI_ALL8_IND) == TNS_OCI_INDICATOR)
6841
0
        || (tns_is_oci(pinfo) && tns_field_version(pinfo) == TNS_FV_10_2)) )
6842
0
      {
6843
        /* An OCI client's execute (sqlplus and other thick
6844
         * clients): a fixed preamble of 8-byte pointer indicators
6845
         * FE FF FF FF FF FF FF FF with little-endian scalar slots
6846
         * between them, and the ub1-length-prefixed SQL at the
6847
         * end. Offsets count from the TTI_FUN byte. The scalar
6848
         * slots are 8 bytes wide or 4, fixed for a connection;
6849
         * the second indicator tells which - it sits at 27 in the
6850
         * wide form and 23 in the narrow one, and the two cannot
6851
         * both hold. The options, cursor id and SQL length
6852
         * precede every slot and do not move; the bind count and
6853
         * the SQL do. The options are the thin client's bits,
6854
         * little-endian: SET AUTOCOMMIT ON sets the commit bit on
6855
         * each statement rather than sending a commit of its own.
6856
         * A session at the 12c band inserts 64 zero bytes ahead
6857
         * of a narrow preamble's SQL, which moves from 176 to
6858
         * 240; the byte before the SQL is its length, never
6859
         * zero, so which one holds shows.
6860
         *
6861
         * sqlplus 10.2 sends a third form: narrow, but with the
6862
         * SQL at 148. Its pointer fields hold real addresses, not
6863
         * the indicator, so only the session's field version
6864
         * tells this form apart. */
6865
0
        int base = fun_start, bind_count_off, sql_off;
6866
0
        uint32_t cursor, sql_len_decl, bind_count;
6867
0
        bool wide, band_12c = false, form_10_2 = false, sql_read = false;
6868
6869
0
        if ( tns_is_oci(pinfo) && tns_field_version(pinfo) == TNS_FV_10_2 )
6870
0
        {
6871
0
          wide = false;
6872
0
          form_10_2 = true;
6873
0
        }
6874
0
        else if ( tvb_bytes_exist(tvb, base + TNS_OCI_ALL8_IND2_WIDE, 8)
6875
0
          && tvb_get_ntoh64(tvb, base + TNS_OCI_ALL8_IND2_WIDE) == TNS_OCI_INDICATOR )
6876
0
          wide = true;
6877
0
        else if ( tvb_bytes_exist(tvb, base + TNS_OCI_ALL8_IND2_NARROW, 8)
6878
0
          && tvb_get_ntoh64(tvb, base + TNS_OCI_ALL8_IND2_NARROW) == TNS_OCI_INDICATOR )
6879
0
          wide = false;
6880
0
        else
6881
0
          break;
6882
0
        if ( !PINFO_FD_VISITED(pinfo) )
6883
0
          tns_get_conv_info(pinfo)->oci_dialect = true;
6884
6885
0
        cursor = tvb_get_letohl(tvb, base + TNS_OCI_ALL8_CURSOR);
6886
        /* the SQL length, as the client's character set has it */
6887
0
        sql_len_decl = tvb_get_letohl(tvb, base + TNS_OCI_ALL8_SQLLEN3);
6888
0
        bind_count_off = base + (wide ? 83 : 71);
6889
0
        sql_off = base + (form_10_2 ? 148 : wide ? 196 : 176);
6890
0
        if ( !wide && !form_10_2 && sql_len_decl > 0 && tvb_bytes_exist(tvb, base + 239, 1)
6891
0
          && tvb_get_uint8(tvb, base + 175) == 0 )
6892
0
        {
6893
0
          uint8_t prefix = tvb_get_uint8(tvb, base + 239);
6894
0
          if ( tns_oci_sql_length_matches(prefix, sql_len_decl) )
6895
0
          {
6896
0
            band_12c = true;
6897
0
            sql_off = base + 240;
6898
0
            if ( !PINFO_FD_VISITED(pinfo) )
6899
0
              tns_get_conv_info(pinfo)->oci_band_12c = true;
6900
0
          }
6901
0
        }
6902
0
        proto_tree_add_string(data_tree, hf_tns_data_all8_oci_preamble, tvb, base, 0,
6903
0
          wide ? "OCI, wide (8-byte slots)" : band_12c ? "OCI, narrow (4-byte slots), 12c band"
6904
0
          : form_10_2 ? "OCI, narrow (4-byte slots), 10.2" : "OCI, narrow (4-byte slots)");
6905
0
        proto_tree_add_bitmask(data_tree, tvb, base + TNS_OCI_ALL8_OPTIONS, hf_tns_data_all8_options,
6906
0
          ett_tns_all8_options, tns_all8_options, ENC_LITTLE_ENDIAN);
6907
0
        proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, base + TNS_OCI_ALL8_CURSOR, 4, cursor);
6908
0
        bind_count = tvb_get_letohl(tvb, bind_count_off);
6909
0
        proto_tree_add_uint(data_tree, hf_tns_data_all8_bind_count, tvb, bind_count_off, 4, bind_count);
6910
0
        if ( sql_len_decl > 0 && tvb_bytes_exist(tvb, sql_off - 1, 1) )
6911
0
        {
6912
0
          const char *sql = NULL;
6913
0
          int start = sql_off - 1;
6914
0
          uint8_t prefix = tvb_get_uint8(tvb, start);
6915
6916
0
          if ( tns_oci_sql_length_matches(prefix, sql_len_decl) )
6917
0
          {
6918
0
            offset = start + get_dalc_custom(tvb, pinfo, start, &sql);
6919
0
            if ( sql )
6920
0
            {
6921
              /* sqlplus NUL-terminates its own queries; the
6922
               * string ends there */
6923
0
              proto_tree_add_string(data_tree, hf_tns_data_all8_sql, tvb, start, offset - start, sql);
6924
0
              col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", sql);
6925
0
            }
6926
0
            sql_read = true;
6927
0
          }
6928
0
        }
6929
        /* Behind the SQL: the al8i4 array of ub4s, one descriptor
6930
         * per bind, then the TTI_RXD row of values. */
6931
0
        uint32_t al8i4_len = tvb_get_letohl(tvb, base + (wide ? TNS_OCI_ALL8_AL8I4_WIDE : TNS_OCI_ALL8_AL8I4_NARROW));
6932
0
        int remaining = tvb_reported_length_remaining(tvb, offset);
6933
0
        if ( sql_read )
6934
0
          dissect_tns_oci_al8i4(tvb, data_tree, offset, al8i4_len);
6935
0
        if ( sql_read && bind_count > 0 && remaining > 0 && al8i4_len <= (uint32_t)remaining / 4
6936
0
          && bind_count <= (uint32_t)(remaining - 4 * al8i4_len) / TNS_OCI_OAC_MIN_LEN )
6937
0
        {
6938
0
          proto_tree *binds_tree, *bind_tree;
6939
0
          proto_item *binds_item, *bind_item;
6940
0
          int binds_start = offset;
6941
0
          bool desc_12c = band_12c || tns_field_version(pinfo) >= TNS_FV_12_1 || tns_is_oci_12c(pinfo);
6942
0
          bool plain = true;
6943
0
          tns_column_t *bcols = wmem_alloc0_array(pinfo->pool, tns_column_t, bind_count);
6944
0
          bool *repeat = wmem_alloc0_array(pinfo->pool, bool, bind_count);
6945
6946
0
          offset += 4 * al8i4_len;
6947
0
          binds_tree = proto_tree_add_subtree(data_tree, tvb, binds_start, -1,
6948
0
            ett_tns_binds, &binds_item, "Binds");
6949
0
          for ( uint32_t i = 0; i < bind_count; i++ )
6950
0
          {
6951
0
            int b_start = offset;
6952
0
            bind_tree = proto_tree_add_subtree_format(binds_tree, tvb, offset, -1,
6953
0
              ett_tns_bind, &bind_item, "Bind %u: %s", i + 1,
6954
0
              val_to_str_const(tvb_get_uint8(tvb, offset + 1), tns_data_types, "unknown"));
6955
0
            offset = dissect_tns_oci_oac(tvb, bind_tree, offset, desc_12c, &bcols[i], &repeat[i]);
6956
0
            proto_item_set_len(bind_item, offset - b_start);
6957
0
            if ( !repeat[i] && !tns_oci_bind_is_plain(bcols[i].type)
6958
0
              && bcols[i].type != TNS_DATATYPE_REFCURSOR )
6959
0
              plain = false;
6960
0
          }
6961
          /* The reply to a block with OUT binds is typed by them. */
6962
0
          if ( call )
6963
0
          {
6964
0
            call->num_binds = bind_count;
6965
0
            call->binds = (tns_column_t *)wmem_memdup(wmem_file_scope(), bcols,
6966
0
              bind_count * sizeof(tns_column_t));
6967
0
          }
6968
0
          if ( plain && tvb_reported_length_remaining(tvb, offset) > 0
6969
0
            && tvb_get_uint8(tvb, offset) == SQLNET_ROW_TRANSF_DATA )
6970
0
            offset = dissect_tns_oci_bind_row(tvb, pinfo, binds_tree, offset, bcols, repeat, bind_count);
6971
0
          proto_item_set_len(binds_item, offset - binds_start);
6972
0
        }
6973
0
      }
6974
0
      else if ( oci_id == TTI_ALL8 )
6975
0
      {
6976
        /* TTI_ALL8: the generic SQL execute — SELECT, DML and
6977
         * PL/SQL all ride this call, in the Oracle 11g shape of a
6978
         * thin client, whose integers use the ub4 variable-length
6979
         * form. The bind (or define) descriptors and the value
6980
         * rows follow the al8 array. */
6981
0
        int v = 0, options = 0, cursor = 0, query_len = 0, all8_len = 0;
6982
0
        int fetch = 0, bind_count = 0, define_count = 0, start;
6983
0
        const uint8_t *sql = NULL;
6984
0
        uint8_t query_flag;
6985
6986
        /* options (ub4) + flag breakdown */
6987
0
        start = offset;
6988
0
        offset += get_sb4_custom(tvb, offset, &options);
6989
0
        proto_tree_add_bitmask_value(data_tree, tvb, start, hf_tns_data_all8_options,
6990
0
          ett_tns_all8_options, tns_all8_options, (uint64_t)(uint32_t)options);
6991
        /* An execute that asks for no work is a parse: the client
6992
         * wants the statement checked, not run. The PARSE bit does
6993
         * not say so - it rides along with EXECUTE on the first
6994
         * execute of any statement, and a parse of a statement the
6995
         * client already has cached sets no bit at all. */
6996
0
        if ( !(options & (TNS_EXEC_OPTION_EXECUTE | TNS_EXEC_OPTION_DEFINE
6997
0
          | TNS_EXEC_OPTION_FETCH)) )
6998
0
        {
6999
0
          proto_item_set_generated(proto_tree_add_boolean(data_tree,
7000
0
            hf_tns_data_all8_parse_only, tvb, start, offset - start, true));
7001
0
          col_append_str(pinfo->cinfo, COL_INFO, " [parse only]");
7002
0
        }
7003
        /* cursor id (ub4) */
7004
0
        start = offset;
7005
0
        offset += get_sb4_custom(tvb, offset, &cursor);
7006
0
        proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, start, offset - start, cursor);
7007
        /* query present flag (ub1) */
7008
0
        query_flag = tvb_get_uint8(tvb, offset);
7009
0
        offset += 1;
7010
        /* query length (ub4) */
7011
0
        offset += get_sb4_custom(tvb, offset, &query_len);
7012
        /* all8 present flag (ub1) */
7013
0
        offset += 1;
7014
        /* all8 length (ub4) */
7015
0
        offset += get_sb4_custom(tvb, offset, &all8_len);
7016
        /* two reserved bytes */
7017
0
        offset += 2;
7018
        /* long max value (ub4, skip) */
7019
0
        offset += get_sb4_custom(tvb, offset, &v);
7020
        /* fetch rows (ub4) */
7021
0
        start = offset;
7022
0
        offset += get_sb4_custom(tvb, offset, &fetch);
7023
0
        proto_tree_add_uint(data_tree, hf_tns_data_all8_fetch_rows, tvb, start, offset - start, fetch);
7024
        /* max value (ub4, skip) */
7025
0
        offset += get_sb4_custom(tvb, offset, &v);
7026
        /* bind indicator (ub1) */
7027
0
        offset += 1;
7028
        /* bind count (ub4) */
7029
0
        start = offset;
7030
0
        offset += get_sb4_custom(tvb, offset, &bind_count);
7031
0
        proto_tree_add_uint(data_tree, hf_tns_data_all8_bind_count, tvb, start, offset - start, bind_count);
7032
        /* The count comes off the wire and sizes an allocation
7033
         * further down, so a count larger than the data left
7034
         * cannot be real - report it and decode no binds. */
7035
0
        if ( bind_count < 0 ||
7036
0
             (unsigned)bind_count > tvb_reported_length_remaining(tvb, offset) )
7037
0
        {
7038
0
          proto_tree_add_expert(data_tree, pinfo, &ei_tns_data_count_too_large,
7039
0
            tvb, start, offset - start);
7040
0
          bind_count = 0;
7041
0
        }
7042
        /* five reserved bytes */
7043
0
        offset += 5;
7044
        /* define-columns present flag (ub1) */
7045
0
        offset += 1;
7046
        /* define-columns count (ub4) */
7047
0
        start = offset;
7048
0
        offset += get_sb4_custom(tvb, offset, &define_count);
7049
0
        proto_tree_add_uint(data_tree, hf_tns_data_all8_define_count, tvb, start, offset - start, define_count);
7050
0
        if ( define_count < 0 ||
7051
0
             (unsigned)define_count > tvb_reported_length_remaining(tvb, offset) )
7052
0
        {
7053
0
          proto_tree_add_expert(data_tree, pinfo, &ei_tns_data_count_too_large,
7054
0
            tvb, start, offset - start);
7055
0
          define_count = 0;
7056
0
        }
7057
        /* registration id (low half), the al8objlist / al8objlen /
7058
         * al8blv pointers, al8blvl, the al8dnam pointer, al8dnaml
7059
         * and the registration id's high half */
7060
0
        offset += get_sb4_custom(tvb, offset, &v);
7061
0
        offset += 3;
7062
0
        offset += get_sb4_custom(tvb, offset, &v);
7063
0
        offset += 1;
7064
0
        offset += get_sb4_custom(tvb, offset, &v);
7065
0
        offset += get_sb4_custom(tvb, offset, &v);
7066
        /* 12.1 adds the per-row DML count block (a pointer, the
7067
         * execution count, a pointer), 12.2 the SQL signature and
7068
         * SQL id fields, 12.2 ext 1 the chunk ids */
7069
0
        unsigned fv = tns_field_version(pinfo);
7070
0
        if ( fv >= TNS_FV_12_1 )
7071
0
        {
7072
0
          offset += 1;
7073
0
          offset += get_sb4_custom(tvb, offset, &v);
7074
0
          offset += 1;
7075
0
        }
7076
0
        if ( fv >= TNS_FV_12_2 )
7077
0
        {
7078
0
          offset += 1;
7079
0
          offset += get_sb4_custom(tvb, offset, &v);
7080
0
          offset += 1;
7081
0
          offset += get_sb4_custom(tvb, offset, &v);
7082
0
          offset += 1;
7083
0
        }
7084
0
        if ( fv >= TNS_FV_12_2_EXT1 )
7085
0
        {
7086
0
          offset += 1;
7087
0
          offset += get_sb4_custom(tvb, offset, &v);
7088
0
        }
7089
        /* SQL text: a flat run of query_len bytes on 11g, length
7090
         * prefixed (and chunked when long) from 12.1 */
7091
0
        if ( query_flag && query_len > 0 && fv >= TNS_FV_12_1 )
7092
0
        {
7093
0
          const char *text = NULL;
7094
0
          start = offset;
7095
0
          offset += get_dalc_custom(tvb, pinfo, offset, &text);
7096
0
          if ( text )
7097
0
          {
7098
0
            sql = (const uint8_t *)text;
7099
0
            proto_tree_add_string(data_tree, hf_tns_data_all8_sql, tvb, start, offset - start, text);
7100
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", text);
7101
0
          }
7102
0
        }
7103
0
        else if ( query_flag && query_len > 0 )
7104
0
        {
7105
0
          proto_tree_add_item_ret_string(data_tree, hf_tns_data_all8_sql, tvb,
7106
0
            offset, query_len, ENC_UTF_8|ENC_NA, pinfo->pool, &sql);
7107
0
          col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", sql);
7108
0
          offset += query_len;
7109
0
        }
7110
        /* al8i4 option array: all8_len ub4 elements. Slot 1 is
7111
         * the execution count for DML but the number of rows to
7112
         * prefetch for a query, and slot 7 says which - so read
7113
         * the array before showing any of it. */
7114
0
        {
7115
0
          int al8i4[13] = {0}, al8i4_start[13] = {0}, al8i4_len[13] = {0};
7116
0
          int i4_start = offset;
7117
0
          proto_tree *i4_tree;
7118
0
          proto_item *i4_item;
7119
7120
0
          for ( int i = 0; i < all8_len && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
7121
0
          {
7122
0
            start = offset;
7123
0
            offset += get_sb4_custom(tvb, offset, &v);
7124
0
            if ( i < (int)array_length(al8i4) )
7125
0
            {
7126
0
              al8i4[i] = v;
7127
0
              al8i4_start[i] = start;
7128
0
              al8i4_len[i] = offset - start;
7129
0
            }
7130
0
          }
7131
0
          if ( all8_len >= (int)array_length(al8i4) )
7132
0
          {
7133
0
            i4_tree = proto_tree_add_subtree(data_tree, tvb, i4_start, offset - i4_start,
7134
0
              ett_tns_all8_i4, &i4_item, "Execute Arguments (al8i4)");
7135
0
            proto_tree_add_uint(i4_tree, al8i4[7] ? hf_tns_data_all8_prefetch : hf_tns_data_all8_iterations,
7136
0
              tvb, al8i4_start[1], al8i4_len[1], al8i4[1]);
7137
0
            proto_tree_add_boolean(i4_tree, hf_tns_data_all8_is_query,
7138
0
              tvb, al8i4_start[7], al8i4_len[7], al8i4[7]);
7139
0
            proto_tree_add_bitmask_value(i4_tree, tvb, al8i4_start[9], hf_tns_data_all8_exec_flags,
7140
0
              ett_tns_all8_exec_flags, tns_all8_exec_flags, (uint64_t)(uint32_t)al8i4[9]);
7141
0
            proto_tree_add_uint(i4_tree, hf_tns_data_all8_fetch_orientation,
7142
0
              tvb, al8i4_start[10], al8i4_len[10], al8i4[10]);
7143
0
            proto_tree_add_uint(i4_tree, hf_tns_data_all8_fetch_pos,
7144
0
              tvb, al8i4_start[11], al8i4_len[11], al8i4[11]);
7145
0
            if ( call )
7146
0
              call->exec_flags = (uint32_t)al8i4[9];
7147
0
          }
7148
0
        }
7149
7150
        /* Bind section: one bare OAC descriptor per bind column,
7151
         * then one TTI_RXD row of values per iteration. A cached
7152
         * re-execute may leave the descriptors out and rely on
7153
         * the ones the cursor was opened with. Whether they are
7154
         * there is decided by the wire, not by the SQL text: an
7155
         * execute with no SQL often still carries them (every
7156
         * executemany after the first), and they are absent
7157
         * exactly when the bind area starts on a TTI_RXD, in
7158
         * which case the types remembered for the cursor apply.
7159
         *
7160
         * An execute that opens a new cursor (cursor id 0) learns
7161
         * its id only from the status that answers it, so its
7162
         * bind types wait for that. */
7163
0
        tns_conv_info_t *tns_info = NULL;
7164
0
        if ( !PINFO_FD_VISITED(pinfo) )
7165
0
        {
7166
0
          tns_info = tns_get_conv_info(pinfo);
7167
0
          if ( cursor == 0 )
7168
0
            tns_info->pending_binds = NULL;
7169
0
        }
7170
0
        if ( bind_count > 0 && tvb_reported_length_remaining(tvb, offset) > 0
7171
0
          && tvb_get_uint8(tvb, offset) == SQLNET_ROW_TRANSF_DATA )
7172
0
        {
7173
0
          tns_binds_t *binds = cursor ? tns_lookup_cursor_binds(pinfo, cursor) : NULL;
7174
0
          if ( binds && binds->count == (uint32_t)bind_count )
7175
0
          {
7176
0
            if ( call )
7177
0
            {
7178
0
              call->num_binds = binds->count;
7179
0
              call->num_return = binds->num_return;
7180
0
              call->binds = binds->cols;
7181
0
              call->bind_rec = binds;
7182
0
            }
7183
0
            proto_item *binds_item;
7184
0
            proto_tree *binds_tree;
7185
0
            int binds_start = offset;
7186
7187
0
            binds_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
7188
0
              ett_tns_binds, &binds_item, "Binds");
7189
0
            offset = dissect_tns_bind_rows(tvb, pinfo, binds_tree, offset, binds->cols,
7190
0
              binds->count - binds->num_return, binds->plsql, NULL);
7191
0
            proto_item_set_len(binds_item, offset - binds_start);
7192
0
          }
7193
0
        }
7194
0
        else if ( bind_count > 0 && tvb_reported_length_remaining(tvb, offset) > 0 )
7195
0
        {
7196
0
          proto_tree *binds_tree, *bind_tree;
7197
0
          proto_item *binds_item, *bind_item;
7198
0
          int binds_start = offset;
7199
0
          tns_column_t *bcols;
7200
7201
0
          bcols = wmem_alloc0_array(tns_info ? wmem_file_scope() : pinfo->pool, tns_column_t, bind_count);
7202
0
          binds_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
7203
0
            ett_tns_binds, &binds_item, "Binds");
7204
7205
0
          for ( int i = 0; i < bind_count && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
7206
0
          {
7207
0
            int b_start = offset;
7208
0
            uint8_t btype = tvb_get_uint8(tvb, offset);
7209
0
            bind_tree = proto_tree_add_subtree_format(binds_tree, tvb, offset, -1,
7210
0
              ett_tns_bind, &bind_item, "Bind %d: %s", i + 1,
7211
0
              val_to_str_const(btype, tns_data_types, "unknown"));
7212
0
            offset = dissect_tns_oac(tvb, pinfo, bind_tree, offset, &bcols[i]);
7213
            /* Below 12.1 the descriptor of a bind whose value
7214
             * rides under a locator - a CLOB, BLOB, JSON or
7215
             * VECTOR - carries a trailing byte the others
7216
             * lack; 12.1 drops it, and from 12.2 every OAC
7217
             * carries an oaccolid, which the OAC decoder
7218
             * reads. */
7219
0
            if ( (btype == TNS_DATATYPE_CLOB || btype == TNS_DATATYPE_BLOB
7220
0
              || btype == TNS_DATATYPE_JSON || btype == TNS_DATATYPE_VECTOR)
7221
0
              && tns_field_version(pinfo) < TNS_FV_12_1 )
7222
0
              offset += 1;
7223
0
            proto_item_set_len(bind_item, offset - b_start);
7224
0
          }
7225
7226
          /* A DML RETURNING ... INTO statement sends no values for
7227
           * its return binds, the last ones. */
7228
0
          unsigned num_return = sql ? tns_count_return_binds((const char *)sql) : 0;
7229
0
          if ( num_return > (unsigned)bind_count )
7230
0
            num_return = 0;
7231
7232
0
          if ( call )
7233
0
          {
7234
0
            call->num_binds = bind_count;
7235
0
            call->num_return = num_return;
7236
0
            call->binds = bcols;
7237
0
          }
7238
7239
          /* Remember the types for later executes of the cursor
7240
           * that leave the descriptors out. */
7241
0
          if ( tns_info )
7242
0
          {
7243
0
            tns_binds_t *binds = wmem_new0(wmem_file_scope(), tns_binds_t);
7244
0
            binds->count = bind_count;
7245
0
            binds->num_return = num_return;
7246
0
            binds->plsql = !(options & TNS_EXEC_OPTION_NOT_PLSQL);
7247
0
            binds->cols = bcols;
7248
0
            if ( call )
7249
0
              call->bind_rec = binds;
7250
0
            if ( cursor != 0 )
7251
0
              wmem_map_insert(tns_info->cursor_binds, GUINT_TO_POINTER(cursor), binds);
7252
0
            else
7253
0
              tns_info->pending_binds = binds;
7254
0
          }
7255
7256
          /* Value rows: a TTI_RXD token then one DALC value per bind
7257
           * column (an ordinary execute sends one row, executemany
7258
           * sends N), decoded and rendered by the bind's type. */
7259
0
          offset = dissect_tns_bind_rows(tvb, pinfo, binds_tree, offset, bcols, bind_count - num_return,
7260
0
            !(options & TNS_EXEC_OPTION_NOT_PLSQL), NULL);
7261
0
          proto_item_set_len(binds_item, offset - binds_start);
7262
0
        }
7263
7264
        /* Define section: a client that wants a column in some
7265
         * other form than the describe gave - a CLOB as a string,
7266
         * say - re-executes the cursor with the DEFINE option and
7267
         * one OAC per column, in the bind OAC layout. It carries
7268
         * no binds. */
7269
0
        if ( define_count > 0 )
7270
0
        {
7271
0
          proto_tree *defs_tree, *def_tree;
7272
0
          proto_item *defs_item, *def_item;
7273
0
          int defs_start = offset;
7274
0
          tns_column_t *dcols = NULL;
7275
7276
0
          if ( !PINFO_FD_VISITED(pinfo) )
7277
0
            dcols = wmem_alloc0_array(pinfo->pool, tns_column_t, define_count);
7278
0
          defs_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1,
7279
0
            ett_tns_defines, &defs_item, "Defines");
7280
0
          for ( int i = 0; i < define_count && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
7281
0
          {
7282
0
            int d_start = offset;
7283
0
            uint8_t dtype = tvb_get_uint8(tvb, offset);
7284
0
            def_tree = proto_tree_add_subtree_format(defs_tree, tvb, offset, -1,
7285
0
              ett_tns_bind, &def_item, "Define %d: %s", i + 1,
7286
0
              val_to_str_const(dtype, tns_data_types, "unknown"));
7287
0
            offset = dissect_tns_oac(tvb, pinfo, def_tree, offset, dcols ? &dcols[i] : NULL);
7288
0
            proto_item_set_len(def_item, offset - d_start);
7289
0
          }
7290
0
          proto_item_set_len(defs_item, offset - defs_start);
7291
7292
          /* The rows that answer a define come framed the way
7293
           * it asked - a CLOB defined as LONG arrives inline,
7294
           * with no locator - and so do the rows of every later
7295
           * execute of the cursor. Rows are still split by the
7296
           * describe's columns, so replace each column's type
7297
           * with the one its define gives. */
7298
0
          if ( tns_info && dcols && tns_info->last_describe
7299
0
            && tns_info->last_describe->num_cols == (uint32_t)define_count )
7300
0
          {
7301
0
            tns_describe_t *desc = wmem_new0(wmem_file_scope(), tns_describe_t);
7302
0
            desc->num_cols = define_count;
7303
0
            desc->cols = (tns_column_t *)wmem_memdup(wmem_file_scope(),
7304
0
              tns_info->last_describe->cols, define_count * sizeof(tns_column_t));
7305
0
            for ( int i = 0; i < define_count; i++ )
7306
0
            {
7307
0
              desc->cols[i].type = dcols[i].type;
7308
0
              desc->cols[i].csform = dcols[i].csform;
7309
0
            }
7310
0
            tns_info->last_describe = desc;
7311
0
          }
7312
0
        }
7313
0
      }
7314
0
      else if ( oci_id == TTI_LOBOPS )
7315
0
      {
7316
        /* TTI_LOBOPS: the LOB operation family (read, write, get
7317
         * length, create/free temp, open/close, BFILE ops). One
7318
         * common request layout selects behaviour by the operation
7319
         * opcode:
7320
         *   ub1 source pointer | ub4 source locator length |
7321
         *   ub1 dest pointer | ub4 dest length |
7322
         *   ub4 short source offset | ub4 short dest offset |
7323
         *   ub1 charset pointer | ub1 short amount pointer |
7324
         *   ub1 null-LOB pointer | ub4 operation |
7325
         *   ub1 SCN array pointer | ub1 SCN array length |
7326
         *   ub8 source offset | ub8 dest offset |
7327
         *   ub1 amount pointer | 3 x ub2 array-LOB slots (fixed) |
7328
         *   [locator] | [ub4 charset, CREATE_TEMP] |
7329
         *   [0x0E and the data, WRITE] | [ub8 amount]
7330
         * The locator is as long as the source locator length says;
7331
         * a temporary LOB's carries its own ub2 length prefix, which
7332
         * that length counts. */
7333
0
        int v = 0, op = 0, loc_len = 0, start;
7334
0
        uint8_t src_ptr, charset_ptr, amount_ptr;
7335
0
        uint64_t u = 0;
7336
7337
0
        src_ptr = tvb_get_uint8(tvb, offset);
7338
0
        offset += 1;                              /* source pointer flag */
7339
0
        offset += get_sb4_custom(tvb, offset, &loc_len); /* source locator length */
7340
0
        offset += 1;                              /* dest pointer flag */
7341
0
        offset += get_sb4_custom(tvb, offset, &v); /* dest length */
7342
0
        offset += get_sb4_custom(tvb, offset, &v); /* short source offset */
7343
0
        offset += get_sb4_custom(tvb, offset, &v); /* short dest offset */
7344
0
        charset_ptr = tvb_get_uint8(tvb, offset);
7345
0
        offset += 3;                              /* charset / amount / null-lob flags */
7346
        /* operation opcode */
7347
0
        start = offset;
7348
0
        offset += get_sb4_custom(tvb, offset, &op);
7349
0
        proto_tree_add_uint(data_tree, hf_tns_data_lob_op, tvb, start, offset - start, op);
7350
0
        col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]",
7351
0
          val_to_str_const(op, tns_lob_ops, "unknown"));
7352
        /* scn-array pointer flag + length */
7353
0
        offset += 2;
7354
0
        if ( op == TNS_LOB_OP_CREATE_TEMP )
7355
0
        {
7356
          /* A CREATE_TEMP has no source and no destination
7357
           * to offset into: the two offsets carry the charset
7358
           * form of the LOB to create and its type. An NCLOB
7359
           * is a CLOB told apart only by the form. */
7360
0
          uint64_t csform = 0, type = 0;
7361
0
          start = offset;
7362
0
          offset += get_ub8_custom(tvb, offset, &csform);
7363
0
          proto_tree_add_uint64(data_tree, hf_tns_data_lob_csform, tvb, start, offset - start, csform);
7364
0
          start = offset;
7365
0
          offset += get_ub8_custom(tvb, offset, &type);
7366
0
          proto_tree_add_uint64(data_tree, hf_tns_data_lob_type, tvb, start, offset - start, type);
7367
0
          if ( type == TNS_DATATYPE_BLOB )
7368
0
            col_append_str(pinfo->cinfo, COL_INFO, " [BLOB]");
7369
0
          else if ( type == TNS_DATATYPE_CLOB )
7370
0
            col_append_str(pinfo->cinfo, COL_INFO, csform == 2 ? " [NCLOB]" : " [CLOB]");
7371
0
        }
7372
0
        else
7373
0
        {
7374
          /* source offset (ub8, 1-based into the LOB) */
7375
0
          start = offset;
7376
0
          offset += get_ub8_custom(tvb, offset, &u);
7377
0
          proto_tree_add_uint64(data_tree, hf_tns_data_lob_offset, tvb, start, offset - start, u);
7378
          /* dest offset (ub8, skip) */
7379
0
          offset += get_ub8_custom(tvb, offset, &u);
7380
0
        }
7381
0
        amount_ptr = tvb_get_uint8(tvb, offset);
7382
0
        offset += 1;                              /* amount pointer flag */
7383
0
        offset += 6;                              /* array-LOB slots */
7384
0
        int locator_start = offset;
7385
0
        if ( src_ptr && loc_len > 0 )
7386
0
        {
7387
0
          int dir_off, dir_len, file_off, file_len;
7388
7389
0
          proto_tree_add_item(data_tree, hf_tns_data_lob_locator, tvb, offset, loc_len, ENC_NA);
7390
0
          if ( tns_bfile_names(tvb, offset, loc_len, &dir_off, &dir_len, &file_off, &file_len) )
7391
0
          {
7392
0
            const char *dir, *file;
7393
0
            proto_tree_add_item_ret_string(data_tree, hf_tns_data_lob_directory, tvb,
7394
0
              dir_off, dir_len, ENC_UTF_8, pinfo->pool, (const uint8_t **)&dir);
7395
0
            proto_tree_add_item_ret_string(data_tree, hf_tns_data_lob_file_name, tvb,
7396
0
              file_off, file_len, ENC_UTF_8, pinfo->pool, (const uint8_t **)&file);
7397
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " [BFILENAME('%s', '%s')]", dir, file);
7398
0
          }
7399
0
          offset += loc_len;
7400
0
        }
7401
0
        if ( charset_ptr )
7402
0
        {
7403
0
          start = offset;
7404
0
          offset += get_sb4_custom(tvb, offset, &v);
7405
0
          proto_tree_add_uint(data_tree, hf_tns_data_lob_charset, tvb, start, offset - start, v);
7406
0
        }
7407
0
        if ( tvb_reported_length_remaining(tvb, offset) > 0
7408
0
          && tvb_get_uint8(tvb, offset) == SQLNET_LOB_FILE_DF )
7409
0
        {
7410
          /* WRITE: a LOB_DATA marker, then the data */
7411
0
          offset += 1;
7412
0
          start = offset;
7413
0
          offset += get_dalc_custom(tvb, pinfo, offset, NULL);
7414
0
          if ( tvb_get_uint8(tvb, start) == 0xfe ) /* chunked: shown whole */
7415
0
            proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start, offset - start, ENC_NA);
7416
0
          else if ( offset - start > 1 )
7417
0
            proto_tree_add_item(data_tree, hf_tns_data_lob_data, tvb, start + 1, offset - start - 1, ENC_NA);
7418
0
        }
7419
0
        if ( amount_ptr )
7420
0
        {
7421
0
          start = offset;
7422
0
          offset += get_ub8_custom(tvb, offset, &u);
7423
0
          proto_tree_add_uint64(data_tree, hf_tns_data_lob_amount, tvb, start, offset - start, u);
7424
0
        }
7425
0
        if ( call )
7426
0
        {
7427
0
          call->lob_op = (uint32_t)op;
7428
0
          call->lob_locator_len = src_ptr ? (uint32_t)loc_len : 0;
7429
0
          call->lob_amount = amount_ptr != 0;
7430
0
          if ( src_ptr && loc_len >= TNS_LOB_LOC_FLAG_4 + 1 )
7431
0
          {
7432
0
            tvb_memcpy(tvb, call->lob_flags, locator_start + TNS_LOB_LOC_FLAG_1, 4);
7433
0
            call->lob_flags_known = true;
7434
0
          }
7435
0
        }
7436
0
      }
7437
0
      break;
7438
0
    }
7439
0
    case SQLNET_RETURN_OPI_PARAM:
7440
0
    {
7441
0
      uint8_t skip = 0, opi = 0;
7442
7443
0
      if ( tvb_bytes_exist(tvb, offset, 11) )
7444
0
      {
7445
        /*
7446
         * OPI_VERSION2 response has a following pattern:
7447
         *
7448
         *                _ banner      _ vsnum
7449
         *               /             /
7450
         *    ..(.?)(Orac[le.+])(.?)(....).+$
7451
         *     |
7452
         *     \ banner length (if equal to 0 then next byte indicates the length).
7453
         *
7454
         * These differences (to skip 1 or 2 bytes) due to differences in the drivers.
7455
         */
7456
                                          /* Orac[le.+] */
7457
0
        if ( tvb_get_ntohl(tvb, offset+2) == 0x4f726163 )
7458
0
        {
7459
0
          opi = OPI_VERSION2;
7460
0
          skip = 1;
7461
0
        }
7462
7463
0
        else if ( tvb_get_ntohl(tvb, offset+3) == 0x4f726163 )
7464
0
        {
7465
0
          opi = OPI_VERSION2;
7466
0
          skip = 2;
7467
0
        }
7468
7469
        /*
7470
         * OPI_OSESSKEY response has a following pattern:
7471
         *
7472
         *               _ pattern (v1|v2)
7473
         *              /        _ params
7474
         *             /        /
7475
         *    (....)(........)(.+).+$
7476
         *       ||
7477
         *        \ if these two bytes are equal to 0x0c00 then first byte is <Param Counts> (v1),
7478
         *          else next byte indicate it (v2).
7479
         */
7480
                                                  /*  ....AUTH (v1) */
7481
0
        else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0000000c41555448 )
7482
0
        {
7483
0
          opi = OPI_OSESSKEY;
7484
0
          skip = 1;
7485
0
        }
7486
                                                  /*  ..AUTH_V (v2) */
7487
0
        else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0c0c415554485f53 )
7488
0
        {
7489
0
          opi = OPI_OSESSKEY;
7490
0
          skip = 2;
7491
0
        }
7492
7493
        /*
7494
         * OPI_OAUTH response has a following pattern:
7495
         *
7496
         *               _ pattern (v1|v2)
7497
         *              /        _ params
7498
         *             /        /
7499
         *    (....)(........)(.+).+$
7500
         *       ||
7501
         *        \ if these two bytes are equal to 0x1300 then first byte is <Param Counts> (v1),
7502
         *          else next byte indicate it (v2).
7503
         */
7504
7505
                                                  /*  ....AUTH (v1) */
7506
0
        else if ( tvb_get_ntoh64(tvb, offset+3) == 0x0000001341555448 )
7507
0
        {
7508
0
          opi = OPI_OAUTH;
7509
0
          skip = 1;
7510
0
        }
7511
                                                        /*  ..AUTH_V (v2) */
7512
0
        else if ( tvb_get_ntoh64(tvb, offset+3) == 0x1313415554485f56 )
7513
0
        {
7514
0
          opi = OPI_OAUTH;
7515
0
          skip = 2;
7516
0
        }
7517
0
      }
7518
7519
0
      if ( opi == OPI_VERSION2 )
7520
0
      {
7521
0
        proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, skip, ENC_NA);
7522
0
        offset += skip;
7523
7524
0
        uint8_t len = tvb_get_uint8(tvb, offset);
7525
7526
0
        proto_tree_add_item(data_tree, hf_tns_data_opi_version2_banner_len, tvb, offset, 1, ENC_BIG_ENDIAN);
7527
0
        offset += 1;
7528
7529
0
        proto_tree_add_item(data_tree, hf_tns_data_opi_version2_banner, tvb, offset, len, ENC_ASCII);
7530
0
        offset += len + (skip == 1 ? 1 : 0);
7531
7532
0
        proto_tree_add_item(data_tree, hf_tns_data_opi_version2_vsnum, tvb, offset, 4, (skip == 1) ? ENC_BIG_ENDIAN : ENC_LITTLE_ENDIAN);
7533
0
        offset += 4;
7534
0
      }
7535
0
      else if ( opi == OPI_OSESSKEY || opi == OPI_OAUTH )
7536
0
      {
7537
0
        proto_tree *params_tree;
7538
0
        proto_item *params_ti;
7539
0
        unsigned par, params;
7540
7541
0
        if ( skip == 1 )
7542
0
        {
7543
0
          proto_tree_add_item_ret_uint(data_tree, hf_tns_data_opi_num_of_params, tvb, offset, 1, ENC_NA, &params);
7544
0
          offset += 1;
7545
7546
0
          proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 5, ENC_NA);
7547
0
          offset += 5;
7548
0
        }
7549
0
        else
7550
0
        {
7551
0
          proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 1, ENC_NA);
7552
0
          offset += 1;
7553
7554
0
          proto_tree_add_item_ret_uint(data_tree, hf_tns_data_opi_num_of_params, tvb, offset, 1, ENC_NA, &params);
7555
0
          offset += 1;
7556
7557
0
          proto_tree_add_item(data_tree, hf_tns_data_unused, tvb, offset, 2, ENC_NA);
7558
0
          offset += 2;
7559
0
        }
7560
7561
0
        params_tree = proto_tree_add_subtree(data_tree, tvb, offset, -1, ett_tns_opi_params, &params_ti, "Parameters");
7562
7563
0
        for ( par = 1; par <= params; par++ )
7564
0
        {
7565
0
          proto_tree *par_tree;
7566
0
          proto_item *par_ti;
7567
0
          unsigned len, offset_prev;
7568
7569
0
          par_tree = proto_tree_add_subtree(params_tree, tvb, offset, -1, ett_tns_opi_par, &par_ti, "Parameter");
7570
0
          proto_item_append_text(par_ti, " %u", par);
7571
7572
          /* Name length */
7573
0
          proto_tree_add_item_ret_uint(par_tree, hf_tns_data_opi_param_length, tvb, offset, 1, ENC_NA, &len);
7574
0
          offset += 1;
7575
7576
          /* Name */
7577
0
          if ( !(len == 0 || len == 2) ) /* Not empty (2 - SQLDeveloper specific sign). */
7578
0
          {
7579
0
            proto_tree_add_item(par_tree, hf_tns_data_opi_param_name, tvb, offset, len, ENC_ASCII);
7580
0
            offset += len;
7581
0
          }
7582
7583
          /* Value can be NULL. So, save offset to calculate unused data. */
7584
0
          offset_prev = offset;
7585
0
          offset += skip == 1 ? 4 : 2;
7586
7587
          /* Value length */
7588
0
          if ( opi == OPI_OSESSKEY )
7589
0
          {
7590
0
            len = get_strtype_custom(tvb, pinfo, par_tree, offset);
7591
0
          }
7592
0
          else /* OPI_OAUTH */
7593
0
          {
7594
0
            len = tvb_get_uint8(tvb, offset_prev) == 0 ? 0 : get_strtype_custom(tvb, pinfo, par_tree, offset);
7595
0
          }
7596
7597
          /*
7598
           * Value
7599
           *   OPI_OSESSKEY: AUTH_VFR_DATA with length 0, 9, 0x39 comes without data.
7600
           *   OPI_OAUTH: AUTH_VFR_DATA with length 0, 0x39 comes without data.
7601
           */
7602
0
          if ( ((opi == OPI_OSESSKEY) && !(len == 0 || len == 9 || len == 0x39))
7603
0
            || ((opi == OPI_OAUTH) && !(len == 0 || len == 0x39)) )
7604
0
          {
7605
0
            proto_tree_add_item(par_tree, hf_tns_data_unused, tvb, offset_prev, offset - offset_prev, ENC_NA);
7606
0
            offset += len;
7607
7608
0
            offset_prev = offset; /* Save offset to calculate rest of unused data */
7609
0
          }
7610
0
          else
7611
0
          {
7612
0
            offset += 1;
7613
0
          }
7614
7615
0
          if ( opi == OPI_OSESSKEY )
7616
0
          {
7617
            /* SQL Developer specific fix */
7618
0
            offset += tvb_get_uint8(tvb, offset) == 2 ? 5 : 3;
7619
0
          }
7620
0
          else /* OPI_OAUTH */
7621
0
          {
7622
0
            offset += len == 0 ? 1 : 3;
7623
0
          }
7624
7625
0
          if ( skip == 1 )
7626
0
          {
7627
0
            offset += 1 + ((len == 0 || len == 0x39) ? 3 : 4);
7628
7629
0
            if ( opi == OPI_OAUTH )
7630
0
            {
7631
0
              offset += len == 0 ? 2 : 0;
7632
0
            }
7633
0
          }
7634
7635
0
          proto_tree_add_item(par_tree, hf_tns_data_unused, tvb, offset_prev, offset - offset_prev, ENC_NA);
7636
0
          proto_item_set_end(par_ti, tvb, offset);
7637
0
        }
7638
0
        proto_item_set_end(params_ti, tvb, offset);
7639
0
      }
7640
0
      else if ( !is_request )
7641
0
      {
7642
        /* Not an authentication reply: an execute answers with
7643
         * its return parameters. */
7644
0
        tns_call_t *call = tns_answered_call(pinfo);
7645
0
        if ( call && (call->func == TTI_ALL8 || call->func == TTI_REEXECUTE
7646
0
          || call->func == TTI_REEXECUTE_AND_FETCH) && tns_is_oci(pinfo) )
7647
0
        {
7648
0
          int end = dissect_tns_oci_return_params(tvb, pinfo, data_tree, offset);
7649
0
          if ( end > 0 )
7650
0
          {
7651
0
            offset = end;
7652
0
            ctx->walk = true;
7653
0
          }
7654
0
        }
7655
0
        else if ( call && (call->func == TTI_ALL8 || call->func == TTI_REEXECUTE
7656
0
          || call->func == TTI_REEXECUTE_AND_FETCH) )
7657
0
        {
7658
0
          offset = dissect_tns_return_params(tvb, pinfo, data_tree, offset,
7659
0
            (call->exec_flags & TNS_EXEC_FLAGS_DML_ROWCOUNTS) != 0);
7660
0
          ctx->walk = true;
7661
0
        }
7662
0
        else if ( call && call->func == TTI_AQ_ENQUEUE )
7663
0
        {
7664
          /* the id the queue gave the message */
7665
0
          int ext_len = 0;
7666
0
          proto_tree_add_item(data_tree, hf_tns_data_aq_msgid, tvb, offset, TNS_AQ_MSGID_LEN, ENC_NA);
7667
0
          offset += TNS_AQ_MSGID_LEN;
7668
0
          offset += get_sb4_custom(tvb, offset, &ext_len); /* extensions */
7669
0
          ctx->walk = true;
7670
0
        }
7671
0
        else if ( call && call->func == TTI_AQ_ARRAY )
7672
0
        {
7673
          /* one message per iteration: its properties when the
7674
           * length before them is not zero, the recipients, the
7675
           * payload, the message ids and the extensions */
7676
0
          int num_iters = 0, len = 0, v = 0, msg_start;
7677
7678
0
          offset += get_sb4_custom(tvb, offset, &num_iters);
7679
0
          for ( int i = 0; i < num_iters && tvb_reported_length_remaining(tvb, offset) > 0; i++ )
7680
0
          {
7681
0
            offset += get_sb4_custom(tvb, offset, &len);
7682
0
            if ( len > 0 )
7683
0
            {
7684
0
              offset += 1;
7685
0
              offset = dissect_tns_aq_msg_props(tvb, pinfo, data_tree, offset, true);
7686
0
            }
7687
0
            offset += get_sb4_custom(tvb, offset, &v);      /* recipients */
7688
0
            offset += get_sb4_custom(tvb, offset, &len);
7689
0
            if ( len > 0 )
7690
0
              offset = dissect_tns_value(tvb, pinfo, data_tree, offset, TNS_DATATYPE_ADT,
7691
0
                0, TNS_VALUE_OUT, i + 1, hf_tns_data_aq_payload, "Payload");
7692
            /* the ids of this iteration's messages, one after
7693
             * another */
7694
0
            offset += get_sb4_custom(tvb, offset, &len);
7695
0
            if ( len > 0 )
7696
0
            {
7697
0
              msg_start = offset;
7698
0
              offset += get_dalc_custom(tvb, pinfo, offset, NULL);
7699
0
              if ( offset - msg_start > 1 )
7700
0
                proto_tree_add_item(data_tree, hf_tns_data_aq_msgid, tvb,
7701
0
                  msg_start + 1, offset - msg_start - 1, ENC_NA);
7702
0
            }
7703
0
            offset += get_sb4_custom(tvb, offset, &v);      /* extensions */
7704
0
            offset += get_sb4_custom(tvb, offset, &v);      /* output ack */
7705
0
          }
7706
0
          ctx->walk = true;
7707
0
        }
7708
0
        else if ( call && call->func == TTI_AQ_DEQUEUE )
7709
0
        {
7710
          /* a length, and when it is not zero the message: its
7711
           * properties, recipients, payload and id */
7712
0
          int len = 0;
7713
0
          offset += get_sb4_custom(tvb, offset, &len);
7714
0
          if ( len > 0 )
7715
0
          {
7716
0
            int v = 0;
7717
0
            offset = dissect_tns_aq_msg_props(tvb, pinfo, data_tree, offset, true);
7718
0
            offset += get_sb4_custom(tvb, offset, &v);  /* recipients */
7719
0
            offset = dissect_tns_value(tvb, pinfo, data_tree, offset, TNS_DATATYPE_ADT, 0,
7720
0
              TNS_VALUE_OUT, 1, hf_tns_data_aq_payload, "Payload");
7721
0
            proto_tree_add_item(data_tree, hf_tns_data_aq_msgid, tvb, offset, TNS_AQ_MSGID_LEN, ENC_NA);
7722
0
            offset += TNS_AQ_MSGID_LEN;
7723
0
          }
7724
0
          ctx->walk = true;
7725
0
        }
7726
0
        else if ( call && call->func == TTI_TPC_TXN_SWITCH )
7727
0
        {
7728
          /* the application value and the transaction context
7729
           * (a ub2 length and the bytes) */
7730
0
          int v = 0, len = 0, start = offset;
7731
0
          offset += get_sb4_custom(tvb, offset, &v);
7732
0
          proto_tree_add_uint(data_tree, hf_tns_data_tpc_app_value, tvb, start, offset - start, v);
7733
0
          offset += get_sb4_custom(tvb, offset, &len);
7734
0
          if ( len > 0 )
7735
0
          {
7736
0
            proto_tree_add_item(data_tree, hf_tns_data_tpc_context, tvb, offset, len, ENC_NA);
7737
0
            offset += len;
7738
0
          }
7739
0
          ctx->walk = true;
7740
0
        }
7741
0
        else if ( call && call->func == TTI_TPC_TXN_CHANGE_STATE )
7742
0
        {
7743
0
          int v = 0, start = offset;
7744
0
          offset += get_sb4_custom(tvb, offset, &v);
7745
0
          proto_tree_add_uint(data_tree, hf_tns_data_tpc_state, tvb, start, offset - start, v);
7746
0
          ctx->walk = true;
7747
0
        }
7748
0
        else if ( call && call->func == TTI_LOBOPS )
7749
0
        {
7750
          /* A LOB operation's reply: the locator as the server
7751
           * now sees it - as long as the one sent, and changed
7752
           * by a mutating call - then per operation the new
7753
           * temporary LOB's charset, the amount, or a boolean. */
7754
0
          uint64_t u = 0;
7755
0
          int start;
7756
7757
0
          if ( call->lob_locator_len > 0 )
7758
0
          {
7759
0
            proto_tree_add_item(data_tree, hf_tns_data_lob_locator, tvb, offset,
7760
0
              call->lob_locator_len, ENC_NA);
7761
0
            offset += call->lob_locator_len;
7762
0
          }
7763
0
          if ( call->lob_op == TNS_LOB_OP_CREATE_TEMP )
7764
0
          {
7765
0
            int v = 0;
7766
0
            start = offset;
7767
0
            offset += get_sb4_custom(tvb, offset, &v);
7768
0
            proto_tree_add_uint(data_tree, hf_tns_data_lob_charset, tvb, start, offset - start, v);
7769
0
            offset += 1; /* trailing flags */
7770
0
          }
7771
0
          else if ( call->lob_amount )
7772
0
          {
7773
0
            start = offset;
7774
0
            offset += get_ub8_custom(tvb, offset, &u);
7775
0
            proto_tree_add_uint64(data_tree, hf_tns_data_lob_amount, tvb, start, offset - start, u);
7776
0
          }
7777
0
          if ( call->lob_op == TNS_LOB_OP_IS_OPEN || call->lob_op == TNS_LOB_OP_FILE_EXISTS
7778
0
            || call->lob_op == TNS_LOB_OP_FILE_ISOPEN )
7779
0
          {
7780
0
            proto_tree_add_item(data_tree, hf_tns_data_lob_flag, tvb, offset, 1, ENC_NA);
7781
0
            offset += 1;
7782
0
          }
7783
0
          ctx->walk = true;
7784
0
        }
7785
0
      }
7786
0
      break;
7787
0
    }
7788
7789
0
    case SQLNET_PIGGYBACK_FUNC:
7790
0
    {
7791
0
      int cursors_len = 0;
7792
0
      int cursors_start;
7793
0
      uint8_t piggyback_id = tvb_get_uint8(tvb, offset);
7794
0
      proto_tree_add_item(data_tree, hf_tns_data_piggyback_id, tvb, offset, 1, ENC_BIG_ENDIAN);
7795
0
      offset += 1;
7796
0
      proto_tree_add_item(data_tree, hf_tns_data_tseq, tvb, offset, 1, ENC_BIG_ENDIAN);
7797
0
      offset += 1;
7798
0
      offset = dissect_tns_call_token(tvb, pinfo, data_tree, offset);
7799
      /* Only the close-cursors piggyback carries a cursor list:
7800
       * a pointer byte, a ub4 count, then that many ub4 cursor
7801
       * ids. The other piggybacks have bodies of their own. */
7802
0
      if ( piggyback_id != TTI_CLOSE_CURSORS )
7803
0
      {
7804
0
        offset = dissect_tns_piggyback_body(tvb, pinfo, data_tree, offset, piggyback_id, &ctx->walk);
7805
0
        break;
7806
0
      }
7807
0
      offset += 1; /* pointer */
7808
0
      cursors_start = offset;
7809
0
      offset += get_sb4_custom(tvb, offset, &cursors_len);
7810
      /* The count comes off the wire and every cursor takes at
7811
       * least one byte, so a count larger than the data left
7812
       * cannot be real. Say so and stop, rather than looping on
7813
       * a number somebody else chose. */
7814
0
      if ( cursors_len < 0 ||
7815
0
           (unsigned)cursors_len > tvb_reported_length_remaining(tvb, offset) )
7816
0
      {
7817
0
        proto_tree_add_expert(data_tree, pinfo, &ei_tns_data_piggyback_cursors,
7818
0
          tvb, cursors_start, offset - cursors_start);
7819
0
        break;
7820
0
      }
7821
0
      for(int i = 0; i < cursors_len; i++) {
7822
0
        int cursor = 0;
7823
0
        int len = get_sb4_custom(tvb, offset, &cursor);
7824
0
        proto_tree_add_uint(data_tree, hf_tns_cursor, tvb, offset, len, cursor);
7825
0
        offset += len;
7826
0
      }
7827
      /* The call this piggyback rides in front of follows it. */
7828
0
      ctx->walk = true;
7829
0
      break;
7830
0
    }
7831
0
    case SQLNET_FAST_AUTH:
7832
0
    {
7833
      /* A 23ai client cannot open a session with the three separate
7834
       * handshake messages: from field version 23.1 ext 1 it sends
7835
       * them in one packet behind this header - a version and two
7836
       * flags - with the protocol message, three unused character
7837
       * set fields, the field version the bundle is written at, the
7838
       * data types message and the session key request following
7839
       * one after another. The server answers with its three
7840
       * replies in one packet too. */
7841
0
      unsigned len;
7842
7843
0
      if ( !is_request )
7844
0
        break;
7845
7846
0
      proto_tree_add_item(data_tree, hf_tns_data_fastauth_version, tvb, offset, 1, ENC_NA);
7847
0
      offset += 3; /* version and two flags */
7848
0
      if ( tvb_get_uint8(tvb, offset) != SQLNET_SET_PROTOCOL )
7849
0
        break;
7850
0
      proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 1, ENC_BIG_ENDIAN);
7851
0
      offset += 1;
7852
0
      proto_tree_add_item(data_tree, hf_tns_data_setp_acc_version, tvb, offset, 1, ENC_BIG_ENDIAN);
7853
0
      offset += 2; /* the version and the list's 0 terminator */
7854
0
      proto_tree_add_item_ret_length(data_tree, hf_tns_data_setp_cli_plat, tvb, offset, -1,
7855
0
        ENC_ASCII|ENC_NA, &len);
7856
0
      offset += len;
7857
0
      offset += 5; /* unused charset, charset flag and ncharset */
7858
0
      proto_tree_add_item(data_tree, hf_tns_data_setdt_field_version, tvb, offset, 1, ENC_NA);
7859
0
      offset += 1;
7860
      /* The data types message and the session key request follow,
7861
       * and the walker steps into them. The call in the bundle
7862
       * carries no token, whatever field version its data types
7863
       * message negotiates. */
7864
0
      ctx->no_token = true;
7865
0
      ctx->walk = true;
7866
0
      break;
7867
0
    }
7868
7869
0
    case SQLNET_SNS:
7870
0
    {
7871
0
      proto_tree_add_item(data_tree, hf_tns_data_id, tvb, offset, 4, ENC_BIG_ENDIAN);
7872
0
      offset += 4;
7873
0
      proto_tree_add_item(data_tree, hf_tns_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
7874
0
      offset += 2;
7875
7876
0
      if ( is_request )
7877
0
      {
7878
0
        proto_tree_add_item(data_tree, hf_tns_data_sns_cli_vers, tvb, offset, 4, ENC_BIG_ENDIAN);
7879
0
      }
7880
0
      else
7881
0
      {
7882
0
        proto_tree_add_item(data_tree, hf_tns_data_sns_srv_vers, tvb, offset, 4, ENC_BIG_ENDIAN);
7883
0
      }
7884
0
      offset += 4;
7885
7886
0
      uint16_t num_services = tvb_get_ntohs(tvb, offset);
7887
0
      proto_tree_add_item(data_tree, hf_tns_data_sns_srvcnt, tvb, offset, 2, ENC_BIG_ENDIAN);
7888
      /* With encryption picked, the client's next negotiation packet
7889
       * - its Diffie-Hellman public key - is the last in the clear. */
7890
0
      if ( is_request && !PINFO_FD_VISITED(pinfo) )
7891
0
      {
7892
0
        tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
7893
0
        if ( tns_info->ano_encryption && !tns_info->ano_active_after )
7894
0
          tns_info->ano_active_after = pinfo->num;
7895
0
      }
7896
0
      offset += 2;
7897
0
      proto_tree_add_item(data_tree, hf_tns_data_sns_error, tvb, offset, 1, ENC_NA);
7898
0
      offset += 1;
7899
7900
      /* Each service: a type, a sub-packet count and an error, then
7901
       * the sub-packets, each a length, a type and that many bytes
7902
       * of payload - all big-endian. A service opens with its
7903
       * version; in the encryption and integrity services the
7904
       * sub-packet after it lists the algorithms a client offers,
7905
       * or holds the one the server picked. */
7906
0
      for ( unsigned i = 0; i < num_services && tvb_bytes_exist(tvb, offset, 8); i++ )
7907
0
      {
7908
0
        proto_tree *svc_tree;
7909
0
        proto_item *svc_item;
7910
0
        int svc_start = offset;
7911
0
        uint16_t svc_type = tvb_get_ntohs(tvb, offset);
7912
0
        uint16_t num_sub = tvb_get_ntohs(tvb, offset + 2);
7913
7914
0
        svc_tree = proto_tree_add_subtree_format(data_tree, tvb, offset, -1, ett_tns_sns_service,
7915
0
          &svc_item, "Service: %s", val_to_str_const(svc_type, tns_sns_services, "unknown"));
7916
0
        proto_tree_add_item(svc_tree, hf_tns_data_sns_service, tvb, offset, 2, ENC_BIG_ENDIAN);
7917
0
        proto_tree_add_item(svc_tree, hf_tns_data_sns_subpackets, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
7918
0
        proto_tree_add_item(svc_tree, hf_tns_data_sns_svc_error, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
7919
0
        offset += 8;
7920
0
        for ( unsigned j = 0; j < num_sub && tvb_bytes_exist(tvb, offset, 4); j++ )
7921
0
        {
7922
0
          uint16_t len = tvb_get_ntohs(tvb, offset);
7923
0
          uint16_t sub_type = tvb_get_ntohs(tvb, offset + 2);
7924
0
          proto_tree *sub_tree = proto_tree_add_subtree_format(svc_tree, tvb, offset, 4 + len,
7925
0
            ett_tns_sns_subpacket, NULL, "Sub-packet %u: %s, %u bytes", j + 1,
7926
0
            val_to_str_const(sub_type, tns_sns_subpacket_types, "unknown"), len);
7927
0
          proto_tree_add_item(sub_tree, hf_tns_data_sns_sub_type, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
7928
0
          offset += 4;
7929
0
          bool algs = j == 1 && (sub_type == TNS_ANO_SP_BYTES || sub_type == TNS_ANO_SP_UB1);
7930
0
          if ( sub_type == TNS_ANO_SP_VERSION && len == 4 )
7931
0
            proto_tree_add_item(sub_tree, hf_tns_data_sns_version, tvb, offset, 4, ENC_BIG_ENDIAN);
7932
0
          else if ( algs && svc_type == TNS_ANO_ENCRYPTION )
7933
0
          {
7934
0
            for ( unsigned k = 0; k < len; k++ )
7935
0
              proto_tree_add_item(sub_tree, hf_tns_data_sns_encryption, tvb, offset + k, 1, ENC_NA);
7936
            /* the server's pick: anything but none turns
7937
             * encryption on once the client has answered */
7938
0
            if ( !is_request && !PINFO_FD_VISITED(pinfo) && len == 1 && tvb_get_uint8(tvb, offset) != 0 )
7939
0
              tns_get_conv_info(pinfo)->ano_encryption = true;
7940
0
          }
7941
0
          else if ( algs && svc_type == TNS_ANO_DATA_INTEGRITY )
7942
0
            for ( unsigned k = 0; k < len; k++ )
7943
0
              proto_tree_add_item(sub_tree, hf_tns_data_sns_integrity, tvb, offset + k, 1, ENC_NA);
7944
0
          else if ( len > 0 )
7945
0
            proto_tree_add_item(sub_tree, hf_tns_data_sns_sub_data, tvb, offset, len, ENC_NA);
7946
0
          offset += len;
7947
0
        }
7948
0
        proto_item_set_len(svc_item, offset - svc_start);
7949
0
      }
7950
0
      break;
7951
0
    }
7952
0
  }
7953
7954
0
  return offset;
7955
0
}
7956
7957
static void dissect_tns_connect(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
7958
0
{
7959
0
  proto_tree *connect_tree;
7960
0
  uint32_t cd_offset, cd_len;
7961
0
  int tns_offset = offset-8;
7962
0
  static int * const flags[] = {
7963
0
    &hf_tns_ntp_flag_hangon,
7964
0
    &hf_tns_ntp_flag_crel,
7965
0
    &hf_tns_ntp_flag_tduio,
7966
0
    &hf_tns_ntp_flag_srun,
7967
0
    &hf_tns_ntp_flag_dtest,
7968
0
    &hf_tns_ntp_flag_cbio,
7969
0
    &hf_tns_ntp_flag_asio,
7970
0
    &hf_tns_ntp_flag_pio,
7971
0
    &hf_tns_ntp_flag_grant,
7972
0
    &hf_tns_ntp_flag_handoff,
7973
0
    &hf_tns_ntp_flag_sigio,
7974
0
    &hf_tns_ntp_flag_sigpipe,
7975
0
    &hf_tns_ntp_flag_sigurg,
7976
0
    &hf_tns_ntp_flag_urgentio,
7977
0
    &hf_tns_ntp_flag_fdio,
7978
0
    &hf_tns_ntp_flag_testop,
7979
0
    NULL
7980
0
  };
7981
7982
0
  connect_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
7983
0
    ett_tns_connect, NULL, "Connect");
7984
7985
0
  proto_tree_add_item(connect_tree, hf_tns_version, tvb,
7986
0
      offset, 2, ENC_BIG_ENDIAN);
7987
0
  offset += 2;
7988
7989
0
  proto_tree_add_item(connect_tree, hf_tns_compat_version, tvb,
7990
0
      offset, 2, ENC_BIG_ENDIAN);
7991
0
  offset += 2;
7992
7993
0
  proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_service_options, ett_tns_sopt_flag, tns_service_options, ENC_BIG_ENDIAN);
7994
0
  offset += 2;
7995
7996
0
  proto_tree_add_item(connect_tree, hf_tns_sdu_size, tvb,
7997
0
      offset, 2, ENC_BIG_ENDIAN);
7998
0
  offset += 2;
7999
8000
0
  proto_tree_add_item(connect_tree, hf_tns_max_tdu_size, tvb,
8001
0
      offset, 2, ENC_BIG_ENDIAN);
8002
0
  offset += 2;
8003
8004
0
  proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_nt_proto_characteristics, ett_tns_ntp_flag, flags, ENC_BIG_ENDIAN);
8005
0
  offset += 2;
8006
8007
0
  proto_tree_add_item(connect_tree, hf_tns_line_turnaround, tvb,
8008
0
      offset, 2, ENC_BIG_ENDIAN);
8009
0
  offset += 2;
8010
8011
0
  proto_tree_add_item(connect_tree, hf_tns_value_of_one, tvb,
8012
0
      offset, 2, ENC_NA);
8013
0
  offset += 2;
8014
8015
0
  proto_tree_add_item_ret_uint(connect_tree, hf_tns_connect_data_length, tvb,
8016
0
      offset, 2, ENC_BIG_ENDIAN, &cd_len);
8017
0
  offset += 2;
8018
8019
0
  proto_tree_add_item_ret_uint(connect_tree, hf_tns_connect_data_offset, tvb,
8020
0
      offset, 2, ENC_BIG_ENDIAN, &cd_offset);
8021
0
  offset += 2;
8022
8023
0
  proto_tree_add_item(connect_tree, hf_tns_connect_data_max, tvb,
8024
0
      offset, 4, ENC_BIG_ENDIAN);
8025
0
  offset += 4;
8026
8027
0
  proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_connect_flags0, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN);
8028
0
  offset += 1;
8029
8030
0
  proto_tree_add_bitmask(connect_tree, tvb, offset, hf_tns_connect_flags1, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN);
8031
0
  offset += 1;
8032
8033
  /*
8034
   * XXX - sometimes it appears that this stuff isn't present
8035
   * in the packet.
8036
   */
8037
0
  if ((uint32_t)(offset + 16) <= tns_offset+cd_offset)
8038
0
  {
8039
0
    proto_tree_add_item(connect_tree, hf_tns_trace_cf1, tvb,
8040
0
        offset, 4, ENC_BIG_ENDIAN);
8041
0
    offset += 4;
8042
8043
0
    proto_tree_add_item(connect_tree, hf_tns_trace_cf2, tvb,
8044
0
        offset, 4, ENC_BIG_ENDIAN);
8045
0
    offset += 4;
8046
8047
0
    proto_tree_add_item(connect_tree, hf_tns_trace_cid, tvb,
8048
0
        offset, 8, ENC_BIG_ENDIAN);
8049
    /* offset += 8;*/
8050
0
  }
8051
8052
0
  if ( cd_len > 0)
8053
0
  {
8054
    /* A server reads at most 230 bytes of connect data from the
8055
     * CONNECT, so a longer descriptor is not in it: the CONNECT
8056
     * ends at the data offset, and the descriptor follows in a
8057
     * Data packet of its own.
8058
     */
8059
0
    if (tvb_reported_length_remaining(tvb, tns_offset + cd_offset)) {
8060
0
      proto_tree_add_item(connect_tree, hf_tns_connect_data, tvb,
8061
0
        tns_offset+cd_offset, -1, ENC_ASCII);
8062
0
    } else {
8063
0
      proto_tree_add_expert(connect_tree, pinfo, &ei_tns_connect_data_next_packet, tvb, 0, 0);
8064
0
      if (!PINFO_FD_VISITED(pinfo)) {
8065
0
        tns_conv_info_t *tns_info = tns_get_conv_info(pinfo);
8066
0
        tns_info->pending_connect_data = cd_len;
8067
0
      }
8068
0
    }
8069
0
  }
8070
0
}
8071
8072
static void dissect_tns_accept(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
8073
0
{
8074
0
  proto_tree *accept_tree;
8075
0
  uint32_t accept_offset, accept_len;
8076
0
  uint16_t version;
8077
0
  int tns_offset = offset-8;
8078
8079
0
  accept_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
8080
0
        ett_tns_accept, NULL, "Accept");
8081
8082
0
  proto_tree_add_item(accept_tree, hf_tns_version, tvb,
8083
0
      offset, 2, ENC_BIG_ENDIAN);
8084
0
  offset += 2;
8085
8086
0
  proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_service_options, ett_tns_sopt_flag, tns_service_options, ENC_BIG_ENDIAN);
8087
0
  offset += 2;
8088
8089
0
  proto_tree_add_item(accept_tree, hf_tns_sdu_size, tvb,
8090
0
      offset, 2, ENC_BIG_ENDIAN);
8091
0
  offset += 2;
8092
8093
0
  proto_tree_add_item(accept_tree, hf_tns_max_tdu_size, tvb,
8094
0
      offset, 2, ENC_BIG_ENDIAN);
8095
0
  offset += 2;
8096
8097
0
  proto_tree_add_item(accept_tree, hf_tns_value_of_one, tvb,
8098
0
      offset, 2, ENC_NA);
8099
0
  offset += 2;
8100
8101
0
  proto_tree_add_item_ret_uint(accept_tree, hf_tns_accept_data_length, tvb,
8102
0
      offset, 2, ENC_BIG_ENDIAN, &accept_len);
8103
0
  offset += 2;
8104
8105
0
  proto_tree_add_item_ret_uint(accept_tree, hf_tns_accept_data_offset, tvb,
8106
0
      offset, 2, ENC_BIG_ENDIAN, &accept_offset);
8107
0
  offset += 2;
8108
8109
0
  proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_connect_flags0, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN);
8110
0
  offset += 1;
8111
8112
0
  proto_tree_add_bitmask(accept_tree, tvb, offset, hf_tns_connect_flags1, ett_tns_conn_flag, tns_connect_flags, ENC_BIG_ENDIAN);
8113
8114
  /* From version 315 the session data unit is offered again as 32
8115
   * bits, 24 bytes into the ACCEPT, and from 318 a flags2 word follows
8116
   * at 33 - both ahead of any connect data. */
8117
0
  version = tvb_get_ntohs(tvb, tns_offset + 8);
8118
0
  if ( version >= 315 && accept_offset >= 8 + 24 + 4 && tvb_bytes_exist(tvb, tns_offset + 8 + 24, 4) )
8119
0
    proto_tree_add_item(accept_tree, hf_tns_accept_sdu, tvb, tns_offset + 8 + 24, 4, ENC_BIG_ENDIAN);
8120
0
  if ( version >= 318 && accept_offset >= 8 + 33 + 4 && tvb_bytes_exist(tvb, tns_offset + 8 + 33, 4) )
8121
0
    proto_tree_add_bitmask(accept_tree, tvb, tns_offset + 8 + 33, hf_tns_accept_flags2,
8122
0
      ett_tns_accept_flags2, tns_accept_flags2, ENC_BIG_ENDIAN);
8123
8124
0
  if ( accept_len > 0)
8125
0
  {
8126
0
    proto_tree_add_item(accept_tree, hf_tns_accept_data, tvb,
8127
0
      tns_offset+accept_offset, -1, ENC_ASCII);
8128
0
  }
8129
0
  return;
8130
0
}
8131
8132
8133
static void dissect_tns_refuse(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
8134
0
{
8135
  /* TODO
8136
   * According to some reverse engineers, the refuse packet is also sent when the login fails.
8137
   * Byte 54 shows if this is due to invalid ID (0x02) or password (0x03).
8138
   * At now we do not have pcaps with such messages to check this statement.
8139
   */
8140
0
  proto_tree *refuse_tree;
8141
8142
0
  refuse_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
8143
0
        ett_tns_refuse, NULL, "Refuse");
8144
8145
0
  proto_tree_add_item(refuse_tree, hf_tns_refuse_reason_user, tvb,
8146
0
      offset, 1, ENC_BIG_ENDIAN);
8147
0
  offset += 1;
8148
8149
0
  proto_tree_add_item(refuse_tree, hf_tns_refuse_reason_system, tvb,
8150
0
      offset, 1, ENC_BIG_ENDIAN);
8151
0
  offset += 1;
8152
8153
0
  proto_tree_add_item(refuse_tree, hf_tns_refuse_data_length, tvb,
8154
0
      offset, 2, ENC_BIG_ENDIAN);
8155
0
  offset += 2;
8156
8157
0
  proto_tree_add_item(refuse_tree, hf_tns_refuse_data, tvb,
8158
0
      offset, -1, ENC_ASCII);
8159
0
}
8160
8161
8162
static void dissect_tns_abort(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
8163
0
{
8164
0
  proto_tree *abort_tree;
8165
8166
0
  abort_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
8167
0
        ett_tns_abort, NULL, "Abort");
8168
8169
0
  proto_tree_add_item(abort_tree, hf_tns_abort_reason_user, tvb,
8170
0
      offset, 1, ENC_BIG_ENDIAN);
8171
0
  offset += 1;
8172
8173
0
  proto_tree_add_item(abort_tree, hf_tns_abort_reason_system, tvb,
8174
0
      offset, 1, ENC_BIG_ENDIAN);
8175
0
  offset += 1;
8176
8177
0
  proto_tree_add_item(abort_tree, hf_tns_abort_data, tvb,
8178
0
      offset, -1, ENC_ASCII);
8179
0
}
8180
8181
8182
static void dissect_tns_marker(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tns_tree, int is_attention)
8183
0
{
8184
0
  proto_tree *marker_tree;
8185
8186
0
  marker_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
8187
0
        ett_tns_marker, NULL, is_attention ? "Attention" : "Marker");
8188
8189
0
  proto_tree_add_item(marker_tree, hf_tns_marker_type, tvb,
8190
0
      offset, 1, ENC_BIG_ENDIAN);
8191
0
  offset += 1;
8192
8193
0
  proto_tree_add_item(marker_tree, hf_tns_marker_data_byte, tvb,
8194
0
      offset, 1, ENC_BIG_ENDIAN);
8195
0
  offset += 1;
8196
8197
  /* The last byte selects break vs reset for a data marker. */
8198
0
  if ( tvb_reported_length_remaining(tvb, offset) > 0 )
8199
0
  {
8200
0
    uint32_t func = tvb_get_uint8(tvb, offset);
8201
0
    proto_tree_add_item(marker_tree, hf_tns_marker_function, tvb,
8202
0
        offset, 1, ENC_BIG_ENDIAN);
8203
0
    col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
8204
0
        val_to_str_const(func, tns_marker_functions, "Unknown"));
8205
0
  }
8206
0
}
8207
8208
static void dissect_tns_redirect(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
8209
0
{
8210
0
  proto_tree *redirect_tree;
8211
8212
0
  redirect_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
8213
0
        ett_tns_redirect, NULL, "Redirect");
8214
8215
0
  proto_tree_add_item(redirect_tree, hf_tns_redirect_data_length, tvb,
8216
0
      offset, 2, ENC_BIG_ENDIAN);
8217
0
  offset += 2;
8218
8219
0
  proto_tree_add_item(redirect_tree, hf_tns_redirect_data, tvb,
8220
0
      offset, -1, ENC_ASCII);
8221
0
}
8222
8223
static void dissect_tns_control(tvbuff_t *tvb, int offset, packet_info *pinfo _U_, proto_tree *tns_tree)
8224
0
{
8225
0
  proto_tree *control_tree;
8226
8227
0
  control_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
8228
0
        ett_tns_control, NULL, "Control");
8229
8230
0
  proto_tree_add_item(control_tree, hf_tns_control_cmd, tvb,
8231
0
      offset, 2, ENC_BIG_ENDIAN);
8232
0
  offset += 2;
8233
8234
0
  proto_tree_add_item(control_tree, hf_tns_control_data, tvb,
8235
0
      offset, -1, ENC_NA);
8236
0
}
8237
8238
static unsigned
8239
get_tns_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
8240
0
{
8241
  /*
8242
   * Get the 16-bit length of the TNS message, including header
8243
   */
8244
0
  unsigned length = tvb_get_ntohs(tvb, offset);
8245
0
  offset += 4;
8246
0
  uint8_t type = tvb_get_uint8(tvb, offset);
8247
  /* Type 0xf (data descriptor, LOB/FILE data) has data which follows
8248
   * immediately (no new PDU header) but is not counted in the PDU
8249
   * length field either.
8250
   */
8251
0
  if (type == TNS_TYPE_DD) {
8252
0
    offset += 8;
8253
0
    if (!tvb_bytes_exist(tvb, offset, 4)) {
8254
      /* return 0 makes tcp_dissect_pdus() report
8255
       * DESEGMENT_ONE_MORE_SEGMENT to the TCP dissector.
8256
       */
8257
0
      return 0;
8258
0
    }
8259
0
    unsigned dd_len = tvb_get_ntohl(tvb, offset);
8260
0
    return length + dd_len;
8261
0
  }
8262
0
  return length;
8263
0
}
8264
8265
static unsigned
8266
get_tns_pdu_len_nochksum(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
8267
3
{
8268
  /*
8269
   * Get the 32-bit length of the TNS message, including header
8270
   */
8271
3
  unsigned length = tvb_get_ntohl(tvb, offset);
8272
3
  offset += 4;
8273
3
  uint8_t type = tvb_get_uint8(tvb, offset);
8274
  /* Type 0xf (data descriptor, LOB/FILE data) has data which follows
8275
   * immediately (no new PDU header) but is not counted in the PDU
8276
   * length field either.
8277
   */
8278
3
  if (type == TNS_TYPE_DD) {
8279
1
    offset += 8;
8280
1
    if (!tvb_bytes_exist(tvb, offset, 4)) {
8281
      /* return 0 makes tcp_dissect_pdus() report
8282
       * DESEGMENT_ONE_MORE_SEGMENT to the TCP dissector.
8283
       */
8284
0
      return 0;
8285
0
    }
8286
1
    unsigned dd_len = tvb_get_ntohl(tvb, offset);
8287
1
    return length + dd_len;
8288
1
  }
8289
8290
2
  return length;
8291
3
}
8292
8293
static int
8294
dissect_tns(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
8295
6
{
8296
6
  uint32_t length;
8297
6
  uint16_t chksum;
8298
6
  uint8_t type;
8299
8300
  /*
8301
   * First, do a sanity check to make sure what we have
8302
   * starts with a TNS PDU.
8303
   */
8304
6
  if (tvb_bytes_exist(tvb, 4, 1)) {
8305
    /*
8306
     * Well, we have the packet type; let's make sure
8307
     * it's a known type.
8308
     */
8309
4
    type = tvb_get_uint8(tvb, 4);
8310
4
    if (type < TNS_TYPE_CONNECT || type > TNS_TYPE_MAX)
8311
2
      return 0; /* it's not a known type */
8312
4
  }
8313
8314
  /*
8315
   * In some messages (observed in Oracle12c) packet length has 4 bytes
8316
   * instead of 2.
8317
   *
8318
   * If packet length has 2 bytes, length and checksum equals two unsigned
8319
   * 16-bit numbers. Packet checksum is generally unused (equal zero),
8320
   * but 10g client may set 2nd byte to 4.
8321
   *
8322
   * Else, Oracle 12c combine these two 16-bit numbers into one 32-bit.
8323
   * This number represents the packet length. Checksum is omitted.
8324
   */
8325
4
  chksum = tvb_get_ntohs(tvb, 2);
8326
8327
4
  length = (chksum == 0 || chksum == 4) ? 2 : 4;
8328
8329
4
  tcp_dissect_pdus(tvb, pinfo, tree, tns_desegment, TNS_HDR_LEN,
8330
4
      (length == 2 ? get_tns_pdu_len : get_tns_pdu_len_nochksum),
8331
4
      dissect_tns_pdu, data);
8332
8333
4
  return tvb_captured_length(tvb);
8334
6
}
8335
8336
static int
8337
dissect_tns_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
8338
2
{
8339
2
  proto_tree *tns_tree, *ti;
8340
2
  proto_item *hidden_item;
8341
2
  unsigned offset = 0;
8342
2
  uint32_t length;
8343
2
  uint16_t chksum;
8344
2
  uint8_t type;
8345
8346
2
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "TNS");
8347
8348
2
  col_set_str(pinfo->cinfo, COL_INFO,
8349
2
      (pinfo->match_uint == pinfo->destport) ? "Request" : "Response");
8350
8351
2
  ti = proto_tree_add_item(tree, proto_tns, tvb, 0, -1, ENC_NA);
8352
2
  tns_tree = proto_item_add_subtree(ti, ett_tns);
8353
8354
2
  if (pinfo->match_uint == pinfo->destport)
8355
2
  {
8356
2
    hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_request,
8357
2
          tvb, offset, 0, true);
8358
2
  }
8359
0
  else
8360
0
  {
8361
0
    hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_response,
8362
0
          tvb, offset, 0, true);
8363
0
  }
8364
2
  proto_item_set_hidden(hidden_item);
8365
8366
2
  chksum = tvb_get_ntohs(tvb, offset+2);
8367
2
  if (chksum == 0 || chksum == 4)
8368
0
  {
8369
0
    proto_tree_add_item_ret_uint(tns_tree, hf_tns_length, tvb, offset,
8370
0
          2, ENC_BIG_ENDIAN, &length);
8371
0
    offset += 2;
8372
0
    proto_tree_add_checksum(tns_tree, tvb, offset, hf_tns_packet_checksum,
8373
0
          -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
8374
0
    offset += 2;
8375
0
  }
8376
2
  else
8377
2
  {
8378
    /* Oracle 12c uses checksum bytes as part of the packet length. */
8379
2
    proto_tree_add_item_ret_uint(tns_tree, hf_tns_length, tvb, offset,
8380
2
          4, ENC_BIG_ENDIAN, &length);
8381
2
    offset += 4;
8382
2
  }
8383
8384
2
  type = tvb_get_uint8(tvb, offset);
8385
2
  proto_tree_add_uint(tns_tree, hf_tns_packet_type, tvb,
8386
2
      offset, 1, type);
8387
2
  offset += 1;
8388
8389
2
  col_append_fstr(pinfo->cinfo, COL_INFO, ", %s (%u)",
8390
2
      val_to_str_const(type, tns_type_vals, "Unknown"), type);
8391
8392
2
  proto_tree_add_item(tns_tree, hf_tns_reserved_byte, tvb,
8393
2
      offset, 1, ENC_NA);
8394
2
  offset += 1;
8395
8396
2
  proto_tree_add_checksum(tns_tree, tvb, offset, hf_tns_header_checksum, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
8397
2
  offset += 2;
8398
8399
2
  switch (type)
8400
2
  {
8401
0
    case TNS_TYPE_CONNECT:
8402
0
      dissect_tns_connect(tvb,offset,pinfo,tns_tree);
8403
0
      break;
8404
0
    case TNS_TYPE_ACCEPT:
8405
0
      dissect_tns_accept(tvb,offset,pinfo,tns_tree);
8406
0
      break;
8407
0
    case TNS_TYPE_REFUSE:
8408
0
      dissect_tns_refuse(tvb,offset,pinfo,tns_tree);
8409
0
      break;
8410
0
    case TNS_TYPE_REDIRECT:
8411
0
      dissect_tns_redirect(tvb,offset,pinfo,tns_tree);
8412
0
      break;
8413
0
    case TNS_TYPE_ABORT:
8414
0
      dissect_tns_abort(tvb,offset,pinfo,tns_tree);
8415
0
      break;
8416
0
    case TNS_TYPE_MARKER:
8417
0
      dissect_tns_marker(tvb,offset,pinfo,tns_tree, 0);
8418
0
      break;
8419
0
    case TNS_TYPE_ATTENTION:
8420
0
      dissect_tns_marker(tvb,offset,pinfo,tns_tree, 1);
8421
0
      break;
8422
0
    case TNS_TYPE_CONTROL:
8423
0
      dissect_tns_control(tvb,offset,pinfo,tns_tree);
8424
0
      break;
8425
0
    case TNS_TYPE_DATA:
8426
0
      dissect_tns_data(tvb,offset,pinfo,tns_tree);
8427
0
      break;
8428
1
    case TNS_TYPE_DD:
8429
1
      dissect_tns_data_descriptor(tvb,offset,pinfo,tns_tree, length);
8430
1
      break;
8431
1
    default:
8432
1
      call_data_dissector(tvb_new_subset_remaining(tvb, offset), pinfo,
8433
1
          tns_tree);
8434
1
      break;
8435
2
  }
8436
8437
1
  return tvb_captured_length(tvb);
8438
2
}
8439
8440
void proto_register_tns(void)
8441
16
{
8442
16
  static hf_register_info hf[] = {
8443
16
    { &hf_tns_response, {
8444
16
      "Response", "tns.response", FT_BOOLEAN, BASE_NONE,
8445
16
      NULL, 0x0, "true if TNS response", HFILL }},
8446
16
    { &hf_tns_request, {
8447
16
      "Request", "tns.request", FT_BOOLEAN, BASE_NONE,
8448
16
      NULL, 0x0, "true if TNS request", HFILL }},
8449
16
    { &hf_tns_length, {
8450
16
      "Packet Length", "tns.length", FT_UINT32, BASE_DEC,
8451
16
      NULL, 0x0, "Length of TNS packet", HFILL }},
8452
16
    { &hf_tns_packet_checksum, {
8453
16
      "Packet Checksum", "tns.packet_checksum", FT_UINT16, BASE_HEX,
8454
16
      NULL, 0x0, "Checksum of Packet Data", HFILL }},
8455
16
    { &hf_tns_header_checksum, {
8456
16
      "Header Checksum", "tns.header_checksum", FT_UINT16, BASE_HEX,
8457
16
      NULL, 0x0, "Checksum of Header Data", HFILL }},
8458
8459
16
    { &hf_tns_version, {
8460
16
      "Version", "tns.version", FT_UINT16, BASE_DEC,
8461
16
      NULL, 0x0, NULL, HFILL }},
8462
16
    { &hf_tns_compat_version, {
8463
16
      "Version (Compatible)", "tns.compat_version", FT_UINT16, BASE_DEC,
8464
16
      NULL, 0x0, NULL, HFILL }},
8465
8466
16
    { &hf_tns_service_options, {
8467
16
      "Service Options", "tns.service_options", FT_UINT16, BASE_HEX,
8468
16
      NULL, 0x0, NULL, HFILL }},
8469
8470
16
    { &hf_tns_sopt_flag_bconn, {
8471
16
      "Broken Connect Notify", "tns.so_flag.bconn", FT_BOOLEAN, 16,
8472
16
      NULL, 0x2000, NULL, HFILL }},
8473
16
    { &hf_tns_sopt_flag_pc, {
8474
16
      "Packet Checksum", "tns.so_flag.pc", FT_BOOLEAN, 16,
8475
16
      NULL, 0x1000, NULL, HFILL }},
8476
16
    { &hf_tns_sopt_flag_hc, {
8477
16
      "Header Checksum", "tns.so_flag.hc", FT_BOOLEAN, 16,
8478
16
      NULL, 0x0800, NULL, HFILL }},
8479
16
    { &hf_tns_sopt_flag_fd, {
8480
16
      "Full Duplex", "tns.so_flag.fd", FT_BOOLEAN, 16,
8481
16
      NULL, 0x0400, NULL, HFILL }},
8482
16
    { &hf_tns_sopt_flag_hd, {
8483
16
      "Half Duplex", "tns.so_flag.hd", FT_BOOLEAN, 16,
8484
16
      NULL, 0x0200, NULL, HFILL }},
8485
16
    { &hf_tns_sopt_flag_dc1, {
8486
16
      "Don't Care", "tns.so_flag.dc1", FT_BOOLEAN, 16,
8487
16
      NULL, 0x0100, NULL, HFILL }},
8488
16
    { &hf_tns_sopt_flag_dc2, {
8489
16
      "Don't Care", "tns.so_flag.dc2", FT_BOOLEAN, 16,
8490
16
      NULL, 0x0080, NULL, HFILL }},
8491
16
    { &hf_tns_sopt_flag_dio, {
8492
16
      "Direct IO to Transport", "tns.so_flag.dio", FT_BOOLEAN, 16,
8493
16
      NULL, 0x0010, NULL, HFILL }},
8494
16
    { &hf_tns_sopt_flag_ap, {
8495
16
      "Attention Processing", "tns.so_flag.ap", FT_BOOLEAN, 16,
8496
16
      NULL, 0x0008, NULL, HFILL }},
8497
16
    { &hf_tns_sopt_flag_ra, {
8498
16
      "Can Receive Attention", "tns.so_flag.ra", FT_BOOLEAN, 16,
8499
16
      NULL, 0x0004, NULL, HFILL }},
8500
16
    { &hf_tns_sopt_flag_sa, {
8501
16
      "Can Send Attention", "tns.so_flag.sa", FT_BOOLEAN, 16,
8502
16
      NULL, 0x0002, NULL, HFILL }},
8503
8504
8505
16
    { &hf_tns_sdu_size, {
8506
16
      "Session Data Unit Size", "tns.sdu_size", FT_UINT16, BASE_DEC,
8507
16
      NULL, 0x0, NULL, HFILL }},
8508
16
    { &hf_tns_max_tdu_size, {
8509
16
      "Maximum Transmission Data Unit Size", "tns.max_tdu_size", FT_UINT16, BASE_DEC,
8510
16
      NULL, 0x0, NULL, HFILL }},
8511
8512
16
    { &hf_tns_nt_proto_characteristics, {
8513
16
      "NT Protocol Characteristics", "tns.nt_proto_characteristics", FT_UINT16, BASE_HEX,
8514
16
      NULL, 0x0, NULL, HFILL }},
8515
16
    { &hf_tns_ntp_flag_hangon, {
8516
16
      "Hangon to listener connect", "tns.ntp_flag.hangon", FT_BOOLEAN, 16,
8517
16
      NULL, 0x8000, NULL, HFILL }},
8518
16
    { &hf_tns_ntp_flag_crel, {
8519
16
      "Confirmed release", "tns.ntp_flag.crel", FT_BOOLEAN, 16,
8520
16
      NULL, 0x4000, NULL, HFILL }},
8521
16
    { &hf_tns_ntp_flag_tduio, {
8522
16
      "TDU based IO", "tns.ntp_flag.tduio", FT_BOOLEAN, 16,
8523
16
      NULL, 0x2000, NULL, HFILL }},
8524
16
    { &hf_tns_ntp_flag_srun, {
8525
16
      "Spawner running", "tns.ntp_flag.srun", FT_BOOLEAN, 16,
8526
16
      NULL, 0x1000, NULL, HFILL }},
8527
16
    { &hf_tns_ntp_flag_dtest, {
8528
16
      "Data test", "tns.ntp_flag.dtest", FT_BOOLEAN, 16,
8529
16
      NULL, 0x0800, NULL, HFILL }},
8530
16
    { &hf_tns_ntp_flag_cbio, {
8531
16
      "Callback IO supported", "tns.ntp_flag.cbio", FT_BOOLEAN, 16,
8532
16
      NULL, 0x0400, NULL, HFILL }},
8533
16
    { &hf_tns_ntp_flag_asio, {
8534
16
      "ASync IO Supported", "tns.ntp_flag.asio", FT_BOOLEAN, 16,
8535
16
      NULL, 0x0200, NULL, HFILL }},
8536
16
    { &hf_tns_ntp_flag_pio, {
8537
16
      "Packet oriented IO", "tns.ntp_flag.pio", FT_BOOLEAN, 16,
8538
16
      NULL, 0x0100, NULL, HFILL }},
8539
16
    { &hf_tns_ntp_flag_grant, {
8540
16
      "Can grant connection to another", "tns.ntp_flag.grant", FT_BOOLEAN, 16,
8541
16
      NULL, 0x0080, NULL, HFILL }},
8542
16
    { &hf_tns_ntp_flag_handoff, {
8543
16
      "Can handoff connection to another", "tns.ntp_flag.handoff", FT_BOOLEAN, 16,
8544
16
      NULL, 0x0040, NULL, HFILL }},
8545
16
    { &hf_tns_ntp_flag_sigio, {
8546
16
      "Generate SIGIO signal", "tns.ntp_flag.sigio", FT_BOOLEAN, 16,
8547
16
      NULL, 0x0020, NULL, HFILL }},
8548
16
    { &hf_tns_ntp_flag_sigpipe, {
8549
16
      "Generate SIGPIPE signal", "tns.ntp_flag.sigpipe", FT_BOOLEAN, 16,
8550
16
      NULL, 0x0010, NULL, HFILL }},
8551
16
    { &hf_tns_ntp_flag_sigurg, {
8552
16
      "Generate SIGURG signal", "tns.ntp_flag.sigurg", FT_BOOLEAN, 16,
8553
16
      NULL, 0x0008, NULL, HFILL }},
8554
16
    { &hf_tns_ntp_flag_urgentio, {
8555
16
      "Urgent IO supported", "tns.ntp_flag.urgentio", FT_BOOLEAN, 16,
8556
16
      NULL, 0x0004, NULL, HFILL }},
8557
16
    { &hf_tns_ntp_flag_fdio, {
8558
16
      "Full duplex IO supported", "tns.ntp_flag.dfio", FT_BOOLEAN, 16,
8559
16
      NULL, 0x0002, NULL, HFILL }},
8560
16
    { &hf_tns_ntp_flag_testop, {
8561
16
      "Test operation", "tns.ntp_flag.testop", FT_BOOLEAN, 16,
8562
16
      NULL, 0x0001, NULL, HFILL }},
8563
8564
8565
8566
8567
16
    { &hf_tns_line_turnaround, {
8568
16
      "Line Turnaround Value", "tns.line_turnaround", FT_UINT16, BASE_DEC,
8569
16
      NULL, 0x0, NULL, HFILL }},
8570
16
    { &hf_tns_value_of_one, {
8571
16
      "Value of 1 in Hardware", "tns.value_of_one", FT_BYTES, BASE_NONE,
8572
16
      NULL, 0x0, NULL, HFILL }},
8573
8574
16
    { &hf_tns_connect_data_length, {
8575
16
      "Length of Connect Data", "tns.connect_data_length", FT_UINT16,
8576
16
      BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }},
8577
16
    { &hf_tns_connect_data_offset, {
8578
16
      "Offset to Connect Data", "tns.connect_data_offset", FT_UINT16, BASE_DEC,
8579
16
      NULL, 0x0, NULL, HFILL }},
8580
16
    { &hf_tns_connect_data_max, {
8581
16
      "Maximum Receivable Connect Data", "tns.connect_data_max", FT_UINT32, BASE_DEC,
8582
16
      NULL, 0x0, NULL, HFILL }},
8583
8584
16
    { &hf_tns_connect_flags0, {
8585
16
      "Connect Flags 0", "tns.connect_flags0", FT_UINT8, BASE_HEX,
8586
16
      NULL, 0x0, NULL, HFILL }},
8587
16
    { &hf_tns_connect_flags1, {
8588
16
      "Connect Flags 1", "tns.connect_flags1", FT_UINT8, BASE_HEX,
8589
16
      NULL, 0x0, NULL, HFILL }},
8590
8591
16
    { &hf_tns_conn_flag_nareq, {
8592
16
      "NA services required", "tns.connect_flags.nareq", FT_BOOLEAN, 8,
8593
16
      NULL, 0x10, NULL, HFILL }},
8594
16
    { &hf_tns_conn_flag_nalink, {
8595
16
      "NA services linked in", "tns.connect_flags.nalink", FT_BOOLEAN, 8,
8596
16
      NULL, 0x08, NULL, HFILL }},
8597
16
    { &hf_tns_conn_flag_enablena, {
8598
16
      "NA services enabled", "tns.connect_flags.enablena", FT_BOOLEAN, 8,
8599
16
      NULL, 0x04, NULL, HFILL }},
8600
16
    { &hf_tns_conn_flag_ichg, {
8601
16
      "Interchange is involved", "tns.connect_flags.ichg", FT_BOOLEAN, 8,
8602
16
      NULL, 0x02, NULL, HFILL }},
8603
16
    { &hf_tns_conn_flag_wantna, {
8604
16
      "NA services wanted", "tns.connect_flags.wantna", FT_BOOLEAN, 8,
8605
16
      NULL, 0x01, NULL, HFILL }},
8606
8607
8608
16
    { &hf_tns_trace_cf1, {
8609
16
      "Trace Cross Facility Item 1", "tns.trace_cf1", FT_UINT32, BASE_HEX,
8610
16
      NULL, 0x0, NULL, HFILL }},
8611
16
    { &hf_tns_trace_cf2, {
8612
16
      "Trace Cross Facility Item 2", "tns.trace_cf2", FT_UINT32, BASE_HEX,
8613
16
      NULL, 0x0, NULL, HFILL }},
8614
16
    { &hf_tns_trace_cid, {
8615
16
      "Trace Unique Connection ID", "tns.trace_cid", FT_UINT64, BASE_HEX,
8616
16
      NULL, 0x0, NULL, HFILL }},
8617
16
    { &hf_tns_connect_data, {
8618
16
      "Connect Data", "tns.connect_data", FT_STRING, BASE_NONE,
8619
16
      NULL, 0x0, NULL, HFILL }},
8620
8621
16
    { &hf_tns_accept_data_length, {
8622
16
      "Accept Data Length", "tns.accept_data_length", FT_UINT16,
8623
16
      BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }},
8624
16
    { &hf_tns_accept_data, {
8625
16
      "Accept Data", "tns.accept_data", FT_STRING, BASE_NONE,
8626
16
      NULL, 0x0, NULL, HFILL }},
8627
16
    { &hf_tns_accept_sdu, {
8628
16
      "Session Data Unit Size (32-bit)", "tns.accept_sdu", FT_UINT32, BASE_DEC,
8629
16
      NULL, 0x0, "The session data unit a version 315 or later ACCEPT offers, past the 16-bit field's reach", HFILL }},
8630
16
    { &hf_tns_accept_flags2, {
8631
16
      "Flags 2", "tns.accept_flags2", FT_UINT32, BASE_HEX,
8632
16
      NULL, 0x0, "What a version 318 or later server offers the client", HFILL }},
8633
16
    { &hf_tns_accept_flags2_check_oob, {
8634
16
      "Check Out-of-Band", "tns.accept_flags2.check_oob", FT_BOOLEAN, 32,
8635
16
      NULL, 0x00000001, NULL, HFILL }},
8636
16
    { &hf_tns_accept_flags2_end_of_response, {
8637
16
      "End of Response", "tns.accept_flags2.end_of_response", FT_BOOLEAN, 32,
8638
16
      NULL, 0x02000000, "Replies end with an end-of-response marker, so the client can pipeline calls", HFILL }},
8639
16
    { &hf_tns_accept_flags2_fast_auth, {
8640
16
      "Fast Authentication", "tns.accept_flags2.fast_auth", FT_BOOLEAN, 32,
8641
16
      NULL, 0x10000000, "The client may send its protocol, data types and session key in one bundle", HFILL }},
8642
16
    { &hf_tns_accept_data_offset, {
8643
16
      "Offset to Accept Data", "tns.accept_data_offset", FT_UINT16, BASE_DEC,
8644
16
      NULL, 0x0, NULL, HFILL }},
8645
8646
16
    { &hf_tns_refuse_reason_user, {
8647
16
      "Refuse Reason (User)", "tns.refuse_reason_user", FT_UINT8, BASE_HEX,
8648
16
      NULL, 0x0, "Refuse Reason from Application", HFILL }},
8649
16
    { &hf_tns_refuse_reason_system, {
8650
16
      "Refuse Reason (System)", "tns.refuse_reason_system", FT_UINT8, BASE_HEX,
8651
16
      NULL, 0x0, "Refuse Reason from System", HFILL }},
8652
16
    { &hf_tns_refuse_data_length, {
8653
16
      "Refuse Data Length", "tns.refuse_data_length", FT_UINT16,
8654
16
      BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }},
8655
16
    { &hf_tns_refuse_data, {
8656
16
      "Refuse Data", "tns.refuse_data", FT_STRING, BASE_NONE,
8657
16
      NULL, 0x0, NULL, HFILL }},
8658
8659
16
    { &hf_tns_abort_reason_user, {
8660
16
      "Abort Reason (User)", "tns.abort_reason_user", FT_UINT8, BASE_HEX,
8661
16
      NULL, 0x0, "Abort Reason from Application", HFILL }},
8662
16
    { &hf_tns_abort_reason_system, {
8663
16
      "Abort Reason (User)", "tns.abort_reason_system", FT_UINT8, BASE_HEX,
8664
16
      NULL, 0x0, "Abort Reason from System", HFILL }},
8665
16
    { &hf_tns_abort_data, {
8666
16
      "Abort Data", "tns.abort_data", FT_STRING, BASE_NONE,
8667
16
      NULL, 0x0, NULL, HFILL }},
8668
8669
16
    { &hf_tns_marker_type, {
8670
16
      "Marker Type", "tns.marker.type", FT_UINT8, BASE_HEX,
8671
16
      VALS(tns_marker_types), 0x0, NULL, HFILL }},
8672
16
    { &hf_tns_marker_data_byte, {
8673
16
      "Marker Data Byte", "tns.marker.databyte", FT_UINT8, BASE_HEX,
8674
16
      NULL, 0x0, NULL, HFILL }},
8675
16
    { &hf_tns_marker_function, {
8676
16
      "Marker Function", "tns.marker.function", FT_UINT8, BASE_DEC,
8677
16
      VALS(tns_marker_functions), 0x0, NULL, HFILL }},
8678
#if 0
8679
    { &hf_tns_marker_data, {
8680
      "Marker Data", "tns.marker.data", FT_UINT16, BASE_HEX,
8681
      NULL, 0x0, NULL, HFILL }},
8682
#endif
8683
8684
16
    { &hf_tns_control_cmd, {
8685
16
      "Control Command", "tns.control.cmd", FT_UINT16, BASE_HEX,
8686
16
      VALS(tns_control_cmds), 0x0, NULL, HFILL }},
8687
16
    { &hf_tns_control_data, {
8688
16
      "Control Data", "tns.control.data", FT_BYTES, BASE_NONE,
8689
16
      NULL, 0x0, NULL, HFILL }},
8690
8691
16
    { &hf_tns_redirect_data_length, {
8692
16
      "Redirect Data Length", "tns.redirect_data_length", FT_UINT16,
8693
16
      BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }},
8694
16
    { &hf_tns_redirect_data, {
8695
16
      "Redirect Data", "tns.redirect_data", FT_STRING, BASE_NONE,
8696
16
      NULL, 0x0, NULL, HFILL }},
8697
8698
16
    { &hf_tns_data_flag, {
8699
16
      "Data Flag", "tns.data_flag", FT_UINT16, BASE_HEX,
8700
16
      NULL, 0x0, NULL, HFILL }},
8701
16
    { &hf_tns_data_flag_send, {
8702
16
      "Send Token", "tns.data_flag.send", FT_BOOLEAN, 16,
8703
16
      NULL, 0x1, NULL, HFILL }},
8704
16
    { &hf_tns_data_flag_rc, {
8705
16
      "Request Confirmation", "tns.data_flag.rc", FT_BOOLEAN, 16,
8706
16
      NULL, 0x2, NULL, HFILL }},
8707
16
    { &hf_tns_data_flag_c, {
8708
16
      "Confirmation", "tns.data_flag.c", FT_BOOLEAN, 16,
8709
16
      NULL, 0x4, NULL, HFILL }},
8710
16
    { &hf_tns_data_flag_reserved, {
8711
16
      "Reserved", "tns.data_flag.reserved", FT_BOOLEAN, 16,
8712
16
      NULL, 0x8, NULL, HFILL }},
8713
16
    { &hf_tns_data_flag_more, {
8714
16
      "More Data to Come", "tns.data_flag.more", FT_BOOLEAN, 16,
8715
16
      NULL, 0x0020, NULL, HFILL }},
8716
16
    { &hf_tns_data_flag_eof, {
8717
16
      "End of File", "tns.data_flag.eof", FT_BOOLEAN, 16,
8718
16
      NULL, 0x0040, NULL, HFILL }},
8719
16
    { &hf_tns_data_flag_dic, {
8720
16
      "Do Immediate Confirmation", "tns.data_flag.dic", FT_BOOLEAN, 16,
8721
16
      NULL, 0x0080, NULL, HFILL }},
8722
16
    { &hf_tns_data_flag_rts, {
8723
16
      "Request To Send", "tns.data_flag.rts", FT_BOOLEAN, 16,
8724
16
      NULL, 0x0100, NULL, HFILL }},
8725
16
    { &hf_tns_data_flag_sntt, {
8726
16
      "Send NT Trailer", "tns.data_flag.sntt", FT_BOOLEAN, 16,
8727
16
      NULL, 0x0200, NULL, HFILL }},
8728
16
    { &hf_tns_data_flag_end_of_request, {
8729
16
      "End of Request", "tns.data_flag.end_of_request", FT_BOOLEAN, 16,
8730
16
      NULL, 0x0800, "The packet ends one of a pipeline's calls", HFILL }},
8731
16
    { &hf_tns_data_flag_begin_pipeline, {
8732
16
      "Begin Pipeline", "tns.data_flag.begin_pipeline", FT_BOOLEAN, 16,
8733
16
      NULL, 0x1000, "The packet carries the first call of a pipeline", HFILL }},
8734
16
    { &hf_tns_data_flag_end_of_response, {
8735
16
      "End of Response", "tns.data_flag.end_of_response", FT_BOOLEAN, 16,
8736
16
      NULL, 0x2000, "The packet ends a reply, which closes with an end-of-response marker", HFILL }},
8737
8738
16
    { &hf_tns_data_id, {
8739
16
      "Data ID", "tns.data_id", FT_UINT32, BASE_HEX,
8740
16
      VALS(tns_data_funcs), 0x0, NULL, HFILL }},
8741
16
    { &hf_tns_data_length, {
8742
16
      "Data Length", "tns.data_length", FT_UINT32,
8743
16
      BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytes), 0x0, NULL, HFILL }},
8744
8745
16
    { &hf_tns_data_oci_id, {
8746
16
      "Call ID", "tns.data_oci.id", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
8747
16
      &tns_data_oci_subfuncs_ext, 0x00, NULL, HFILL }},
8748
8749
16
    { &hf_tns_data_tseq, {
8750
16
      "TSeq", "tns.data_tseq", FT_UINT8, BASE_HEX,
8751
16
      NULL, 0x00, NULL, HFILL }},
8752
8753
16
    { &hf_tns_data_token, {
8754
16
      "Token", "tns.data.token", FT_UINT64, BASE_DEC,
8755
16
      NULL, 0x0, "Call token (23ai); the reply echoes it", HFILL }},
8756
16
    { &hf_tns_data_piggyback_id, {
8757
      /* Also Call ID.
8758
         Piggyback is a message what calls a small subset of functions
8759
         declared in tns_data_oci_subfuncs. */
8760
16
      "Call ID", "tns.data_piggyback.id", FT_UINT8, BASE_HEX|BASE_EXT_STRING,
8761
16
      &tns_data_oci_subfuncs_ext, 0x00, NULL, HFILL }},
8762
8763
16
    { &hf_tns_data_unused, {
8764
16
      "Unused", "tns.data.unused", FT_BYTES, BASE_NONE,
8765
16
      NULL, 0x0, NULL, HFILL }},
8766
8767
16
    { &hf_tns_cursor, {
8768
16
      "Cursor", "tns.data.cursor", FT_UINT32, BASE_DEC,
8769
16
      NULL, 0x0, NULL, HFILL }},
8770
8771
16
    { &hf_tns_data_setp_acc_version, {
8772
16
      "Accepted Version", "tns.data_setp_req.acc_vers", FT_UINT8, BASE_DEC,
8773
16
      NULL, 0x0, NULL, HFILL }},
8774
16
    { &hf_tns_data_fastauth_version, {
8775
16
      "Fast Authentication Version", "tns.data_fastauth.version", FT_UINT8, BASE_DEC,
8776
16
      NULL, 0x0, NULL, HFILL }},
8777
16
    { &hf_tns_data_setp_cli_plat, {
8778
16
      "Client Platform", "tns.data_setp_req.cli_plat", FT_STRINGZ, BASE_NONE,
8779
16
      NULL, 0x0, NULL, HFILL }},
8780
16
    { &hf_tns_data_setp_version, {
8781
16
      "Version", "tns.data_setp_resp.version", FT_UINT8, BASE_DEC,
8782
16
      NULL, 0x0, NULL, HFILL }},
8783
16
    { &hf_tns_data_setp_charset, {
8784
16
      "Charset", "tns.data_setp_resp.charset", FT_UINT16, BASE_DEC,
8785
16
      VALS(tns_charsets), 0x0, "The database character set", HFILL }},
8786
16
    { &hf_tns_data_setp_flags, {
8787
16
      "Server Flags", "tns.data_setp_resp.flags", FT_UINT8, BASE_HEX,
8788
16
      NULL, 0x0, NULL, HFILL }},
8789
16
    { &hf_tns_data_setp_ncharset, {
8790
16
      "National Charset", "tns.data_setp_resp.ncharset", FT_UINT16, BASE_DEC,
8791
16
      VALS(tns_charsets), 0x0, NULL, HFILL }},
8792
16
    { &hf_tns_data_setp_compile_caps, {
8793
16
      "Compile Capabilities", "tns.data_setp_resp.compile_caps", FT_BYTES, BASE_NONE,
8794
16
      NULL, 0x0, NULL, HFILL }},
8795
16
    { &hf_tns_data_setp_runtime_caps, {
8796
16
      "Runtime Capabilities", "tns.data_setp_resp.runtime_caps", FT_BYTES, BASE_NONE,
8797
16
      NULL, 0x0, NULL, HFILL }},
8798
16
    { &hf_tns_data_setp_field_version, {
8799
16
      "Field Version", "tns.data_setp_resp.field_version", FT_UINT8, BASE_DEC,
8800
16
      VALS(tns_field_versions), 0x0, "The highest TTC field version the server offers", HFILL }},
8801
16
    { &hf_tns_data_setp_banner, {
8802
16
      "Server Banner", "tns.data_setp_resp.banner", FT_STRINGZ, BASE_NONE,
8803
16
      NULL, 0x0, NULL, HFILL }},
8804
8805
16
    { &hf_tns_data_sns_cli_vers, {
8806
16
      "Client Version", "tns.data_sns.cli_vers", FT_UINT32, BASE_CUSTOM,
8807
16
      CF_FUNC(vsnum_to_vstext_basecustom), 0x0, NULL, HFILL }},
8808
16
    { &hf_tns_data_sns_srv_vers, {
8809
16
      "Server Version", "tns.data_sns.srv_vers", FT_UINT32, BASE_CUSTOM,
8810
16
      CF_FUNC(vsnum_to_vstext_basecustom), 0x0, NULL, HFILL }},
8811
16
    { &hf_tns_data_sns_srvcnt, {
8812
16
      "Services", "tns.data_sns.srvcnt", FT_UINT16, BASE_DEC,
8813
16
      NULL, 0x0, NULL, HFILL }},
8814
16
    { &hf_tns_data_sns_error, {
8815
16
      "Error", "tns.data_sns.error", FT_UINT8, BASE_DEC,
8816
16
      NULL, 0x0, NULL, HFILL }},
8817
16
    { &hf_tns_data_sns_service, {
8818
16
      "Service", "tns.data_sns.service", FT_UINT16, BASE_DEC,
8819
16
      VALS(tns_sns_services), 0x0, NULL, HFILL }},
8820
16
    { &hf_tns_data_sns_subpackets, {
8821
16
      "Sub-packets", "tns.data_sns.subpackets", FT_UINT16, BASE_DEC,
8822
16
      NULL, 0x0, NULL, HFILL }},
8823
16
    { &hf_tns_data_sns_svc_error, {
8824
16
      "Service Error", "tns.data_sns.service_error", FT_UINT32, BASE_DEC,
8825
16
      NULL, 0x0, NULL, HFILL }},
8826
16
    { &hf_tns_data_sns_sub_type, {
8827
16
      "Sub-packet Type", "tns.data_sns.sub_type", FT_UINT16, BASE_DEC,
8828
16
      VALS(tns_sns_subpacket_types), 0x0, NULL, HFILL }},
8829
16
    { &hf_tns_data_sns_version, {
8830
16
      "Version", "tns.data_sns.version", FT_UINT32, BASE_HEX,
8831
16
      NULL, 0x0, NULL, HFILL }},
8832
16
    { &hf_tns_data_sns_sub_data, {
8833
16
      "Sub-packet Data", "tns.data_sns.sub_data", FT_BYTES, BASE_NONE,
8834
16
      NULL, 0x0, NULL, HFILL }},
8835
16
    { &hf_tns_data_sns_encryption, {
8836
16
      "Encryption Algorithm", "tns.data_sns.encryption", FT_UINT8, BASE_DEC,
8837
16
      VALS(tns_sns_encryption_algs), 0x0, NULL, HFILL }},
8838
16
    { &hf_tns_data_sns_integrity, {
8839
16
      "Integrity Algorithm", "tns.data_sns.integrity", FT_UINT8, BASE_DEC,
8840
16
      VALS(tns_sns_integrity_algs), 0x0, NULL, HFILL }},
8841
8842
16
    { &hf_tns_data_setdt_charset_in, {
8843
16
      "Charset In", "tns.data_setdt.charset_in", FT_UINT16, BASE_DEC,
8844
16
      VALS(tns_charsets), 0x0, "NLS_LANGUAGE charset id", HFILL }},
8845
16
    { &hf_tns_data_setdt_charset_out, {
8846
16
      "Charset Out", "tns.data_setdt.charset_out", FT_UINT16, BASE_DEC,
8847
16
      VALS(tns_charsets), 0x0, "NLS_NCHAR charset id", HFILL }},
8848
16
    { &hf_tns_data_setdt_tz, {
8849
16
      "Time Zone Block", "tns.data_setdt.tz", FT_BYTES, BASE_NONE,
8850
16
      NULL, 0x0, NULL, HFILL }},
8851
16
    { &hf_tns_data_setdt_tz_offset, {
8852
16
      "Time Zone Offset", "tns.data_setdt.tz_offset", FT_STRING, BASE_NONE,
8853
16
      NULL, 0x0, "The offset from UTC the time zone block carries", HFILL }},
8854
16
    { &hf_tns_data_setdt_tzfile, {
8855
16
      "Timezone File Version", "tns.data_setdt.tzfile_version", FT_UINT32, BASE_DEC,
8856
16
      NULL, 0x0, NULL, HFILL }},
8857
16
    { &hf_tns_data_setdt_ncharset, {
8858
16
      "National Charset", "tns.data_setdt.ncharset", FT_UINT16, BASE_DEC,
8859
16
      VALS(tns_charsets), 0x0, NULL, HFILL }},
8860
16
    { &hf_tns_data_setdt_flag, {
8861
16
      "Flag", "tns.data_setdt.flag", FT_UINT8, BASE_HEX,
8862
16
      NULL, 0x0, NULL, HFILL }},
8863
16
    { &hf_tns_data_setdt_caphdr, {
8864
16
      "Compile Capabilities", "tns.data_setdt.caphdr", FT_BYTES, BASE_NONE,
8865
16
      NULL, 0x0, NULL, HFILL }},
8866
16
    { &hf_tns_data_setdt_caphdr_version, {
8867
16
      "Version", "tns.data_setdt.caphdr.version", FT_UINT24, BASE_HEX,
8868
16
      NULL, 0x0, NULL, HFILL }},
8869
16
    { &hf_tns_data_setdt_caphdr_flags, {
8870
16
      "Flags", "tns.data_setdt.caphdr.flags", FT_BYTES, BASE_NONE,
8871
16
      NULL, 0x0, NULL, HFILL }},
8872
16
    { &hf_tns_data_field_version, {
8873
16
      "Field Version", "tns.data.field_version", FT_UINT8, BASE_DEC,
8874
16
      VALS(tns_field_versions), 0x0, "TTC field version in force on the connection", HFILL }},
8875
16
    { &hf_tns_data_setdt_field_version, {
8876
16
      "Field Version", "tns.data_setdt.field_version", FT_UINT8, BASE_DEC,
8877
16
      VALS(tns_field_versions), 0x0, "TTC field version the connection uses", HFILL }},
8878
16
    { &hf_tns_data_setdt_tblhdr, {
8879
16
      "Runtime Capabilities", "tns.data_setdt.tblhdr", FT_BYTES, BASE_NONE,
8880
16
      NULL, 0x0, NULL, HFILL }},
8881
16
    { &hf_tns_data_setdt_type, {
8882
16
      "Data Type", "tns.data_setdt.type", FT_UINT16, BASE_DEC,
8883
16
      VALS(tns_data_types), 0x0, NULL, HFILL }},
8884
16
    { &hf_tns_data_setdt_conv_type, {
8885
16
      "Conversion Type", "tns.data_setdt.conv_type", FT_UINT16, BASE_DEC,
8886
16
      VALS(tns_data_types), 0x0, "The type the server sends it as", HFILL }},
8887
16
    { &hf_tns_data_setdt_rep, {
8888
16
      "Representation", "tns.data_setdt.rep", FT_UINT16, BASE_DEC,
8889
16
      NULL, 0x0, NULL, HFILL }},
8890
16
    { &hf_tns_data_setdt_idmap, {
8891
16
      "Identity Map", "tns.data_setdt.idmap", FT_BYTES, BASE_NONE,
8892
16
      NULL, 0x0, "245 entries: type N -> repr N (default mapping)", HFILL }},
8893
16
    { &hf_tns_data_setdt_overrides, {
8894
16
      "Type Overrides", "tns.data_setdt.overrides", FT_NONE, BASE_NONE,
8895
16
      NULL, 0x0, NULL, HFILL }},
8896
16
    { &hf_tns_data_setdt_override_client, {
8897
16
      "Client Type", "tns.data_setdt.override.client", FT_UINT8, BASE_DEC,
8898
16
      VALS(tns_data_types), 0x0, NULL, HFILL }},
8899
16
    { &hf_tns_data_setdt_override_repr, {
8900
16
      "Server Repr", "tns.data_setdt.override.repr", FT_UINT8, BASE_DEC,
8901
16
      VALS(tns_data_types), 0x0, NULL, HFILL }},
8902
16
    { &hf_tns_data_setdt_override_format, {
8903
16
      "Format", "tns.data_setdt.override.format", FT_UINT8, BASE_DEC,
8904
16
      NULL, 0x0, NULL, HFILL }},
8905
8906
16
    { &hf_tns_data_rpa_num_al8o4, {
8907
16
      "Number of al8o4 Words", "tns.data_rpa.num_al8o4", FT_UINT32, BASE_DEC,
8908
16
      NULL, 0x0, NULL, HFILL }},
8909
16
    { &hf_tns_data_rpa_al8o4, {
8910
16
      "al8o4", "tns.data_rpa.al8o4", FT_UINT32, BASE_HEX,
8911
16
      NULL, 0x0, NULL, HFILL }},
8912
16
    { &hf_tns_data_rpa_al8txl, {
8913
16
      "al8txl", "tns.data_rpa.al8txl", FT_BYTES, BASE_NONE,
8914
16
      NULL, 0x0, NULL, HFILL }},
8915
16
    { &hf_tns_data_rpa_num_kv, {
8916
16
      "Number of Key/Value Pairs", "tns.data_rpa.num_kv", FT_UINT32, BASE_DEC,
8917
16
      NULL, 0x0, NULL, HFILL }},
8918
16
    { &hf_tns_data_rpa_registration, {
8919
16
      "Registration", "tns.data_rpa.registration", FT_BYTES, BASE_NONE,
8920
16
      NULL, 0x0, "Query registration; the last 8 bytes are the query id", HFILL }},
8921
16
    { &hf_tns_data_rpa_num_rowcounts, {
8922
16
      "Number of Row Counts", "tns.data_rpa.num_rowcounts", FT_UINT32, BASE_DEC,
8923
16
      NULL, 0x0, NULL, HFILL }},
8924
16
    { &hf_tns_data_rpa_dml_rowcount, {
8925
16
      "DML Row Count", "tns.data_rpa.dml_rowcount", FT_UINT64, BASE_DEC,
8926
16
      NULL, 0x0, "Rows one iteration of an array DML affected", HFILL }},
8927
16
    { &hf_tns_data_spb_opcode, {
8928
16
      "Opcode", "tns.data_spb.opcode", FT_UINT8, BASE_DEC,
8929
16
      VALS(tns_spb_opcodes), 0x0, NULL, HFILL }},
8930
16
    { &hf_tns_data_spb_ltxid, {
8931
16
      "Logical Transaction Id", "tns.data_spb.ltxid", FT_BYTES, BASE_NONE,
8932
16
      NULL, 0x0, NULL, HFILL }},
8933
16
    { &hf_tns_data_spb_os_pid, {
8934
16
      "OS PID", "tns.data_spb.os_pid", FT_STRING, BASE_NONE,
8935
16
      NULL, 0x0, NULL, HFILL }},
8936
16
    { &hf_tns_data_spb_num_kv, {
8937
16
      "Number of Key/Value Pairs", "tns.data_spb.num_kv", FT_UINT32, BASE_DEC,
8938
16
      NULL, 0x0, NULL, HFILL }},
8939
16
    { &hf_tns_data_spb_flags, {
8940
16
      "Flags", "tns.data_spb.flags", FT_UINT32, BASE_HEX,
8941
16
      NULL, 0x0, NULL, HFILL }},
8942
16
    { &hf_tns_data_spb_session_id, {
8943
16
      "Session Id", "tns.data_spb.session_id", FT_UINT32, BASE_DEC,
8944
16
      NULL, 0x0, NULL, HFILL }},
8945
16
    { &hf_tns_data_spb_serial_num, {
8946
16
      "Serial Number", "tns.data_spb.serial_num", FT_UINT16, BASE_DEC,
8947
16
      NULL, 0x0, NULL, HFILL }},
8948
16
    { &hf_tns_data_kv_text, {
8949
16
      "Text Value", "tns.data_kv.text", FT_STRING, BASE_NONE,
8950
16
      NULL, 0x0, NULL, HFILL }},
8951
16
    { &hf_tns_data_kv_binary, {
8952
16
      "Binary Value", "tns.data_kv.binary", FT_BYTES, BASE_NONE,
8953
16
      NULL, 0x0, NULL, HFILL }},
8954
16
    { &hf_tns_data_kv_keyword, {
8955
16
      "Keyword", "tns.data_kv.keyword", FT_UINT16, BASE_DEC,
8956
16
      VALS(tns_kv_keywords), 0x0, NULL, HFILL }},
8957
16
    { &hf_tns_data_wrn_code, {
8958
16
      "Warning Code", "tns.data_wrn.code", FT_UINT16, BASE_DEC,
8959
16
      NULL, 0x0, NULL, HFILL }},
8960
16
    { &hf_tns_data_wrn_length, {
8961
16
      "Message Length", "tns.data_wrn.length", FT_UINT16, BASE_DEC,
8962
16
      NULL, 0x0, NULL, HFILL }},
8963
16
    { &hf_tns_data_wrn_flags, {
8964
16
      "Flags", "tns.data_wrn.flags", FT_UINT16, BASE_HEX,
8965
16
      NULL, 0x0, NULL, HFILL }},
8966
16
    { &hf_tns_data_wrn_message, {
8967
16
      "Message", "tns.data_wrn.message", FT_STRING, BASE_NONE,
8968
16
      NULL, 0x0, NULL, HFILL }},
8969
16
    { &hf_tns_data_oci_oer_status, {
8970
16
      "Status", "tns.data_oer.oci_status", FT_UINT8, BASE_DEC,
8971
16
      VALS(tns_oci_oer_status_vals), 0x0, NULL, HFILL }},
8972
16
    { &hf_tns_data_oci_oer_seq, {
8973
16
      "End-to-End Sequence", "tns.data_oer.seq", FT_UINT16, BASE_DEC,
8974
16
      NULL, 0x0, "A per-session counter the server advances with each reply", HFILL }},
8975
16
    { &hf_tns_data_oci_oer_error_pos, {
8976
16
      "Error Position", "tns.data_oer.error_pos", FT_UINT8, BASE_DEC,
8977
16
      NULL, 0x0, "Offset into the SQL text of the parse error", HFILL }},
8978
16
    { &hf_tns_data_oci_oer_command, {
8979
16
      "Command Type", "tns.data_oer.command_type", FT_UINT8, BASE_DEC,
8980
16
      VALS(tns_command_types), 0x0, NULL, HFILL }},
8981
16
    { &hf_tns_data_oci_oer_call_seq, {
8982
16
      "Call Sequence", "tns.data_oer.call_seq", FT_UINT16, BASE_DEC,
8983
16
      NULL, 0x0, "Sequence number of the call this status answers", HFILL }},
8984
16
    { &hf_tns_data_auth_mode, {
8985
16
      "Authentication Mode", "tns.data_auth.mode", FT_UINT32, BASE_HEX,
8986
16
      NULL, 0x0, NULL, HFILL }},
8987
16
    { &hf_tns_data_auth_mode_logon, {
8988
16
      "Logon", "tns.data_auth.mode.logon", FT_BOOLEAN, 32,
8989
16
      NULL, 0x00000001, NULL, HFILL }},
8990
16
    { &hf_tns_data_auth_mode_change_password, {
8991
16
      "Change Password", "tns.data_auth.mode.change_password", FT_BOOLEAN, 32,
8992
16
      NULL, 0x00000002, NULL, HFILL }},
8993
16
    { &hf_tns_data_auth_mode_sysdba, {
8994
16
      "SYSDBA", "tns.data_auth.mode.sysdba", FT_BOOLEAN, 32,
8995
16
      NULL, 0x00000020, NULL, HFILL }},
8996
16
    { &hf_tns_data_auth_mode_sysoper, {
8997
16
      "SYSOPER", "tns.data_auth.mode.sysoper", FT_BOOLEAN, 32,
8998
16
      NULL, 0x00000040, NULL, HFILL }},
8999
16
    { &hf_tns_data_auth_mode_with_password, {
9000
16
      "With Password", "tns.data_auth.mode.with_password", FT_BOOLEAN, 32,
9001
16
      NULL, 0x00000100, NULL, HFILL }},
9002
16
    { &hf_tns_data_auth_user, {
9003
16
      "User", "tns.data_auth.user", FT_STRING, BASE_NONE,
9004
16
      NULL, 0x0, NULL, HFILL }},
9005
16
    { &hf_tns_data_sta_call_status, {
9006
16
      "Call Status", "tns.data_sta.call_status", FT_UINT32, BASE_HEX,
9007
16
      NULL, 0x0, NULL, HFILL }},
9008
16
    { &hf_tns_data_sta_seq, {
9009
16
      "End-to-End Sequence", "tns.data_sta.seq", FT_UINT16, BASE_DEC,
9010
16
      NULL, 0x0, NULL, HFILL }},
9011
16
    { &hf_tns_data_call_status_txn, {
9012
16
      "Transaction in progress", "tns.data.call_status.txn_in_progress", FT_BOOLEAN, 32,
9013
16
      NULL, TNS_CALL_STATUS_TXN_IN_PROGRESS, NULL, HFILL }},
9014
16
    { &hf_tns_data_call_status_sess_release, {
9015
16
      "Session release", "tns.data.call_status.sess_release", FT_BOOLEAN, 32,
9016
16
      NULL, TNS_CALL_STATUS_SESS_RELEASE, NULL, HFILL }},
9017
16
    { &hf_tns_data_oer_call_status, {
9018
16
      "Call Status", "tns.data_oer.call_status", FT_INT32, BASE_DEC,
9019
16
      NULL, 0x0, NULL, HFILL }},
9020
16
    { &hf_tns_data_oer_rowcount, {
9021
16
      "Row Count", "tns.data_oer.rowcount", FT_INT32, BASE_DEC,
9022
16
      NULL, 0x0, "The rows the call applied - on an error, the rows it managed before failing (11g)", HFILL }},
9023
16
    { &hf_tns_data_oer_err_code, {
9024
16
      "Error Code", "tns.data_oer.err_code", FT_INT32, BASE_DEC,
9025
16
      NULL, 0x0, "ORA-NNNNN (0 = success)", HFILL }},
9026
16
    { &hf_tns_data_oer_cursor_id, {
9027
16
      "Cursor Id", "tns.data_oer.cursor_id", FT_INT32, BASE_DEC,
9028
16
      NULL, 0x0, NULL, HFILL }},
9029
16
    { &hf_tns_data_oer_rowid, {
9030
16
      "Last Rowid", "tns.data_oer.rowid", FT_STRING, BASE_NONE,
9031
16
      NULL, 0x0, "The rowid of the last row the statement touched", HFILL }},
9032
16
    { &hf_tns_data_oer_n_batch_errcodes, {
9033
16
      "Batch Error Codes", "tns.data_oer.n_batch_errcodes", FT_INT32, BASE_DEC,
9034
16
      NULL, 0x0, NULL, HFILL }},
9035
16
    { &hf_tns_data_oer_n_batch_offsets, {
9036
16
      "Batch Error Offsets", "tns.data_oer.n_batch_offsets", FT_INT32, BASE_DEC,
9037
16
      NULL, 0x0, NULL, HFILL }},
9038
16
    { &hf_tns_data_oer_n_batch_messages, {
9039
16
      "Batch Error Messages", "tns.data_oer.n_batch_messages", FT_INT32, BASE_DEC,
9040
16
      NULL, 0x0, NULL, HFILL }},
9041
16
    { &hf_tns_data_oer_err_num_ext, {
9042
16
      "Error Number", "tns.data_oer.err_num", FT_UINT32, BASE_DEC,
9043
16
      NULL, 0x0, "The error code at its full width (12.1 and later)", HFILL }},
9044
16
    { &hf_tns_data_oer_rowcount_ext, {
9045
16
      "Row Count (64 bit)", "tns.data_oer.rowcount64", FT_UINT64, BASE_DEC,
9046
16
      NULL, 0x0, "The rows the call applied, at full width (12.1 and later)", HFILL }},
9047
16
    { &hf_tns_data_oer_sql_type, {
9048
16
      "SQL Type", "tns.data_oer.sql_type", FT_UINT32, BASE_DEC,
9049
16
      NULL, 0x0, NULL, HFILL }},
9050
16
    { &hf_tns_data_oer_checksum, {
9051
16
      "Server Checksum", "tns.data_oer.checksum", FT_UINT32, BASE_HEX,
9052
16
      NULL, 0x0, NULL, HFILL }},
9053
16
    { &hf_tns_data_oer_warn_flags, {
9054
16
      "Warning Flags", "tns.data_oer.warn_flags", FT_UINT8, BASE_HEX,
9055
16
      NULL, 0x0, NULL, HFILL }},
9056
16
    { &hf_tns_data_oer_warn_compile, {
9057
16
      "Compiled with errors", "tns.data_oer.warn_flags.compilation_error", FT_BOOLEAN, 8,
9058
16
      NULL, TNS_WARN_COMPILATION_ERROR, "A PL/SQL object was created in an invalid state", HFILL }},
9059
16
    { &hf_tns_data_oer_message, {
9060
16
      "Message", "tns.data_oer.message", FT_STRING, BASE_NONE,
9061
16
      NULL, 0x0, NULL, HFILL }},
9062
9063
16
    { &hf_tns_data_opi_version2_banner_len, {
9064
16
      "Banner Length", "tns.data_opi.vers2.banner_len", FT_UINT8, BASE_DEC,
9065
16
      NULL, 0x0, NULL, HFILL }},
9066
16
    { &hf_tns_data_opi_version2_banner, {
9067
16
      "Banner", "tns.data_opi.vers2.banner", FT_STRING, BASE_NONE,
9068
16
      NULL, 0x0, NULL, HFILL }},
9069
16
    { &hf_tns_data_opi_version2_vsnum, {
9070
16
      "Version", "tns.data_opi.vers2.version", FT_UINT32, BASE_CUSTOM,
9071
16
      CF_FUNC(vsnum_to_vstext_basecustom), 0x0, NULL, HFILL }},
9072
9073
16
    { &hf_tns_data_opi_num_of_params, {
9074
16
      "Number of parameters", "tns.data_opi.num_of_params", FT_UINT8, BASE_DEC,
9075
16
      NULL, 0x0, NULL, HFILL }},
9076
16
    { &hf_tns_data_opi_param_length, {
9077
16
      "Length", "tns.data_opi.param_length", FT_UINT8, BASE_DEC,
9078
16
      NULL, 0x0, NULL, HFILL }},
9079
16
    { &hf_tns_data_opi_param_name, {
9080
16
      "Name", "tns.data_opi.param_name", FT_STRING, BASE_NONE,
9081
16
      NULL, 0x0, NULL, HFILL }},
9082
16
    { &hf_tns_data_opi_param_value, {
9083
16
      "Value", "tns.data_opi.param_value", FT_STRING, BASE_NONE,
9084
16
      NULL, 0x0, NULL, HFILL }},
9085
9086
16
    { &hf_tns_data_iov_num_binds, {
9087
16
      "Number of Binds", "tns.data_iov.num_binds", FT_UINT32, BASE_DEC,
9088
16
      NULL, 0x0, "num_iters * 256 + num_requests", HFILL }},
9089
16
    { &hf_tns_data_iov_bind_dir, {
9090
16
      "Bind Direction", "tns.data_iov.bind_dir", FT_UINT8, BASE_DEC,
9091
16
      VALS(tns_iov_bind_dirs), 0x0, NULL, HFILL }},
9092
9093
16
    { &hf_tns_data_bind_actual_len, {
9094
16
      "Actual Length", "tns.data_bind.actual_len", FT_INT32, BASE_DEC,
9095
16
      NULL, 0x0, "The returned value's length before it was cut to the declared size: 0 when it fitted, -1 when NULL", HFILL }},
9096
16
    { &hf_tns_data_dcb_num_columns, {
9097
16
      "Number of Columns", "tns.data_dcb.num_columns", FT_UINT32, BASE_DEC,
9098
16
      NULL, 0x0, NULL, HFILL }},
9099
16
    { &hf_tns_data_col_type, {
9100
16
      "Data Type", "tns.data_col.type", FT_UINT8, BASE_DEC,
9101
16
      VALS(tns_data_types), 0x0, NULL, HFILL }},
9102
16
    { &hf_tns_data_col_precision, {
9103
16
      "Precision", "tns.data_col.precision", FT_UINT8, BASE_DEC,
9104
16
      NULL, 0x0, NULL, HFILL }},
9105
16
    { &hf_tns_data_col_scale, {
9106
16
      "Scale", "tns.data_col.scale", FT_INT32, BASE_DEC,
9107
16
      NULL, 0x0, NULL, HFILL }},
9108
16
    { &hf_tns_data_col_max_length, {
9109
16
      "Max Data Length", "tns.data_col.max_length", FT_UINT32, BASE_DEC,
9110
16
      NULL, 0x0, NULL, HFILL }},
9111
16
    { &hf_tns_data_col_charset, {
9112
16
      "Charset", "tns.data_col.charset", FT_UINT32, BASE_DEC,
9113
16
      VALS(tns_charsets), 0x0, NULL, HFILL }},
9114
16
    { &hf_tns_data_col_csform, {
9115
16
      "Charset Form", "tns.data_col.csform", FT_UINT8, BASE_DEC,
9116
16
      VALS(tns_csform_vals), 0x0, NULL, HFILL }},
9117
16
    { &hf_tns_data_col_max_elements, {
9118
16
      "Max Array Elements", "tns.data_col.max_elements", FT_UINT32, BASE_DEC,
9119
16
      NULL, 0x0, "Capacity of an array bind", HFILL }},
9120
16
    { &hf_tns_data_bind_num_elements, {
9121
16
      "Array Elements", "tns.data_bind.num_elements", FT_UINT32, BASE_DEC,
9122
16
      NULL, 0x0, NULL, HFILL }},
9123
16
    { &hf_tns_data_bind_cursor_count, {
9124
16
      "Cursor Count", "tns.data_bind.cursor_count", FT_UINT32, BASE_DEC,
9125
16
      NULL, 0x0, "The cursor ids a REF CURSOR bind passes; none asks for a new cursor", HFILL }},
9126
16
    { &hf_tns_data_bind_oci_flags, {
9127
16
      "Flags", "tns.data_bind.oci_flags", FT_UINT8, BASE_HEX,
9128
16
      NULL, 0x0, NULL, HFILL }},
9129
16
    { &hf_tns_data_bind_oci_repeat, {
9130
16
      "Repeated name", "tns.data_bind.oci_flags.repeat", FT_BOOLEAN, 8,
9131
16
      NULL, TNS_OCI_BIND_REPEAT, "The name occurs earlier in the statement; the row carries no value for it", HFILL }},
9132
16
    { &hf_tns_data_bind_oci_return_code, {
9133
16
      "Return Code", "tns.data_bind.oci_return_code", FT_INT16, BASE_DEC,
9134
16
      NULL, 0x0, "The code behind an OUT value an OCI client gets: 0, or -1 for a NULL", HFILL }},
9135
16
    { &hf_tns_data_col_max_size, {
9136
16
      "Max Size", "tns.data_col.max_size", FT_UINT32, BASE_DEC,
9137
16
      NULL, 0x0, NULL, HFILL }},
9138
16
    { &hf_tns_data_col_nulls_ok, {
9139
16
      "Nulls Allowed", "tns.data_col.nulls_ok", FT_UINT8, BASE_DEC,
9140
16
      NULL, 0x0, NULL, HFILL }},
9141
16
    { &hf_tns_data_col_name, {
9142
16
      "Column Name", "tns.data_col.name", FT_STRING, BASE_NONE,
9143
16
      NULL, 0x0, NULL, HFILL }},
9144
9145
16
    { &hf_tns_data_col_uds_flags, {
9146
16
      "UDS Flags", "tns.data_col.uds_flags", FT_UINT32, BASE_HEX,
9147
16
      NULL, 0x0, "Marks a JSON column", HFILL }},
9148
16
    { &hf_tns_data_col_domain_schema, {
9149
16
      "Domain Schema", "tns.data_col.domain_schema", FT_STRING, BASE_NONE,
9150
16
      NULL, 0x0, NULL, HFILL }},
9151
16
    { &hf_tns_data_col_domain_name, {
9152
16
      "Domain Name", "tns.data_col.domain_name", FT_STRING, BASE_NONE,
9153
16
      NULL, 0x0, "The column's SQL domain", HFILL }},
9154
16
    { &hf_tns_data_col_annotation, {
9155
16
      "Annotation", "tns.data_col.annotation", FT_STRING, BASE_NONE,
9156
16
      NULL, 0x0, NULL, HFILL }},
9157
16
    { &hf_tns_data_col_vector_dims, {
9158
16
      "Vector Dimensions", "tns.data_col.vector_dims", FT_UINT32, BASE_DEC,
9159
16
      NULL, 0x0, NULL, HFILL }},
9160
16
    { &hf_tns_data_col_vector_format, {
9161
16
      "Vector Format", "tns.data_col.vector_format", FT_UINT8, BASE_DEC,
9162
16
      NULL, 0x0, NULL, HFILL }},
9163
16
    { &hf_tns_data_rxh_num_requests, {
9164
16
      "Number of Requests", "tns.data_rxh.num_requests", FT_UINT32, BASE_DEC,
9165
16
      NULL, 0x0, NULL, HFILL }},
9166
16
    { &hf_tns_data_rxh_iter_num, {
9167
16
      "Iteration Number", "tns.data_rxh.iter_num", FT_UINT32, BASE_DEC,
9168
16
      NULL, 0x0, NULL, HFILL }},
9169
16
    { &hf_tns_data_bit_vector, {
9170
16
      "Bit Vector", "tns.data.bit_vector", FT_BYTES, BASE_NONE,
9171
16
      NULL, 0x0, "Columns the next row sends; a clear bit repeats the previous row's value", HFILL }},
9172
16
    { &hf_tns_data_bvc_num_cols_sent, {
9173
16
      "Columns Sent", "tns.data_bvc.num_cols_sent", FT_UINT16, BASE_DEC,
9174
16
      NULL, 0x0, NULL, HFILL }},
9175
16
    { &hf_tns_data_irs_num_results, {
9176
16
      "Number of Result Sets", "tns.data_irs.num_results", FT_UINT32, BASE_DEC,
9177
16
      NULL, 0x0, NULL, HFILL }},
9178
16
    { &hf_tns_data_rxh_num_iters, {
9179
16
      "Number of Iterations", "tns.data_rxh.num_iters", FT_UINT32, BASE_DEC,
9180
16
      NULL, 0x0, NULL, HFILL }},
9181
9182
16
    { &hf_tns_data_all8_options, {
9183
16
      "Options", "tns.data_all8.options", FT_UINT32, BASE_HEX,
9184
16
      NULL, 0x0, NULL, HFILL }},
9185
16
    { &hf_tns_data_all8_opt_parse, {
9186
16
      "Parse", "tns.data_all8.options.parse", FT_BOOLEAN, 32,
9187
16
      NULL, 0x00000001, NULL, HFILL }},
9188
16
    { &hf_tns_data_all8_opt_bind, {
9189
16
      "Bind Values Present", "tns.data_all8.options.bind", FT_BOOLEAN, 32,
9190
16
      NULL, 0x00000008, NULL, HFILL }},
9191
16
    { &hf_tns_data_all8_opt_define, {
9192
16
      "Define Columns Present", "tns.data_all8.options.define", FT_BOOLEAN, 32,
9193
16
      NULL, 0x00000010, NULL, HFILL }},
9194
16
    { &hf_tns_data_all8_opt_execute, {
9195
16
      "Execute", "tns.data_all8.options.execute", FT_BOOLEAN, 32,
9196
16
      NULL, 0x00000020, NULL, HFILL }},
9197
16
    { &hf_tns_data_all8_opt_commit, {
9198
16
      "Autocommit", "tns.data_all8.options.commit", FT_BOOLEAN, 32,
9199
16
      NULL, 0x00000100, NULL, HFILL }},
9200
16
    { &hf_tns_data_all8_opt_plsql, {
9201
16
      "PL/SQL Binds", "tns.data_all8.options.plsql", FT_BOOLEAN, 32,
9202
16
      NULL, 0x00000400, NULL, HFILL }},
9203
16
    { &hf_tns_data_all8_opt_fetch, {
9204
16
      "Fetch", "tns.data_all8.options.fetch", FT_BOOLEAN, 32,
9205
16
      NULL, 0x00000040, NULL, HFILL }},
9206
16
    { &hf_tns_data_all8_opt_not_plsql, {
9207
16
      "Not PL/SQL", "tns.data_all8.options.not_plsql", FT_BOOLEAN, 32,
9208
16
      NULL, 0x00008000, NULL, HFILL }},
9209
16
    { &hf_tns_data_all8_parse_only, {
9210
16
      "Parse Only", "tns.data_all8.parse_only", FT_BOOLEAN, BASE_NONE,
9211
16
      NULL, 0x0, "The execute asks for no work: nothing to run, nothing to fetch", HFILL }},
9212
16
    { &hf_tns_data_all8_opt_describe, {
9213
16
      "Describe", "tns.data_all8.options.describe", FT_BOOLEAN, 32,
9214
16
      NULL, 0x00020000, NULL, HFILL }},
9215
16
    { &hf_tns_data_all8_opt_batch_errors, {
9216
16
      "Batch Errors", "tns.data_all8.options.batch_errors", FT_BOOLEAN, 32,
9217
16
      NULL, 0x00080000, NULL, HFILL }},
9218
16
    { &hf_tns_data_all8_fetch_rows, {
9219
16
      "Fetch Rows", "tns.data_all8.fetch_rows", FT_UINT32, BASE_DEC,
9220
16
      NULL, 0x0, NULL, HFILL }},
9221
16
    { &hf_tns_data_all8_iterations, {
9222
16
      "Execution Count", "tns.data_all8.iterations", FT_UINT32, BASE_DEC,
9223
16
      NULL, 0x0, "Number of times a DML statement runs (array DML)", HFILL }},
9224
16
    { &hf_tns_data_all8_prefetch, {
9225
16
      "Prefetch Rows", "tns.data_all8.prefetch", FT_UINT32, BASE_DEC,
9226
16
      NULL, 0x0, "Rows a query returns with the execute, before any fetch", HFILL }},
9227
16
    { &hf_tns_data_all8_is_query, {
9228
16
      "Query", "tns.data_all8.is_query", FT_BOOLEAN, BASE_NONE,
9229
16
      NULL, 0x0, NULL, HFILL }},
9230
16
    { &hf_tns_data_all8_oci_stmt_type, {
9231
16
      "Statement Type", "tns.data_all8.oci_stmt_type", FT_UINT32, BASE_DEC,
9232
16
      VALS(tns_oci_stmt_types), 0x0, NULL, HFILL }},
9233
16
    { &hf_tns_data_all8_exec_flags, {
9234
16
      "Execute Flags", "tns.data_all8.exec_flags", FT_UINT32, BASE_HEX,
9235
16
      NULL, 0x0, NULL, HFILL }},
9236
16
    { &hf_tns_data_all8_xflag_scrollable, {
9237
16
      "Scrollable", "tns.data_all8.exec_flags.scrollable", FT_BOOLEAN, 32,
9238
16
      NULL, 0x00000002, NULL, HFILL }},
9239
16
    { &hf_tns_data_all8_xflag_no_cancel_on_eof, {
9240
16
      "No Cancel on EOF", "tns.data_all8.exec_flags.no_cancel_on_eof", FT_BOOLEAN, 32,
9241
16
      NULL, 0x00000080, NULL, HFILL }},
9242
16
    { &hf_tns_data_all8_xflag_dml_rowcounts, {
9243
16
      "DML Row Counts", "tns.data_all8.exec_flags.dml_rowcounts", FT_BOOLEAN, 32,
9244
16
      NULL, 0x00004000, "Return the rows each iteration of an array DML affected", HFILL }},
9245
16
    { &hf_tns_data_all8_xflag_implicit_rs, {
9246
16
      "Implicit Result Sets", "tns.data_all8.exec_flags.implicit_resultset", FT_BOOLEAN, 32,
9247
16
      NULL, 0x00008000, NULL, HFILL }},
9248
16
    { &hf_tns_data_all8_fetch_orientation, {
9249
16
      "Fetch Orientation", "tns.data_all8.fetch_orientation", FT_UINT32, BASE_HEX,
9250
16
      VALS(tns_fetch_orientations), 0x0, NULL, HFILL }},
9251
16
    { &hf_tns_data_all8_fetch_pos, {
9252
16
      "Fetch Position", "tns.data_all8.fetch_pos", FT_UINT32, BASE_DEC,
9253
16
      NULL, 0x0, NULL, HFILL }},
9254
16
    { &hf_tns_data_reexec_iterations, {
9255
16
      "Execution Count", "tns.data_reexec.iterations", FT_UINT32, BASE_DEC,
9256
16
      NULL, 0x0, NULL, HFILL }},
9257
16
    { &hf_tns_data_reexec_options2, {
9258
16
      "Options 2", "tns.data_reexec.options2", FT_UINT32, BASE_HEX,
9259
16
      NULL, 0x0, NULL, HFILL }},
9260
16
    { &hf_tns_data_reexec_opt2_commit, {
9261
16
      "Autocommit", "tns.data_reexec.options2.commit", FT_BOOLEAN, 32,
9262
16
      NULL, 0x00000001, NULL, HFILL }},
9263
16
    { &hf_tns_data_all8_oci_preamble, {
9264
16
      "Preamble", "tns.data_all8.oci_preamble", FT_STRING, BASE_NONE,
9265
16
      NULL, 0x0, "The fixed execute preamble of an OCI client", HFILL }},
9266
16
    { &hf_tns_data_all8_define_count, {
9267
16
      "Define Count", "tns.data_all8.define_count", FT_UINT32, BASE_DEC,
9268
16
      NULL, 0x0, NULL, HFILL }},
9269
16
    { &hf_tns_data_all8_bind_count, {
9270
16
      "Bind Count", "tns.data_all8.bind_count", FT_UINT32, BASE_DEC,
9271
16
      NULL, 0x0, NULL, HFILL }},
9272
16
    { &hf_tns_data_all8_sql, {
9273
16
      "SQL Text", "tns.data_all8.sql", FT_STRING, BASE_NONE,
9274
16
      NULL, 0x0, NULL, HFILL }},
9275
16
    { &hf_tns_data_bind_value, {
9276
16
      "Bind Value", "tns.data_bind.value", FT_BYTES, BASE_NONE,
9277
16
      NULL, 0x0, "Raw type-encoded bind value", HFILL }},
9278
16
    { &hf_tns_data_fetch_rows, {
9279
16
      "Rows to Fetch", "tns.data_fetch.rows", FT_UINT32, BASE_DEC,
9280
16
      NULL, 0x0, NULL, HFILL }},
9281
16
    { &hf_tns_data_kod_opcode, {
9282
16
      "Describe Opcode", "tns.data_kod.opcode", FT_UINT32, BASE_DEC,
9283
16
      VALS(tns_kod_opcodes), 0x0, NULL, HFILL }},
9284
16
    { &hf_tns_data_kod_kind, {
9285
16
      "Message Kind", "tns.data_kod.kind", FT_UINT8, BASE_DEC,
9286
16
      VALS(tns_kod_kinds), 0x0, NULL, HFILL }},
9287
16
    { &hf_tns_data_kod_schema, {
9288
16
      "Schema", "tns.data_kod.schema", FT_STRING, BASE_NONE,
9289
16
      NULL, 0x0, NULL, HFILL }},
9290
16
    { &hf_tns_data_kod_name, {
9291
16
      "Type Name", "tns.data_kod.name", FT_STRING, BASE_NONE,
9292
16
      NULL, 0x0, NULL, HFILL }},
9293
16
    { &hf_tns_data_kod_oid, {
9294
16
      "Object Id", "tns.data_kod.oid", FT_BYTES, BASE_NONE,
9295
16
      NULL, 0x0, "The id of the type described", HFILL }},
9296
16
    { &hf_tns_data_kod_type_oid, {
9297
16
      "Type Id", "tns.data_kod.type_oid", FT_BYTES, BASE_NONE,
9298
16
      NULL, 0x0, "The id of the system type the descriptor is an instance of", HFILL }},
9299
16
    { &hf_tns_data_kod_system_type, {
9300
16
      "System Type", "tns.data_kod.system_type", FT_UINT8, BASE_HEX,
9301
16
      VALS(tns_kod_system_types), 0x0, NULL, HFILL }},
9302
16
    { &hf_tns_data_kod_image, {
9303
16
      "Descriptor Image", "tns.data_kod.image", FT_BYTES, BASE_NONE,
9304
16
      NULL, 0x0, NULL, HFILL }},
9305
16
    { &hf_tns_data_kod_version, {
9306
16
      "Type Version", "tns.data_kod.version", FT_STRING, BASE_NONE,
9307
16
      NULL, 0x0, NULL, HFILL }},
9308
16
    { &hf_tns_data_kod_typecode, {
9309
16
      "Typecode", "tns.data_kod.typecode", FT_UINT16, BASE_DEC,
9310
16
      VALS(tns_kod_typecodes), 0x0, NULL, HFILL }},
9311
16
    { &hf_tns_data_lob_op, {
9312
16
      "LOB Operation", "tns.data_lob.op", FT_UINT32, BASE_HEX,
9313
16
      VALS(tns_lob_ops), 0x0, NULL, HFILL }},
9314
16
    { &hf_tns_data_lob_offset, {
9315
16
      "Source Offset", "tns.data_lob.offset", FT_UINT64, BASE_DEC,
9316
16
      NULL, 0x0, "1-based offset into the LOB", HFILL }},
9317
16
    { &hf_tns_data_lob_locator, {
9318
16
      "Locator", "tns.data_lob.locator", FT_BYTES, BASE_NONE,
9319
16
      NULL, 0x0, NULL, HFILL }},
9320
16
    { &hf_tns_data_lob_directory, {
9321
16
      "Directory", "tns.data_lob.directory", FT_STRING, BASE_NONE,
9322
16
      NULL, 0x0, "The directory object a BFILE's locator names", HFILL }},
9323
16
    { &hf_tns_data_lob_file_name, {
9324
16
      "File Name", "tns.data_lob.file_name", FT_STRING, BASE_NONE,
9325
16
      NULL, 0x0, "The file a BFILE's locator names", HFILL }},
9326
16
    { &hf_tns_data_lob_charset, {
9327
16
      "Charset", "tns.data_lob.charset", FT_UINT32, BASE_DEC,
9328
16
      VALS(tns_charsets), 0x0, NULL, HFILL }},
9329
16
    { &hf_tns_data_lob_csform, {
9330
16
      "Charset Form", "tns.data_lob.csform", FT_UINT64, BASE_DEC|BASE_VAL64_STRING,
9331
16
      VALS64(tns_csform_vals64), 0x0, "The charset form of a temporary LOB to create: 0 for a BLOB", HFILL }},
9332
16
    { &hf_tns_data_lob_type, {
9333
16
      "LOB Type", "tns.data_lob.type", FT_UINT64, BASE_DEC|BASE_VAL64_STRING,
9334
16
      VALS64(tns_lob_types64), 0x0, "The type of a temporary LOB to create", HFILL }},
9335
16
    { &hf_tns_data_lob_data, {
9336
16
      "Data", "tns.data_lob.data", FT_BYTES, BASE_NONE,
9337
16
      NULL, 0x0, "LOB content; UTF-16BE for a CLOB", HFILL }},
9338
16
    { &hf_tns_data_lob_total_size, {
9339
16
      "Total Locator Size", "tns.data_lob.total_size", FT_UINT32, BASE_DEC,
9340
16
      NULL, 0x0, NULL, HFILL }},
9341
16
    { &hf_tns_data_pgy_schema, {
9342
16
      "Current Schema", "tns.data_piggyback.schema", FT_STRING, BASE_NONE,
9343
16
      NULL, 0x0, NULL, HFILL }},
9344
16
    { &hf_tns_data_pgy_app_ctx_op, {
9345
16
      "Application Context Operation", "tns.data_piggyback.app_context_op", FT_UINT16, BASE_DEC,
9346
16
      VALS(tns_app_ctx_ops), 0x0, NULL, HFILL }},
9347
16
    { &hf_tns_data_pgy_app_ctx_namespace, {
9348
16
      "Application Context Namespace", "tns.data_piggyback.app_context_namespace", FT_STRING, BASE_NONE,
9349
16
      NULL, 0x0, NULL, HFILL }},
9350
16
    { &hf_tns_data_pgy_app_ctx_attr, {
9351
16
      "Attribute", "tns.data_piggyback.app_context_attr", FT_STRING, BASE_NONE,
9352
16
      NULL, 0x0, NULL, HFILL }},
9353
16
    { &hf_tns_data_pgy_app_ctx_value, {
9354
16
      "Value", "tns.data_piggyback.app_context_value", FT_STRING, BASE_NONE,
9355
16
      NULL, 0x0, NULL, HFILL }},
9356
16
    { &hf_tns_data_pgy_alter_param, {
9357
16
      "Session Parameter", "tns.data_piggyback.alter_session_param", FT_STRING, BASE_NONE,
9358
16
      NULL, 0x0, NULL, HFILL }},
9359
16
    { &hf_tns_data_pgy_alter_value, {
9360
16
      "Value", "tns.data_piggyback.alter_session_value", FT_STRING, BASE_NONE,
9361
16
      NULL, 0x0, "Empty to restore the database default", HFILL }},
9362
16
    { &hf_tns_data_pgy_session_state, {
9363
16
      "Session State", "tns.data_piggyback.session_state", FT_UINT64, BASE_HEX,
9364
16
      NULL, 0x0, "Request boundary: the client begins or ends a request", HFILL }},
9365
16
    { &hf_tns_data_pgy_e2e_flags, {
9366
16
      "Changed Attributes", "tns.data_piggyback.e2e_flags", FT_UINT32, BASE_HEX,
9367
16
      NULL, 0x0, NULL, HFILL }},
9368
16
    { &hf_tns_data_pgy_client_id, {
9369
16
      "Client Identifier", "tns.data_piggyback.client_id", FT_STRING, BASE_NONE,
9370
16
      NULL, 0x0, NULL, HFILL }},
9371
16
    { &hf_tns_data_pgy_module, {
9372
16
      "Module", "tns.data_piggyback.module", FT_STRING, BASE_NONE,
9373
16
      NULL, 0x0, NULL, HFILL }},
9374
16
    { &hf_tns_data_pgy_action, {
9375
16
      "Action", "tns.data_piggyback.action", FT_STRING, BASE_NONE,
9376
16
      NULL, 0x0, NULL, HFILL }},
9377
16
    { &hf_tns_data_pgy_client_info, {
9378
16
      "Client Info", "tns.data_piggyback.client_info", FT_STRING, BASE_NONE,
9379
16
      NULL, 0x0, NULL, HFILL }},
9380
16
    { &hf_tns_data_pgy_dbop, {
9381
16
      "Database Operation", "tns.data_piggyback.dbop", FT_STRING, BASE_NONE,
9382
16
      NULL, 0x0, NULL, HFILL }},
9383
16
    { &hf_tns_data_pgy_error_set_id, {
9384
16
      "Error Set Id", "tns.data_piggyback.error_set_id", FT_UINT16, BASE_DEC,
9385
16
      NULL, 0x0, NULL, HFILL }},
9386
16
    { &hf_tns_data_pgy_error_set_mode, {
9387
16
      "Error Set Mode", "tns.data_piggyback.error_set_mode", FT_UINT8, BASE_DEC,
9388
16
      NULL, 0x0, NULL, HFILL }},
9389
16
    { &hf_tns_data_pgy_pipeline_mode, {
9390
16
      "Pipeline Mode", "tns.data_piggyback.pipeline_mode", FT_UINT8, BASE_DEC,
9391
16
      NULL, 0x0, NULL, HFILL }},
9392
16
    { &hf_tns_data_pgy_sec_flags, {
9393
16
      "Security Context Flags", "tns.data_piggyback.sec_flags", FT_UINT32, BASE_HEX,
9394
16
      NULL, 0x0, NULL, HFILL }},
9395
16
    { &hf_tns_data_pgy_sec_key, {
9396
16
      "Security Context Key", "tns.data_piggyback.sec_key", FT_STRING, BASE_NONE,
9397
16
      NULL, 0x0, NULL, HFILL }},
9398
16
    { &hf_tns_data_pgy_sec_value, {
9399
16
      "Security Context Value", "tns.data_piggyback.sec_value", FT_BYTES, BASE_NONE,
9400
16
      NULL, 0x0, NULL, HFILL }},
9401
16
    { &hf_tns_data_lob_text, {
9402
16
      "Text", "tns.data_lob.text", FT_STRING, BASE_NONE,
9403
16
      NULL, 0x0, "A CLOB's content, decoded as its locator says", HFILL }},
9404
16
    { &hf_tns_data_release_tag, {
9405
16
      "Tag", "tns.data_release.tag", FT_STRING, BASE_NONE,
9406
16
      NULL, 0x0, "Session tag for the pool", HFILL }},
9407
16
    { &hf_tns_data_release_mode, {
9408
16
      "Release Mode", "tns.data_release.mode", FT_UINT32, BASE_HEX,
9409
16
      NULL, 0x0, NULL, HFILL }},
9410
16
    { &hf_tns_data_release_mode_deauth, {
9411
16
      "Deauthenticate", "tns.data_release.mode.deauthenticate", FT_BOOLEAN, 32,
9412
16
      NULL, 0x00000002, "The session is being closed, not just returned", HFILL }},
9413
16
    { &hf_tns_data_aq_queue, {
9414
16
      "Queue", "tns.data_aq.queue", FT_STRING, BASE_NONE,
9415
16
      NULL, 0x0, NULL, HFILL }},
9416
16
    { &hf_tns_data_aq_consumer, {
9417
16
      "Consumer", "tns.data_aq.consumer", FT_STRING, BASE_NONE,
9418
16
      NULL, 0x0, NULL, HFILL }},
9419
16
    { &hf_tns_data_aq_correlation, {
9420
16
      "Correlation", "tns.data_aq.correlation", FT_STRING, BASE_NONE,
9421
16
      NULL, 0x0, NULL, HFILL }},
9422
16
    { &hf_tns_data_aq_exception_queue, {
9423
16
      "Exception Queue", "tns.data_aq.exception_queue", FT_STRING, BASE_NONE,
9424
16
      NULL, 0x0, NULL, HFILL }},
9425
16
    { &hf_tns_data_aq_condition, {
9426
16
      "Condition", "tns.data_aq.condition", FT_STRING, BASE_NONE,
9427
16
      NULL, 0x0, NULL, HFILL }},
9428
16
    { &hf_tns_data_aq_msgid, {
9429
16
      "Message Id", "tns.data_aq.msgid", FT_BYTES, BASE_NONE,
9430
16
      NULL, 0x0, NULL, HFILL }},
9431
16
    { &hf_tns_data_aq_toid, {
9432
16
      "Payload Type OID", "tns.data_aq.toid", FT_BYTES, BASE_NONE,
9433
16
      NULL, 0x0, NULL, HFILL }},
9434
16
    { &hf_tns_data_aq_payload, {
9435
16
      "Payload", "tns.data_aq.payload", FT_BYTES, BASE_NONE,
9436
16
      NULL, 0x0, NULL, HFILL }},
9437
16
    { &hf_tns_data_aq_priority, {
9438
16
      "Priority", "tns.data_aq.priority", FT_UINT32, BASE_DEC,
9439
16
      NULL, 0x0, NULL, HFILL }},
9440
16
    { &hf_tns_data_aq_delay, {
9441
16
      "Delay", "tns.data_aq.delay", FT_UINT32, BASE_DEC,
9442
16
      NULL, 0x0, "Seconds before the message becomes available", HFILL }},
9443
16
    { &hf_tns_data_aq_expiration, {
9444
16
      "Expiration", "tns.data_aq.expiration", FT_INT32, BASE_DEC,
9445
16
      NULL, 0x0, "Seconds the message stays available, -1 for ever", HFILL }},
9446
16
    { &hf_tns_data_aq_attempts, {
9447
16
      "Attempts", "tns.data_aq.attempts", FT_UINT32, BASE_DEC,
9448
16
      NULL, 0x0, "Delivery attempts so far", HFILL }},
9449
16
    { &hf_tns_data_aq_state, {
9450
16
      "State", "tns.data_aq.state", FT_UINT32, BASE_DEC,
9451
16
      VALS(tns_aq_states), 0x0, NULL, HFILL }},
9452
16
    { &hf_tns_data_aq_enq_time, {
9453
16
      "Enqueue Time", "tns.data_aq.enq_time", FT_STRING, BASE_NONE,
9454
16
      NULL, 0x0, NULL, HFILL }},
9455
16
    { &hf_tns_data_aq_visibility, {
9456
16
      "Visibility", "tns.data_aq.visibility", FT_UINT32, BASE_DEC,
9457
16
      VALS(tns_aq_visibility), 0x0, NULL, HFILL }},
9458
16
    { &hf_tns_data_aq_deq_mode, {
9459
16
      "Dequeue Mode", "tns.data_aq.deq_mode", FT_UINT32, BASE_DEC,
9460
16
      VALS(tns_aq_deq_modes), 0x0, NULL, HFILL }},
9461
16
    { &hf_tns_data_aq_navigation, {
9462
16
      "Navigation", "tns.data_aq.navigation", FT_UINT32, BASE_DEC,
9463
16
      VALS(tns_aq_navigation), 0x0, NULL, HFILL }},
9464
16
    { &hf_tns_data_aq_wait, {
9465
16
      "Wait", "tns.data_aq.wait", FT_INT32, BASE_DEC,
9466
16
      NULL, 0x0, "Seconds to wait for a message; -1 waits for ever", HFILL }},
9467
16
    { &hf_tns_data_aq_flags, {
9468
16
      "Flags", "tns.data_aq.flags", FT_UINT32, BASE_HEX,
9469
16
      NULL, 0x0, NULL, HFILL }},
9470
16
    { &hf_tns_data_aq_delivery_flags, {
9471
16
      "Delivery Flags", "tns.data_aq.delivery_flags", FT_UINT32, BASE_HEX,
9472
16
      NULL, 0x0, "0x02 marks a buffered message", HFILL }},
9473
16
    { &hf_tns_data_aq_array_op, {
9474
16
      "Array Operation", "tns.data_aq.array_op", FT_UINT32, BASE_DEC,
9475
16
      VALS(tns_aq_array_ops), 0x0, NULL, HFILL }},
9476
16
    { &hf_tns_data_aq_num_messages, {
9477
16
      "Messages", "tns.data_aq.num_messages", FT_UINT32, BASE_DEC,
9478
16
      NULL, 0x0, NULL, HFILL }},
9479
16
    { &hf_tns_data_tpc_switch_op, {
9480
16
      "Operation", "tns.data_tpc.switch_op", FT_UINT32, BASE_HEX,
9481
16
      VALS(tns_tpc_switch_ops), 0x0, NULL, HFILL }},
9482
16
    { &hf_tns_data_tpc_change_op, {
9483
16
      "Operation", "tns.data_tpc.change_op", FT_UINT32, BASE_HEX,
9484
16
      VALS(tns_tpc_change_ops), 0x0, NULL, HFILL }},
9485
16
    { &hf_tns_data_tpc_format_id, {
9486
16
      "XID Format Id", "tns.data_tpc.format_id", FT_UINT32, BASE_DEC,
9487
16
      NULL, 0x0, NULL, HFILL }},
9488
16
    { &hf_tns_data_tpc_gtrid, {
9489
16
      "Global Transaction Id", "tns.data_tpc.gtrid", FT_BYTES, BASE_NONE,
9490
16
      NULL, 0x0, NULL, HFILL }},
9491
16
    { &hf_tns_data_tpc_bqual, {
9492
16
      "Branch Qualifier", "tns.data_tpc.bqual", FT_BYTES, BASE_NONE,
9493
16
      NULL, 0x0, NULL, HFILL }},
9494
16
    { &hf_tns_data_tpc_flags, {
9495
16
      "Flags", "tns.data_tpc.flags", FT_UINT32, BASE_HEX,
9496
16
      NULL, 0x0, NULL, HFILL }},
9497
16
    { &hf_tns_data_tpc_timeout, {
9498
16
      "Timeout", "tns.data_tpc.timeout", FT_UINT32, BASE_DEC,
9499
16
      NULL, 0x0, NULL, HFILL }},
9500
16
    { &hf_tns_data_tpc_state, {
9501
16
      "State", "tns.data_tpc.state", FT_UINT32, BASE_DEC,
9502
16
      VALS(tns_tpc_states), 0x0, NULL, HFILL }},
9503
16
    { &hf_tns_data_tpc_context, {
9504
16
      "Transaction Context", "tns.data_tpc.context", FT_BYTES, BASE_NONE,
9505
16
      NULL, 0x0, NULL, HFILL }},
9506
16
    { &hf_tns_data_tpc_app_value, {
9507
16
      "Application Value", "tns.data_tpc.app_value", FT_UINT32, BASE_DEC,
9508
16
      NULL, 0x0, NULL, HFILL }},
9509
16
    { &hf_tns_data_tpc_internal_name, {
9510
16
      "Internal Name", "tns.data_tpc.internal_name", FT_STRING, BASE_NONE,
9511
16
      NULL, 0x0, NULL, HFILL }},
9512
16
    { &hf_tns_data_tpc_external_name, {
9513
16
      "External Name", "tns.data_tpc.external_name", FT_STRING, BASE_NONE,
9514
16
      NULL, 0x0, NULL, HFILL }},
9515
16
    { &hf_tns_data_lob_flag, {
9516
16
      "Result", "tns.data_lob.flag", FT_BOOLEAN, BASE_NONE,
9517
16
      NULL, 0x0, "Whether the LOB is open, or the file exists", HFILL }},
9518
16
    { &hf_tns_data_lob_amount, {
9519
16
      "Amount", "tns.data_lob.amount", FT_UINT64, BASE_DEC,
9520
16
      NULL, 0x0, "Characters for a CLOB, bytes for a BLOB; the mode for OPEN", HFILL }},
9521
16
    { &hf_tns_data_col_value, {
9522
16
      "Column Value", "tns.data_col.value", FT_BYTES, BASE_NONE,
9523
16
      NULL, 0x0, "Raw type-encoded row column value", HFILL }},
9524
9525
16
    { &hf_tns_data_lob_size, {
9526
16
      "LOB Size", "tns.data_lob.size", FT_UINT64, BASE_DEC,
9527
16
      NULL, 0x0, "Characters for a CLOB, bytes for a BLOB", HFILL }},
9528
16
    { &hf_tns_data_lob_chunk_size, {
9529
16
      "LOB Chunk Size", "tns.data_lob.chunk_size", FT_UINT32, BASE_DEC,
9530
16
      NULL, 0x0, NULL, HFILL }},
9531
16
    { &hf_tns_data_json_image, {
9532
16
      "OSON Image", "tns.data_json.image", FT_BYTES, BASE_NONE,
9533
16
      NULL, 0x0, "Binary JSON (OSON) value", HFILL }},
9534
16
    { &hf_tns_data_vector_image, {
9535
16
      "Vector Image", "tns.data_vector.image", FT_BYTES, BASE_NONE,
9536
16
      NULL, 0x0, NULL, HFILL }},
9537
16
    { &hf_tns_data_obj_toid, {
9538
16
      "Type OID", "tns.data_obj.toid", FT_BYTES, BASE_NONE,
9539
16
      NULL, 0x0, NULL, HFILL }},
9540
16
    { &hf_tns_data_obj_image, {
9541
16
      "Object Image", "tns.data_obj.image", FT_BYTES, BASE_NONE,
9542
16
      NULL, 0x0, "Packed object attributes, or an XMLType document", HFILL }},
9543
16
    { &hf_tns_data_descriptor_row_count, {
9544
16
      "Row Count", "tns.data_descriptor.row_count", FT_UINT32, BASE_DEC,
9545
16
      NULL, 0x0, NULL, HFILL }},
9546
16
    { &hf_tns_data_descriptor_row_size, {
9547
16
      "Row Size", "tns.data_descriptor.row_size", FT_UINT32, BASE_DEC,
9548
16
      NULL, 0x0, NULL, HFILL }},
9549
9550
16
    { &hf_tns_reserved_byte, {
9551
16
      "Reserved Byte", "tns.reserved_byte", FT_BYTES, BASE_NONE,
9552
16
      NULL, 0x0, NULL, HFILL }},
9553
16
    { &hf_tns_packet_type, {
9554
16
      "Packet Type", "tns.type", FT_UINT8, BASE_DEC,
9555
16
      VALS(tns_type_vals), 0x0, "Type of TNS packet", HFILL }}
9556
9557
16
  };
9558
9559
16
  static int *ett[] = {
9560
16
    &ett_tns,
9561
16
    &ett_tns_connect,
9562
16
    &ett_tns_accept,
9563
16
    &ett_tns_refuse,
9564
16
    &ett_tns_abort,
9565
16
    &ett_tns_redirect,
9566
16
    &ett_tns_marker,
9567
16
    &ett_tns_attention,
9568
16
    &ett_tns_control,
9569
16
    &ett_tns_data,
9570
16
    &ett_tns_data_flag,
9571
16
    &ett_tns_acc_versions,
9572
16
    &ett_tns_opi_params,
9573
16
    &ett_tns_opi_par,
9574
16
    &ett_tns_sopt_flag,
9575
16
    &ett_tns_ntp_flag,
9576
16
    &ett_tns_conn_flag,
9577
16
    &ett_tns_accept_flags2,
9578
16
    &ett_tns_rows,
9579
16
    &ett_tns_setdt_caphdr,
9580
16
    &ett_tns_setdt_overrides,
9581
16
    &ett_tns_setdt_override,
9582
16
    &ett_tns_oer,
9583
16
    &ett_tns_kod,
9584
16
    &ett_tns_app_ctx,
9585
16
    &ett_tns_alter_session,
9586
16
    &ett_tns_call_status,
9587
16
    &ett_tns_warn_flags,
9588
16
    &ett_tns_auth_mode,
9589
16
    &ett_tns_sns_service,
9590
16
    &ett_tns_sns_subpacket,
9591
16
    &ett_tns_release_mode,
9592
16
    &ett_tns_aq_props,
9593
16
    &ett_tns_rpa,
9594
16
    &ett_tns_kv,
9595
16
    &ett_tns_iov,
9596
16
    &ett_tns_dcb_col,
9597
16
    &ett_tns_all8_options,
9598
16
    &ett_tns_all8_i4,
9599
16
    &ett_tns_all8_exec_flags,
9600
16
    &ett_tns_binds,
9601
16
    &ett_tns_bind,
9602
16
    &ett_tns_defines,
9603
16
    &ett_tns_reexec_options2,
9604
16
    &ett_tns_bind_row,
9605
16
    &ett_tns_bind_oci_flags,
9606
16
    &ett_tns_rxd_row,
9607
16
    &ett_tns_value,
9608
16
    &ett_tns_irs,
9609
16
    &ett_tns_out_binds,
9610
16
    &ett_sql
9611
16
  };
9612
9613
16
  static ei_register_info ei[] = {
9614
16
    { &ei_tns_connect_data_next_packet, { "tns.connect_data.next_packet", PI_REQUEST_CODE, PI_CHAT, "Long Connect Data (over 230 bytes) carried in subsequent Data packet", EXPFILL }},
9615
16
    { &ei_tns_data_descriptor_size_mismatch, { "tns.data_descriptor.size_mismatch", PI_PROTOCOL, PI_WARN, "Data size from summing row sizes differs from size in descriptor", EXPFILL }},
9616
16
    { &ei_tns_data_piggyback_cursors, { "tns.data.piggyback.cursors.invalid", PI_MALFORMED, PI_ERROR, "Cursor count is larger than the data left in the packet", EXPFILL }},
9617
16
    { &ei_tns_data_count_too_large, { "tns.data.count.invalid", PI_MALFORMED, PI_ERROR, "Count is larger than the data left in the packet", EXPFILL }},
9618
16
    { &ei_tns_data_value_truncated, { "tns.data_bind.truncated", PI_RESPONSE_CODE, PI_WARN, "The value was cut to the size the client declared", EXPFILL }},
9619
16
    { &ei_tns_data_compilation_error, { "tns.data_oer.compilation_error", PI_RESPONSE_CODE, PI_NOTE, "The statement created a PL/SQL object that compiled with errors", EXPFILL }},
9620
16
    { &ei_tns_data_encrypted, { "tns.data.encrypted", PI_DECRYPTION, PI_NOTE, "Encrypted by native network encryption", EXPFILL }},
9621
16
  };
9622
9623
16
  module_t *tns_module;
9624
16
  expert_module_t* expert_tns;
9625
9626
16
  proto_tns = proto_register_protocol("Transparent Network Substrate Protocol", "TNS", "tns");
9627
16
  proto_register_field_array(proto_tns, hf, array_length(hf));
9628
16
  proto_register_subtree_array(ett, array_length(ett));
9629
16
  expert_tns = expert_register_protocol(proto_tns);
9630
16
  expert_register_field_array(expert_tns, ei, array_length(ei));
9631
16
  tns_handle = register_dissector("tns", dissect_tns, proto_tns);
9632
9633
16
  tns_module = prefs_register_protocol(proto_tns, NULL);
9634
16
  prefs_register_bool_preference(tns_module, "desegment_tns_messages",
9635
16
    "Reassemble TNS messages spanning multiple TCP segments",
9636
16
    "Whether the TNS dissector should reassemble messages spanning multiple TCP segments. "
9637
16
    "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
9638
16
    &tns_desegment);
9639
16
}
9640
9641
void
9642
proto_reg_handoff_tns(void)
9643
16
{
9644
16
  dissector_add_uint_with_preference("tcp.port", TCP_PORT_TNS, tns_handle);
9645
16
}
9646
9647
/*
9648
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
9649
 *
9650
 * Local variables:
9651
 * c-basic-offset: 8
9652
 * tab-width: 8
9653
 * indent-tabs-mode: t
9654
 * End:
9655
 *
9656
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
9657
 * :indentSize=8:tabSize=8:noTabs=false:
9658
 */