Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-pgsql.c
Warning:line 881, column 9
Value stored to 'n' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-pgsql.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-18/lib/clang/18 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/epan -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -dwarf-debug-flags /usr/lib/llvm-18/bin/clang -### --analyze -x c -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/epan -fvisibility=hidden -fexcess-precision=fast -fstrict-flex-arrays=3 -fstack-clash-protection -fcf-protection=full -D _GLIBCXX_ASSERTIONS -fstack-protector-strong -fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -fexceptions -Wno-format-truncation -Wno-format-nonliteral -fdiagnostics-color=always -Wno-pointer-sign -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -std=gnu11 -fPIC /builds/wireshark/wireshark/epan/dissectors/packet-pgsql.c -o /builds/wireshark/wireshark/sbout/2025-06-27-100304-3847-1 -Xclang -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-06-27-100304-3847-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-pgsql.c
1/* packet-pgsql.c
2 * Routines for PostgreSQL v3 protocol dissection.
3 * <http://www.postgresql.org/docs/current/static/protocol.html>
4 * Copyright 2004 Abhijit Menon-Sen <ams@oryx.com>
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13#include "config.h"
14
15#include <epan/packet.h>
16#include <epan/proto_data.h>
17
18#include "packet-gssapi.h"
19#include "packet-tls-utils.h"
20#include "packet-tcp.h"
21
22void proto_register_pgsql(void);
23void proto_reg_handoff_pgsql(void);
24
25static dissector_handle_t pgsql_handle;
26static dissector_handle_t pgsql_gssapi_handle;
27static dissector_handle_t tls_handle;
28static dissector_handle_t gssapi_handle;
29static dissector_handle_t ntlmssp_handle;
30
31static int proto_pgsql;
32static int hf_frontend;
33static int hf_type;
34static int hf_copydata;
35static int hf_copydata_type;
36static int hf_xlogdata;
37static int hf_logical_msg_type;
38static int hf_custom_type_name;
39static int hf_namespace;
40static int hf_relation_name;
41static int hf_relation_oid;
42static int hf_xid_subtransaction;
43static int hf_xid;
44static int hf_length;
45static int hf_version_major;
46static int hf_version_minor;
47static int hf_request_code;
48static int hf_supported_minor_version;
49static int hf_number_nonsupported_options;
50static int hf_nonsupported_option;
51static int hf_parameter_name;
52static int hf_parameter_value;
53static int hf_query;
54static int hf_authtype;
55static int hf_passwd;
56static int hf_salt;
57static int hf_gssapi_sspi_data;
58static int hf_sasl_auth_mech;
59static int hf_sasl_auth_data;
60static int hf_sasl_auth_data_length;
61static int hf_statement;
62static int hf_portal;
63static int hf_return;
64static int hf_tag;
65static int hf_status;
66static int hf_error;
67static int hf_pid;
68static int hf_key;
69static int hf_condition;
70static int hf_text;
71static int hf_tableoid;
72static int hf_typeoid;
73static int hf_oid;
74static int hf_format;
75static int hf_field_count;
76static int hf_val_name;
77static int hf_val_idx;
78static int hf_val_length;
79static int hf_val_data;
80static int hf_val_text_data;
81static int hf_val_mod;
82static int hf_severity;
83static int hf_code;
84static int hf_message;
85static int hf_detail;
86static int hf_hint;
87static int hf_position;
88static int hf_internal_position;
89static int hf_internal_query;
90static int hf_where;
91static int hf_schema_name;
92static int hf_table_name;
93static int hf_column_name;
94static int hf_type_name;
95static int hf_tuple_type;
96static int hf_tuple_data_type;
97static int hf_constraint_name;
98static int hf_file;
99static int hf_line;
100static int hf_routine;
101static int hf_ssl_response;
102static int hf_gssenc_response;
103static int hf_gssapi_encrypted_payload;
104static int hf_logical_column_flags;
105static int hf_logical_column_length;
106static int hf_logical_column_name;
107static int hf_logical_number_columns;
108static int hf_logical_column_oid;
109static int hf_logical_column_type_modifier;
110static int hf_logical_commit_flags;
111static int hf_logical_commit_ts;
112static int hf_logical_lsn_abort;
113static int hf_logical_lsn_commit;
114static int hf_logical_lsn_final;
115static int hf_logical_lsn_origin;
116static int hf_logical_lsn_transaction;
117static int hf_logical_message_content;
118static int hf_logical_message_flags;
119static int hf_logical_message_length;
120static int hf_logical_message_lsn;
121static int hf_logical_message_prefix;
122static int hf_logical_origin_name;
123static int hf_logical_prepare_commit_ts;
124static int hf_logical_prepare_flags;
125static int hf_logical_prepare_gid;
126static int hf_logical_prepare_lsn_end;
127static int hf_logical_prepare_lsn_rollback;
128static int hf_logical_prepare_lsn;
129static int hf_logical_prepare_rollback_ts;
130static int hf_logical_prepare_ts;
131static int hf_logical_relation_number;
132static int hf_logical_replica_identity;
133static int hf_logical_stream_abort_ts;
134static int hf_logical_stream_first_segment;
135static int hf_logical_stream_flags;
136static int hf_logical_truncate_flags;
137static int hf_standby_catalog_xmin_epoch;
138static int hf_standby_catalog_xmin;
139static int hf_standby_clock_ts;
140static int hf_standby_immediate_ack;
141static int hf_standby_last_wal_applied;
142static int hf_standby_last_wal_flushed;
143static int hf_standby_last_wal_written;
144static int hf_standby_xmin_epoch;
145static int hf_standby_xmin;
146static int hf_xlog_wal_end;
147static int hf_xlog_wal_start;
148
149static int ett_pgsql;
150static int ett_values;
151
152#define PGSQL_PORT5432 5432
153static bool_Bool pgsql_desegment = true1;
154static bool_Bool first_message = true1;
155
156typedef enum {
157 /* Reserve 0 (== GPOINTER_TO_UINT(NULL)) for no PGSQL detected */
158 PGSQL_AUTH_STATE_NONE = 1, /* No authentication seen or used */
159 PGSQL_AUTH_SASL_REQUESTED, /* Server sends SASL auth request with supported SASL mechanisms*/
160 PGSQL_AUTH_SASL_CONTINUE, /* Server and/or client send further SASL challenge-response messages */
161 PGSQL_AUTH_GSSAPI_SSPI_DATA, /* GSSAPI/SSPI in use */
162 PGSQL_AUTH_SSL_REQUESTED, /* Client sends SSL encryption request */
163 PGSQL_AUTH_GSSENC_REQUESTED, /* Client sends GSSAPI encryption request */
164} pgsql_auth_state_t;
165
166typedef struct pgsql_conn_data {
167 wmem_tree_t *state_tree; /* Tree of encryption and auth state changes */
168 uint32_t server_port;
169 bool_Bool streamed_txn;
170} pgsql_conn_data_t;
171
172struct pgsql_per_packet_data_t {
173 bool_Bool streamed_txn;
174};
175
176static const value_string fe_messages[] = {
177 { 'p', "Authentication message" },
178 { 'Q', "Simple query" },
179 { 'P', "Parse" },
180 { 'B', "Bind" },
181 { 'E', "Execute" },
182 { 'D', "Describe" },
183 { 'C', "Close" },
184 { 'H', "Flush" },
185 { 'S', "Sync" },
186 { 'F', "Function call" },
187 { 'd', "Copy data" },
188 { 'c', "Copy completion" },
189 { 'f', "Copy failure" },
190 { 'X', "Termination" },
191 { 0, NULL((void*)0) }
192};
193
194static const value_string be_messages[] = {
195 { 'R', "Authentication request" },
196 { 'K', "Backend key data" },
197 { 'S', "Parameter status" },
198 { '1', "Parse completion" },
199 { '2', "Bind completion" },
200 { '3', "Close completion" },
201 { 'C', "Command completion" },
202 { 't', "Parameter description" },
203 { 'T', "Row description" },
204 { 'D', "Data row" },
205 { 'I', "Empty query" },
206 { 'n', "No data" },
207 { 'E', "Error" },
208 { 'N', "Notice" },
209 { 's', "Portal suspended" },
210 { 'Z', "Ready for query" },
211 { 'A', "Notification" },
212 { 'V', "Function call response" },
213 { 'G', "CopyIn response" },
214 { 'H', "CopyOut response" },
215 { 'd', "Copy data" },
216 { 'c', "Copy completion" },
217 { 'v', "Negotiate protocol version" },
218 { 0, NULL((void*)0) }
219};
220
221static const value_string tuple_types[] = {
222 { 'n', "NULL" },
223 { 'u', "Unchanged TOASTed" },
224 { 't', "Text" },
225 { 'b', "Binary" },
226 { 0, NULL((void*)0) }
227};
228
229static const value_string tuple_data_types[] = {
230 { 'K', "Key" },
231 { 'O', "Old tuple" },
232 { 'N', "New tuple" },
233 { 0, NULL((void*)0) }
234};
235
236static const value_string logical_message_types[] = {
237 { 'B', "Begin" },
238 { 'b', "Begin Prepare" },
239 { 'C', "Commit" },
240 { 'K', "Commit Prepared" },
241 { 'D', "Delete" },
242 { 'I', "Insert" },
243 { 'M', "Message" },
244 { 'P', "Prepare" },
245 { 'r', "Rollback Prepared" },
246 { 'R', "Relation" },
247 { 'T', "Truncate" },
248 { 'U', "Update" },
249 { 'O', "Origin" },
250 { 'Y', "Type" },
251 { 'S', "Stream Start" },
252 { 'E', "Stream Stop" },
253 { 'c', "Stream Commit" },
254 { 'A', "Stream Abort" },
255 { 'p', "Stream Prepare" },
256 { 0, NULL((void*)0) }
257};
258
259#define PGSQL_AUTH_TYPE_SUCCESS0 0
260#define PGSQL_AUTH_TYPE_KERBEROS41 1
261#define PGSQL_AUTH_TYPE_KERBEROS52 2
262#define PGSQL_AUTH_TYPE_PLAINTEXT3 3
263#define PGSQL_AUTH_TYPE_CRYPT4 4
264#define PGSQL_AUTH_TYPE_MD55 5
265#define PGSQL_AUTH_TYPE_SCM6 6
266#define PGSQL_AUTH_TYPE_GSSAPI7 7
267#define PGSQL_AUTH_TYPE_GSSAPI_SSPI_CONTINUE8 8
268#define PGSQL_AUTH_TYPE_SSPI9 9
269#define PGSQL_AUTH_TYPE_SASL10 10
270#define PGSQL_AUTH_TYPE_SASL_CONTINUE11 11
271#define PGSQL_AUTH_TYPE_SASL_COMPLETE12 12
272
273static const value_string auth_types[] = {
274 { PGSQL_AUTH_TYPE_SUCCESS0 , "Success" },
275 { PGSQL_AUTH_TYPE_KERBEROS41 , "Kerberos V4" },
276 { PGSQL_AUTH_TYPE_KERBEROS52 , "Kerberos V5" },
277 { PGSQL_AUTH_TYPE_PLAINTEXT3 , "Plaintext password" },
278 { PGSQL_AUTH_TYPE_CRYPT4 , "crypt()ed password" },
279 { PGSQL_AUTH_TYPE_MD55 , "MD5 password" },
280 { PGSQL_AUTH_TYPE_SCM6 , "SCM credentials" },
281 { PGSQL_AUTH_TYPE_GSSAPI7 , "GSSAPI" },
282 { PGSQL_AUTH_TYPE_GSSAPI_SSPI_CONTINUE8 , "GSSAPI/SSPI continue" },
283 { PGSQL_AUTH_TYPE_SSPI9 , "SSPI" },
284 { PGSQL_AUTH_TYPE_SASL10 , "SASL" },
285 { PGSQL_AUTH_TYPE_SASL_CONTINUE11 , "SASL continue" },
286 { PGSQL_AUTH_TYPE_SASL_COMPLETE12 , "SASL complete" },
287 { 0, NULL((void*)0) }
288};
289
290static const value_string status_vals[] = {
291 { 'I', "Idle" },
292 { 'T', "In a transaction" },
293 { 'E', "In a failed transaction" },
294 { 0, NULL((void*)0) }
295};
296
297static const value_string format_vals[] = {
298 { 0, "Text" },
299 { 1, "Binary" },
300 { 0, NULL((void*)0) }
301};
302
303#define PGSQL_CANCELREQUEST80877102 80877102
304#define PGSQL_SSLREQUEST80877103 80877103
305#define PGSQL_GSSENCREQUEST80877104 80877104
306
307static const value_string request_code_vals[] = {
308 { PGSQL_CANCELREQUEST80877102, "CancelRequest" },
309 { PGSQL_SSLREQUEST80877103, "SSLRequest" },
310 { PGSQL_GSSENCREQUEST80877104, "GSSENCRequest" },
311 { 0, NULL((void*)0) }
312};
313
314static const value_string ssl_response_vals[] = {
315 { 'N', "Unwilling to perform SSL" },
316 { 'S', "Willing to perform SSL" },
317 { 0, NULL((void*)0) }
318};
319
320static const value_string gssenc_response_vals[] = {
321 { 'G', "Willing to perform GSSAPI encryption" },
322 { 'N', "Unwilling to perform GSSAPI encryption" },
323 { 0, NULL((void*)0) }
324};
325
326static void
327dissect_pg_epoch(tvbuff_t *tvb, int n, proto_tree *tree, int hfindex)
328{
329 uint64_t system_clock = tvb_get_uint64(tvb, n, ENC_BIG_ENDIAN0x00000000);
330 /* PostgreSQL epoch starts at 2000-01-01, which translates to a timestamp of 946681200 */
331 nstime_t system_time = NSTIME_INIT_SECS_USECS(system_clock / 1000000 + 946681200, system_clock % 1000000){system_clock / 1000000 + 946681200, system_clock % 1000000*1000
}
;
332 proto_tree_add_time(tree, hfindex, tvb, n, 8, &system_time);
333}
334
335static int
336get_tuple_data_length(tvbuff_t *tvb, int start)
337{
338 int number_columns;
339 int n = start;
340 number_columns = tvb_get_uint16(tvb, n, ENC_BIG_ENDIAN0x00000000);
341 n += 2;
342 for (int i = 0; i < number_columns; i++) {
343 unsigned char tuple_type;
344 tuple_type = tvb_get_uint8(tvb, n);
345 n += 1;
346
347 if (tuple_type == 't' || tuple_type == 'b') {
348 int column_length;
349 column_length = tvb_get_ntohl(tvb, n);
350 n += 4 + column_length;
351 }
352 }
353 return n - start;
354}
355
356static int
357dissect_tuple_data(tvbuff_t *tvb, int n, proto_tree *tree)
358{
359 int number_columns;
360
361 number_columns = tvb_get_uint16(tvb, n, ENC_BIG_ENDIAN0x00000000);
362 proto_tree_add_item_ret_uint(tree, hf_logical_number_columns, tvb, n, 2, ENC_BIG_ENDIAN0x00000000, &number_columns);
363 n += 2;
364
365 for (int i = 0; i < number_columns; i++) {
366 unsigned char tuple_type;
367 int shrub_start = 0;
368 const char *typestr;
369 proto_tree *shrub;
370
371 /* tuple_type is included in the column's shrub, save the start position */
372 shrub_start = n;
373
374 tuple_type = tvb_get_uint8(tvb, n);
375 typestr = val_to_str_const(tuple_type, tuple_types, "Unknown");
376 n += 1;
377
378 if (tuple_type == 't' || tuple_type == 'b') {
379 int column_length;
380
381 column_length = tvb_get_ntohl(tvb, n);
382 /* Shrub's size includes tuple_type (1 byte) + column_length (4 bytes) of column length */
383 shrub = proto_tree_add_subtree_format(tree, tvb, shrub_start, 5 + column_length, ett_values, NULL((void*)0), "Column %d", i);
384 /* Now that the shrub is created, add the typestr. n was already incremented */
385 proto_tree_add_string(shrub, hf_tuple_type, tvb, shrub_start, 1, typestr);
386
387 proto_tree_add_item_ret_int(shrub, hf_logical_column_length, tvb, n, 4, ENC_BIG_ENDIAN0x00000000, &column_length);
388 n += 4;
389
390 if (tuple_type == 't') {
391 proto_tree_add_item(shrub, hf_val_text_data, tvb, n, column_length, ENC_ASCII0x00000000);
392 } else {
393 proto_tree_add_item(shrub, hf_val_data, tvb, n, column_length, ENC_NA0x00000000);
394 }
395 n += column_length;
396 } else {
397 shrub = proto_tree_add_subtree_format(tree, tvb, shrub_start, 1, ett_values, NULL((void*)0), "Column %d", i);
398 proto_tree_add_string(shrub, hf_tuple_type, tvb, shrub_start, 1, typestr);
399 }
400 }
401 return n;
402}
403
404static int
405dissect_new_tuple_data(tvbuff_t *tvb, int n, proto_tree *tree)
406{
407 proto_tree *shrub;
408 const char * tupledatastr;
409 unsigned char type;
410 int length, start_shrub = n;
411
412 type = tvb_get_uint8(tvb, n);
413 tupledatastr = val_to_str_const(type, tuple_data_types, "Unknown");
414 n += 1;
415
416 length = get_tuple_data_length(tvb, n);
417 shrub = proto_tree_add_subtree_format(tree, tvb, start_shrub, length + 1, ett_values, NULL((void*)0), "%s", tupledatastr);
418 proto_tree_add_string(shrub, hf_tuple_data_type, tvb, start_shrub, 1, tupledatastr);
419
420 n = dissect_tuple_data(tvb, n, shrub);
421 return n;
422}
423
424static int
425dissect_old_tuple_data(tvbuff_t *tvb, int n, proto_tree *tree)
426{
427 proto_tree *shrub;
428 const char *tupledatastr;
429 int length, start_shrub = n;
430 unsigned char type;
431
432 type = tvb_get_uint8(tvb, n);
433 if (type != 'K' && type != 'O') {
434 /* No optional old tuple detected */
435 return n;
436 }
437
438 n += 1;
439 tupledatastr = val_to_str_const(type, tuple_data_types, "Unknown");
440
441 /* Get the size of the tuple data so we can build our shrub */
442 length = get_tuple_data_length(tvb, n);
443 shrub = proto_tree_add_subtree_format(tree, tvb, start_shrub, length - (start_shrub - 1), ett_values, NULL((void*)0), "%s", tupledatastr);
444 proto_tree_add_string(shrub, hf_tuple_data_type, tvb, start_shrub, 1, tupledatastr);
445
446 /* Now we can dissect tuple data for real */
447 return dissect_tuple_data(tvb, n, shrub);
448}
449
450static bool_Bool is_streamed_txn(packet_info *pinfo, pgsql_conn_data_t *conv_data)
451{
452 struct pgsql_per_packet_data_t *pgsql_ppd;
453 pgsql_ppd = (struct pgsql_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pgsql, pinfo->curr_layer_num);
454 if (!pgsql_ppd) {
455 /* First time, allocate the per packet and copy the current
456 * streamed_txn from the conversation
457 */
458 pgsql_ppd = wmem_new0(wmem_file_scope(), struct pgsql_per_packet_data_t)((struct pgsql_per_packet_data_t*)wmem_alloc0((wmem_file_scope
()), sizeof(struct pgsql_per_packet_data_t)))
;
459 p_add_proto_data(wmem_file_scope(), pinfo, proto_pgsql, pinfo->curr_layer_num, pgsql_ppd);
460 pgsql_ppd->streamed_txn = conv_data->streamed_txn;
461 }
462 return pgsql_ppd->streamed_txn;
463}
464
465static void set_streamed_txn(packet_info *pinfo, pgsql_conn_data_t *conv_data, bool_Bool streamed_txn)
466{
467 struct pgsql_per_packet_data_t *pgsql_ppd;
468 /* Set both the conversation's and the ppd stream_txn state.
469 * Conversation is used to set the stream_txn's value when ppd is
470 * created.
471 */
472 conv_data->streamed_txn = streamed_txn;
473 pgsql_ppd = (struct pgsql_per_packet_data_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pgsql, pinfo->curr_layer_num);
474 if (!pgsql_ppd) {
475 pgsql_ppd = wmem_new0(wmem_file_scope(), struct pgsql_per_packet_data_t)((struct pgsql_per_packet_data_t*)wmem_alloc0((wmem_file_scope
()), sizeof(struct pgsql_per_packet_data_t)))
;
476 p_add_proto_data(wmem_file_scope(), pinfo, proto_pgsql, pinfo->curr_layer_num, pgsql_ppd);
477 }
478 pgsql_ppd->streamed_txn = streamed_txn;;
479}
480
481static void dissect_pgsql_logical_be_msg(int32_t length, tvbuff_t *tvb, int n, proto_tree *tree, packet_info *pinfo,
482 pgsql_conn_data_t *conv_data)
483{
484 proto_tree *shrub;
485 proto_item *ti;
486 int siz, i, content_length, leftover;
487 char *s;
488
489 unsigned char message_type = tvb_get_uint8(tvb, n);
490 const char *logical_message_name = try_val_to_str(message_type, logical_message_types);
491 if (logical_message_name == NULL((void*)0))
492 {
493 /* Doesn't look like a logical replication message. It's probably WAL
494 * data stream from physical replication.
495 */
496 proto_tree_add_item(tree, hf_xlogdata, tvb, n, length - (n - 1), ENC_NA0x00000000);
497 return;
498 }
499
500 proto_tree_add_string(tree, hf_logical_msg_type, tvb, n, 1, logical_message_name);
501 n += 1;
502
503 /* Payload's length doesn't include the type */
504 shrub = proto_tree_add_subtree_format(tree, tvb, n, length - (n - 1), ett_values, NULL((void*)0), "%s", logical_message_name);
505
506 switch (message_type) {
507 /* Begin */
508 case 'B':
509 proto_tree_add_item(shrub, hf_logical_lsn_final, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
510 n += 8;
511 dissect_pg_epoch(tvb, n, shrub, hf_logical_commit_ts);
512 n += 8;
513 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
514 n += 4;
515 break;
516
517 /* Message */
518 case 'M':
519 if (is_streamed_txn(pinfo, conv_data)) {
520 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
521 n += 4;
522 }
523 proto_tree_add_item(shrub, hf_logical_message_flags, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
524 n += 1;
525 proto_tree_add_item(shrub, hf_logical_message_lsn, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
526 n += 8;
527 siz = tvb_strsize(tvb, n);
528 proto_tree_add_item(shrub, hf_logical_message_prefix, tvb, n, siz, ENC_ASCII0x00000000);
529 n += siz;
530 content_length = tvb_strsize(tvb, n);
531 proto_tree_add_item_ret_int(shrub, hf_logical_message_length, tvb, n, 4, ENC_BIG_ENDIAN0x00000000, &content_length);
532 n += 4;
533 proto_tree_add_item(shrub, hf_logical_message_content, tvb, n, content_length, ENC_ASCII0x00000000);
534 n += content_length;
535 break;
536
537 /* Commit */
538 case 'C':
539 proto_tree_add_item(shrub, hf_logical_commit_flags, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
540 n += 1;
541 proto_tree_add_item(shrub, hf_logical_lsn_commit, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
542 n += 8;
543 proto_tree_add_item(shrub, hf_logical_lsn_transaction, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
544 n += 8;
545 dissect_pg_epoch(tvb, n, shrub, hf_standby_clock_ts);
546 n += 8;
547 break;
548
549 /* Origin */
550 case 'O':
551 proto_tree_add_item(shrub, hf_logical_lsn_origin, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
552 n += 8;
553 siz = tvb_strsize(tvb, n);
554 proto_tree_add_item(shrub, hf_logical_origin_name, tvb, n, siz, ENC_ASCII0x00000000);
555 n += siz;
556 break;
557
558 /* Relation */
559 case 'R':
560 if (is_streamed_txn(pinfo, conv_data)) {
561 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
562 n += 4;
563 }
564 proto_tree_add_item(shrub, hf_relation_oid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
565 n += 4;
566 s = tvb_get_stringz_enc(pinfo->pool, tvb, n, &siz, ENC_ASCII0x00000000);
567 proto_tree_add_string(shrub, hf_namespace, tvb, n, siz, s);
568 n += siz;
569 s = tvb_get_stringz_enc(pinfo->pool, tvb, n, &siz, ENC_ASCII0x00000000);
570 proto_tree_add_string(shrub, hf_relation_name, tvb, n, siz, s);
571 n += siz;
572 proto_tree_add_item(shrub, hf_logical_replica_identity, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
573 n += 1;
574 i = tvb_get_ntohs(tvb, n);
575 shrub = proto_tree_add_subtree_format(shrub, tvb, n, 2, ett_values, NULL((void*)0), "Columns: %d", i);
576 n += 2;
577 while (i-- > 0) {
578 proto_tree *twig;
579 siz = tvb_strsize(tvb, n+1);
580 ti = proto_tree_add_item(shrub, hf_val_name, tvb, n+1, siz, ENC_ASCII0x00000000);
581 twig = proto_item_add_subtree(ti, ett_values);
582 proto_tree_add_item(twig, hf_logical_column_flags, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
583 n +=1;
584 proto_tree_add_item(twig, hf_logical_column_name, tvb, n, siz, ENC_ASCII0x00000000);
585 n += siz;
586 proto_tree_add_item(twig, hf_logical_column_oid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
587 n += 4;
588 proto_tree_add_item(twig, hf_logical_column_type_modifier, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
589 n += 4;
590 }
591 break;
592
593 /* Type */
594 case 'Y':
595 if (is_streamed_txn(pinfo, conv_data)) {
596 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
597 n += 4;
598 }
599 proto_tree_add_item(shrub, hf_typeoid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
600 n += 4;
601 s = tvb_get_stringz_enc(pinfo->pool, tvb, n, &siz, ENC_ASCII0x00000000);
602 proto_tree_add_string(shrub, hf_namespace, tvb, n, siz, s);
603 n += siz;
604 s = tvb_get_stringz_enc(pinfo->pool, tvb, n, &siz, ENC_ASCII0x00000000);
605 proto_tree_add_string(shrub, hf_custom_type_name, tvb, n, siz, s);
606 n += siz;
607 break;
608
609 /* Insert */
610 case 'I':
611 if (is_streamed_txn(pinfo, conv_data)) {
612 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
613 n += 4;
614 }
615 proto_tree_add_item(shrub, hf_relation_oid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
616 n += 4;
617 n = dissect_new_tuple_data(tvb, n, shrub);
618 break;
619
620 /* Update */
621 case 'U':
622 if (is_streamed_txn(pinfo, conv_data)) {
623 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
624 n += 4;
625 }
626 i = tvb_get_ntohl(tvb, n);
627 proto_tree_add_item(shrub, hf_logical_column_oid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
628 n += 4;
629 n = dissect_old_tuple_data(tvb, n, shrub);
630 n = dissect_new_tuple_data(tvb, n, shrub);
631 break;
632
633 /* Delete */
634 case 'D':
635 if (is_streamed_txn(pinfo, conv_data)) {
636 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
637 n += 4;
638 }
639 i = tvb_get_ntohl(tvb, n);
640 proto_tree_add_item(shrub, hf_logical_column_oid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
641 n += 4;
642 n = dissect_old_tuple_data(tvb, n, shrub);
643 break;
644
645 /* Truncate */
646 case 'T':
647 if (is_streamed_txn(pinfo, conv_data)) {
648 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
649 n += 4;
650 }
651 i = tvb_get_ntohl(tvb, n);
652 proto_tree_add_item_ret_uint(shrub, hf_logical_relation_number, tvb, n, 4, ENC_BIG_ENDIAN0x00000000, &i);
653 n += 4;
654 proto_tree_add_item(shrub, hf_logical_truncate_flags, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
655 n += 1;
656 shrub = proto_tree_add_subtree_format(shrub, tvb, n, length - n, ett_values, NULL((void*)0), "Relation Oids: %d", i);
657 while (i-- > 0) {
658 proto_tree_add_item(shrub, hf_relation_oid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
659 n += 4;
660 }
661 break;
662
663 /* Stream Start */
664 case 'S':
665 set_streamed_txn(pinfo, conv_data, true1);
666 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
667 n += 4;
668 proto_tree_add_item(shrub, hf_logical_stream_first_segment, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
669 n += 1;
670 break;
671
672 /* Stream Stop */
673 case 'E':
674 set_streamed_txn(pinfo, conv_data, false0);
675 break;
676
677 /* Stream Commit */
678 case 'c':
679 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
680 n += 4;
681 proto_tree_add_item(shrub, hf_logical_stream_flags, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
682 n += 1;
683 proto_tree_add_item(shrub, hf_logical_lsn_commit, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
684 n += 8;
685 proto_tree_add_item(shrub, hf_logical_lsn_transaction, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
686 n += 8;
687 dissect_pg_epoch(tvb, n, shrub, hf_logical_prepare_commit_ts);
688 n += 8;
689 break;
690
691 /* Stream Abort */
692 case 'A':
693 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
694 n += 4;
695 proto_tree_add_item(shrub, hf_xid_subtransaction, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
696 n += 4;
697 leftover = length - (n - 1);
698 /* PostgreSQL's doc is currently a bit confusing here as the abort LSN
699 * and abort ts are marked as "available since protocol version 4".
700 * However, it will only be sent if streaming=parallel which is only
701 * supported with protocol version 4.
702 * So in any case, since this is the last message, we can assume that if
703 * we have enough data, they are the abort lsn and ts.
704 */
705 if (leftover == 16) {
706 proto_tree_add_item(shrub, hf_logical_lsn_abort, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
707 n += 8;
708 dissect_pg_epoch(tvb, n, shrub, hf_logical_stream_abort_ts);
709 n += 8;
710 }
711 break;
712
713 /* Begin Prepare*/
714 case 'b':
715 proto_tree_add_item(shrub, hf_logical_prepare_lsn, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
716 n += 8;
717 proto_tree_add_item(shrub, hf_logical_prepare_lsn_end, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
718 n += 8;
719 dissect_pg_epoch(tvb, n, shrub, hf_logical_prepare_ts);
720 n += 8;
721 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
722 n += 4;
723 siz = tvb_strsize(tvb, n);
724 proto_tree_add_item(shrub, hf_logical_prepare_gid, tvb, n, siz, ENC_ASCII0x00000000);
725 n += siz;
726 break;
727
728 /* Prepare*/
729 case 'P':
730 proto_tree_add_item(shrub, hf_logical_prepare_flags, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
731 n += 1;
732 proto_tree_add_item(shrub, hf_logical_prepare_lsn, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
733 n += 8;
734 proto_tree_add_item(shrub, hf_logical_prepare_lsn_end, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
735 n += 8;
736 dissect_pg_epoch(tvb, n, shrub, hf_logical_prepare_ts);
737 n += 8;
738 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
739 n += 4;
740 siz = tvb_strsize(tvb, n);
741 proto_tree_add_item(shrub, hf_logical_prepare_gid, tvb, n, siz, ENC_ASCII0x00000000);
742 n += siz;
743 break;
744
745 /* Commit Prepared */
746 case 'K':
747 proto_tree_add_item(shrub, hf_logical_prepare_flags, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
748 n += 1;
749 proto_tree_add_item(shrub, hf_logical_prepare_lsn, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
750 n += 8;
751 proto_tree_add_item(shrub, hf_logical_prepare_lsn_end, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
752 n += 8;
753 dissect_pg_epoch(tvb, n, shrub, hf_logical_prepare_commit_ts);
754 n += 8;
755 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
756 n += 4;
757 siz = tvb_strsize(tvb, n);
758 proto_tree_add_item(shrub, hf_logical_prepare_gid, tvb, n, siz, ENC_ASCII0x00000000);
759 n += siz;
760 break;
761
762 /* Rollback Prepared */
763 case 'r':
764 proto_tree_add_item(shrub, hf_logical_prepare_flags, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
765 n += 1;
766 proto_tree_add_item(shrub, hf_logical_prepare_lsn_end, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
767 n += 8;
768 proto_tree_add_item(shrub, hf_logical_prepare_lsn_rollback, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
769 n += 8;
770 dissect_pg_epoch(tvb, n, shrub, hf_logical_prepare_ts);
771 n += 8;
772 dissect_pg_epoch(tvb, n, shrub, hf_logical_prepare_rollback_ts);
773 n += 8;
774 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
775 n += 4;
776 siz = tvb_strsize(tvb, n);
777 proto_tree_add_item(shrub, hf_logical_prepare_gid, tvb, n, siz, ENC_ASCII0x00000000);
778 n += siz;
779 break;
780
781 /* Stream Prepare */
782 case 'p':
783 proto_tree_add_item(shrub, hf_logical_stream_flags, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
784 n +=1;
785 proto_tree_add_item(shrub, hf_logical_prepare_lsn, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
786 n += 8;
787 proto_tree_add_item(shrub, hf_logical_prepare_lsn_end, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
788 n += 8;
789 dissect_pg_epoch(tvb, n, shrub, hf_logical_prepare_ts);
790 n += 8;
791 proto_tree_add_item(shrub, hf_xid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
792 n += 4;
793 siz = tvb_strsize(tvb, n);
794 proto_tree_add_item(shrub, hf_logical_prepare_gid, tvb, n, siz, ENC_ASCII0x00000000);
795 n += siz;
796 break;
797 default:
798 return;
799 }
800 col_append_fstr(pinfo->cinfo, COL_INFO, "/%c", message_type);
801}
802
803static void dissect_pgsql_copy_data_be_msg(int32_t length, tvbuff_t *tvb,
804 int n, proto_tree *tree, packet_info *pinfo,
805 pgsql_conn_data_t *conv_data)
806{
807 proto_tree *shrub;
808 unsigned char type = tvb_get_uint8(tvb, n);
809 switch (type) {
810 /* XLogData */
811 case 'w':
812 col_append_fstr(pinfo->cinfo, COL_INFO, "/%c", type);
813 shrub = proto_tree_add_subtree_format(tree, tvb, n, length - (n - 1), ett_values, NULL((void*)0), "XLogData");
814 proto_tree_add_string(shrub, hf_copydata_type, tvb, n, 1, "XLogData");
815 n += 1;
816 proto_tree_add_item(shrub, hf_xlog_wal_start, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
817 n += 8;
818 proto_tree_add_item(shrub, hf_xlog_wal_end, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
819 n += 8;
820 dissect_pg_epoch(tvb, n, shrub, hf_standby_clock_ts);
821 n += 8;
822 dissect_pgsql_logical_be_msg(length, tvb, n, shrub, pinfo, conv_data);
823 break;
824
825 /* Primary keep alive */
826 case 'k':
827 col_append_fstr(pinfo->cinfo, COL_INFO, "/%c", type);
828 shrub = proto_tree_add_subtree_format(tree, tvb, n, length - (n - 1), ett_values, NULL((void*)0), "Primary keepalive");
829 proto_tree_add_string(shrub, hf_copydata_type, tvb, n, 1, "Primary Keepalive Message");
830 n += 1;
831 proto_tree_add_item(shrub, hf_xlog_wal_end, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
832 n += 8;
833 dissect_pg_epoch(tvb, n, shrub, hf_standby_clock_ts);
834 n += 8;
835 proto_tree_add_item(shrub, hf_standby_immediate_ack, tvb, n, 1, ENC_NULL0x3D);
836 n += 1;
837 break;
838
839 default:
840 proto_tree_add_item(tree, hf_copydata, tvb, n, length-n+1, ENC_NA0x00000000);
841 return;
842 }
843}
844
845static void dissect_pgsql_copy_data_fe_msg(tvbuff_t *tvb, int n, proto_tree *tree, int32_t length, packet_info *pinfo)
846{
847 proto_tree *shrub;
848 unsigned char type = tvb_get_uint8(tvb, n);
849 switch (type) {
850 /* Standby status update */
851 case 'r':
852 shrub = proto_tree_add_subtree_format(tree, tvb, n, length - (n - 1), ett_values, NULL((void*)0), "Standby status update");
853 proto_tree_add_string(shrub, hf_copydata_type, tvb, n, 1, "Standby status update");
854 n += 1;
855 proto_tree_add_item(shrub, hf_standby_last_wal_written, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
856 n += 8;
857 proto_tree_add_item(shrub, hf_standby_last_wal_flushed, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
858 n += 8;
859 proto_tree_add_item(shrub, hf_standby_last_wal_applied, tvb, n, 8, ENC_BIG_ENDIAN0x00000000);
860 n += 8;
861 dissect_pg_epoch(tvb, n, shrub, hf_standby_clock_ts);
862 n += 8;
863 proto_tree_add_item(shrub, hf_standby_immediate_ack, tvb, n, 1, ENC_NULL0x3D);
864 n += 1;
865 break;
866
867 /* Hot standby feedback */
868 case 'h':
869 proto_tree_add_string(tree, hf_copydata_type, tvb, n, 1, "Hot standby feedback");
870 shrub = proto_tree_add_subtree_format(tree, tvb, n, length - (n - 1), ett_values, NULL((void*)0), "Hot standby feedback");
871 n += 1;
872 dissect_pg_epoch(tvb, n, shrub, hf_standby_clock_ts);
873 n += 8;
874 proto_tree_add_item(shrub, hf_standby_xmin, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
875 n += 4;
876 proto_tree_add_item(shrub, hf_standby_xmin_epoch, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
877 n += 4;
878 proto_tree_add_item(shrub, hf_standby_catalog_xmin, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
879 n += 4;
880 proto_tree_add_item(shrub, hf_standby_catalog_xmin_epoch, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
881 n += 4;
Value stored to 'n' is never read
882 break;
883
884 default:
885 proto_tree_add_item(tree, hf_copydata, tvb, n, length-n+1, ENC_NA0x00000000);
886 return;
887 }
888 col_append_fstr(pinfo->cinfo, COL_INFO, "/%c", type);
889}
890
891static void dissect_pgsql_fe_msg(unsigned char type, unsigned length, tvbuff_t *tvb,
892 int n, proto_tree *tree, packet_info *pinfo,
893 pgsql_conn_data_t *conv_data)
894{
895 unsigned char c;
896 int i, siz;
897 char *s;
898 proto_tree *shrub;
899 int32_t data_length;
900 pgsql_auth_state_t state;
901 tvbuff_t *next_tvb;
902 dissector_handle_t payload_handle;
903
904 switch (type) {
905 /* Password, SASL or GSSAPI Response, depending on context */
906 case 'p':
907 state = GPOINTER_TO_UINT(wmem_tree_lookup32_le(conv_data->state_tree, pinfo->num))((guint) (gulong) (wmem_tree_lookup32_le(conv_data->state_tree
, pinfo->num)))
;
908 switch(state) {
909
910 case PGSQL_AUTH_SASL_REQUESTED:
911 /* SASLInitResponse */
912 siz = tvb_strsize(tvb, n);
913 proto_tree_add_item(tree, hf_sasl_auth_mech, tvb, n, siz, ENC_ASCII0x00000000);
914 n += siz;
915 proto_tree_add_item_ret_int(tree, hf_sasl_auth_data_length, tvb, n, 4, ENC_BIG_ENDIAN0x00000000, &data_length);
916 n += 4;
917 if (data_length) {
918 proto_tree_add_item(tree, hf_sasl_auth_data, tvb, n, data_length, ENC_NA0x00000000);
919 }
920 break;
921
922 case PGSQL_AUTH_SASL_CONTINUE:
923 proto_tree_add_item(tree, hf_sasl_auth_data, tvb, n, length-4, ENC_NA0x00000000);
924 break;
925
926 case PGSQL_AUTH_GSSAPI_SSPI_DATA:
927 next_tvb = tvb_new_subset_length(tvb, n, length - 4);
928 /* https://www.postgresql.org/docs/current/sspi-auth.html
929 * "PostgreSQL will use SSPI in negotiate mode, which will use
930 * Kerberos when possible and automatically fall back to NTLM
931 * in other cases... When using Kerberos authentication, SSPI
932 * works the same way GSSAPI does."
933 * Assume this means the Kerberos mode for SSPI works like
934 * GSSAPI, and not, say, SPNEGO the way TDS does. (Need
935 * a sample.)
936 */
937 if (tvb_strneql(next_tvb, 0, "NTLMSSP", 7) == 0) {
938 payload_handle = ntlmssp_handle;
939 } else {
940 payload_handle = gssapi_handle;
941 }
942 n = call_dissector_only(payload_handle, next_tvb, pinfo, tree, NULL((void*)0));
943 if ((length = tvb_reported_length_remaining(next_tvb, n))) {
944 proto_tree_add_item(tree, hf_gssapi_sspi_data, next_tvb, n, length, ENC_NA0x00000000);
945 }
946 break;
947
948 default:
949 siz = tvb_strsize(tvb, n);
950 proto_tree_add_item(tree, hf_passwd, tvb, n, siz, ENC_ASCII0x00000000);
951 break;
952 }
953 break;
954
955 /* Simple query */
956 case 'Q':
957 siz = tvb_strsize(tvb, n);
958 proto_tree_add_item(tree, hf_query, tvb, n, siz, ENC_ASCII0x00000000);
959 break;
960
961 /* Parse */
962 case 'P':
963 siz = tvb_strsize(tvb, n);
964 proto_tree_add_item(tree, hf_statement, tvb, n, siz, ENC_ASCII0x00000000);
965 n += siz;
966
967 siz = tvb_strsize(tvb, n);
968 proto_tree_add_item(tree, hf_query, tvb, n, siz, ENC_ASCII0x00000000);
969 n += siz;
970
971 i = tvb_get_ntohs(tvb, n);
972 shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL((void*)0), "Parameters: %d", i);
973 n += 2;
974 while (i-- > 0) {
975 proto_tree_add_item(shrub, hf_typeoid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
976 n += 4;
977 }
978 break;
979
980 /* Bind */
981 case 'B':
982 siz = tvb_strsize(tvb, n);
983 proto_tree_add_item(tree, hf_portal, tvb, n, siz, ENC_ASCII0x00000000);
984 n += siz;
985
986 siz = tvb_strsize(tvb, n);
987 proto_tree_add_item(tree, hf_statement, tvb, n, siz, ENC_ASCII0x00000000);
988 n += siz;
989
990 i = tvb_get_ntohs(tvb, n);
991 shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL((void*)0), "Parameter formats: %d", i);
992 n += 2;
993 while (i-- > 0) {
994 proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN0x00000000);
995 n += 2;
996 }
997
998 i = tvb_get_ntohs(tvb, n);
999 shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL((void*)0), "Parameter values: %d", i);
1000 n += 2;
1001 while (i-- > 0) {
1002 siz = tvb_get_ntohl(tvb, n);
1003 proto_tree_add_int(shrub, hf_val_length, tvb, n, 4, siz);
1004 n += 4;
1005 if (siz > 0) {
1006 proto_tree_add_item(shrub, hf_val_data, tvb, n, siz, ENC_NA0x00000000);
1007 n += siz;
1008 }
1009 }
1010
1011 i = tvb_get_ntohs(tvb, n);
1012 shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL((void*)0), "Result formats: %d", i);
1013 n += 2;
1014 while (i-- > 0) {
1015 proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN0x00000000);
1016 n += 2;
1017 }
1018 break;
1019
1020 /* Execute */
1021 case 'E':
1022 siz = tvb_strsize(tvb, n);
1023 proto_tree_add_item(tree, hf_portal, tvb, n, siz, ENC_ASCII0x00000000);
1024 n += siz;
1025
1026 i = tvb_get_ntohl(tvb, n);
1027 if (i == 0)
1028 proto_tree_add_uint_format_value(tree, hf_return, tvb, n, 4, i, "all rows");
1029 else
1030 proto_tree_add_uint_format_value(tree, hf_return, tvb, n, 4, i, "%d rows", i);
1031 break;
1032
1033 /* Describe, Close */
1034 case 'D':
1035 case 'C':
1036 c = tvb_get_uint8(tvb, n);
1037 if (c == 'P')
1038 i = hf_portal;
1039 else
1040 i = hf_statement;
1041
1042 n += 1;
1043 s = tvb_get_stringz_enc(pinfo->pool, tvb, n, &siz, ENC_ASCII0x00000000);
1044 proto_tree_add_string(tree, i, tvb, n, siz, s);
1045 break;
1046
1047 /* Messages without a type identifier */
1048 case '\0':
1049 i = tvb_get_ntohl(tvb, n);
1050 n += 4;
1051 length -= n;
1052 switch (i) {
1053 /* Startup message */
1054 case 196608:
1055 proto_tree_add_item(tree, hf_version_major, tvb, n-4, 2, ENC_BIG_ENDIAN0x00000000);
1056 proto_tree_add_item(tree, hf_version_minor, tvb, n-2, 2, ENC_BIG_ENDIAN0x00000000);
1057 while ((signed)length > 0) {
1058 siz = tvb_strsize(tvb, n);
1059 length -= siz;
1060 if ((signed)length <= 0) {
1061 break;
1062 }
1063 proto_tree_add_item(tree, hf_parameter_name, tvb, n, siz, ENC_ASCII0x00000000);
1064 i = tvb_strsize(tvb, n+siz);
1065 proto_tree_add_item(tree, hf_parameter_value, tvb, n + siz, i, ENC_ASCII0x00000000);
1066 length -= i;
1067
1068 n += siz+i;
1069 if (length == 1 && tvb_get_uint8(tvb, n) == 0)
1070 break;
1071 }
1072 break;
1073
1074 case PGSQL_SSLREQUEST80877103:
1075 proto_tree_add_item(tree, hf_request_code, tvb, n-4, 4, ENC_BIG_ENDIAN0x00000000);
1076 /* Next reply will be a single byte. */
1077 wmem_tree_insert32(conv_data->state_tree, pinfo->num, GUINT_TO_POINTER(PGSQL_AUTH_SSL_REQUESTED)((gpointer) (gulong) (PGSQL_AUTH_SSL_REQUESTED)));
1078 break;
1079
1080 case PGSQL_GSSENCREQUEST80877104:
1081 proto_tree_add_item(tree, hf_request_code, tvb, n-4, 4, ENC_BIG_ENDIAN0x00000000);
1082 /* Next reply will be a single byte. */
1083 wmem_tree_insert32(conv_data->state_tree, pinfo->num, GUINT_TO_POINTER(PGSQL_AUTH_GSSENC_REQUESTED)((gpointer) (gulong) (PGSQL_AUTH_GSSENC_REQUESTED)));
1084 break;
1085
1086 case PGSQL_CANCELREQUEST80877102:
1087 proto_tree_add_item(tree, hf_request_code, tvb, n-4, 4, ENC_BIG_ENDIAN0x00000000);
1088 proto_tree_add_item(tree, hf_pid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
1089 proto_tree_add_item(tree, hf_key, tvb, n+4, 4, ENC_BIG_ENDIAN0x00000000);
1090 break;
1091 }
1092 break;
1093
1094 /* Copy data */
1095 case 'd':
1096 dissect_pgsql_copy_data_fe_msg(tvb, n, tree, length, pinfo);
1097 break;
1098
1099 /* Copy failure */
1100 case 'f':
1101 siz = tvb_strsize(tvb, n);
1102 proto_tree_add_item(tree, hf_error, tvb, n, siz, ENC_ASCII0x00000000);
1103 break;
1104
1105 /* Function call */
1106 case 'F':
1107 proto_tree_add_item(tree, hf_oid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
1108 n += 4;
1109
1110 i = tvb_get_ntohs(tvb, n);
1111 shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL((void*)0), "Parameter formats: %d", i);
1112 n += 2;
1113 while (i-- > 0) {
1114 proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN0x00000000);
1115 n += 2;
1116 }
1117
1118 i = tvb_get_ntohs(tvb, n);
1119 shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL((void*)0), "Parameter values: %d", i);
1120 n += 2;
1121 while (i-- > 0) {
1122 siz = tvb_get_ntohl(tvb, n);
1123 proto_tree_add_item(shrub, hf_val_length, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
1124 n += 4;
1125 if (siz > 0) {
1126 proto_tree_add_item(shrub, hf_val_data, tvb, n, siz, ENC_NA0x00000000);
1127 n += siz;
1128 }
1129 }
1130
1131 proto_tree_add_item(tree, hf_format, tvb, n, 2, ENC_BIG_ENDIAN0x00000000);
1132 break;
1133 }
1134}
1135
1136static void dissect_pgsql_be_msg(unsigned char type, unsigned length, tvbuff_t *tvb,
1137 int n, proto_tree *tree, packet_info *pinfo,
1138 pgsql_conn_data_t *conv_data)
1139{
1140 unsigned char c;
1141 int i, siz;
1142 char *s, *t;
1143 int32_t num_nonsupported_options;
1144 proto_item *ti;
1145 proto_tree *shrub;
1146 uint32_t auth_type;
1147
1148 switch (type) {
1149 /* Authentication request */
1150 case 'R':
1151 proto_tree_add_item_ret_uint(tree, hf_authtype, tvb, n, 4, ENC_BIG_ENDIAN0x00000000, &auth_type);
1152 switch (auth_type) {
1153 case PGSQL_AUTH_TYPE_CRYPT4:
1154 case PGSQL_AUTH_TYPE_MD55:
1155 n += 4;
1156 siz = (auth_type == PGSQL_AUTH_TYPE_CRYPT4 ? 2 : 4);
1157 proto_tree_add_item(tree, hf_salt, tvb, n, siz, ENC_NA0x00000000);
1158 break;
1159 case PGSQL_AUTH_TYPE_GSSAPI_SSPI_CONTINUE8:
1160 proto_tree_add_item(tree, hf_gssapi_sspi_data, tvb, n, length-8, ENC_NA0x00000000);
1161 /* FALLTHROUGH */
1162 case PGSQL_AUTH_TYPE_GSSAPI7:
1163 case PGSQL_AUTH_TYPE_SSPI9:
1164 wmem_tree_insert32(conv_data->state_tree, pinfo->num, GUINT_TO_POINTER(PGSQL_AUTH_GSSAPI_SSPI_DATA)((gpointer) (gulong) (PGSQL_AUTH_GSSAPI_SSPI_DATA)));
1165 break;
1166 case PGSQL_AUTH_TYPE_SASL10:
1167 wmem_tree_insert32(conv_data->state_tree, pinfo->num, GUINT_TO_POINTER(PGSQL_AUTH_SASL_REQUESTED)((gpointer) (gulong) (PGSQL_AUTH_SASL_REQUESTED)));
1168 n += 4;
1169 while ((unsigned)n < length) {
1170 siz = tvb_strsize(tvb, n);
1171 proto_tree_add_item(tree, hf_sasl_auth_mech, tvb, n, siz, ENC_ASCII0x00000000);
1172 n += siz;
1173 }
1174 break;
1175 case PGSQL_AUTH_TYPE_SASL_CONTINUE11:
1176 case PGSQL_AUTH_TYPE_SASL_COMPLETE12:
1177 wmem_tree_insert32(conv_data->state_tree, pinfo->num, GUINT_TO_POINTER(PGSQL_AUTH_SASL_CONTINUE)((gpointer) (gulong) (PGSQL_AUTH_SASL_CONTINUE)));
1178 n += 4;
1179 if ((unsigned)n < length) {
1180 proto_tree_add_item(tree, hf_sasl_auth_data, tvb, n, length-8, ENC_NA0x00000000);
1181 }
1182 break;
1183 }
1184 break;
1185
1186 /* Key data */
1187 case 'K':
1188 proto_tree_add_item(tree, hf_pid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
1189 proto_tree_add_item(tree, hf_key, tvb, n+4, 4, ENC_BIG_ENDIAN0x00000000);
1190 break;
1191
1192 /* Parameter status */
1193 case 'S':
1194 s = tvb_get_stringz_enc(pinfo->pool, tvb, n, &siz, ENC_ASCII0x00000000);
1195 proto_tree_add_string(tree, hf_parameter_name, tvb, n, siz, s);
1196 n += siz;
1197 t = tvb_get_stringz_enc(pinfo->pool, tvb, n, &i, ENC_ASCII0x00000000);
1198 proto_tree_add_string(tree, hf_parameter_value, tvb, n, i, t);
1199 break;
1200
1201 /* Parameter description */
1202 case 't':
1203 i = tvb_get_ntohs(tvb, n);
1204 shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL((void*)0), "Parameters: %d", i);
1205 n += 2;
1206 while (i-- > 0) {
1207 proto_tree_add_item(shrub, hf_typeoid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
1208 n += 4;
1209 }
1210 break;
1211
1212 /* Row description */
1213 case 'T':
1214 i = tvb_get_ntohs(tvb, n);
1215 ti = proto_tree_add_item(tree, hf_field_count, tvb, n, 2, ENC_BIG_ENDIAN0x00000000);
1216 shrub = proto_item_add_subtree(ti, ett_values);
1217 n += 2;
1218 while (i-- > 0) {
1219 proto_tree *twig;
1220 siz = tvb_strsize(tvb, n);
1221 ti = proto_tree_add_item(shrub, hf_val_name, tvb, n, siz, ENC_ASCII0x00000000);
1222 twig = proto_item_add_subtree(ti, ett_values);
1223 n += siz;
1224 proto_tree_add_item(twig, hf_tableoid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
1225 n += 4;
1226 proto_tree_add_item(twig, hf_val_idx, tvb, n, 2, ENC_BIG_ENDIAN0x00000000);
1227 n += 2;
1228 proto_tree_add_item(twig, hf_typeoid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
1229 n += 4;
1230 proto_tree_add_item(twig, hf_val_length, tvb, n, 2, ENC_BIG_ENDIAN0x00000000);
1231 n += 2;
1232 proto_tree_add_item(twig, hf_val_mod, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
1233 n += 4;
1234 proto_tree_add_item(twig, hf_format, tvb, n, 2, ENC_BIG_ENDIAN0x00000000);
1235 n += 2;
1236 }
1237 break;
1238
1239 /* Data row */
1240 case 'D':
1241 i = tvb_get_ntohs(tvb, n);
1242 ti = proto_tree_add_item(tree, hf_field_count, tvb, n, 2, ENC_BIG_ENDIAN0x00000000);
1243 shrub = proto_item_add_subtree(ti, ett_values);
1244 n += 2;
1245 while (i-- > 0) {
1246 siz = tvb_get_ntohl(tvb, n);
1247 proto_tree_add_int(shrub, hf_val_length, tvb, n, 4, siz);
1248 n += 4;
1249 if (siz > 0) {
1250 proto_tree_add_item(shrub, hf_val_data, tvb, n, siz, ENC_NA0x00000000);
1251 n += siz;
1252 }
1253 }
1254 break;
1255
1256 /* Command completion */
1257 case 'C':
1258 siz = tvb_strsize(tvb, n);
1259 proto_tree_add_item(tree, hf_tag, tvb, n, siz, ENC_ASCII0x00000000);
1260 break;
1261
1262 /* Ready */
1263 case 'Z':
1264 proto_tree_add_item(tree, hf_status, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
1265 break;
1266
1267 /* Error, Notice */
1268 case 'E':
1269 case 'N':
1270 length -= 4;
1271 while ((signed)length > 0) {
1272 c = tvb_get_uint8(tvb, n);
1273 if (c == '\0')
1274 break;
1275 --length;
1276 s = tvb_get_stringz_enc(pinfo->pool, tvb, n+1, &siz, ENC_ASCII0x00000000);
1277 i = hf_text;
1278 switch (c) {
1279 case 'S': i = hf_severity; break;
1280 case 'C': i = hf_code; break;
1281 case 'M': i = hf_message; break;
1282 case 'D': i = hf_detail; break;
1283 case 'H': i = hf_hint; break;
1284 case 'P': i = hf_position; break;
1285 case 'p': i = hf_internal_position; break;
1286 case 'q': i = hf_internal_query; break;
1287 case 'W': i = hf_where; break;
1288 case 's': i = hf_schema_name; break;
1289 case 't': i = hf_table_name; break;
1290 case 'c': i = hf_column_name; break;
1291 case 'd': i = hf_type_name; break;
1292 case 'n': i = hf_constraint_name; break;
1293 case 'F': i = hf_file; break;
1294 case 'L': i = hf_line; break;
1295 case 'R': i = hf_routine; break;
1296 }
1297 proto_tree_add_string(tree, i, tvb, n, siz+1, s);
1298 length -= siz+1;
1299 n += siz+1;
1300 }
1301 break;
1302
1303 /* NOTICE response */
1304 case 'A':
1305 proto_tree_add_item(tree, hf_pid, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
1306 n += 4;
1307 siz = tvb_strsize(tvb, n);
1308 proto_tree_add_item(tree, hf_condition, tvb, n, siz, ENC_ASCII0x00000000);
1309 n += siz;
1310 siz = tvb_strsize(tvb, n);
1311 if (siz > 1)
1312 proto_tree_add_item(tree, hf_text, tvb, n, siz, ENC_ASCII0x00000000);
1313 break;
1314
1315 /* Copy in/out */
1316 case 'G':
1317 case 'H':
1318 proto_tree_add_item(tree, hf_format, tvb, n, 1, ENC_BIG_ENDIAN0x00000000);
1319 n += 1;
1320 i = tvb_get_ntohs(tvb, n);
1321 shrub = proto_tree_add_subtree_format(tree, tvb, n, 2, ett_values, NULL((void*)0), "Columns: %d", i);
1322 n += 2;
1323 while (i-- > 2) {
1324 proto_tree_add_item(shrub, hf_format, tvb, n, 2, ENC_BIG_ENDIAN0x00000000);
1325 n += 2;
1326 }
1327 break;
1328
1329 /* Copy data */
1330 case 'd':
1331 dissect_pgsql_copy_data_be_msg(length, tvb, n, tree, pinfo, conv_data);
1332 break;
1333
1334 /* Function call response */
1335 case 'V':
1336 siz = tvb_get_ntohl(tvb, n);
1337 proto_tree_add_int(tree, hf_val_length, tvb, n, 4, siz);
1338 if (siz > 0)
1339 proto_tree_add_item(tree, hf_val_data, tvb, n+4, siz, ENC_NA0x00000000);
1340 break;
1341
1342 /* Negotiate Protocol Version */
1343 case 'v':
1344 proto_tree_add_item(tree, hf_supported_minor_version, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
1345 n += 4;
1346 proto_tree_add_item_ret_int(tree, hf_number_nonsupported_options, tvb, n, 4, ENC_BIG_ENDIAN0x00000000, &num_nonsupported_options);
1347 n += 4;
1348 while (num_nonsupported_options > 0) {
1349 siz = tvb_strsize(tvb, n);
1350 proto_tree_add_item(tree, hf_nonsupported_option, tvb, n, siz, ENC_ASCII0x00000000);
1351 n += siz;
1352 num_nonsupported_options--;
1353 }
1354 break;
1355 }
1356}
1357
1358/* This function is called by tcp_dissect_pdus() to find the size of the
1359 message starting at tvb[offset]. */
1360static unsigned
1361pgsql_length(packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, void *data _U___attribute__((unused)))
1362{
1363 int n = 0;
1364 unsigned char type;
1365 unsigned length;
1366
1367 /* The length is either the four bytes after the type, or, if the
1368 type is 0, the first four bytes. */
1369 type = tvb_get_uint8(tvb, offset);
1370 if (type != '\0')
1371 n = 1;
1372 length = tvb_get_ntohl(tvb, offset+n);
1373 return length+n;
1374}
1375
1376/* This function is called by tcp_dissect_pdus() to find the size of the
1377 wrapped GSS-API message starting at tvb[offset] whe. */
1378static unsigned
1379pgsql_gssapi_length(packet_info *pinfo _U___attribute__((unused)), tvbuff_t *tvb, int offset, void *data _U___attribute__((unused)))
1380{
1381 /* The length of the GSS-API message is the first four bytes, and does
1382 * not include the 4 byte length (the gss_wrap). */
1383 return tvb_get_ntohl(tvb, offset) + 4;
1384}
1385
1386
1387/* This function is responsible for dissecting a single message. */
1388
1389static int
1390dissect_pgsql_msg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U___attribute__((unused)))
1391{
1392 proto_item *ti, *hidden_item;
1393 proto_tree *ptree;
1394 conversation_t *conversation;
1395 pgsql_conn_data_t *conn_data;
1396 pgsql_auth_state_t state;
1397
1398 int n;
1399 unsigned char type;
1400 const char *typestr;
1401 unsigned length;
1402 bool_Bool fe;
1403
1404 conversation = find_or_create_conversation(pinfo);
1405 conn_data = (pgsql_conn_data_t *)conversation_get_proto_data(conversation, proto_pgsql);
1406 if (!conn_data) {
1407 conn_data = wmem_new(wmem_file_scope(), pgsql_conn_data_t)((pgsql_conn_data_t*)wmem_alloc((wmem_file_scope()), sizeof(pgsql_conn_data_t
)))
;
1408 conn_data->state_tree = wmem_tree_new(wmem_file_scope());
1409 conn_data->server_port = pinfo->match_uint;
1410 conn_data->streamed_txn = false0;
1411 wmem_tree_insert32(conn_data->state_tree, pinfo->num, GUINT_TO_POINTER(PGSQL_AUTH_STATE_NONE)((gpointer) (gulong) (PGSQL_AUTH_STATE_NONE)));
1412 conversation_add_proto_data(conversation, proto_pgsql, conn_data);
1413 }
1414
1415 fe = (conn_data->server_port == pinfo->destport);
1416
1417 n = 0;
1418 type = tvb_get_uint8(tvb, 0);
1419 if (type != '\0')
1420 n += 1;
1421 length = tvb_get_ntohl(tvb, n);
1422
1423 /* This is like specifying VALS(messages) for hf_type, which we can't do
1424 directly because of messages without type bytes, and because the type
1425 interpretation depends on fe. */
1426 if (fe) {
1427 /* There are a few frontend messages that have no leading type byte.
1428 We identify them by the fact that the first byte of their length
1429 must be zero, and that the next four bytes are a unique tag. */
1430 if (type == '\0') {
1431 unsigned tag = tvb_get_ntohl(tvb, 4);
1432
1433 if (length == 16 && tag == PGSQL_CANCELREQUEST80877102)
1434 typestr = "Cancel request";
1435 else if (length == 8 && tag == PGSQL_SSLREQUEST80877103)
1436 typestr = "SSL request";
1437 else if (length == 8 && tag == PGSQL_GSSENCREQUEST80877104)
1438 typestr = "GSS encrypt request";
1439 else if (tag == 196608)
1440 typestr = "Startup message";
1441 else
1442 typestr = "Unknown";
1443 } else if (type == 'p') {
1444 state = GPOINTER_TO_UINT(wmem_tree_lookup32_le(conn_data->state_tree, pinfo->num))((guint) (gulong) (wmem_tree_lookup32_le(conn_data->state_tree
, pinfo->num)))
;
1445 switch (state) {
1446 case PGSQL_AUTH_SASL_REQUESTED:
1447 typestr = "SASLInitialResponse message";
1448 break;
1449 case PGSQL_AUTH_SASL_CONTINUE:
1450 typestr = "SASLResponse message";
1451 break;
1452 case PGSQL_AUTH_GSSAPI_SSPI_DATA:
1453 typestr = "GSSResponse message";
1454 break;
1455 default:
1456 typestr = "Password message";
1457 break;
1458 }
1459 } else
1460 typestr = val_to_str_const(type, fe_messages, "Unknown");
1461 }
1462 else {
1463 typestr = val_to_str_const(type, be_messages, "Unknown");
1464 }
1465
1466 /* This is a terrible hack. It makes the "Info" column reflect
1467 the contents of every message in a TCP packet. Could it be
1468 done any better? */
1469 col_append_fstr(pinfo->cinfo, COL_INFO, "%s%c",
1470 ( first_message ? "" : "/" ), g_ascii_isprint(type)((g_ascii_table[(guchar) (type)] & G_ASCII_PRINT) != 0) ? type : '?');
1471 first_message = false0;
1472
1473 {
1474 ti = proto_tree_add_item(tree, proto_pgsql, tvb, 0, -1, ENC_NA0x00000000);
1475 ptree = proto_item_add_subtree(ti, ett_pgsql);
1476
1477 n = 1;
1478 if (type == '\0')
1479 n = 0;
1480 proto_tree_add_string(ptree, hf_type, tvb, 0, n, typestr);
1481 proto_tree_add_item(ptree, hf_length, tvb, n, 4, ENC_BIG_ENDIAN0x00000000);
1482 hidden_item = proto_tree_add_boolean(ptree, hf_frontend, tvb, 0, 0, fe);
1483 proto_item_set_hidden(hidden_item);
1484 n += 4;
1485
1486 if (fe)
1487 dissect_pgsql_fe_msg(type, length, tvb, n, ptree, pinfo, conn_data);
1488 else
1489 dissect_pgsql_be_msg(type, length, tvb, n, ptree, pinfo, conn_data);
1490 }
1491
1492 return tvb_captured_length(tvb);
1493}
1494
1495static int
1496dissect_pgsql_gssapi_wrap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1497{
1498 proto_item *ti;
1499 proto_tree *ptree;
1500
1501 conversation_t *conversation;
1502 pgsql_conn_data_t *conn_data;
1503
1504 conversation = find_or_create_conversation(pinfo);
1505 conn_data = (pgsql_conn_data_t *)conversation_get_proto_data(conversation, proto_pgsql);
1506
1507 if (!conn_data) {
1508 /* This shouldn't happen. */
1509 conn_data = wmem_new0(wmem_file_scope(), pgsql_conn_data_t)((pgsql_conn_data_t*)wmem_alloc0((wmem_file_scope()), sizeof(
pgsql_conn_data_t)))
;
1510 conn_data->state_tree = wmem_tree_new(wmem_file_scope());
1511 conn_data->server_port = pinfo->match_uint;
1512 wmem_tree_insert32(conn_data->state_tree, pinfo->num, GUINT_TO_POINTER(PGSQL_AUTH_GSSAPI_SSPI_DATA)((gpointer) (gulong) (PGSQL_AUTH_GSSAPI_SSPI_DATA)));
1513 conversation_add_proto_data(conversation, proto_pgsql, conn_data);
1514 }
1515
1516 bool_Bool fe = (pinfo->destport == conn_data->server_port);
1517
1518 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PGSQL");
1519 col_set_str(pinfo->cinfo, COL_INFO,
1520 fe ? ">" : "<");
1521
1522 ti = proto_tree_add_item(tree, proto_pgsql, tvb, 0, -1, ENC_NA0x00000000);
1523 ptree = proto_item_add_subtree(ti, ett_pgsql);
1524
1525 proto_tree_add_string(ptree, hf_type, tvb, 0, 0, "GSS-API encrypted message");
1526 proto_tree_add_item(ptree, hf_length, tvb, 0, 4, ENC_BIG_ENDIAN0x00000000);
1527
1528 gssapi_encrypt_info_t encrypt;
1529 memset(&encrypt, 0, sizeof(encrypt));
1530 encrypt.decrypt_gssapi_tvb = DECRYPT_GSSAPI_NORMAL1;
1531
1532 int ver_len;
1533 tvbuff_t *gssapi_tvb = tvb_new_subset_remaining(tvb, 4);
1534
1535 ver_len = call_dissector_with_data(gssapi_handle, gssapi_tvb, pinfo, ptree, &encrypt);
1536 if (ver_len == 0) {
1537 /* GSS-API couldn't do anything with it. */
1538 return tvb_captured_length(tvb);
1539 }
1540 if (encrypt.gssapi_data_encrypted) {
1541 if (encrypt.gssapi_decrypted_tvb) {
1542 tvbuff_t *decr_tvb = encrypt.gssapi_decrypted_tvb;
1543 add_new_data_source(pinfo, encrypt.gssapi_decrypted_tvb, "Decrypted GSS-API");
1544 dissect_pgsql_msg(decr_tvb, pinfo, ptree, data);
1545 } else {
1546 /* Encrypted but couldn't be decrypted. */
1547 proto_tree_add_item(ptree, hf_gssapi_encrypted_payload, gssapi_tvb, ver_len, -1, ENC_NA0x00000000);
1548 }
1549 } else {
1550 /* No encrypted (sealed) payload. If any bytes are left, that is
1551 * signed-only payload. */
1552 tvbuff_t *plain_tvb;
1553 if (encrypt.gssapi_decrypted_tvb) {
1554 plain_tvb = encrypt.gssapi_decrypted_tvb;
1555 } else {
1556 plain_tvb = tvb_new_subset_remaining(gssapi_tvb, ver_len);
1557 }
1558 if (tvb_reported_length(plain_tvb)) {
1559 dissect_pgsql_msg(plain_tvb, pinfo, ptree, data);
1560 }
1561 }
1562 return tvb_captured_length(tvb);
1563}
1564
1565static int
1566dissect_pgsql_gssapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1567{
1568 tcp_dissect_pdus(tvb, pinfo, tree, pgsql_desegment, 4,
1569 pgsql_gssapi_length, dissect_pgsql_gssapi_wrap, data);
1570 return tvb_captured_length(tvb);
1571}
1572
1573/* This function is called once per TCP packet. It sets COL_PROTOCOL and
1574 * identifies FE/BE messages by adding a ">" or "<" to COL_INFO. Then it
1575 * arranges for each message to be dissected individually. */
1576
1577static int
1578dissect_pgsql(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
1579{
1580 proto_item *ti;
1581 proto_tree *ptree;
1582 conversation_t *conversation;
1583 pgsql_conn_data_t *conn_data;
1584 pgsql_auth_state_t state;
1585
1586 first_message = true1;
1587
1588 conversation = find_or_create_conversation(pinfo);
1589 conn_data = (pgsql_conn_data_t *)conversation_get_proto_data(conversation, proto_pgsql);
1590
1591 bool_Bool fe = (pinfo->match_uint == pinfo->destport);
1592
1593 if (fe && tvb_get_uint8(tvb, 0) == 0x16 &&
1594 (!conn_data || wmem_tree_lookup32_le(conn_data->state_tree, pinfo->num) == NULL((void*)0)))
1595 {
1596 /* This is the first message in the conversation, and it looks
1597 * like a TLS handshake. Assume the client is performing
1598 * "direct SSL" negotiation.
1599 */
1600 tls_set_appdata_dissector(tls_handle, pinfo, pgsql_handle);
1601 }
1602
1603 if (!tvb_ascii_isprint(tvb, 0, 1) && tvb_get_uint8(tvb, 0) != '\0') {
1604 /* Doesn't look like the start of a PostgreSQL packet. Have we
1605 * seen Postgres yet?
1606 */
1607 if (!conn_data || wmem_tree_lookup32_le(conn_data->state_tree, pinfo->num) == NULL((void*)0)) {
1608 /* No. Reject. This might be PostgreSQL over TLS and we missed
1609 * the start of the transaction. The TLS dissector should get
1610 * a chance.
1611 */
1612 return 0;
1613 }
1614 /* Was there segmentation, and we lost a packet or were out of
1615 * order without out of order processing, or we couldn't do
1616 * desegmentation of a segment because of a bad checksum?
1617 * XXX: Should we call this Continuation Data if this happens,
1618 * so we don't send it to tcp_dissect_pdus()?
1619 */
1620 }
1621
1622 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PGSQL");
1623 col_set_str(pinfo->cinfo, COL_INFO,
1624 fe ? ">" : "<");
1625
1626 if (conn_data && !fe) {
1627 state = GPOINTER_TO_UINT(wmem_tree_lookup32_le(conn_data->state_tree, pinfo->num))((guint) (gulong) (wmem_tree_lookup32_le(conn_data->state_tree
, pinfo->num)))
;
1628 if (state == PGSQL_AUTH_SSL_REQUESTED) {
1629 /* Response to SSLRequest. */
1630 wmem_tree_insert32(conn_data->state_tree, pinfo->num + 1, GUINT_TO_POINTER(PGSQL_AUTH_STATE_NONE)((gpointer) (gulong) (PGSQL_AUTH_STATE_NONE)));
1631 ti = proto_tree_add_item(tree, proto_pgsql, tvb, 0, -1, ENC_NA0x00000000);
1632 ptree = proto_item_add_subtree(ti, ett_pgsql);
1633 proto_tree_add_string(ptree, hf_type, tvb, 0, 0, "SSL response");
1634 proto_tree_add_item(ptree, hf_ssl_response, tvb, 0, 1, ENC_ASCII0x00000000);
1635 switch (tvb_get_uint8(tvb, 0)) {
1636 case 'S': /* Willing to perform SSL */
1637 /* Next packet will start using SSL. */
1638 ssl_starttls_ack(tls_handle, pinfo, pgsql_handle);
1639 break;
1640 case 'E': /* ErrorResponse when server does not support SSL. */
1641 /* Process normally. */
1642 tcp_dissect_pdus(tvb, pinfo, tree, pgsql_desegment, 5,
1643 pgsql_length, dissect_pgsql_msg, data);
1644 break;
1645 case 'N': /* Unwilling to perform SSL */
1646 default: /* Unexpected response. */
1647 /* TODO: maybe add expert info here? */
1648 break;
1649 }
1650 /* XXX: If it's anything other than 'E', a length of more
1651 * than one character is unexpected and should possibly have
1652 * an expert info (possible MitM:
1653 * https://www.postgresql.org/support/security/CVE-2021-23222/ )
1654 */
1655 return tvb_captured_length(tvb);
1656 } else if (state == PGSQL_AUTH_GSSENC_REQUESTED) {
1657 /* Response to GSSENCRequest. */
1658 wmem_tree_insert32(conn_data->state_tree, pinfo->num + 1, GUINT_TO_POINTER(PGSQL_AUTH_STATE_NONE)((gpointer) (gulong) (PGSQL_AUTH_STATE_NONE)));
1659 ti = proto_tree_add_item(tree, proto_pgsql, tvb, 0, -1, ENC_NA0x00000000);
1660 ptree = proto_item_add_subtree(ti, ett_pgsql);
1661 proto_tree_add_string(ptree, hf_type, tvb, 0, 0, "GSS encrypt response");
1662 proto_tree_add_item(ptree, hf_gssenc_response, tvb, 0, 1, ENC_ASCII0x00000000);
1663 switch (tvb_get_uint8(tvb, 0)) {
1664 case 'E': /* ErrorResponse; server does not support GSSAPI. */
1665 /* Process normally. */
1666 tcp_dissect_pdus(tvb, pinfo, tree, pgsql_desegment, 5,
1667 pgsql_length, dissect_pgsql_msg, data);
1668 break;
1669 case 'G': /* Willing to perform GSSAPI Enc */
1670 wmem_tree_insert32(conn_data->state_tree, pinfo->num + 1, GUINT_TO_POINTER(PGSQL_AUTH_GSSAPI_SSPI_DATA)((gpointer) (gulong) (PGSQL_AUTH_GSSAPI_SSPI_DATA)));
1671 conversation_set_dissector_from_frame_number(conversation, pinfo->num + 1, pgsql_gssapi_handle);
1672 break;
1673 case 'N': /* Unwilling to perform GSSAPI Enc */
1674 default: /* Unexpected response. */
1675 /* TODO: maybe add expert info here? */
1676 break;
1677 }
1678 return tvb_captured_length(tvb);
1679 }
1680 }
1681
1682 tcp_dissect_pdus(tvb, pinfo, tree, pgsql_desegment, 5,
1683 pgsql_length, dissect_pgsql_msg, data);
1684 return tvb_captured_length(tvb);
1685}
1686
1687void
1688proto_register_pgsql(void)
1689{
1690 static hf_register_info hf[] = {
1691 { &hf_frontend,
1692 { "Frontend", "pgsql.frontend", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x0,
1693 "True for messages from the frontend, false otherwise.",
1694 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1695 },
1696 { &hf_type,
1697 { "Type", "pgsql.type", FT_STRING, BASE_NONE, NULL((void*)0), 0,
1698 "A one-byte message type identifier.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1699 },
1700 { &hf_length,
1701 { "Length", "pgsql.length", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1702 "The length of the message (not including the type).",
1703 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1704 },
1705 { &hf_version_major,
1706 { "Protocol major version", "pgsql.version_major", FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1707 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1708 },
1709 { &hf_version_minor,
1710 { "Protocol minor version", "pgsql.version_minor", FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1711 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1712 },
1713 { &hf_request_code,
1714 { "Request code", "pgsql.request_code", FT_UINT32, BASE_DEC,
1715 VALS(request_code_vals)((0 ? (const struct _value_string*)0 : ((request_code_vals)))
)
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1716 },
1717 { &hf_supported_minor_version,
1718 { "Supported minor version", "pgsql.version_supported_minor", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1719 "Newest minor protocol version supported by the server for the major protocol version requested by the client.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1720 },
1721 { &hf_number_nonsupported_options,
1722 { "Number nonsupported options", "pgsql.number_nonsupported_options", FT_INT32, BASE_DEC, NULL((void*)0), 0,
1723 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1724 },
1725 { &hf_nonsupported_option,
1726 { "Nonsupported option", "pgsql.nonsupported_option", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1727 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1728 },
1729 { &hf_parameter_name,
1730 { "Parameter name", "pgsql.parameter_name", FT_STRINGZ,
1731 BASE_NONE, NULL((void*)0), 0, "The name of a database parameter.",
1732 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1733 },
1734 { &hf_parameter_value,
1735 { "Parameter value", "pgsql.parameter_value", FT_STRINGZ,
1736 BASE_NONE, NULL((void*)0), 0, "The value of a database parameter.",
1737 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1738 },
1739 { &hf_query,
1740 { "Query", "pgsql.query", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1741 "A query string.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1742 },
1743 { &hf_passwd,
1744 { "Password", "pgsql.password", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1745 "A password.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1746 },
1747 { &hf_authtype,
1748 { "Authentication type", "pgsql.authtype", FT_UINT32, BASE_DEC,
1749 VALS(auth_types)((0 ? (const struct _value_string*)0 : ((auth_types)))), 0,
1750 "The type of authentication requested by the backend.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1751 },
1752 { &hf_salt,
1753 { "Salt value", "pgsql.salt", FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1754 "The salt to use while encrypting a password.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1755 },
1756 { &hf_gssapi_sspi_data,
1757 { "GSSAPI or SSPI authentication data", "pgsql.auth.gssapi_sspi.data", FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1758 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1759 },
1760 { &hf_sasl_auth_mech,
1761 { "SASL authentication mechanism", "pgsql.auth.sasl.mech", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1762 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1763 },
1764 { &hf_sasl_auth_data_length,
1765 { "SASL authentication data length", "pgsql.auth.sasl.data.length", FT_INT32, BASE_DEC, NULL((void*)0), 0,
1766 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1767 },
1768 { &hf_sasl_auth_data,
1769 { "SASL authentication data", "pgsql.auth.sasl.data", FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1770 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1771 },
1772 { &hf_statement,
1773 { "Statement", "pgsql.statement", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1774 "The name of a prepared statement.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1775 },
1776 { &hf_portal,
1777 { "Portal", "pgsql.portal", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1778 "The name of a portal.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1779 },
1780 { &hf_return,
1781 { "Returns", "pgsql.returns", FT_UINT32, BASE_DEC,
1782 NULL((void*)0), 0,
1783 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1784 },
1785 { &hf_tag,
1786 { "Tag", "pgsql.tag", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1787 "A completion tag.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1788 },
1789 { &hf_status,
1790 { "Status", "pgsql.status", FT_UINT8, BASE_DEC, VALS(status_vals)((0 ? (const struct _value_string*)0 : ((status_vals)))),
1791 0, "The transaction status of the backend.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1792 },
1793 { &hf_copydata,
1794 { "Copy data", "pgsql.copydata", FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1795 "Data sent following a Copy-in or Copy-out response.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1796 },
1797 { &hf_copydata_type,
1798 { "Copy data type", "pgsql.copydata_type", FT_STRING, BASE_NONE, NULL((void*)0), 0,
1799 "A one-byte message type identifier for Copy data.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1800 },
1801 { &hf_xlogdata,
1802 { "XLog data", "pgsql.xlogdata", FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1803 "XLog data.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1804 },
1805 { &hf_error,
1806 { "Error", "pgsql.error", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1807 "An error message.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1808 },
1809 { &hf_pid,
1810 { "PID", "pgsql.pid", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1811 "The process ID of a backend.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1812 },
1813 { &hf_key,
1814 { "Key", "pgsql.key", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1815 "The secret key used by a particular backend.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1816 },
1817 { &hf_condition,
1818 { "Condition", "pgsql.condition", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1819 "The name of a NOTIFY condition.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1820 },
1821 { &hf_text,
1822 { "Text", "pgsql.text", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1823 "Text from the backend.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1824 },
1825 { &hf_tableoid,
1826 { "Table OID", "pgsql.oid.table", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1827 "The object identifier of a table.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1828 },
1829 { &hf_typeoid,
1830 { "Type OID", "pgsql.oid.type", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1831 "The object identifier of a type.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1832 },
1833 { &hf_oid,
1834 { "OID", "pgsql.oid", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1835 "An object identifier.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1836 },
1837 { &hf_format,
1838 { "Format", "pgsql.format", FT_UINT16, BASE_DEC, VALS(format_vals)((0 ? (const struct _value_string*)0 : ((format_vals)))),
1839 0, "A format specifier.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1840 },
1841 { &hf_field_count,
1842 { "Field count", "pgsql.field.count", FT_UINT16, BASE_DEC, NULL((void*)0), 0,
1843 "The number of fields within a row.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1844 },
1845 { &hf_val_name,
1846 { "Column name", "pgsql.col.name", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1847 "The name of a column.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1848 },
1849 { &hf_val_idx,
1850 { "Column index", "pgsql.col.index", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1851 "The position of a column within a row.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1852 },
1853 { &hf_val_length,
1854 { "Column length", "pgsql.val.length", FT_INT32, BASE_DEC, NULL((void*)0), 0,
1855 "The length of a parameter value, in bytes. -1 means NULL.",
1856 HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1857 },
1858 { &hf_val_data,
1859 { "Data", "pgsql.val.data", FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1860 "Parameter data.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1861 },
1862 { &hf_val_text_data,
1863 { "Text data", "pgsql.val.text_data", FT_STRING, BASE_NONE, NULL((void*)0), 0,
1864 "Text data.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1865 },
1866 { &hf_val_mod,
1867 { "Type modifier", "pgsql.col.typemod", FT_INT32, BASE_DEC, NULL((void*)0), 0,
1868 "The type modifier for a column.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1869 },
1870 { &hf_severity,
1871 { "Severity", "pgsql.severity", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1872 "Message severity.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1873 },
1874 { &hf_code,
1875 { "Code", "pgsql.code", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1876 "SQLState code.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1877 },
1878 { &hf_message,
1879 { "Message", "pgsql.message", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1880 "Error message.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1881 },
1882 { &hf_detail,
1883 { "Detail", "pgsql.detail", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1884 "Detailed error message.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1885 },
1886 { &hf_hint,
1887 { "Hint", "pgsql.hint", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1888 "A suggestion to resolve an error.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1889 },
1890 { &hf_position,
1891 { "Position", "pgsql.position", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1892 "The index of the error within the query string.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1893 },
1894 { &hf_internal_position,
1895 { "Position (Internal)", "pgsql.internal_position", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1896 "The index of the error within the internally-generated query string.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1897 },
1898 { &hf_internal_query,
1899 { "Query (Internal)", "pgsql.internal_query", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1900 "The internally-generated query string", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1901 },
1902 { &hf_where,
1903 { "Context", "pgsql.where", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1904 "The context in which an error occurred.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1905 },
1906 { &hf_schema_name,
1907 { "Schema", "pgsql.schema_name", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1908 "The schema with which an error is associated.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1909 },
1910 { &hf_table_name,
1911 { "Table", "pgsql.table_name", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1912 "The table with which an error is associated.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1913 },
1914 { &hf_column_name,
1915 { "Column", "pgsql.column_name", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1916 "The column with which an error is associated.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1917 },
1918 { &hf_type_name,
1919 { "Type", "pgsql.type_name", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1920 "The date type with which an error is associated.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1921 },
1922 { &hf_constraint_name,
1923 { "Constraint", "pgsql.constraint_name", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1924 "The constraint with which an error is associated.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1925 },
1926 { &hf_file,
1927 { "File", "pgsql.file", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1928 "The source-code file where an error was reported.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1929 },
1930 { &hf_line,
1931 { "Line", "pgsql.line", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1932 "The line number on which an error was reported.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1933 },
1934 { &hf_routine,
1935 { "Routine", "pgsql.routine", FT_STRINGZ, BASE_NONE, NULL((void*)0), 0,
1936 "The routine that reported an error.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1937 },
1938 { &hf_ssl_response,
1939 { "SSL Response", "pgsql.ssl_response", FT_CHAR, BASE_HEX,
1940 VALS(ssl_response_vals)((0 ? (const struct _value_string*)0 : ((ssl_response_vals)))
)
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1941 },
1942 { &hf_gssenc_response,
1943 { "GSSAPI Encrypt Response", "pgsql.gssenc_response", FT_CHAR,
1944 BASE_HEX, VALS(gssenc_response_vals)((0 ? (const struct _value_string*)0 : ((gssenc_response_vals
))))
, 0, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1945 },
1946 { &hf_gssapi_encrypted_payload,
1947 { "GSS-API encrypted payload", "pgsql.gssapi.encrypted_payload", FT_BYTES, BASE_NONE, NULL((void*)0), 0,
1948 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1949 },
1950 { &hf_standby_clock_ts,
1951 { "Server time", "pgsql.xlog_ts", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL((void*)0), 0,
1952 "The server's system clock at the time of transmission.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1953 },
1954 { &hf_xid,
1955 { "Transaction id", "pgsql.xid", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1956 "Xid of the transaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1957 },
1958 { &hf_xid_subtransaction,
1959 { "Subtransaction id", "pgsql.xid_subtransaction", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
1960 "Xid of the subtransaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1961 },
1962 { &hf_custom_type_name,
1963 { "Type name", "pgsql.custom_type_name", FT_STRING, BASE_NONE, NULL((void*)0), 0,
1964 "Name of the data type.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1965 },
1966 { &hf_namespace,
1967 { "Namespace", "pgsql.namespace", FT_STRING, BASE_NONE, NULL((void*)0), 0,
1968 "Namespace (empty string for pg_catalog).", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1969 },
1970 { &hf_relation_name,
1971 { "Relation name", "pgsql.relation", FT_STRING, BASE_NONE, NULL((void*)0), 0,
1972 "Relation name.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1973 },
1974 { &hf_tuple_type,
1975 { "Tuple type", "pgsql.tuple_type", FT_STRING, BASE_NONE, NULL((void*)0), 0,
1976 "Tuple type.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1977 },
1978 { &hf_tuple_data_type,
1979 { "Tuple data type", "pgsql.tuple_data_type", FT_STRING, BASE_NONE, NULL((void*)0), 0,
1980 "Tuple data type.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1981 },
1982 { &hf_xlog_wal_start,
1983 { "WAL start", "pgsql.xlog_wal_start", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
1984 "The starting point of the WAL data in this message.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1985 },
1986 { &hf_xlog_wal_end,
1987 { "WAL end", "pgsql.xlog_wal_end", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
1988 "The current end of WAL on the server.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1989 },
1990 { &hf_standby_last_wal_written,
1991 { "Last WAL written", "pgsql.standby.last_wal_written", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
1992 "The location of the last WAL byte + 1 received and written to disk in the standby.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1993 },
1994 { &hf_standby_last_wal_flushed,
1995 { "Last WAL flushed", "pgsql.standby.last_wal_flushed", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
1996 "The location of the last WAL byte + 1 flushed to disk in the standby.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
1997 },
1998 { &hf_standby_last_wal_applied,
1999 { "Last WAL applied", "pgsql.standby.last_wal_applied", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
2000 "The location of the last WAL byte + 1 applied in the standby.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2001 },
2002 { &hf_standby_immediate_ack,
2003 { "Immediate ack", "pgsql.standby.immediate_ack", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0,
2004 "If true, except a reply as soon as possible. 0 otherwise.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2005 },
2006 { &hf_standby_xmin,
2007 { "xmin", "pgsql.standby.xmin", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
2008 "The standby's current global xmin, excluding the catalog_xmin from any replication slots. If both this value and the following catalog_xmin are 0, this is treated as a notification that hot standby feedback will no longer be sent on this connection. Later non-zero messages may reinitiate the feedback mechanism.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2009 },
2010 { &hf_standby_xmin_epoch,
2011 { "xmin epoch", "pgsql.standby.xmin_epoch", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
2012 "The epoch of the global xmin xid on the standby.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2013 },
2014 { &hf_standby_catalog_xmin,
2015 { "catalog xmin", "pgsql.standby.catalog_xmin", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
2016 "The lowest catalog_xmin of any replication slots on the standby. Set to 0 if no catalog_xmin exists on the standby or if hot standby feedback is being disabled.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2017 },
2018 { &hf_standby_catalog_xmin_epoch,
2019 { "catalog xmin epoch", "pgsql.standby.catalog_xmin_epoch", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
2020 "The epoch of the catalog_xmin xid on the standby.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2021 },
2022 { &hf_logical_msg_type,
2023 { "Logical message type", "pgsql.logical.msg_type", FT_STRING, BASE_NONE, NULL((void*)0), 0,
2024 "A one-byte message type identifier for logical message.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2025 },
2026 { &hf_logical_replica_identity,
2027 { "Replica identity", "pgsql.logical.replica_identity", FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2028 "Replica identity setting for the relation (same as relreplident in pg_class).", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2029 },
2030 { &hf_logical_number_columns,
2031 { "Number columns", "pgsql.logical.number_columns", FT_UINT16, BASE_DEC, NULL((void*)0), 0,
2032 "Number of columns.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2033 },
2034 { &hf_logical_column_length,
2035 { "Length column", "pgsql.logical.column_length", FT_INT32, BASE_DEC, NULL((void*)0), 0,
2036 "Length of the column value.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2037 },
2038 { &hf_logical_column_flags,
2039 { "Column flags", "pgsql.logical.column_flags", FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2040 "Flags for the column. Currently can be either 0 for no flags or 1 which marks the column as part of the key.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2041 },
2042 { &hf_logical_column_name,
2043 { "Column name", "pgsql.logical.column_name", FT_STRING, BASE_NONE, NULL((void*)0), 0,
2044 "Name of the column.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2045 },
2046 { &hf_logical_column_oid,
2047 { "Column OID", "pgsql.logical.column_oid", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
2048 "OID of the column's data type.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2049 },
2050 { &hf_logical_column_type_modifier,
2051 { "Type modifier", "pgsql.logical.type_modifier", FT_INT32, BASE_DEC, NULL((void*)0), 0,
2052 "Type modifier of the column (atttypmod).", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2053 },
2054 { &hf_relation_oid,
2055 { "Relation OID", "pgsql.relation_oid", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
2056 "OID of the relation.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2057 },
2058 { &hf_logical_lsn_final,
2059 { "LSN transaction", "pgsql.logical.lsn", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
2060 "The final LSN of the transaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2061 },
2062 { &hf_logical_prepare_flags,
2063 { "Prepare flags", "pgsql.logical.prepare.flags", FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2064 "Prepare Flags. Currently unused.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2065 },
2066 { &hf_logical_prepare_gid,
2067 { "Prepare GID", "pgsql.logical.prepare.gid", FT_STRING, BASE_NONE, NULL((void*)0), 0,
2068 "The user defined GID of the prepared transaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2069 },
2070 { &hf_logical_prepare_lsn,
2071 { "LSN prepare", "pgsql.logical.prepare.lsn", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
2072 "The LSN of the prepare.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2073 },
2074 { &hf_logical_prepare_lsn_end,
2075 { "LSN prepare end", "pgsql.logical.prepare.lsn_end", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
2076 "The end LSN of the prepared transaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2077 },
2078 { &hf_logical_prepare_lsn_rollback,
2079 { "LSN rollback prepare end", "pgsql.logical.prepare.rollback_lsn_end", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
2080 "The end LSN of the rollback of the prepared transaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2081 },
2082 { &hf_logical_commit_ts,
2083 { "Commit timestamp", "pgsql.logical.commit_ts", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL((void*)0), 0,
2084 "Commit timestamp of the transaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2085 },
2086 { &hf_logical_prepare_ts,
2087 { "Prepare timestamp", "pgsql.logical.prepare.ts", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL((void*)0), 0,
2088 "Prepare timestamp of the transaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2089 },
2090 { &hf_logical_prepare_commit_ts,
2091 { "Commit timestamp", "pgsql.logical.prepare.commit_ts", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL((void*)0), 0,
2092 "Commit timestamp of the transaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2093 },
2094 { &hf_logical_prepare_rollback_ts,
2095 { "Rollback timestamp", "pgsql.logical.prepare.rollback_ts", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL((void*)0), 0,
2096 "Rollback timestamp of the transaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2097 },
2098 { &hf_logical_relation_number,
2099 { "Number relations", "pgsql.logical.relation_number", FT_UINT32, BASE_DEC, NULL((void*)0), 0,
2100 "Number of relations.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2101 },
2102 { &hf_logical_truncate_flags,
2103 { "Truncate flags", "pgsql.logical.truncate_flags", FT_INT8, BASE_DEC, NULL((void*)0), 0,
2104 "Truncate Flags. 1 for CASCADE, 2 for RESTART IDENTITY.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2105 },
2106 { &hf_logical_commit_flags,
2107 { "Commit flags", "pgsql.logical.commit_flags", FT_INT8, BASE_DEC, NULL((void*)0), 0,
2108 "Commit Flags. Currently unused.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2109 },
2110 { &hf_logical_lsn_commit,
2111 { "Commit LSN", "pgsql.logical.lsn_commit", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
2112 "The LSN of the commit.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2113 },
2114 { &hf_logical_lsn_transaction,
2115 { "Transaction LSN", "pgsql.logical.lsn_transaction", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
2116 "The end LSN of the transaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2117 },
2118 { &hf_logical_lsn_origin,
2119 { "Origin LSN", "pgsql.logical.lsn_origin", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
2120 "The LSN of the commit on the origin server.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2121 },
2122 { &hf_logical_lsn_abort,
2123 { "Abort LSN", "pgsql.logical.lsn_abort", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
2124 "The LSN of the abort.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2125 },
2126 { &hf_logical_message_flags,
2127 { "Message flags", "pgsql.logical.message.flags", FT_UINT8, BASE_DEC, NULL((void*)0), 0,
2128 "Message Flags. Either 0 for no flags or 1 if the logical decoding message is transactional.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2129 },
2130 { &hf_logical_message_lsn,
2131 { "LSN message", "pgsql.logical.message.lsn", FT_UINT64, BASE_HEX, NULL((void*)0), 0,
2132 "The LSN of the logical decoding message.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2133 },
2134 { &hf_logical_message_prefix,
2135 { "Message prefix", "pgsql.logical.message.prefix", FT_STRING, BASE_NONE, NULL((void*)0), 0,
2136 "The prefix of the logical decoding message.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2137 },
2138 { &hf_logical_message_content,
2139 { "Message content", "pgsql.logical.message.content", FT_STRING, BASE_NONE, NULL((void*)0), 0,
2140 "The content of the logical decoding message.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2141 },
2142 { &hf_logical_message_length,
2143 { "Message length", "pgsql.logical.message.length", FT_INT32, BASE_DEC, NULL((void*)0), 0,
2144 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2145 },
2146 { &hf_logical_stream_first_segment,
2147 { "First segment", "pgsql.logical.stream.first_segment", FT_INT8, BASE_DEC, NULL((void*)0), 0,
2148 "First segment.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2149 },
2150 { &hf_logical_stream_flags,
2151 { "Stream flags", "pgsql.logical.stream.flags", FT_INT8, BASE_DEC, NULL((void*)0), 0,
2152 "Stream flags. Currently Unused.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2153 },
2154 { &hf_logical_stream_abort_ts,
2155 { "Abort timestamp", "pgsql.logical.stream.abort_ts", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL((void*)0), 0,
2156 "Abort timestamp of the transaction.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2157 },
2158 { &hf_logical_origin_name,
2159 { "Origin name", "pgsql.logical.origin_name", FT_STRING, BASE_NONE, NULL((void*)0), 0,
2160 "Name of the origin.", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
2161 },
2162 };
2163
2164 static int *ett[] = {
2165 &ett_pgsql,
2166 &ett_values
2167 };
2168
2169 proto_pgsql = proto_register_protocol("PostgreSQL", "PGSQL", "pgsql");
2170 pgsql_handle = register_dissector("pgsql", dissect_pgsql, proto_pgsql);
2171 proto_register_field_array(proto_pgsql, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0]));
2172 proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0]));
2173
2174 /* Unfortunately there's no way to set up a GSS-API conversation
2175 * instructing the GSS-API dissector to use our wrap handle; that
2176 * only works for protocols that have an OID and that begin the
2177 * GSS-API conversation by sending that OID.
2178 */
2179 pgsql_gssapi_handle = register_dissector("pgsql.gssapi", dissect_pgsql_gssapi, proto_pgsql);
2180}
2181
2182void
2183proto_reg_handoff_pgsql(void)
2184{
2185 dissector_add_uint_with_preference("tcp.port", PGSQL_PORT5432, pgsql_handle);
2186
2187 tls_handle = find_dissector_add_dependency("tls", proto_pgsql);
2188 gssapi_handle = find_dissector_add_dependency("gssapi", proto_pgsql);
2189 ntlmssp_handle = find_dissector_add_dependency("ntlmssp", proto_pgsql);
2190}
2191
2192/*
2193 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2194 *
2195 * Local variables:
2196 * c-basic-offset: 4
2197 * tab-width: 8
2198 * indent-tabs-mode: nil
2199 * End:
2200 *
2201 * vi: set shiftwidth=4 tabstop=8 expandtab:
2202 * :indentSize=4:tabSize=8:noTabs=true:
2203 */