kafka: don't use an empty tvb list.
[gd/wireshark/.git] / epan / dissectors / packet-kafka.c
1 /* packet-kafka.c
2  * Routines for Apache Kafka Protocol dissection (version 0.8 - 2.3)
3  * Copyright 2013, Evan Huus <eapache@gmail.com>
4  * Update from Kafka 0.10.1.0 to 2.3 by Piotr Smolinski <piotr.smolinski@confluent.io>
5  *
6  * https://cwiki.apache.org/confluence/display/KAFKA/A+Guide+To+The+Kafka+Protocol
7  * https://kafka.apache.org/protocol.html
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * SPDX-License-Identifier: GPL-2.0-or-later
14  */
15
16 #include "config.h"
17
18 #include <epan/packet.h>
19 #include <epan/expert.h>
20 #include <epan/prefs.h>
21 #include <epan/proto_data.h>
22 #ifdef HAVE_SNAPPY
23 #include <snappy-c.h>
24 #endif
25 #ifdef HAVE_LZ4FRAME_H
26 #include <lz4.h>
27 #include <lz4frame.h>
28 #endif
29 #ifdef HAVE_ZSTD
30 #include <zstd.h>
31 #endif
32 #include "packet-tcp.h"
33 #include "packet-tls.h"
34
35 void proto_register_kafka(void);
36 void proto_reg_handoff_kafka(void);
37
38 static int proto_kafka = -1;
39 static dissector_handle_t kafka_handle;
40
41 static int hf_kafka_len = -1;
42 static int hf_kafka_api_key = -1;
43 static int hf_kafka_api_version = -1;
44 static int hf_kafka_request_api_key = -1;
45 static int hf_kafka_response_api_key = -1;
46 static int hf_kafka_request_api_version = -1;
47 static int hf_kafka_response_api_version = -1;
48 static int hf_kafka_correlation_id = -1;
49 static int hf_kafka_client_id = -1;
50 static int hf_kafka_client_host = -1;
51 static int hf_kafka_string_len = -1;
52 static int hf_kafka_bytes_len = -1;
53 static int hf_kafka_required_acks = -1;
54 static int hf_kafka_timeout = -1;
55 static int hf_kafka_topic_name = -1;
56 static int hf_kafka_transactional_id = -1;
57 static int hf_kafka_transaction_result = -1;
58 static int hf_kafka_transaction_timeout = -1;
59 static int hf_kafka_partition_id = -1;
60 static int hf_kafka_replica = -1;
61 static int hf_kafka_replication_factor = -1;
62 static int hf_kafka_isr = -1;
63 static int hf_kafka_offline = -1;
64 static int hf_kafka_last_stable_offset = -1;
65 static int hf_kafka_log_start_offset = -1;
66 static int hf_kafka_first_offset = -1;
67 static int hf_kafka_producer_id = -1;
68 static int hf_kafka_producer_epoch = -1;
69 static int hf_kafka_message_size = -1;
70 static int hf_kafka_message_crc = -1;
71 static int hf_kafka_message_magic = -1;
72 static int hf_kafka_message_codec = -1;
73 static int hf_kafka_message_timestamp_type = -1;
74 static int hf_kafka_message_timestamp = -1;
75 static int hf_kafka_batch_crc = -1;
76 static int hf_kafka_batch_codec = -1;
77 static int hf_kafka_batch_timestamp_type = -1;
78 static int hf_kafka_batch_transactional = -1;
79 static int hf_kafka_batch_control_batch = -1;
80 static int hf_kafka_batch_last_offset_delta = -1;
81 static int hf_kafka_batch_first_timestamp = -1;
82 static int hf_kafka_batch_last_timestamp = -1;
83 static int hf_kafka_batch_base_sequence = -1;
84 static int hf_kafka_batch_size = -1;
85 static int hf_kafka_message_key = -1;
86 static int hf_kafka_message_value = -1;
87 static int hf_kafka_message_compression_reduction = -1;
88 static int hf_kafka_request_frame = -1;
89 static int hf_kafka_response_frame = -1;
90 static int hf_kafka_consumer_group = -1;
91 static int hf_kafka_consumer_group_instance = -1;
92 static int hf_kafka_coordinator_key = -1;
93 static int hf_kafka_coordinator_type = -1;
94 static int hf_kafka_group_state = -1;
95 static int hf_kafka_offset = -1;
96 static int hf_kafka_offset_time = -1;
97 static int hf_kafka_max_offsets = -1;
98 static int hf_kafka_metadata = -1;
99 static int hf_kafka_error = -1;
100 static int hf_kafka_error_message = -1;
101 static int hf_kafka_broker_nodeid = -1;
102 static int hf_kafka_broker_epoch = -1;
103 static int hf_kafka_broker_host = -1;
104 static int hf_kafka_listener_name = -1;
105 static int hf_kafka_broker_port = -1;
106 static int hf_kafka_rack = -1;
107 static int hf_kafka_broker_security_protocol_type = -1;
108 static int hf_kafka_cluster_id = -1;
109 static int hf_kafka_controller_id = -1;
110 static int hf_kafka_controller_epoch = -1;
111 static int hf_kafka_delete_partitions = -1;
112 static int hf_kafka_leader_id = -1;
113 static int hf_kafka_group_leader_id = -1;
114 static int hf_kafka_leader_epoch = -1;
115 static int hf_kafka_current_leader_epoch = -1;
116 static int hf_kafka_is_internal = -1;
117 static int hf_kafka_isolation_level = -1;
118 static int hf_kafka_min_bytes = -1;
119 static int hf_kafka_max_bytes = -1;
120 static int hf_kafka_max_wait_time = -1;
121 static int hf_kafka_throttle_time = -1;
122 static int hf_kafka_api_versions_api_key = -1;
123 static int hf_kafka_api_versions_min_version = -1;
124 static int hf_kafka_api_versions_max_version = -1;
125 static int hf_kafka_session_timeout = -1;
126 static int hf_kafka_rebalance_timeout = -1;
127 static int hf_kafka_member_id = -1;
128 static int hf_kafka_protocol_type = -1;
129 static int hf_kafka_protocol_name = -1;
130 static int hf_kafka_protocol_metadata = -1;
131 static int hf_kafka_member_metadata = -1;
132 static int hf_kafka_generation_id = -1;
133 static int hf_kafka_member_assignment = -1;
134 static int hf_kafka_sasl_mechanism = -1;
135 static int hf_kafka_num_partitions = -1;
136 static int hf_kafka_zk_version = -1;
137 static int hf_kafka_config_key = -1;
138 static int hf_kafka_config_value = -1;
139 static int hf_kafka_commit_timestamp = -1;
140 static int hf_kafka_retention_time = -1;
141 static int hf_kafka_forgotten_topic_name = -1;
142 static int hf_kafka_forgotten_topic_partition = -1;
143 static int hf_kafka_fetch_session_id = -1;
144 static int hf_kafka_fetch_session_epoch = -1;
145 static int hf_kafka_record_header_key = -1;
146 static int hf_kafka_record_header_value = -1;
147 static int hf_kafka_record_attributes = -1;
148 static int hf_kafka_allow_auto_topic_creation = -1;
149 static int hf_kafka_validate_only = -1;
150 static int hf_kafka_coordinator_epoch = -1;
151 static int hf_kafka_sasl_auth_bytes = -1;
152 static int hf_kafka_session_lifetime_ms = -1;
153 static int hf_kafka_acl_resource_type = -1;
154 static int hf_kafka_acl_resource_name = -1;
155 static int hf_kafka_acl_resource_pattern_type = -1;
156 static int hf_kafka_acl_principal = -1;
157 static int hf_kafka_acl_host = -1;
158 static int hf_kafka_acl_operation = -1;
159 static int hf_kafka_acl_permission_type = -1;
160 static int hf_kafka_config_resource_type = -1;
161 static int hf_kafka_config_resource_name = -1;
162 static int hf_kafka_config_include_synonyms = -1;
163 static int hf_kafka_config_source = -1;
164 static int hf_kafka_config_readonly = -1;
165 static int hf_kafka_config_default = -1;
166 static int hf_kafka_config_sensitive = -1;
167 static int hf_kafka_config_operation = -1;
168 static int hf_kafka_log_dir = -1;
169 static int hf_kafka_segment_size = -1;
170 static int hf_kafka_offset_lag = -1;
171 static int hf_kafka_future = -1;
172 static int hf_kafka_partition_count = -1;
173 static int hf_kafka_token_max_life_time = -1;
174 static int hf_kafka_token_renew_time = -1;
175 static int hf_kafka_token_expiry_time = -1;
176 static int hf_kafka_token_principal_type = -1;
177 static int hf_kafka_token_principal_name = -1;
178 static int hf_kafka_token_issue_timestamp = -1;
179 static int hf_kafka_token_expiry_timestamp = -1;
180 static int hf_kafka_token_max_timestamp = -1;
181 static int hf_kafka_token_id = -1;
182 static int hf_kafka_token_hmac = -1;
183 static int hf_kafka_include_cluster_authorized_ops = -1;
184 static int hf_kafka_include_topic_authorized_ops = -1;
185 static int hf_kafka_include_group_authorized_ops = -1;
186 static int hf_kafka_cluster_authorized_ops = -1;
187 static int hf_kafka_topic_authorized_ops = -1;
188 static int hf_kafka_group_authorized_ops = -1;
189 static int hf_kafka_election_type = -1;
190
191 static int ett_kafka = -1;
192 static int ett_kafka_batch = -1;
193 static int ett_kafka_message = -1;
194 static int ett_kafka_message_set = -1;
195 static int ett_kafka_replicas = -1;
196 static int ett_kafka_isrs = -1;
197 static int ett_kafka_offline = -1;
198 static int ett_kafka_broker = -1;
199 static int ett_kafka_brokers = -1;
200 static int ett_kafka_broker_end_point = -1;
201 static int ett_kafka_markers = -1;
202 static int ett_kafka_marker = -1;
203 static int ett_kafka_topics = -1;
204 static int ett_kafka_topic = -1;
205 static int ett_kafka_partitions = -1;
206 static int ett_kafka_partition = -1;
207 static int ett_kafka_api_version = -1;
208 static int ett_kafka_group_protocols = -1;
209 static int ett_kafka_group_protocol = -1;
210 static int ett_kafka_group_members = -1;
211 static int ett_kafka_group_member = -1;
212 static int ett_kafka_group_assignments = -1;
213 static int ett_kafka_group_assignment = -1;
214 static int ett_kafka_groups = -1;
215 static int ett_kafka_group = -1;
216 static int ett_kafka_sasl_enabled_mechanisms = -1;
217 static int ett_kafka_replica_assignment = -1;
218 static int ett_kafka_configs = -1;
219 static int ett_kafka_config = -1;
220 static int ett_kafka_request_forgotten_topic = -1;
221 static int ett_kafka_record = -1;
222 static int ett_kafka_record_headers = -1;
223 static int ett_kafka_record_headers_header = -1;
224 static int ett_kafka_aborted_transactions = -1;
225 static int ett_kafka_aborted_transaction = -1;
226 static int ett_kafka_resources = -1;
227 static int ett_kafka_resource = -1;
228 static int ett_kafka_acls = -1;
229 static int ett_kafka_acl = -1;
230 static int ett_kafka_acl_creations = -1;
231 static int ett_kafka_acl_creation = -1;
232 static int ett_kafka_acl_filters = -1;
233 static int ett_kafka_acl_filter = -1;
234 static int ett_kafka_acl_filter_matches = -1;
235 static int ett_kafka_acl_filter_match = -1;
236 static int ett_kafka_config_synonyms = -1;
237 static int ett_kafka_config_synonym = -1;
238 static int ett_kafka_config_entries = -1;
239 static int ett_kafka_config_entry = -1;
240 static int ett_kafka_log_dirs = -1;
241 static int ett_kafka_log_dir = -1;
242 static int ett_kafka_renewers = -1;
243 static int ett_kafka_renewer = -1;
244 static int ett_kafka_owners = -1;
245 static int ett_kafka_owner = -1;
246 static int ett_kafka_tokens = -1;
247 static int ett_kafka_token = -1;
248
249 static expert_field ei_kafka_request_missing = EI_INIT;
250 static expert_field ei_kafka_unknown_api_key = EI_INIT;
251 static expert_field ei_kafka_unsupported_api_version = EI_INIT;
252 static expert_field ei_kafka_bad_string_length = EI_INIT;
253 static expert_field ei_kafka_bad_bytes_length = EI_INIT;
254 static expert_field ei_kafka_bad_array_length = EI_INIT;
255 static expert_field ei_kafka_bad_record_length = EI_INIT;
256 static expert_field ei_kafka_bad_varint = EI_INIT;
257 static expert_field ei_kafka_bad_message_set_length = EI_INIT;
258 static expert_field ei_kafka_unknown_message_magic = EI_INIT;
259
260 typedef gint16 kafka_api_key_t;
261 typedef gint16 kafka_api_version_t;
262 typedef gint16 kafka_error_t;
263 typedef gint32 kafka_partition_t;
264 typedef gint64 kafka_offset_t;
265
266 typedef struct _kafka_api_info_t {
267     kafka_api_key_t api_key;
268     const char *name;
269     /* If api key is not supported then set min_version and max_version to -1 */
270     kafka_api_version_t min_version;
271     kafka_api_version_t max_version;
272 } kafka_api_info_t;
273
274 #define KAFKA_TCP_DEFAULT_RANGE     "9092"
275
276 #define KAFKA_PRODUCE                        0
277 #define KAFKA_FETCH                          1
278 #define KAFKA_OFFSETS                        2
279 #define KAFKA_METADATA                       3
280 #define KAFKA_LEADER_AND_ISR                 4
281 #define KAFKA_STOP_REPLICA                   5
282 #define KAFKA_UPDATE_METADATA                6
283 #define KAFKA_CONTROLLED_SHUTDOWN            7
284 #define KAFKA_OFFSET_COMMIT                  8
285 #define KAFKA_OFFSET_FETCH                   9
286 #define KAFKA_FIND_COORDINATOR              10
287 #define KAFKA_JOIN_GROUP                    11
288 #define KAFKA_HEARTBEAT                     12
289 #define KAFKA_LEAVE_GROUP                   13
290 #define KAFKA_SYNC_GROUP                    14
291 #define KAFKA_DESCRIBE_GROUPS               15
292 #define KAFKA_LIST_GROUPS                   16
293 #define KAFKA_SASL_HANDSHAKE                17
294 #define KAFKA_API_VERSIONS                  18
295 #define KAFKA_CREATE_TOPICS                 19
296 #define KAFKA_DELETE_TOPICS                 20
297 #define KAFKA_DELETE_RECORDS                21
298 #define KAFKA_INIT_PRODUCER_ID              22
299 #define KAFKA_OFFSET_FOR_LEADER_EPOCH       23
300 #define KAFKA_ADD_PARTITIONS_TO_TXN         24
301 #define KAFKA_ADD_OFFSETS_TO_TXN            25
302 #define KAFKA_END_TXN                       26
303 #define KAFKA_WRITE_TXN_MARKERS             27
304 #define KAFKA_TXN_OFFSET_COMMIT             28
305 #define KAFKA_DESCRIBE_ACLS                 29
306 #define KAFKA_CREATE_ACLS                   30
307 #define KAFKA_DELETE_ACLS                   31
308 #define KAFKA_DESCRIBE_CONFIGS              32
309 #define KAFKA_ALTER_CONFIGS                 33
310 #define KAFKA_ALTER_REPLICA_LOG_DIRS        34
311 #define KAFKA_DESCRIBE_LOG_DIRS             35
312 #define KAFKA_SASL_AUTHENTICATE             36
313 #define KAFKA_CREATE_PARTITIONS             37
314 #define KAFKA_CREATE_DELEGATION_TOKEN       38
315 #define KAFKA_RENEW_DELEGATION_TOKEN        39
316 #define KAFKA_EXPIRE_DELEGATION_TOKEN       40
317 #define KAFKA_DESCRIBE_DELEGATION_TOKEN     41
318 #define KAFKA_DELETE_GROUPS                 42
319 #define KAFKA_ELECT_LEADERS                 43
320 #define KAFKA_INC_ALTER_CONFIGS             44
321 #define KAFKA_ALTER_PARTITION_REASSIGNMENTS 45
322 #define KAFKA_LIST_PARTITION_REASSIGNMENTS  46
323
324 /*
325  * Check for message changes here:
326  * https://github.com/apache/kafka/tree/trunk/clients/src/main/resources/common/message
327  */
328 static const kafka_api_info_t kafka_apis[] = {
329     { KAFKA_PRODUCE,                       "Produce",
330       0, 7 },
331     { KAFKA_FETCH,                         "Fetch",
332       0, 11 },
333     { KAFKA_OFFSETS,                       "Offsets",
334       0, 5 },
335     { KAFKA_METADATA,                      "Metadata",
336       0, 8 },
337     { KAFKA_LEADER_AND_ISR,                "LeaderAndIsr",
338       0, 3 },
339     { KAFKA_STOP_REPLICA,                  "StopReplica",
340       0, 1 },
341     { KAFKA_UPDATE_METADATA,               "UpdateMetadata",
342       0, 5 },
343     { KAFKA_CONTROLLED_SHUTDOWN,           "ControlledShutdown",
344       0, 2 },
345     { KAFKA_OFFSET_COMMIT,                 "OffsetCommit",
346       0, 7 },
347     { KAFKA_OFFSET_FETCH,                  "OffsetFetch",
348       0, 5 },
349     { KAFKA_FIND_COORDINATOR,              "FindCoordinator",
350       0, 2 },
351     { KAFKA_JOIN_GROUP,                    "JoinGroup",
352       0, 5 },
353     { KAFKA_HEARTBEAT,                     "Heartbeat",
354       0, 3 },
355     { KAFKA_LEAVE_GROUP,                   "LeaveGroup",
356       0, 3 },
357     { KAFKA_SYNC_GROUP,                    "SyncGroup",
358       0, 3 },
359     { KAFKA_DESCRIBE_GROUPS,               "DescribeGroups",
360       0, 4 },
361     { KAFKA_LIST_GROUPS,                   "ListGroups",
362       0, 2 },
363     { KAFKA_SASL_HANDSHAKE,                "SaslHandshake",
364       0, 1 },
365     { KAFKA_API_VERSIONS,                  "ApiVersions",
366       0, 2 },
367     { KAFKA_CREATE_TOPICS,                 "CreateTopics",
368       0, 4 },
369     { KAFKA_DELETE_TOPICS,                 "DeleteTopics",
370       0, 3 },
371     { KAFKA_DELETE_RECORDS,                "DeleteRecords",
372       0, 1 },
373     { KAFKA_INIT_PRODUCER_ID,              "InitProducerId",
374       0, 1 },
375     { KAFKA_OFFSET_FOR_LEADER_EPOCH,       "OffsetForLeaderEpoch",
376       0, 3 },
377     { KAFKA_ADD_PARTITIONS_TO_TXN,         "AddPartitionsToTxn",
378       0, 1 },
379     { KAFKA_ADD_OFFSETS_TO_TXN,            "AddOffsetsToTxn",
380       0, 1 },
381     { KAFKA_END_TXN,                       "EndTxn",
382       0, 1 },
383     { KAFKA_WRITE_TXN_MARKERS,             "WriteTxnMarkers",
384       0, 0 },
385     { KAFKA_TXN_OFFSET_COMMIT,             "TxnOffsetCommit",
386       0, 2 },
387     { KAFKA_DESCRIBE_ACLS,                 "DescribeAcls",
388       0, 1 },
389     { KAFKA_CREATE_ACLS,                   "CreateAcls",
390       0, 1 },
391     { KAFKA_DELETE_ACLS,                   "DeleteAcls",
392       0, 1 },
393     { KAFKA_DESCRIBE_CONFIGS,              "DescribeConfigs",
394       0, 2 },
395     { KAFKA_ALTER_CONFIGS,                 "AlterConfigs",
396       0, 1 },
397     { KAFKA_ALTER_REPLICA_LOG_DIRS,        "AlterReplicaLogDirs",
398       0, 1 },
399     { KAFKA_DESCRIBE_LOG_DIRS,             "DescribeLogDirs",
400       0, 1 },
401     { KAFKA_SASL_AUTHENTICATE,             "SaslAuthenticate",
402       0, 1 },
403     { KAFKA_CREATE_PARTITIONS,             "CreatePartitions",
404       0, 1 },
405     { KAFKA_CREATE_DELEGATION_TOKEN,       "CreateDelegationToken",
406       0, 1 },
407     { KAFKA_RENEW_DELEGATION_TOKEN,        "RenewDelegationToken",
408       0, 1 },
409     { KAFKA_EXPIRE_DELEGATION_TOKEN,       "ExpireDelegationToken",
410       0, 1 },
411     { KAFKA_DESCRIBE_DELEGATION_TOKEN,     "DescribeDelegationToken",
412       0, 1 },
413     { KAFKA_DELETE_GROUPS,                 "DeleteGroups",
414       0, 1 },
415     { KAFKA_ELECT_LEADERS,                 "ElectLeaders",
416       0, 1 },
417     { KAFKA_INC_ALTER_CONFIGS,             "IncrementalAlterConfigs",
418       0, 0 },
419     { KAFKA_ALTER_PARTITION_REASSIGNMENTS, "AlterPartitionReassignments",
420       0, 0 },
421     { KAFKA_LIST_PARTITION_REASSIGNMENTS,  "ListPartitionReassignments",
422       0, 0 },
423 };
424
425 /*
426  * Generated from kafka_apis. Add 1 to length for last dummy element.
427  */
428 static value_string kafka_api_names[array_length(kafka_apis) + 1];
429
430 /*
431  * For the current list of error codes check here:
432  * https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/common/protocol/Errors.java
433  */
434 static const value_string kafka_errors[] = {
435     { -1, "Unexpected Server Error" },
436     { 0, "No Error" },
437     { 1, "Offset Out Of Range" },
438     { 2, "Invalid Message" },
439     { 3, "Unknown Topic or Partition" },
440     { 4, "Invalid Message Size" },
441     { 5, "Leader Not Available" },
442     { 6, "Not Leader For Partition" },
443     { 7, "Request Timed Out" },
444     { 8, "Broker Not Available" },
445     { 10, "Message Size Too Large" },
446     { 11, "Stale Controller Epoch Code" },
447     { 12, "Offset Metadata Too Large" },
448     { 14, "Offsets Load In Progress" },
449     { 15, "The Coordinator is not Available" },
450     { 16, "Not Coordinator For Consumer" },
451     { 17, "Invalid topic" },
452     { 18, "Message batch larger than configured server segment size" },
453     { 19, "Not enough in-sync replicas" },
454     { 20, "Message(s) written to insufficient number of in-sync replicas" },
455     { 21, "Invalid required acks value" },
456     { 22, "Specified group generation id is not valid" },
457     { 23, "Inconsistent group protocol" },
458     { 24, "Invalid group.id" },
459     { 25, "Unknown member" },
460     { 26, "Invalid session timeout" },
461     { 27, "Group rebalance in progress" },
462     { 28, "Commit offset data size is not valid" },
463     { 29, "Topic authorization failed" },
464     { 30, "Group authorization failed" },
465     { 31, "Cluster authorization failed" },
466     { 32, "Invalid timestamp" },
467     { 33, "Unsupported SASL mechanism" },
468     { 34, "Illegal SASL state" },
469     { 35, "Unsupported version" },
470     { 36, "Topic already exists" },
471     { 37, "Invalid number of partitions" },
472     { 38, "Invalid replication-factor" },
473     { 39, "Invalid replica assignment" },
474     { 40, "Invalid configuration" },
475     { 41, "Not controller" },
476     { 42, "Invalid request" },
477     { 43, "Unsupported for Message Format" },
478     { 44, "Policy Violation" },
479     { 45, "Out of Order Sequence Number" },
480     { 46, "Duplicate Sequence Number" },
481     { 47, "Invalid Producer Epoch" },
482     { 48, "Invalid Transaction State" },
483     { 49, "Invalid Producer ID Mapping" },
484     { 50, "Invalid Transaction Timeout" },
485     { 51, "Concurrent Transactions" },
486     { 52, "Transaction Coordinator Fenced" },
487     { 53, "Transactional ID Authorization Failed" },
488     { 54, "Security Disabled" },
489     { 55, "Operation not Attempted" },
490     { 56, "Kafka Storage Error" },
491     { 57, "Log Directory not Found" },
492     { 58, "SASL Authentication failed" },
493     { 59, "Unknown Producer ID" },
494     { 60, "Partition Reassignment in Progress" },
495     { 61, "Delegation Token Auth Disabled" },
496     { 62, "Delegation Token not Found" },
497     { 63, "Delegation Token Owner Mismatch" },
498     { 64, "Delegation Token Request not Allowed" },
499     { 65, "Delegation Token Authorization Failed" },
500     { 66, "Delegation Token Expired" },
501     { 67, "Supplied Principal Type Unsupported" },
502     { 68, "Not Empty Group" },
503     { 69, "Group ID not Found" },
504     { 70, "Fetch Session ID not Found" },
505     { 71, "Invalid Fetch Session Epoch" },
506     { 72, "Listener not Found" },
507     { 73, "Topic Deletion Disabled" },
508     { 74, "Fenced Leader Epoch" },
509     { 75, "Unknown Leader Epoch" },
510     { 76, "Unsupported Compression Type" },
511     { 77, "Stale Broker Epoch" },
512     { 78, "Offset not Available" },
513     { 79, "Member ID Required" },
514     { 80, "Preferred Leader not Available" },
515     { 81, "Group Max Size Reached" },
516     { 82, "Fenced Instance ID" },
517     { 83, "Eligible topic partition leaders are not available" },
518     { 84, "Leader election not needed for topic partition" },
519     { 85, "No partition reassignment is in progress" },
520     { 0, NULL }
521 };
522
523 #define KAFKA_ACK_NOT_REQUIRED 0
524 #define KAFKA_ACK_LEADER       1
525 #define KAFKA_ACK_FULL_ISR     -1
526 static const value_string kafka_acks[] = {
527     { KAFKA_ACK_NOT_REQUIRED, "Not Required" },
528     { KAFKA_ACK_LEADER,       "Leader"       },
529     { KAFKA_ACK_FULL_ISR,     "Full ISR"     },
530     { 0, NULL }
531 };
532
533 #define KAFKA_MESSAGE_CODEC_MASK   0x07
534 #define KAFKA_MESSAGE_CODEC_NONE   0
535 #define KAFKA_MESSAGE_CODEC_GZIP   1
536 #define KAFKA_MESSAGE_CODEC_SNAPPY 2
537 #define KAFKA_MESSAGE_CODEC_LZ4    3
538 #define KAFKA_MESSAGE_CODEC_ZSTD   4
539 static const value_string kafka_message_codecs[] = {
540     { KAFKA_MESSAGE_CODEC_NONE,   "None"   },
541     { KAFKA_MESSAGE_CODEC_GZIP,   "Gzip"   },
542     { KAFKA_MESSAGE_CODEC_SNAPPY, "Snappy" },
543     { KAFKA_MESSAGE_CODEC_LZ4,    "LZ4"    },
544     { KAFKA_MESSAGE_CODEC_ZSTD,   "Zstd"   },
545     { 0, NULL }
546 };
547 #ifdef HAVE_SNAPPY
548 static const guint8 kafka_xerial_header[8] = {0x82, 0x53, 0x4e, 0x41, 0x50, 0x50, 0x59, 0x00};
549 #endif
550
551 #define KAFKA_MESSAGE_TIMESTAMP_MASK 0x08
552 static const value_string kafka_message_timestamp_types[] = {
553     { 0, "CreateTime" },
554     { 1, "LogAppendTime" },
555     { 0, NULL }
556 };
557
558 #define KAFKA_BATCH_TRANSACTIONAL_MASK 0x10
559 static const value_string kafka_batch_transactional_values[] = {
560     { 0, "Non-transactional" },
561     { 1, "Transactional" },
562     { 0, NULL }
563 };
564
565 #define KAFKA_BATCH_CONTROL_BATCH_MASK 0x20
566 static const value_string kafka_batch_control_batch_values[] = {
567     { 0, "Data batch" },
568     { 1, "Control batch" },
569     { 0, NULL }
570 };
571
572 static const value_string kafka_coordinator_types[] = {
573     { 0, "Group" },
574     { 1, "Transaction" },
575     { 0, NULL }
576 };
577
578 static const value_string kafka_security_protocol_types[] = {
579     { 0, "PLAINTEXT" },
580     { 1, "SSL" },
581     { 2, "SASL_PLAINTEXT" },
582     { 3, "SASL_SSL" },
583     { 0, NULL }
584 };
585
586 static const value_string kafka_isolation_levels[] = {
587     { 0, "Read Uncommitted" },
588     { 1, "Read Committed" },
589     { 0, NULL }
590 };
591
592 static const value_string kafka_transaction_results[] = {
593     { 0, "ABORT" },
594     { 1, "COMMIT" },
595     { 0, NULL }
596 };
597
598 static const value_string acl_resource_types[] = {
599     { 0, "Unknown" },
600     { 1, "Any" },
601     { 2, "Topic" },
602     { 3, "Group" },
603     { 4, "Cluster" },
604     { 5, "TransactionalId" },
605     { 6, "DelegationToken" },
606     { 0, NULL }
607 };
608
609 static const value_string acl_resource_pattern_types[] = {
610     { 0, "Unknown" },
611     { 1, "Any" },
612     { 2, "Match" },
613     { 3, "Literal" },
614     { 4, "Prefixed" },
615     { 0, NULL }
616 };
617
618 static const value_string acl_operations[] = {
619     { 0, "Unknown" },
620     { 1, "Any" },
621     { 2, "All" },
622     { 3, "Read" },
623     { 4, "Write" },
624     { 5, "Create" },
625     { 6, "Delete" },
626     { 7, "Alter" },
627     { 8, "Describe" },
628     { 9, "Cluster Action" },
629     { 10, "Describe Configs" },
630     { 11, "Alter Configs" },
631     { 12, "Idempotent Write" },
632     { 0, NULL }
633 };
634
635 static const value_string acl_permission_types[] = {
636     { 0, "Unknown" },
637     { 1, "Any" },
638     { 2, "Deny" },
639     { 3, "Allow" },
640     { 0, NULL }
641 };
642
643 static const value_string config_resource_types[] = {
644     { 0, "Unknown" },
645     { 2, "Topic" },
646     { 4, "Broker" },
647     { 0, NULL }
648 };
649
650 static const value_string config_sources[] = {
651     { 0, "Unknown" },
652     { 1, "Topic" },
653     { 2, "Broker (Dynamic)" },
654     { 3, "Broker (Dynamic/Default)" },
655     { 4, "Broker (Static)" },
656     { 5, "Default" },
657     { 0, NULL }
658 };
659
660 static const value_string config_operations[] = {
661     { 0, "Set" },
662     { 1, "Delete" },
663     { 2, "Append" },
664     { 3, "Subtract" },
665     { 0, NULL }
666 };
667
668 static const value_string election_types[] = {
669     { 0, "Preferred" },
670     { 1, "Unclean" },
671     { 0, NULL }
672 };
673
674 /* Whether to show the lengths of string and byte fields in the protocol tree.
675  * It can be useful to see these, but they do clutter up the display, so disable
676  * by default */
677 static gboolean kafka_show_string_bytes_lengths = FALSE;
678
679 typedef struct _kafka_query_response_t {
680     kafka_api_key_t     api_key;
681     kafka_api_version_t api_version;
682     guint32  request_frame;
683     guint32  response_frame;
684     gboolean response_found;
685 } kafka_query_response_t;
686
687
688 /* Some values to temporarily remember during dissection */
689 typedef struct kafka_packet_values_t {
690     kafka_partition_t partition_id;
691     kafka_offset_t    offset;
692 } kafka_packet_values_t;
693
694 /* Forward declaration (dissect_kafka_message_set() and dissect_kafka_message() call each other...) */
695 static int
696 dissect_kafka_message_set(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, guint len, guint8 codec);
697
698
699 /* HELPERS */
700
701 #ifdef HAVE_LZ4FRAME_H
702 /* Local copy of XXH32() algorithm as found in https://github.com/lz4/lz4/blob/v1.7.5/lib/xxhash.c
703    as some packagers are not providing xxhash.h in liblz4 */
704 typedef struct {
705     guint32 total_len_32;
706     guint32 large_len;
707     guint32 v1;
708     guint32 v2;
709     guint32 v3;
710     guint32 v4;
711     guint32 mem32[4];   /* buffer defined as U32 for alignment */
712     guint32 memsize;
713     guint32 reserved;   /* never read nor write, will be removed in a future version */
714 } XXH32_state_t;
715
716 typedef enum {
717     XXH_bigEndian=0,
718     XXH_littleEndian=1
719 } XXH_endianess;
720
721 static const int g_one = 1;
722 #define XXH_CPU_LITTLE_ENDIAN   (*(const char*)(&g_one))
723
724 static const guint32 PRIME32_1 = 2654435761U;
725 static const guint32 PRIME32_2 = 2246822519U;
726 static const guint32 PRIME32_3 = 3266489917U;
727 static const guint32 PRIME32_4 =  668265263U;
728 static const guint32 PRIME32_5 =  374761393U;
729
730 #define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r)))
731
732 static guint32 XXH_read32(const void* memPtr)
733 {
734     guint32 val;
735     memcpy(&val, memPtr, sizeof(val));
736     return val;
737 }
738
739 static guint32 XXH_swap32(guint32 x)
740 {
741     return  ((x << 24) & 0xff000000 ) |
742             ((x <<  8) & 0x00ff0000 ) |
743             ((x >>  8) & 0x0000ff00 ) |
744             ((x >> 24) & 0x000000ff );
745 }
746
747 #define XXH_readLE32(ptr, endian) (endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)))
748
749 static guint32 XXH32_round(guint32 seed, guint32 input)
750 {
751     seed += input * PRIME32_2;
752     seed  = XXH_rotl32(seed, 13);
753     seed *= PRIME32_1;
754     return seed;
755 }
756
757 static guint32 XXH32_endian(const void* input, size_t len, guint32 seed, XXH_endianess endian)
758 {
759     const gint8* p = (const gint8*)input;
760     const gint8* bEnd = p + len;
761     guint32 h32;
762 #define XXH_get32bits(p) XXH_readLE32(p, endian)
763
764     if (len>=16) {
765         const gint8* const limit = bEnd - 16;
766         guint32 v1 = seed + PRIME32_1 + PRIME32_2;
767         guint32 v2 = seed + PRIME32_2;
768         guint32 v3 = seed + 0;
769         guint32 v4 = seed - PRIME32_1;
770
771         do {
772             v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4;
773             v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4;
774             v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4;
775             v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4;
776         } while (p<=limit);
777
778         h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18);
779     } else {
780         h32  = seed + PRIME32_5;
781     }
782
783     h32 += (guint32) len;
784
785     while (p+4<=bEnd) {
786         h32 += XXH_get32bits(p) * PRIME32_3;
787         h32  = XXH_rotl32(h32, 17) * PRIME32_4 ;
788         p+=4;
789     }
790
791     while (p<bEnd) {
792         h32 += (*p) * PRIME32_5;
793         h32 = XXH_rotl32(h32, 11) * PRIME32_1 ;
794         p++;
795     }
796
797     h32 ^= h32 >> 15;
798     h32 *= PRIME32_2;
799     h32 ^= h32 >> 13;
800     h32 *= PRIME32_3;
801     h32 ^= h32 >> 16;
802
803     return h32;
804 }
805
806 static guint XXH32(const void* input, size_t len, guint seed)
807 {
808     XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN;
809     if (endian_detected==XXH_littleEndian)
810         return XXH32_endian(input, len, seed, XXH_littleEndian);
811     else
812         return XXH32_endian(input, len, seed, XXH_bigEndian);
813 }
814 #endif /* HAVE_LZ4FRAME_H */
815
816 static const char *
817 kafka_error_to_str(kafka_error_t error)
818 {
819     return val_to_str(error, kafka_errors, "Unknown %d");
820 }
821
822 static const char *
823 kafka_api_key_to_str(kafka_api_key_t api_key)
824 {
825     return val_to_str(api_key, kafka_api_names, "Unknown %d");
826 }
827
828 static const kafka_api_info_t *
829 kafka_get_api_info(kafka_api_key_t api_key)
830 {
831     if ((api_key >= 0) && (api_key < ((kafka_api_key_t) array_length(kafka_apis)))) {
832         return &kafka_apis[api_key];
833     } else {
834         return NULL;
835     }
836 }
837
838 static gboolean
839 kafka_is_api_version_supported(const kafka_api_info_t *api_info, kafka_api_version_t api_version)
840 {
841     DISSECTOR_ASSERT(api_info);
842
843     return !(api_info->min_version == -1 ||
844              api_version < api_info->min_version ||
845              api_version > api_info->max_version);
846 }
847
848 static void
849 kafka_check_supported_api_key(packet_info *pinfo, proto_item *ti, kafka_query_response_t *matcher)
850 {
851     if (kafka_get_api_info(matcher->api_key) == NULL) {
852         col_append_str(pinfo->cinfo, COL_INFO, " [Unknown API key]");
853         expert_add_info_format(pinfo, ti, &ei_kafka_unknown_api_key,
854                                "%s API key", kafka_api_key_to_str(matcher->api_key));
855     }
856 }
857
858 static void
859 kafka_check_supported_api_version(packet_info *pinfo, proto_item *ti, kafka_query_response_t *matcher)
860 {
861     const kafka_api_info_t *api_info;
862
863     api_info = kafka_get_api_info(matcher->api_key);
864     if (api_info != NULL && !kafka_is_api_version_supported(api_info, matcher->api_version)) {
865         col_append_str(pinfo->cinfo, COL_INFO, " [Unsupported API version]");
866         if (api_info->min_version == -1) {
867             expert_add_info_format(pinfo, ti, &ei_kafka_unsupported_api_version,
868                                    "Unsupported %s version.",
869                                    kafka_api_key_to_str(matcher->api_key));
870         }
871         else if (api_info->min_version == api_info->max_version) {
872             expert_add_info_format(pinfo, ti, &ei_kafka_unsupported_api_version,
873                                    "Unsupported %s version. Supports v%d.",
874                                    kafka_api_key_to_str(matcher->api_key), api_info->min_version);
875         } else {
876             expert_add_info_format(pinfo, ti, &ei_kafka_unsupported_api_version,
877                                    "Unsupported %s version. Supports v%d-%d.",
878                                    kafka_api_key_to_str(matcher->api_key),
879                                    api_info->min_version, api_info->max_version);
880         }
881     }
882 }
883
884 static guint
885 get_kafka_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
886 {
887     return 4 + tvb_get_ntohl(tvb, offset);
888 }
889
890 static int
891 dissect_kafka_array_ref(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset,
892                     kafka_api_version_t api_version,
893                     int(*func)(tvbuff_t*, packet_info*, proto_tree*, int, kafka_api_version_t),
894                     int *p_count)
895 {
896     gint32 count, i;
897
898     count = (gint32) tvb_get_ntohl(tvb, offset);
899     offset += 4;
900
901     if (count < -1) { // -1 means null array
902         expert_add_info(pinfo, proto_tree_get_parent(tree), &ei_kafka_bad_array_length);
903     }
904     else {
905         for (i=0; i<count; i++) {
906             offset = func(tvb, pinfo, tree, offset, api_version);
907         }
908     }
909
910     if (p_count != NULL) {
911         *p_count = count;
912     }
913
914     return offset;
915 }
916
917 static int
918 dissect_kafka_array(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset,
919                     kafka_api_version_t api_version,
920                     int(*func)(tvbuff_t*, packet_info*, proto_tree*, int, kafka_api_version_t))
921 {
922     return dissect_kafka_array_ref(tree, tvb, pinfo, offset, api_version, func, NULL);
923 }
924
925 static int
926 dissect_kafka_string(proto_tree *tree, int hf_item, tvbuff_t *tvb, packet_info *pinfo, int offset,
927                      int *p_string_offset, int *p_string_len)
928 {
929     gint16 len;
930     proto_item *pi;
931
932     /* String length */
933     len = (gint16) tvb_get_ntohs(tvb, offset);
934     pi = proto_tree_add_item(tree, hf_kafka_string_len, tvb, offset, 2, ENC_BIG_ENDIAN);
935     offset += 2;
936
937     if (p_string_offset != NULL) *p_string_offset = offset;
938
939     if (len < -1) {
940         expert_add_info(pinfo, pi, &ei_kafka_bad_string_length);
941     }
942     else {
943         /* Only showing length field if preference indicates */
944         if (!kafka_show_string_bytes_lengths) {
945             proto_item_set_hidden(pi);
946         }
947
948         if (len == -1) {
949             /* -1 indicates a NULL string */
950             proto_tree_add_string(tree, hf_item, tvb, offset, 0, NULL);
951         }
952         else {
953             /* Add the string itself. */
954             proto_tree_add_item(tree, hf_item, tvb, offset, len, ENC_NA|ENC_ASCII);
955             offset += len;
956         }
957     }
958
959     if (p_string_len != NULL) *p_string_len = len;
960
961     return offset;
962 }
963
964 static int
965 dissect_kafka_bytes(proto_tree *tree, int hf_item, tvbuff_t *tvb, packet_info *pinfo, int offset,
966                     int *p_bytes_offset, int *p_bytes_len)
967 {
968     gint32 len;
969     proto_item *pi;
970
971     /* Length */
972     len = (gint32) tvb_get_ntohl(tvb, offset);
973     pi = proto_tree_add_item(tree, hf_kafka_bytes_len, tvb, offset, 4, ENC_BIG_ENDIAN);
974     offset += 4;
975
976     if (p_bytes_offset != NULL) *p_bytes_offset = offset;
977
978     if (len < -1) {
979         expert_add_info(pinfo, pi, &ei_kafka_bad_bytes_length);
980     }
981     else {
982         /* Only showing length field if preference indicates */
983         if (!kafka_show_string_bytes_lengths) {
984             proto_item_set_hidden(pi);
985         }
986
987         if (len == -1) {
988             proto_tree_add_bytes(tree, hf_item, tvb, offset, 0, NULL);
989         }
990         else {
991             proto_tree_add_item(tree, hf_item, tvb, offset, len, ENC_NA);
992             offset += len;
993         }
994     }
995
996     if (p_bytes_len != NULL) *p_bytes_len = len;
997
998     return offset;
999 }
1000
1001 static int
1002 dissect_kafka_timestamp_delta(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int hf_item, int offset, guint64 first_timestamp)
1003 {
1004     nstime_t   nstime;
1005     guint64    milliseconds;
1006     guint64    val;
1007     guint      len;
1008     proto_item *pi;
1009
1010     len = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, &val, ENC_VARINT_ZIGZAG);
1011
1012     milliseconds = first_timestamp + val;
1013     nstime.secs  = (time_t) (milliseconds / 1000);
1014     nstime.nsecs = (int) ((milliseconds % 1000) * 1000000);
1015
1016     pi = proto_tree_add_time(tree, hf_item, tvb, offset, len, &nstime);
1017     if (len == 0) {
1018         //This will probably lead to a malformed packet, but it's better than not incrementing the offset
1019         len = FT_VARINT_MAX_LEN;
1020         expert_add_info(pinfo, pi, &ei_kafka_bad_varint);
1021     }
1022
1023     return offset+len;
1024 }
1025
1026 static int
1027 dissect_kafka_offset_delta(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int hf_item, int offset, guint64 base_offset)
1028 {
1029     gint64     val;
1030     guint      len;
1031     proto_item *pi;
1032
1033     len = tvb_get_varint(tvb, offset, FT_VARINT_MAX_LEN, &val, ENC_VARINT_ZIGZAG);
1034
1035     pi = proto_tree_add_int64(tree, hf_item, tvb, offset, len, base_offset+val);
1036     if (len == 0) {
1037         //This will probably lead to a malformed packet, but it's better than not incrementing the offset
1038         len = FT_VARINT_MAX_LEN;
1039         expert_add_info(pinfo, pi, &ei_kafka_bad_varint);
1040     }
1041
1042     return offset+len;
1043 }
1044
1045 /*
1046  * Function: dissect_kafka_string_new
1047  * ---------------------------------------------------
1048  * Decodes UTF string using the new length encoding. This format is used
1049  * in the v2 message encoding, where the string length is encoded using
1050  * ProtoBuf's ZigZag integer format (inspired by Avro). The main advantage
1051  * of ZigZag is very compact representation for small numbers.
1052  *
1053  * tvb: actual data buffer
1054  * pinfo: packet information (unused)
1055  * tree: protocol information tree to append the item
1056  * hf_item: protocol information item descriptor index
1057  * offset: offset in the buffer where the string length is to be found
1058  * p_string_offset: pointer to a variable to store the actual string begin
1059  * p_string_length: pointer to a variable to store the actual string length
1060  *
1061  * returns: pointer to the next field in the message
1062  */
1063 static int
1064 dissect_kafka_string_new(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int hf_item, int offset, int *p_string_offset, int *p_string_length)
1065 {
1066     gint64 val;
1067     guint len;
1068     proto_item *pi;
1069
1070     len = tvb_get_varint(tvb, offset, 5, &val, ENC_VARINT_ZIGZAG);
1071
1072     if (len == 0) {
1073         pi = proto_tree_add_string_format_value(tree, hf_item, tvb, offset+len, 0, NULL, "<INVALID>");
1074         expert_add_info(pinfo, pi, &ei_kafka_bad_varint);
1075         len = 5;
1076         val = 0;
1077     } else if (val > 0) {
1078         // there is payload available, possibly with 0 octets
1079         proto_tree_add_item(tree, hf_item, tvb, offset+len, (gint)val, ENC_NA | ENC_UTF_8);
1080     } else if (val == 0) {
1081         // there is empty payload (0 octets)
1082         proto_tree_add_string_format_value(tree, hf_item, tvb, offset+len, 0, NULL, "<EMPTY>");
1083     } else if (val == -1) {
1084         // there is no payload (null)
1085         proto_tree_add_string_format_value(tree, hf_item, tvb, offset+len, 0, NULL, "<NULL>");
1086         val = 0;
1087     } else {
1088         pi = proto_tree_add_string_format_value(tree, hf_item, tvb, offset+len, 0, NULL, "<INVALID>");
1089         expert_add_info(pinfo, pi, &ei_kafka_bad_string_length);
1090         val = 0;
1091     }
1092
1093     if (p_string_offset != NULL) {
1094         *p_string_offset = offset+len;
1095     }
1096     if (p_string_length != NULL) {
1097         *p_string_length = (gint)val;
1098     }
1099
1100     return offset+len+(gint)val;
1101 }
1102
1103 /*
1104  * Function: dissect_kafka_bytes_new
1105  * ---------------------------------------------------
1106  * Decodes byte buffer using the new length encoding. This format is used
1107  * in the v2 message encoding, where the buffer length is encoded using
1108  * ProtoBuf's ZigZag integer format (inspired by Avro). The main advantage
1109  * of ZigZag is very compact representation for small numbers.
1110  *
1111  * tvb: actual data buffer
1112  * pinfo: packet information (unused)
1113  * tree: protocol information tree to append the item
1114  * hf_item: protocol information item descriptor index
1115  * offset: offset in the buffer where the string length is to be found
1116  * p_bytes_offset: pointer to a variable to store the actual buffer begin
1117  * p_bytes_length: pointer to a variable to store the actual buffer length
1118  * p_invalid: pointer to a variable to store whether the length is valid
1119  *
1120  * returns: pointer to the next field in the message
1121  */
1122 static int
1123 dissect_kafka_bytes_new(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int hf_item, int offset, int *p_bytes_offset, int *p_bytes_length, gboolean *p_invalid)
1124 {
1125     gint64     val;
1126     guint      len;
1127     proto_item *pi;
1128
1129     *p_invalid = FALSE;
1130
1131     len = tvb_get_varint(tvb, offset, 5, &val, ENC_VARINT_ZIGZAG);
1132
1133     if (len == 0) {
1134         pi = proto_tree_add_bytes_format_value(tree, hf_item, tvb, offset+len, 0, NULL, "<INVALID>");
1135         expert_add_info(pinfo, pi, &ei_kafka_bad_varint);
1136         len = 5;
1137         val = 0;
1138     } else if (val > 0) {
1139         // there is payload available, possibly with 0 octets
1140         proto_tree_add_item(tree, hf_item, tvb, offset+len, (gint)val, ENC_NA);
1141     } else if (val == 0) {
1142         // there is empty payload (0 octets)
1143         proto_tree_add_bytes_format_value(tree, hf_item, tvb, offset+len, 0, NULL, "<EMPTY>");
1144     } else if (val == -1) {
1145         // there is no payload (null)
1146         proto_tree_add_bytes_format_value(tree, hf_item, tvb, offset+len, 0, NULL, "<NULL>");
1147         val = 0;
1148     } else {
1149         pi = proto_tree_add_bytes_format_value(tree, hf_item, tvb, offset+len, 0, NULL, "<INVALID>");
1150         expert_add_info(pinfo, pi, &ei_kafka_bad_bytes_length);
1151         val = 0;
1152         *p_invalid = TRUE;
1153     }
1154
1155     if (p_bytes_offset != NULL) {
1156         *p_bytes_offset = offset+len;
1157     }
1158     if (p_bytes_length != NULL) {
1159         *p_bytes_length = (gint)val;
1160     }
1161     return offset+len+(gint)val;
1162 }
1163
1164 /* Calculate and show the reduction in transmitted size due to compression */
1165 static void
1166 show_compression_reduction(tvbuff_t *tvb, proto_tree *tree, guint compressed_size, guint uncompressed_size)
1167 {
1168     proto_item *ti;
1169     /* Not really expecting a message to compress down to nothing, but defend against dividing by 0 anyway */
1170     if (uncompressed_size != 0) {
1171         ti = proto_tree_add_float(tree, hf_kafka_message_compression_reduction, tvb, 0, 0,
1172                                   (float)compressed_size / (float)uncompressed_size);
1173         proto_item_set_generated(ti);
1174     }
1175 }
1176
1177 static int
1178 dissect_kafka_record_headers_header(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset, gboolean *p_invalid)
1179 {
1180     proto_item *header_ti;
1181     proto_tree *subtree;
1182
1183     int key_off, key_len;
1184
1185     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_record_headers_header, &header_ti, "Header");
1186
1187     offset = dissect_kafka_string_new(tvb, pinfo, subtree, hf_kafka_record_header_key, offset, &key_off, &key_len);
1188     offset = dissect_kafka_bytes_new(tvb, pinfo, subtree, hf_kafka_record_header_value, offset, NULL, NULL, p_invalid);
1189
1190     proto_item_append_text(header_ti, " (Key: %s)",
1191                            tvb_get_string_enc(wmem_packet_scope(), tvb, key_off, key_len, ENC_UTF_8));
1192     proto_item_set_end(header_ti, tvb, offset);
1193
1194     return offset;
1195 }
1196
1197 static int
1198 dissect_kafka_record_headers(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1199 {
1200     proto_item *record_headers_ti;
1201     proto_tree *subtree;
1202     gint64     count;
1203     guint      len;
1204     int        i;
1205     gboolean   invalid = FALSE;
1206
1207     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_record_headers, &record_headers_ti, "Headers");
1208
1209     len = tvb_get_varint(tvb, offset, 5, &count, ENC_VARINT_ZIGZAG);
1210     if (len == 0) {
1211         expert_add_info(pinfo, record_headers_ti, &ei_kafka_bad_varint);
1212         len = 5;
1213     } else if (count < -1) { // -1 means null array
1214         expert_add_info(pinfo, record_headers_ti, &ei_kafka_bad_array_length);
1215     }
1216
1217     offset += len;
1218     for (i = 0; i < count && !invalid; i++) {
1219         offset = dissect_kafka_record_headers_header(tvb, pinfo, subtree, offset, &invalid);
1220     }
1221
1222     proto_item_set_end(record_headers_ti, tvb, offset);
1223
1224     return offset;
1225 }
1226
1227 static int
1228 dissect_kafka_record(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int start_offset, guint64 base_offset, guint64 first_timestamp)
1229 {
1230     proto_item *record_ti;
1231     proto_tree *subtree;
1232
1233     gint64     size;
1234     guint      len;
1235
1236     int offset, end_offset;
1237     gboolean   invalid;
1238
1239     offset = start_offset;
1240
1241     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_record, &record_ti, "Record");
1242
1243     len = tvb_get_varint(tvb, offset, 5, &size, ENC_VARINT_ZIGZAG);
1244     if (len == 0) {
1245         expert_add_info(pinfo, record_ti, &ei_kafka_bad_varint);
1246         return offset + 5;
1247     } else if (size < 6) {
1248         expert_add_info(pinfo, record_ti, &ei_kafka_bad_record_length);
1249         return offset + len;
1250     }
1251
1252     end_offset = offset + len + (gint)size;
1253     offset += len;
1254
1255     proto_tree_add_item(subtree, hf_kafka_record_attributes, tvb, offset, 1, ENC_BIG_ENDIAN);
1256     offset += 1;
1257
1258     offset = dissect_kafka_timestamp_delta(tvb, pinfo, subtree, hf_kafka_message_timestamp, offset, first_timestamp);
1259     offset = dissect_kafka_offset_delta(tvb, pinfo, subtree, hf_kafka_offset, offset, base_offset);
1260
1261     offset = dissect_kafka_bytes_new(tvb, pinfo, subtree, hf_kafka_message_key, offset, NULL, NULL, &invalid);
1262     if (invalid)
1263         return end_offset;
1264     offset = dissect_kafka_bytes_new(tvb, pinfo, subtree, hf_kafka_message_value, offset, NULL, NULL, &invalid);
1265     if (invalid)
1266         return end_offset;
1267
1268     offset = dissect_kafka_record_headers(tvb, pinfo, subtree, offset);
1269
1270     if (offset != end_offset) {
1271         expert_add_info(pinfo, record_ti, &ei_kafka_bad_record_length);
1272     }
1273
1274     return end_offset;
1275 }
1276
1277 static int
1278 decompress_none(tvbuff_t *tvb, packet_info *pinfo _U_, int offset, guint32 length _U_, tvbuff_t **decompressed_tvb, int *decompressed_offset)
1279 {
1280     *decompressed_tvb = tvb;
1281     *decompressed_offset = offset;
1282     return 1;
1283 }
1284
1285 static int
1286 decompress_gzip(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 length, tvbuff_t **decompressed_tvb, int *decompressed_offset)
1287 {
1288     *decompressed_tvb = tvb_child_uncompress(tvb, tvb, offset, length);
1289     *decompressed_offset = 0;
1290     if (*decompressed_tvb) {
1291         return 1;
1292     } else {
1293         col_append_str(pinfo->cinfo, COL_INFO, " [gzip decompression failed] ");
1294         return 0;
1295     }
1296 }
1297
1298 #ifdef HAVE_LZ4FRAME_H
1299 static int
1300 decompress_lz4(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 length, tvbuff_t **decompressed_tvb, int *decompressed_offset)
1301 {
1302     LZ4F_decompressionContext_t lz4_ctxt = NULL;
1303     LZ4F_frameInfo_t lz4_info;
1304     LZ4F_errorCode_t rc = 0;
1305     size_t src_offset = 0, src_size = 0, dst_size = 0;
1306     guchar *decompressed_buffer = NULL;
1307     tvbuff_t *composite_tvb = tvb_new_composite();
1308
1309     int ret = 0;
1310
1311     /* Prepare compressed data buffer */
1312     guint8 *data = (guint8*)tvb_memdup(wmem_packet_scope(), tvb, offset, length);
1313     /* Override header checksum to workaround buggy Kafka implementations */
1314     if (length > 7) {
1315         guint32 hdr_end = 6;
1316         if (data[4] & 0x08) {
1317             hdr_end += 8;
1318         }
1319         if (hdr_end < length) {
1320             data[hdr_end] = (XXH32(&data[4], hdr_end - 4, 0) >> 8) & 0xff;
1321         }
1322     }
1323
1324     /* Allocate output buffer */
1325     rc = LZ4F_createDecompressionContext(&lz4_ctxt, LZ4F_VERSION);
1326     if (LZ4F_isError(rc)) {
1327         goto end;
1328     }
1329
1330     src_offset = length;
1331     rc = LZ4F_getFrameInfo(lz4_ctxt, &lz4_info, data, &src_offset);
1332     if (LZ4F_isError(rc)) {
1333         goto end;
1334     }
1335
1336     switch (lz4_info.blockSizeID) {
1337         case LZ4F_max64KB:
1338             dst_size = 1 << 16;
1339             break;
1340         case LZ4F_max256KB:
1341             dst_size = 1 << 18;
1342             break;
1343         case LZ4F_max1MB:
1344             dst_size = 1 << 20;
1345             break;
1346         case LZ4F_max4MB:
1347             dst_size = 1 << 22;
1348             break;
1349         default:
1350             goto end;
1351     }
1352
1353     if (lz4_info.contentSize && lz4_info.contentSize < dst_size) {
1354         dst_size = (size_t)lz4_info.contentSize;
1355     }
1356
1357     do {
1358         src_size = length - src_offset; // set the number of available octets
1359         if (src_size == 0) {
1360             goto end;
1361         }
1362         decompressed_buffer = (guchar*)wmem_alloc(pinfo->pool, dst_size);
1363         rc = LZ4F_decompress(lz4_ctxt, decompressed_buffer, &dst_size,
1364                               &data[src_offset], &src_size, NULL);
1365         if (LZ4F_isError(rc)) {
1366             goto end;
1367         }
1368         if (dst_size == 0) {
1369             goto end;
1370         }
1371         tvb_composite_append(composite_tvb,
1372                              tvb_new_child_real_data(tvb, (guint8*)decompressed_buffer, (guint)dst_size, (gint)dst_size));
1373         src_offset += src_size; // bump up the offset for the next iteration
1374     } while (rc > 0);
1375
1376     tvb_composite_finalize(composite_tvb);
1377     *decompressed_tvb = composite_tvb;
1378     *decompressed_offset = 0;
1379     composite_tvb = NULL;
1380     ret = 1;
1381 end:
1382     LZ4F_freeDecompressionContext(lz4_ctxt);
1383     if (composite_tvb != NULL) {
1384         tvb_free_chain(composite_tvb);
1385     }
1386     if (ret == 0) {
1387         col_append_str(pinfo->cinfo, COL_INFO, " [lz4 decompression failed]");
1388     }
1389     return ret;
1390 }
1391 #else
1392 static int
1393 decompress_lz4(tvbuff_t *tvb _U_, packet_info *pinfo, int offset _U_, guint32 length _U_, tvbuff_t **decompressed_tvb _U_, int *decompressed_offset _U_)
1394 {
1395     col_append_str(pinfo->cinfo, COL_INFO, " [lz4 decompression unsupported]");
1396     return 0;
1397 }
1398 #endif /* HAVE_LZ4FRAME_H */
1399
1400 #ifdef HAVE_SNAPPY
1401 static int
1402 decompress_snappy(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 length, tvbuff_t **decompressed_tvb, int *decompressed_offset)
1403 {
1404     guint8 *data = (guint8*)tvb_memdup(wmem_packet_scope(), tvb, offset, length);
1405     size_t uncompressed_size;
1406     snappy_status rc = SNAPPY_OK;
1407     tvbuff_t *composite_tvb = NULL;
1408     int ret = 0;
1409
1410     if (tvb_memeql(tvb, offset, kafka_xerial_header, sizeof(kafka_xerial_header)) == 0) {
1411
1412         /* xerial framing format */
1413         guint32 chunk_size, pos = 16;
1414
1415         composite_tvb = tvb_new_composite();
1416
1417         while (pos < length) {
1418             if (pos > length-4) {
1419                 // XXX - this is presumably an error, as the chunk size
1420                 // doesn't fully fit in the data, so an error should be
1421                 // reported.
1422                 goto end;
1423             }
1424             chunk_size = tvb_get_ntohl(tvb, offset+pos);
1425             pos += 4;
1426             if (chunk_size > length) {
1427                 // XXX - this is presumably an error, as the chunk to be
1428                 // decompressed doesn't fully fit in the data, so an error
1429                 // should be reported.
1430                 goto end;
1431             }
1432             if (pos > length-chunk_size) {
1433                 // XXX - this is presumably an error, as the chunk to be
1434                 // decompressed doesn't fully fit in the data, so an error
1435                 // should be reported.
1436                 goto end;
1437             }
1438             rc = snappy_uncompressed_length(&data[pos], chunk_size, &uncompressed_size);
1439             if (rc != SNAPPY_OK) {
1440                 goto end;
1441             }
1442             guint8 *decompressed_buffer = (guint8*)wmem_alloc(pinfo->pool, uncompressed_size);
1443             rc = snappy_uncompress(&data[pos], chunk_size, decompressed_buffer, &uncompressed_size);
1444             if (rc != SNAPPY_OK) {
1445                 goto end;
1446             }
1447             tvb_composite_append(composite_tvb,
1448                       tvb_new_child_real_data(tvb, decompressed_buffer, (guint)uncompressed_size, (gint)uncompressed_size));
1449             pos += chunk_size;
1450         }
1451
1452         tvb_composite_finalize(composite_tvb);
1453         *decompressed_tvb = composite_tvb;
1454         *decompressed_offset = 0;
1455         composite_tvb = NULL;
1456
1457     } else {
1458
1459         /* unframed format */
1460         rc = snappy_uncompressed_length(data, length, &uncompressed_size);
1461         if (rc != SNAPPY_OK) {
1462             goto end;
1463         }
1464
1465         guint8 *decompressed_buffer = (guint8*)wmem_alloc(pinfo->pool, uncompressed_size);
1466
1467         rc = snappy_uncompress(data, length, decompressed_buffer, &uncompressed_size);
1468         if (rc != SNAPPY_OK) {
1469             goto end;
1470         }
1471
1472         *decompressed_tvb = tvb_new_child_real_data(tvb, decompressed_buffer, (guint)uncompressed_size, (gint)uncompressed_size);
1473         *decompressed_offset = 0;
1474
1475     }
1476     ret = 1;
1477 end:
1478     if (composite_tvb != NULL) {
1479         tvb_free_chain(composite_tvb);
1480     }
1481     if (ret == 0) {
1482         col_append_str(pinfo->cinfo, COL_INFO, " [snappy decompression failed]");
1483     }
1484     return ret;
1485 }
1486 #else
1487 static int
1488 decompress_snappy(tvbuff_t *tvb _U_, packet_info *pinfo, int offset _U_, int length _U_, tvbuff_t **decompressed_tvb _U_, int *decompressed_offset _U_)
1489 {
1490     col_append_str(pinfo->cinfo, COL_INFO, " [snappy decompression unsupported]");
1491     return 0;
1492 }
1493 #endif /* HAVE_SNAPPY */
1494
1495 #ifdef HAVE_ZSTD
1496 static int
1497 decompress_zstd(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 length, tvbuff_t **decompressed_tvb, int *decompressed_offset)
1498 {
1499     ZSTD_inBuffer input = { tvb_memdup(wmem_packet_scope(), tvb, offset, length), length, 0 };
1500     ZSTD_DStream *zds = ZSTD_createDStream();
1501     size_t rc = 0;
1502     tvbuff_t *composite_tvb = tvb_new_composite();
1503     int ret = 0;
1504
1505     do {
1506         ZSTD_outBuffer output = { wmem_alloc(pinfo->pool, ZSTD_DStreamOutSize()), ZSTD_DStreamOutSize(), 0 };
1507         rc = ZSTD_decompressStream(zds, &output, &input);
1508         // rc holds either the number of decompressed offsets or the error code.
1509         // Both values are positive, one has to use ZSTD_isError to determine if the call succeeded.
1510         if (ZSTD_isError(rc)) {
1511             goto end;
1512         }
1513         tvb_composite_append(composite_tvb,
1514                              tvb_new_child_real_data(tvb, (guint8*)output.dst, (guint)output.pos, (gint)output.pos));
1515         // rc == 0 means there is nothing more to decompress, but there could be still something in the data
1516     } while (rc > 0);
1517     tvb_composite_finalize(composite_tvb);
1518     *decompressed_tvb = composite_tvb;
1519     *decompressed_offset = 0;
1520     composite_tvb = NULL;
1521     ret = 1;
1522 end:
1523     ZSTD_freeDStream(zds);
1524     if (composite_tvb != NULL) {
1525         tvb_free_chain(composite_tvb);
1526     }
1527     if (ret == 0) {
1528         col_append_str(pinfo->cinfo, COL_INFO, " [zstd decompression failed]");
1529     }
1530     return ret;
1531 }
1532 #else
1533 static int
1534 decompress_zstd(tvbuff_t *tvb _U_, packet_info *pinfo, int offset _U_, guint32 length _U_, tvbuff_t **decompressed_tvb _U_, int *decompressed_offset _U_)
1535 {
1536     col_append_str(pinfo->cinfo, COL_INFO, " [zstd compression unsupported]");
1537     return 0;
1538 }
1539 #endif /* HAVE_ZSTD */
1540
1541 static int
1542 decompress(tvbuff_t *tvb, packet_info *pinfo, int offset, guint32 length, int codec, tvbuff_t **decompressed_tvb, int *decompressed_offset)
1543 {
1544     switch (codec) {
1545         case KAFKA_MESSAGE_CODEC_SNAPPY:
1546             return decompress_snappy(tvb, pinfo, offset, length, decompressed_tvb, decompressed_offset);
1547         case KAFKA_MESSAGE_CODEC_LZ4:
1548             return decompress_lz4(tvb, pinfo, offset, length, decompressed_tvb, decompressed_offset);
1549         case KAFKA_MESSAGE_CODEC_ZSTD:
1550             return decompress_zstd(tvb, pinfo, offset, length, decompressed_tvb, decompressed_offset);
1551         case KAFKA_MESSAGE_CODEC_GZIP:
1552             return decompress_gzip(tvb, pinfo, offset, length, decompressed_tvb, decompressed_offset);
1553         case KAFKA_MESSAGE_CODEC_NONE:
1554             return decompress_none(tvb, pinfo, offset, length, decompressed_tvb, decompressed_offset);
1555         default:
1556             col_append_str(pinfo->cinfo, COL_INFO, " [unsupported compression type]");
1557             return 0;
1558     }
1559 }
1560
1561 /*
1562  * Function: dissect_kafka_message_old
1563  * ---------------------------------------------------
1564  * Handles decoding of pre-0.11 message format. In the old format
1565  * only the message payload was the subject of compression
1566  * and the batches were special kind of message payload.
1567  *
1568  * https://kafka.apache.org/0100/documentation/#messageformat
1569  *
1570  * tvb: actual data buffer
1571  * pinfo: packet information
1572  * tree: protocol information tree to append the item
1573  * hf_item: protocol information item descriptor index
1574  * offset: pointer to the message
1575  *
1576  * returns: pointer to the next message/batch
1577  */
1578 static int
1579 dissect_kafka_message_old(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1580 {
1581     proto_item  *message_ti;
1582     proto_tree  *subtree;
1583     tvbuff_t    *decompressed_tvb;
1584     int         decompressed_offset;
1585     int         start_offset = offset;
1586     gint8       magic_byte;
1587     guint8      codec;
1588     guint32     message_size;
1589     guint32     length;
1590
1591     message_size = tvb_get_guint32(tvb, start_offset + 8, ENC_BIG_ENDIAN);
1592
1593     subtree = proto_tree_add_subtree(tree, tvb, start_offset, message_size + 12, ett_kafka_message, &message_ti, "Message");
1594
1595     proto_tree_add_item(subtree, hf_kafka_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
1596     offset += 8;
1597
1598     proto_tree_add_item(subtree, hf_kafka_message_size, tvb, offset, 4, ENC_BIG_ENDIAN);
1599     offset += 4;
1600
1601     proto_tree_add_item(subtree, hf_kafka_message_crc, tvb, offset, 4, ENC_BIG_ENDIAN);
1602     offset += 4;
1603
1604     magic_byte = tvb_get_guint8(tvb, offset);
1605
1606     proto_tree_add_item(subtree, hf_kafka_message_magic, tvb, offset, 1, ENC_BIG_ENDIAN);
1607     offset += 1;
1608
1609     proto_tree_add_item(subtree, hf_kafka_message_codec, tvb, offset, 1, ENC_BIG_ENDIAN);
1610     codec = tvb_get_guint8(tvb, offset) & KAFKA_MESSAGE_CODEC_MASK;
1611     proto_tree_add_item(subtree, hf_kafka_message_timestamp_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1612     offset += 1;
1613
1614     if (magic_byte == 1) {
1615         proto_tree_add_item(subtree, hf_kafka_message_timestamp, tvb, offset, 8, ENC_TIME_MSECS|ENC_BIG_ENDIAN);
1616         offset += 8;
1617     }
1618
1619     offset = dissect_kafka_bytes(subtree, hf_kafka_message_key, tvb, pinfo, offset, NULL, NULL);
1620
1621     /*
1622      * depending on the compression codec, the payload is the actual message payload (codes=none)
1623      * or compressed set of messages (otherwise). In the new format (since Kafka 1.0) there
1624      * is no such duality.
1625      */
1626     if (codec == 0) {
1627         offset = dissect_kafka_bytes(subtree, hf_kafka_message_value, tvb, pinfo, offset, NULL, &length);
1628     } else {
1629         length = tvb_get_ntohl(tvb, offset);
1630         offset += 4;
1631         if (decompress(tvb, pinfo, offset, length, codec, &decompressed_tvb, &decompressed_offset)==1) {
1632             add_new_data_source(pinfo, decompressed_tvb, "Decompressed content");
1633             show_compression_reduction(tvb, subtree, length, tvb_captured_length(decompressed_tvb));
1634             dissect_kafka_message_set(decompressed_tvb, pinfo, subtree, decompressed_offset,
1635                 tvb_reported_length_remaining(decompressed_tvb, decompressed_offset), codec);
1636         } else {
1637             proto_item_append_text(subtree, " [Cannot decompress records]");
1638         }
1639         offset += length;
1640     }
1641
1642     proto_item_set_end(message_ti, tvb, offset);
1643
1644     return offset;
1645 }
1646
1647 /*
1648  * Function: dissect_kafka_message_new
1649  * ---------------------------------------------------
1650  * Handles decoding of the new message format. In the new format
1651  * there is no difference between compressed and plain batch.
1652  *
1653  * https://kafka.apache.org/documentation/#messageformat
1654  *
1655  * tvb: actual data buffer
1656  * pinfo: packet information
1657  * tree: protocol information tree to append the item
1658  * hf_item: protocol information item descriptor index
1659  * offset: pointer to the message
1660  *
1661  * returns: pointer to the next message/batch
1662  */
1663 static int
1664 dissect_kafka_message_new(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1665 {
1666     proto_item *batch_ti;
1667     proto_tree *subtree;
1668     int         start_offset = offset;
1669     gint8       magic_byte;
1670     guint8      codec;
1671     guint32     message_size;
1672     guint32     count, i, length;
1673     guint64     base_offset, first_timestamp;
1674
1675     tvbuff_t    *decompressed_tvb;
1676     int         decompressed_offset;
1677
1678     message_size = tvb_get_guint32(tvb, start_offset + 8, ENC_BIG_ENDIAN);
1679
1680     subtree = proto_tree_add_subtree(tree, tvb, start_offset, message_size + 12, ett_kafka_batch, &batch_ti, "Record Batch");
1681
1682     base_offset = tvb_get_ntoh64(tvb, offset);
1683     proto_tree_add_item(subtree, hf_kafka_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
1684     offset += 8;
1685
1686     proto_tree_add_item(subtree, hf_kafka_message_size, tvb, offset, 4, ENC_BIG_ENDIAN);
1687     offset += 4;
1688
1689     proto_tree_add_item(subtree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
1690     offset += 4;
1691
1692     magic_byte = tvb_get_guint8(tvb, offset);
1693     proto_tree_add_item(subtree, hf_kafka_message_magic, tvb, offset, 1, ENC_BIG_ENDIAN);
1694     offset += 1;
1695
1696     if (magic_byte != 2) {
1697         proto_item_append_text(subtree, "[Unknown message magic]");
1698         expert_add_info_format(pinfo, batch_ti, &ei_kafka_unknown_message_magic,
1699                                "message magic: %d", magic_byte);
1700         return start_offset + 8 /*base offset*/ + 4 /*message size*/ + message_size;
1701     }
1702
1703     proto_tree_add_item(subtree, hf_kafka_batch_crc, tvb, offset, 4, ENC_BIG_ENDIAN);
1704     offset += 4;
1705
1706     proto_tree_add_item(subtree, hf_kafka_batch_codec, tvb, offset, 2, ENC_BIG_ENDIAN);
1707     codec = tvb_get_ntohs(tvb, offset) & KAFKA_MESSAGE_CODEC_MASK;
1708     proto_tree_add_item(subtree, hf_kafka_batch_timestamp_type, tvb, offset, 2, ENC_BIG_ENDIAN);
1709     proto_tree_add_item(subtree, hf_kafka_batch_transactional, tvb, offset, 2, ENC_BIG_ENDIAN);
1710     proto_tree_add_item(subtree, hf_kafka_batch_control_batch, tvb, offset, 2, ENC_BIG_ENDIAN);
1711     // next octet is reserved
1712     offset += 2;
1713
1714     proto_tree_add_item(subtree, hf_kafka_batch_last_offset_delta, tvb, offset, 4, ENC_BIG_ENDIAN);
1715     offset += 4;
1716
1717     first_timestamp = tvb_get_ntoh64(tvb, offset);
1718     proto_tree_add_item(subtree, hf_kafka_batch_first_timestamp, tvb, offset, 8, ENC_TIME_MSECS|ENC_BIG_ENDIAN);
1719     offset += 8;
1720     proto_tree_add_item(subtree, hf_kafka_batch_last_timestamp, tvb, offset, 8, ENC_TIME_MSECS|ENC_BIG_ENDIAN);
1721     offset += 8;
1722
1723     proto_tree_add_item(subtree, hf_kafka_producer_id, tvb, offset, 8, ENC_BIG_ENDIAN);
1724     offset += 8;
1725     proto_tree_add_item(subtree, hf_kafka_producer_epoch, tvb, offset, 2, ENC_BIG_ENDIAN);
1726     offset += 2;
1727     proto_tree_add_item(subtree, hf_kafka_batch_base_sequence, tvb, offset, 4, ENC_BIG_ENDIAN);
1728     offset += 4;
1729
1730     proto_tree_add_item(subtree, hf_kafka_batch_size, tvb, offset, 4, ENC_BIG_ENDIAN);
1731     count = tvb_get_ntohl(tvb, offset);
1732     offset += 4;
1733
1734     length = start_offset + 8 /*base offset*/ + 4 /*message size*/ + message_size - offset;
1735
1736     if (decompress(tvb, pinfo, offset, length, codec, &decompressed_tvb, &decompressed_offset)==1) {
1737         if (codec != 0) {
1738             add_new_data_source(pinfo, decompressed_tvb, "Decompressed Records");
1739             show_compression_reduction(tvb, subtree, length, tvb_captured_length(decompressed_tvb));
1740         }
1741         for (i=0;i<count;i++) {
1742             decompressed_offset = dissect_kafka_record(decompressed_tvb, pinfo, subtree, decompressed_offset, base_offset, first_timestamp);
1743         }
1744     } else {
1745         proto_item_append_text(subtree, " [Cannot decompress records]");
1746     }
1747
1748     return start_offset + 8 /*base offset*/ + 4 /*message size*/ + message_size;
1749 }
1750
1751 static int
1752 dissect_kafka_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1753 {
1754     gint8       magic_byte;
1755
1756     magic_byte = tvb_get_guint8(tvb, offset+16);
1757     if (magic_byte < 2) {
1758         return dissect_kafka_message_old(tvb, pinfo, tree, offset);
1759     } else {
1760         return dissect_kafka_message_new(tvb, pinfo, tree, offset);
1761     }
1762 }
1763
1764 static int
1765 dissect_kafka_message_set(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, guint len, guint8 codec)
1766 {
1767     proto_item *ti;
1768     proto_tree *subtree;
1769     gint        end_offset = offset + len;
1770     guint       messages = 0;
1771
1772     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_message_set, &ti, "Message Set");
1773     /* If set came from a compressed message, make it obvious in tree root */
1774     if (codec != KAFKA_MESSAGE_CODEC_NONE) {
1775         proto_item_append_text(subtree, " [from compressed %s message]", val_to_str_const(codec, kafka_message_codecs, "Unknown"));
1776     }
1777
1778     while (offset < end_offset) {
1779         offset = dissect_kafka_message(tvb, pinfo, subtree, offset);
1780         messages += 1;
1781     }
1782
1783     if (offset != end_offset) {
1784         expert_add_info(pinfo, ti, &ei_kafka_bad_message_set_length);
1785     }
1786
1787     proto_item_append_text(ti, " (%d Messages)", messages);
1788     proto_item_set_end(ti, tvb, offset);
1789
1790     return offset;
1791 }
1792
1793 /* OFFSET FETCH REQUEST/RESPONSE */
1794
1795 static int
1796 dissect_kafka_partition_id_ret(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset,
1797                            kafka_partition_t *p_partition)
1798 {
1799     proto_tree_add_item(tree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
1800     if (p_partition != NULL) {
1801         *p_partition = tvb_get_ntohl(tvb, offset);
1802     }
1803     offset += 4;
1804
1805     return offset;
1806 }
1807
1808 static int
1809 dissect_kafka_partition_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
1810                            kafka_api_version_t api_version _U_)
1811 {
1812     return dissect_kafka_partition_id_ret(tvb, pinfo, tree, offset, NULL);
1813 }
1814
1815 static int
1816 dissect_kafka_offset_ret(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset,
1817                      kafka_offset_t *p_offset)
1818 {
1819     proto_tree_add_item(tree, hf_kafka_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
1820     if (p_offset != NULL) {
1821         *p_offset = tvb_get_ntoh64(tvb, offset);
1822     }
1823     offset += 8;
1824
1825     return offset;
1826 }
1827
1828 static int
1829 dissect_kafka_offset(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
1830                      kafka_api_version_t api_version _U_)
1831 {
1832     return dissect_kafka_offset_ret(tvb, pinfo, tree, offset, NULL);
1833 }
1834
1835 static int
1836 dissect_kafka_leader_epoch(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset,
1837                      kafka_api_version_t api_version _U_)
1838 {
1839     proto_tree_add_item(tree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
1840     offset += 4;
1841
1842     return offset;
1843 }
1844
1845 static int
1846 dissect_kafka_offset_time(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset,
1847                           kafka_api_version_t api_version _U_)
1848 {
1849     proto_item *ti;
1850     gint64 message_offset_time;
1851
1852     message_offset_time = tvb_get_ntoh64(tvb, offset);
1853
1854     ti = proto_tree_add_item(tree, hf_kafka_offset_time, tvb, offset, 8, ENC_BIG_ENDIAN);
1855     offset += 8;
1856
1857     // The query for offset at given time takes the time in milliseconds since epoch.
1858     // It has two additional special values:
1859     // * -1 - the latest offset (to consume new messages only)
1860     // * -2 - the oldest offset (to consume all available messages)
1861     if (message_offset_time == -1) {
1862         proto_item_append_text(ti, " (latest)");
1863     } else if (message_offset_time == -2) {
1864         proto_item_append_text(ti, " (earliest)");
1865     }
1866
1867     return offset;
1868 }
1869
1870 static int
1871 dissect_kafka_offset_fetch_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
1872                                          kafka_api_version_t api_version)
1873 {
1874     proto_item *ti;
1875     proto_tree *subtree;
1876     int         offset = start_offset;
1877     gint32     count;
1878     int topic_start, topic_len;
1879
1880     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &ti, "Topic");
1881
1882     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
1883
1884     count = tvb_get_ntohil(tvb, offset);
1885     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version, &dissect_kafka_partition_id);
1886
1887     proto_item_set_len(ti, offset - start_offset);
1888     proto_item_append_text(ti, " (Topic: %s, Partitions: %u)",
1889                            tvb_get_string_enc(wmem_packet_scope(), tvb, topic_start, topic_len, ENC_UTF_8|ENC_NA),
1890                            count);
1891
1892     return offset;
1893 }
1894
1895 static int
1896 dissect_kafka_offset_fetch_request_topics(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
1897                                          kafka_api_version_t api_version)
1898 {
1899     proto_item *ti;
1900     proto_tree *subtree;
1901     int         offset = start_offset;
1902     gint32     count;
1903
1904     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topics, &ti, "Topics");
1905
1906     count = tvb_get_ntohil(tvb, offset);
1907
1908     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
1909                                  &dissect_kafka_offset_fetch_request_topic);
1910
1911     proto_item_set_len(ti, offset - start_offset);
1912
1913     if (count < 0) {
1914         proto_item_append_text(ti, " (all committed topics)");
1915     } else {
1916         proto_item_append_text(ti, " (%u topics)", count);
1917     }
1918
1919     return offset;
1920 }
1921
1922 static int
1923 dissect_kafka_offset_fetch_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
1924                                    kafka_api_version_t api_version)
1925 {
1926     offset = dissect_kafka_string(tree, hf_kafka_consumer_group, tvb, pinfo, offset, NULL, NULL);
1927
1928     offset = dissect_kafka_offset_fetch_request_topics(tvb, pinfo, tree, offset, api_version);
1929
1930     return offset;
1931 }
1932
1933 static int
1934 dissect_kafka_error_ret(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
1935                         kafka_error_t *ret)
1936 {
1937     kafka_error_t error = (kafka_error_t) tvb_get_ntohs(tvb, offset);
1938     proto_tree_add_item(tree, hf_kafka_error, tvb, offset, 2, ENC_BIG_ENDIAN);
1939     offset += 2;
1940
1941     /* Show error in Info column */
1942     if (error != 0) {
1943         col_append_fstr(pinfo->cinfo, COL_INFO,
1944                         " [%s] ", kafka_error_to_str(error));
1945     }
1946
1947     if (ret) {
1948         *ret = error;
1949     }
1950
1951     return offset;
1952 }
1953
1954 static int
1955 dissect_kafka_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset)
1956 {
1957     return dissect_kafka_error_ret(tvb, pinfo, tree, offset, NULL);
1958 }
1959
1960 static int
1961 dissect_kafka_throttle_time(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset)
1962 {
1963     proto_tree_add_item(tree, hf_kafka_throttle_time, tvb, offset, 4, ENC_BIG_ENDIAN);
1964     offset += 4;
1965     return offset;
1966 }
1967
1968 static int
1969 dissect_kafka_offset_fetch_response_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1970                                               int start_offset, kafka_api_version_t api_version)
1971 {
1972     proto_item *ti;
1973     proto_tree *subtree;
1974     int         offset = start_offset;
1975     kafka_packet_values_t packet_values;
1976     memset(&packet_values, 0, sizeof(packet_values));
1977
1978     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &ti, "Partition");
1979
1980     offset = dissect_kafka_partition_id_ret(tvb, pinfo, subtree, offset, &packet_values.partition_id);
1981     offset = dissect_kafka_offset_ret(tvb, pinfo, subtree, offset, &packet_values.offset);
1982
1983     if (api_version >= 5) {
1984         offset = dissect_kafka_leader_epoch(tvb, pinfo, subtree, offset, api_version);
1985     }
1986
1987     offset = dissect_kafka_string(subtree, hf_kafka_metadata, tvb, pinfo, offset, NULL, NULL);
1988
1989     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
1990
1991     if (packet_values.offset==-1) {
1992         proto_item_append_text(ti, " (ID=%u, Offset=None)",
1993                                packet_values.partition_id);
1994     } else {
1995         proto_item_append_text(ti, " (ID=%u, Offset=%" G_GINT64_MODIFIER "i)",
1996                                packet_values.partition_id, packet_values.offset);
1997     }
1998
1999     proto_item_set_len(ti, offset - start_offset);
2000
2001     return offset;
2002 }
2003
2004 static int
2005 dissect_kafka_offset_fetch_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
2006                                           kafka_api_version_t api_version)
2007 {
2008     proto_item *ti;
2009     proto_tree *subtree;
2010     int         offset = start_offset;
2011
2012     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &ti, "Topic");
2013
2014     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, NULL, NULL);
2015     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
2016                                  &dissect_kafka_offset_fetch_response_partition);
2017
2018     proto_item_set_len(ti, offset - start_offset);
2019
2020     return offset;
2021 }
2022
2023 static int
2024 dissect_kafka_offset_fetch_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2025                                     kafka_api_version_t api_version)
2026 {
2027     if (api_version >= 3) {
2028         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
2029     }
2030
2031     return dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
2032                                &dissect_kafka_offset_fetch_response_topic);
2033 }
2034
2035 /* METADATA REQUEST/RESPONSE */
2036
2037 static int
2038 dissect_kafka_metadata_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2039                                      kafka_api_version_t api_version _U_)
2040 {
2041     return dissect_kafka_string(tree, hf_kafka_topic_name, tvb, pinfo, offset, NULL, NULL);
2042 }
2043
2044 static int
2045 dissect_kafka_metadata_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2046                                kafka_api_version_t api_version)
2047 {
2048     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
2049                                &dissect_kafka_metadata_request_topic);
2050
2051     if (api_version >= 4) {
2052         proto_tree_add_item(tree, hf_kafka_allow_auto_topic_creation, tvb, offset, 1, ENC_BIG_ENDIAN);
2053         offset += 1;
2054     }
2055
2056     if (api_version >= 8) {
2057         proto_tree_add_item(tree, hf_kafka_include_cluster_authorized_ops, tvb, offset, 1, ENC_BIG_ENDIAN);
2058         offset += 1;
2059     }
2060
2061     if (api_version >= 8) {
2062         proto_tree_add_item(tree, hf_kafka_include_topic_authorized_ops, tvb, offset, 1, ENC_BIG_ENDIAN);
2063         offset += 1;
2064     }
2065
2066     return offset;
2067 }
2068
2069 static int
2070 dissect_kafka_metadata_broker(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
2071                               kafka_api_version_t api_version)
2072 {
2073     proto_item *ti;
2074     proto_tree *subtree;
2075     int         offset = start_offset;
2076     guint32     nodeid;
2077     int         host_start, host_len;
2078     guint32     broker_port;
2079
2080     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_broker, &ti, "Broker");
2081
2082     nodeid = tvb_get_ntohl(tvb, offset);
2083     proto_tree_add_item(subtree, hf_kafka_broker_nodeid, tvb, offset, 4, ENC_BIG_ENDIAN);
2084     offset += 4;
2085
2086     offset = dissect_kafka_string(subtree, hf_kafka_broker_host, tvb, pinfo, offset, &host_start, &host_len);
2087
2088     broker_port = tvb_get_ntohl(tvb, offset);
2089     proto_tree_add_item(subtree, hf_kafka_broker_port, tvb, offset, 4, ENC_BIG_ENDIAN);
2090     offset += 4;
2091
2092     if (api_version >= 1) {
2093         offset = dissect_kafka_string(subtree, hf_kafka_rack, tvb, pinfo, offset, NULL, NULL);
2094     }
2095
2096     proto_item_append_text(ti, " (node %u: %s:%u)",
2097                            nodeid,
2098                            tvb_get_string_enc(wmem_packet_scope(), tvb,
2099                            host_start, host_len, ENC_UTF_8|ENC_NA),
2100                            broker_port);
2101
2102     proto_item_set_len(ti, offset - start_offset);
2103
2104     return offset;
2105 }
2106
2107 static int
2108 dissect_kafka_metadata_replica(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset,
2109                                kafka_api_version_t api_version _U_)
2110 {
2111     proto_tree_add_item(tree, hf_kafka_replica, tvb, offset, 4, ENC_BIG_ENDIAN);
2112     return offset + 4;
2113 }
2114
2115 static int
2116 dissect_kafka_metadata_isr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset,
2117                            kafka_api_version_t api_version _U_)
2118 {
2119     proto_tree_add_item(tree, hf_kafka_isr, tvb, offset, 4, ENC_BIG_ENDIAN);
2120     return offset + 4;
2121 }
2122
2123 static int
2124 dissect_kafka_metadata_offline(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset,
2125                            kafka_api_version_t api_version _U_)
2126 {
2127     proto_tree_add_item(tree, hf_kafka_offline, tvb, offset, 4, ENC_BIG_ENDIAN);
2128     return offset + 4;
2129 }
2130
2131 static int
2132 dissect_kafka_metadata_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
2133                                  kafka_api_version_t api_version)
2134 {
2135     proto_item *ti, *subti;
2136     proto_tree *subtree, *subsubtree;
2137     int         offset = start_offset;
2138     int         sub_start_offset;
2139     kafka_partition_t partition;
2140
2141     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &ti, "Partition");
2142
2143     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
2144
2145     offset = dissect_kafka_partition_id_ret(tvb, pinfo, subtree, offset, &partition);
2146
2147     proto_tree_add_item(subtree, hf_kafka_leader_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2148     offset += 4;
2149
2150     if (api_version >= 7) {
2151         proto_tree_add_item(subtree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
2152         offset += 4;
2153     }
2154
2155     sub_start_offset = offset;
2156     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_replicas, &subti, "Replicas");
2157     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version, &dissect_kafka_metadata_replica);
2158     proto_item_set_len(subti, offset - sub_start_offset);
2159
2160     sub_start_offset = offset;
2161     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_isrs, &subti, "Caught-Up Replicas");
2162     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version, &dissect_kafka_metadata_isr);
2163     proto_item_set_len(subti, offset - sub_start_offset);
2164
2165     if (api_version >= 5) {
2166         sub_start_offset = offset;
2167         subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_offline, &subti, "Offline Replicas");
2168         offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version, &dissect_kafka_metadata_offline);
2169         proto_item_set_len(subti, offset - sub_start_offset);
2170     }
2171
2172     proto_item_set_len(ti, offset - start_offset);
2173     proto_item_append_text(ti, " (ID=%u)", partition);
2174
2175     return offset;
2176 }
2177
2178 static int
2179 dissect_kafka_metadata_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
2180                              kafka_api_version_t api_version)
2181 {
2182     proto_item *ti;
2183     proto_tree *subtree;
2184     int         offset = start_offset;
2185     int         name_start, name_length;
2186
2187     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &ti, "Topic");
2188
2189     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
2190
2191     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &name_start, &name_length);
2192     proto_item_append_text(ti, " (%s)",
2193                            tvb_get_string_enc(wmem_packet_scope(), tvb,
2194                            name_start, name_length, ENC_UTF_8|ENC_NA));
2195
2196     if (api_version >= 1) {
2197         proto_tree_add_item(subtree, hf_kafka_is_internal, tvb, offset, 1, ENC_NA);
2198         offset += 1;
2199     }
2200
2201     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version, &dissect_kafka_metadata_partition);
2202
2203     if (api_version >= 8) {
2204         proto_tree_add_item(subtree, hf_kafka_topic_authorized_ops, tvb, offset, 4, ENC_BIG_ENDIAN);
2205         offset += 4;
2206     }
2207
2208     proto_item_set_len(ti, offset - start_offset);
2209
2210     return offset;
2211 }
2212
2213 static int
2214 dissect_kafka_metadata_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
2215                                 kafka_api_version_t api_version)
2216 {
2217     proto_item *ti;
2218     proto_tree *subtree;
2219     int         offset = start_offset;
2220
2221     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_brokers, &ti, "Broker Metadata");
2222
2223     if (api_version >= 3) {
2224         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
2225     }
2226
2227     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version, &dissect_kafka_metadata_broker);
2228     proto_item_set_len(ti, offset - start_offset);
2229
2230     if (api_version >= 2) {
2231         offset = dissect_kafka_string(tree, hf_kafka_cluster_id, tvb, pinfo, offset, NULL, NULL);
2232     }
2233
2234     if (api_version >= 1) {
2235         proto_tree_add_item(tree, hf_kafka_controller_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2236         offset += 4;
2237     }
2238
2239     start_offset = offset;
2240     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topics, &ti, "Topic Metadata");
2241     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version, &dissect_kafka_metadata_topic);
2242     proto_item_set_len(ti, offset - start_offset);
2243
2244     if (api_version >= 8) {
2245         proto_tree_add_item(tree, hf_kafka_cluster_authorized_ops, tvb, offset, 4, ENC_BIG_ENDIAN);
2246         offset += 4;
2247     }
2248
2249     return offset;
2250 }
2251
2252 /* LEADER_AND_ISR REQUEST/RESPONSE */
2253
2254 static int
2255 dissect_kafka_leader_and_isr_request_isr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2256                                          int offset, kafka_api_version_t api_version _U_)
2257 {
2258     /* isr */
2259     proto_tree_add_item(tree, hf_kafka_isr, tvb, offset, 4, ENC_BIG_ENDIAN);
2260     offset += 4;
2261
2262     return offset;
2263 }
2264
2265 static int
2266 dissect_kafka_leader_and_isr_request_replica(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2267                                              int offset, kafka_api_version_t api_version _U_)
2268 {
2269     /* replica */
2270     proto_tree_add_item(tree, hf_kafka_replica, tvb, offset, 4, ENC_BIG_ENDIAN);
2271     offset += 4;
2272
2273     return offset;
2274 }
2275
2276
2277 static int
2278 dissect_kafka_leader_and_isr_request_partition_state(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2279                                                      int offset, kafka_api_version_t api_version)
2280 {
2281     proto_tree *subtree, *subsubtree;
2282     proto_item *subti, *subsubti;
2283     int topic_start, topic_len;
2284     kafka_partition_t partition;
2285
2286     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
2287                                      ett_kafka_partition,
2288                                      &subti, "Partition");
2289
2290     if (api_version < 2) {
2291         /* topic */
2292         offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset,
2293                                       &topic_start, &topic_len);
2294     }
2295
2296     /* partition */
2297     partition = (kafka_partition_t) tvb_get_ntohl(tvb, offset);
2298     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2299     offset += 4;
2300
2301     /* controller_epoch */
2302     proto_tree_add_item(subtree, hf_kafka_controller_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
2303     offset += 4;
2304
2305     /* leader */
2306     proto_tree_add_item(subtree, hf_kafka_leader_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2307     offset += 4;
2308
2309     /* leader_epoch */
2310     proto_tree_add_item(subtree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
2311     offset += 4;
2312
2313     /* [isr] */
2314     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
2315                                         ett_kafka_isrs,
2316                                         &subsubti, "ISRs");
2317     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
2318                                  &dissect_kafka_leader_and_isr_request_isr);
2319     proto_item_set_end(subsubti, tvb, offset);
2320
2321     /* zk_version */
2322     proto_tree_add_item(subtree, hf_kafka_zk_version, tvb, offset, 4, ENC_BIG_ENDIAN);
2323     offset += 4;
2324
2325     /* [replica] */
2326     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
2327                                         ett_kafka_replicas,
2328                                         &subsubti, "Current Replicas");
2329     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
2330                                  &dissect_kafka_leader_and_isr_request_replica);
2331     proto_item_set_end(subsubti, tvb, offset);
2332
2333     if (api_version >= 3) {
2334
2335         subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
2336                                             ett_kafka_replicas,
2337                                             &subsubti, "Adding Replicas");
2338         offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
2339                                      &dissect_kafka_leader_and_isr_request_replica);
2340         proto_item_set_end(subsubti, tvb, offset);
2341
2342         subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
2343                                             ett_kafka_replicas,
2344                                             &subsubti, "Removing Replicas");
2345         offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
2346                                      &dissect_kafka_leader_and_isr_request_replica);
2347         proto_item_set_end(subsubti, tvb, offset);
2348
2349     }
2350
2351     proto_item_set_end(subti, tvb, offset);
2352
2353     if (api_version < 2) {
2354         proto_item_append_text(subti, " (Topic=%s, Partition-ID=%u)",
2355                                tvb_get_string_enc(wmem_packet_scope(), tvb,
2356                                                   topic_start, topic_len, ENC_UTF_8|ENC_NA),
2357                                partition);
2358     } else {
2359         proto_item_append_text(subti, " (Partition-ID=%u)",
2360                                partition);
2361     }
2362
2363     return offset;
2364 }
2365
2366 static int
2367 dissect_kafka_leader_and_isr_request_topic_state(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2368                                                      int offset, kafka_api_version_t api_version)
2369 {
2370     proto_tree *subtree;
2371     proto_item *subti;
2372     int topic_start, topic_len;
2373
2374     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
2375                                      ett_kafka_topic,
2376                                      &subti, "Topic");
2377
2378     /* topic */
2379     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset,
2380                                   &topic_start, &topic_len);
2381
2382     /* [partition_state] */
2383     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
2384                                  &dissect_kafka_leader_and_isr_request_partition_state);
2385
2386     proto_item_append_text(subti, " (Name=%s)",
2387                            tvb_get_string_enc(wmem_packet_scope(), tvb,
2388                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
2389
2390     return offset;
2391 }
2392
2393 static int
2394 dissect_kafka_leader_and_isr_request_live_leader(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2395                                                  int offset, kafka_api_version_t api_version _U_)
2396 {
2397     proto_item *subti;
2398     proto_tree *subtree;
2399     gint32 nodeid;
2400     int host_start, host_len;
2401     gint32 broker_port;
2402
2403     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_broker,
2404                                      &subti, "Live Leader");
2405
2406     /* id */
2407     nodeid = (kafka_partition_t) tvb_get_ntohl(tvb, offset);
2408     proto_tree_add_item(subtree, hf_kafka_broker_nodeid, tvb, offset, 4, ENC_BIG_ENDIAN);
2409     offset += 4;
2410
2411     /* host */
2412     offset = dissect_kafka_string(subtree, hf_kafka_broker_host, tvb, pinfo, offset, &host_start, &host_len);
2413
2414     /* port */
2415     broker_port = (gint32) tvb_get_ntohl(tvb, offset);
2416     proto_tree_add_item(subtree, hf_kafka_broker_port, tvb, offset, 4, ENC_BIG_ENDIAN);
2417     offset += 4;
2418
2419     proto_item_set_end(subti, tvb, offset);
2420     proto_item_append_text(subti, " (node %u: %s:%u)",
2421                            nodeid,
2422                            tvb_get_string_enc(wmem_packet_scope(), tvb, host_start, host_len, ENC_UTF_8|ENC_NA),
2423                            broker_port);
2424
2425     return offset;
2426 }
2427
2428 static int
2429 dissect_kafka_leader_and_isr_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2430                                      kafka_api_version_t api_version)
2431 {
2432     gint32 controller_id;
2433
2434     /* controller_id */
2435     controller_id = (gint32) tvb_get_ntohl(tvb, offset);
2436     proto_tree_add_item(tree, hf_kafka_controller_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2437     offset += 4;
2438
2439     /* controller_epoch */
2440     proto_tree_add_item(tree, hf_kafka_controller_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
2441     offset += 4;
2442
2443     if (api_version >= 2) {
2444         /* broker_epoch */
2445         proto_tree_add_item(tree, hf_kafka_broker_epoch, tvb, offset, 8, ENC_BIG_ENDIAN);
2446         offset += 8;
2447     }
2448
2449     if (api_version >= 2) {
2450         /* [topic_state] */
2451         offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
2452                                      &dissect_kafka_leader_and_isr_request_topic_state);
2453     } else {
2454         /* [partition_state] */
2455         offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
2456                                      &dissect_kafka_leader_and_isr_request_partition_state);
2457     }
2458
2459     /* [live_leader] */
2460     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
2461                                  &dissect_kafka_leader_and_isr_request_live_leader);
2462
2463     col_append_fstr(pinfo->cinfo, COL_INFO, " (Controller-ID=%d)", controller_id);
2464
2465     return offset;
2466 }
2467
2468 static int
2469 dissect_kafka_leader_and_isr_response_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2470                                                 int offset, kafka_api_version_t api_version _U_)
2471 {
2472     proto_item *subti;
2473     proto_tree *subtree;
2474     int topic_start, topic_len;
2475     kafka_partition_t partition;
2476     kafka_error_t error;
2477
2478     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
2479                                      ett_kafka_partition,
2480                                      &subti, "Partition");
2481
2482     /* topic */
2483     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
2484
2485     /* partition */
2486     partition = (gint32) tvb_get_ntohl(tvb, offset);
2487     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2488     offset += 4;
2489
2490     /* error_code */
2491     offset = dissect_kafka_error_ret(tvb, pinfo, subtree, offset, &error);
2492
2493     proto_item_set_end(subti, tvb, offset);
2494     proto_item_append_text(subti, " (Topic=%s, Partition-ID=%u, Error=%s)",
2495                            tvb_get_string_enc(wmem_packet_scope(), tvb,
2496                                               topic_start, topic_len, ENC_UTF_8|ENC_NA),
2497                            partition,
2498                            kafka_error_to_str(error));
2499
2500     return offset;
2501 }
2502
2503 static int
2504 dissect_kafka_leader_and_isr_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2505                                       kafka_api_version_t api_version)
2506 {
2507     /* error_code */
2508     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
2509
2510     /* [partition] */
2511     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
2512                                  &dissect_kafka_leader_and_isr_response_partition);
2513
2514     return offset;
2515 }
2516
2517 /* STOP_REPLICA REQUEST/RESPONSE */
2518
2519 static int
2520 dissect_kafka_stop_replica_request_topic_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2521                                              int offset, kafka_api_version_t api_version _U_)
2522 {
2523     proto_tree_add_item(tree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2524     offset += 4;
2525     return offset;
2526 }
2527
2528 static int
2529 dissect_kafka_stop_replica_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2530                                              int offset, kafka_api_version_t api_version)
2531 {
2532     proto_item *subti;
2533     proto_tree *subtree;
2534     int topic_start, topic_len;
2535
2536     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
2537                                      ett_kafka_topic,
2538                                      &subti, "Topic");
2539
2540     /* topic */
2541     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
2542
2543     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
2544                                  &dissect_kafka_stop_replica_request_topic_partition);
2545
2546     proto_item_set_end(subti, tvb, offset);
2547     proto_item_append_text(subti, " (Name=%s)",
2548                            tvb_get_string_enc(wmem_packet_scope(), tvb,
2549                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
2550
2551     return offset;
2552 }
2553
2554 static int
2555 dissect_kafka_stop_replica_request_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2556                                              int offset, kafka_api_version_t api_version _U_)
2557 {
2558     proto_item *subti;
2559     proto_tree *subtree;
2560     int topic_start, topic_len;
2561     kafka_partition_t partition;
2562
2563     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
2564                                      ett_kafka_partition,
2565                                      &subti, "Partition");
2566
2567     /* topic */
2568     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
2569
2570     /* partition */
2571     partition = (gint32) tvb_get_ntohl(tvb, offset);
2572     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2573     offset += 4;
2574
2575     proto_item_set_end(subti, tvb, offset);
2576     proto_item_append_text(subti, " (Topic=%s, Partition-ID=%u)",
2577                            tvb_get_string_enc(wmem_packet_scope(), tvb,
2578                                               topic_start, topic_len, ENC_UTF_8|ENC_NA),
2579                            partition);
2580
2581     return offset;
2582 }
2583
2584 static int
2585 dissect_kafka_stop_replica_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2586                                    kafka_api_version_t api_version)
2587 {
2588     gint32 controller_id;
2589
2590     /* controller_id */
2591     controller_id = (gint32) tvb_get_ntohl(tvb, offset);
2592     proto_tree_add_item(tree, hf_kafka_controller_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2593     offset += 4;
2594
2595     /* controller_epoch */
2596     proto_tree_add_item(tree, hf_kafka_controller_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
2597     offset += 4;
2598
2599     if (api_version >= 1) {
2600         /* broker_epoch */
2601         proto_tree_add_item(tree, hf_kafka_broker_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
2602         offset += 4;
2603     }
2604
2605     /* delete_partitions */
2606     proto_tree_add_item(tree, hf_kafka_delete_partitions, tvb, offset, 1, ENC_BIG_ENDIAN);
2607     offset += 1;
2608
2609     /* [partition] */
2610     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
2611                                  &dissect_kafka_stop_replica_request_partition);
2612
2613     if (api_version >= 1) {
2614         offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
2615                                      &dissect_kafka_stop_replica_request_topic);
2616     }
2617
2618     col_append_fstr(pinfo->cinfo, COL_INFO, " (Controller-ID=%d)", controller_id);
2619
2620     return offset;
2621 }
2622
2623 static int
2624 dissect_kafka_stop_replica_response_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2625                                               int offset, kafka_api_version_t api_version _U_)
2626 {
2627     proto_item *subti;
2628     proto_tree *subtree;
2629     int topic_start, topic_len;
2630     kafka_error_t error;
2631     kafka_partition_t partition;
2632
2633     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
2634                                      ett_kafka_partition,
2635                                      &subti, "Partition");
2636
2637     /* topic */
2638     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
2639
2640     /* partition */
2641     partition = (gint32) tvb_get_ntohl(tvb, offset);
2642     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2643     offset += 4;
2644
2645     /* error_code */
2646     offset = dissect_kafka_error_ret(tvb, pinfo, subtree, offset, &error);
2647
2648     proto_item_set_end(subti, tvb, offset);
2649     proto_item_append_text(subti, " (Topic=%s, Partition-ID=%u, Error=%s)",
2650                            tvb_get_string_enc(wmem_packet_scope(), tvb,
2651                                               topic_start, topic_len, ENC_UTF_8|ENC_NA),
2652                            partition,
2653                            kafka_error_to_str(error));
2654
2655     return offset;
2656 }
2657
2658 static int
2659 dissect_kafka_stop_replica_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2660                                     kafka_api_version_t api_version)
2661 {
2662     /* error_code */
2663     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
2664
2665     /* [partition] */
2666     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
2667                                  &dissect_kafka_stop_replica_response_partition);
2668
2669     return offset;
2670 }
2671
2672 /* FETCH REQUEST/RESPONSE */
2673
2674 static int
2675 dissect_kafka_fetch_request_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2676                                       kafka_api_version_t api_version _U_)
2677 {
2678     proto_item *ti;
2679     proto_tree *subtree;
2680     kafka_packet_values_t packet_values;
2681     memset(&packet_values, 0, sizeof(packet_values));
2682
2683     subtree = proto_tree_add_subtree(tree, tvb, offset, 16, ett_kafka_partition, &ti, "Partition");
2684
2685     offset = dissect_kafka_partition_id_ret(tvb, pinfo, subtree, offset, &packet_values.partition_id);
2686
2687     if (api_version >= 9) {
2688         proto_tree_add_item(subtree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
2689         offset += 4;
2690     }
2691
2692     offset = dissect_kafka_offset_ret(tvb, pinfo, subtree, offset, &packet_values.offset);
2693
2694     if (api_version >= 5) {
2695         proto_tree_add_item(subtree, hf_kafka_log_start_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
2696         offset += 8;
2697     }
2698
2699     proto_tree_add_item(subtree, hf_kafka_max_bytes, tvb, offset, 4, ENC_BIG_ENDIAN);
2700     offset += 4;
2701
2702     proto_item_append_text(ti, " (ID=%u, Offset=%" G_GINT64_MODIFIER "i)",
2703                            packet_values.partition_id, packet_values.offset);
2704
2705     return offset;
2706 }
2707
2708 static int
2709 dissect_kafka_fetch_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
2710                                   kafka_api_version_t api_version)
2711 {
2712     proto_item *ti;
2713     proto_tree *subtree;
2714     int         offset = start_offset;
2715     guint32     count;
2716     int         name_start, name_length;
2717
2718     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &ti, "Topic");
2719
2720     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &name_start, &name_length);
2721     count = tvb_get_ntohl(tvb, offset);
2722     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
2723                                  &dissect_kafka_fetch_request_partition);
2724
2725     proto_item_set_len(ti, offset - start_offset);
2726     proto_item_append_text(ti, " (%u partitions)", count);
2727
2728     return offset;
2729 }
2730
2731 static int
2732 dissect_kafka_fetch_request_forgottent_topic_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, int offset,
2733                                                   kafka_api_version_t api_version _U_)
2734 {
2735     proto_tree_add_item(tree, hf_kafka_forgotten_topic_partition, tvb, offset, 4, ENC_BIG_ENDIAN);
2736     offset += 4;
2737     return offset;
2738 }
2739
2740 static int
2741 dissect_kafka_fetch_request_forgotten_topics_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
2742                                   kafka_api_version_t api_version)
2743 {
2744     proto_item *ti;
2745     proto_tree *subtree;
2746     int         offset = start_offset;
2747     guint32     count;
2748     int         name_start, name_length;
2749
2750     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_request_forgotten_topic, &ti, "Fetch Request Forgotten Topic Data");
2751
2752     offset = dissect_kafka_string(subtree, hf_kafka_forgotten_topic_name, tvb, pinfo, offset, &name_start, &name_length);
2753     count = tvb_get_ntohl(tvb, offset);
2754     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
2755                                  &dissect_kafka_fetch_request_forgottent_topic_partition);
2756
2757     proto_item_set_len(ti, offset - start_offset);
2758     proto_item_append_text(ti, " (%u partitions)", count);
2759
2760     return offset;
2761 }
2762
2763 static int
2764 dissect_kafka_fetch_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2765                             kafka_api_version_t api_version)
2766 {
2767     proto_tree_add_item(tree, hf_kafka_replica, tvb, offset, 4, ENC_BIG_ENDIAN);
2768     offset += 4;
2769
2770     proto_tree_add_item(tree, hf_kafka_max_wait_time, tvb, offset, 4, ENC_BIG_ENDIAN);
2771     offset += 4;
2772
2773     proto_tree_add_item(tree, hf_kafka_min_bytes, tvb, offset, 4, ENC_BIG_ENDIAN);
2774     offset += 4;
2775
2776     if (api_version >= 3) {
2777         proto_tree_add_item(tree, hf_kafka_max_bytes, tvb, offset, 4, ENC_BIG_ENDIAN);
2778         offset += 4;
2779     }
2780
2781     if (api_version >= 4) {
2782         proto_tree_add_item(tree, hf_kafka_isolation_level, tvb, offset, 1, ENC_BIG_ENDIAN);
2783         offset += 1;
2784     }
2785
2786     if (api_version >= 7) {
2787         proto_tree_add_item(tree, hf_kafka_fetch_session_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2788         offset += 4;
2789     }
2790
2791     if (api_version >= 7) {
2792         proto_tree_add_item(tree, hf_kafka_fetch_session_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
2793         offset += 4;
2794     }
2795
2796     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version, &dissect_kafka_fetch_request_topic);
2797
2798     if (api_version >= 7) {
2799         offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version, &dissect_kafka_fetch_request_forgotten_topics_data);
2800     }
2801
2802     if (api_version >= 11) {
2803         offset = dissect_kafka_string(tree, hf_kafka_rack, tvb, pinfo, offset, NULL, NULL);
2804     }
2805
2806     return offset;
2807 }
2808
2809 static int
2810 dissect_kafka_aborted_transaction(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2811                                   int start_offset, kafka_api_version_t api_version _U_)
2812 {
2813     proto_item *ti;
2814     proto_tree *subtree;
2815     int         offset = start_offset;
2816
2817     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_aborted_transaction, &ti, "Transaction");
2818
2819     proto_tree_add_item(subtree, hf_kafka_producer_id, tvb, offset, 8, ENC_BIG_ENDIAN);
2820     offset += 8;
2821
2822     proto_tree_add_item(subtree, hf_kafka_first_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
2823     offset += 8;
2824
2825     proto_item_set_len(ti, offset - start_offset);
2826
2827     return offset;
2828 }
2829
2830 static int
2831 dissect_kafka_aborted_transactions(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2832                                   int start_offset, kafka_api_version_t api_version _U_)
2833 {
2834     proto_item *ti;
2835     proto_tree *subtree;
2836     int         offset = start_offset;
2837
2838     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_aborted_transactions, &ti, "Aborted Transactions");
2839
2840     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version, &dissect_kafka_aborted_transaction);
2841
2842     proto_item_set_len(ti, offset - start_offset);
2843
2844     return offset;
2845 }
2846
2847 static int
2848 dissect_kafka_fetch_response_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
2849                                        kafka_api_version_t api_version _U_)
2850 {
2851     proto_item *ti;
2852     proto_tree *subtree;
2853     int        offset = start_offset;
2854     guint      len;
2855     kafka_packet_values_t packet_values;
2856     memset(&packet_values, 0, sizeof(packet_values));
2857
2858     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &ti, "Partition");
2859
2860     offset = dissect_kafka_partition_id_ret(tvb, pinfo, subtree, offset, &packet_values.partition_id);
2861
2862     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
2863
2864     offset = dissect_kafka_offset_ret(tvb, pinfo, subtree, offset, &packet_values.offset);
2865
2866     if (api_version >= 4) {
2867         proto_tree_add_item(subtree, hf_kafka_last_stable_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
2868         offset += 8;
2869     }
2870
2871     if (api_version >= 5) {
2872         proto_tree_add_item(subtree, hf_kafka_log_start_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
2873         offset += 8;
2874     }
2875
2876     if (api_version >= 4) {
2877         offset = dissect_kafka_aborted_transactions(tvb, pinfo, subtree, offset, api_version);
2878     }
2879
2880     len = tvb_get_ntohl(tvb, offset);
2881     offset += 4;
2882
2883     if (len > 0) {
2884         offset = dissect_kafka_message_set(tvb, pinfo, subtree, offset, len, KAFKA_MESSAGE_CODEC_NONE);
2885     }
2886
2887     proto_item_set_len(ti, offset - start_offset);
2888
2889     proto_item_append_text(ti, " (ID=%u, Offset=%" G_GINT64_MODIFIER "i)",
2890                            packet_values.partition_id, packet_values.offset);
2891
2892     return offset;
2893 }
2894
2895 static int
2896 dissect_kafka_fetch_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
2897                                    kafka_api_version_t api_version)
2898 {
2899     proto_item *ti;
2900     proto_tree *subtree;
2901     int         offset = start_offset;
2902     guint32     count;
2903
2904     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &ti, "Topic");
2905
2906     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, NULL, NULL);
2907     count = tvb_get_ntohl(tvb, offset);
2908     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
2909                                  &dissect_kafka_fetch_response_partition);
2910
2911     proto_item_set_len(ti, offset - start_offset);
2912     proto_item_append_text(ti, " (%u partitions)", count);
2913
2914     return offset;
2915 }
2916
2917 static int
2918 dissect_kafka_fetch_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2919                              kafka_api_version_t api_version)
2920 {
2921     if (api_version >= 1) {
2922         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
2923     }
2924
2925     if (api_version >= 7) {
2926         offset = dissect_kafka_error(tvb, pinfo, tree, offset);
2927     }
2928
2929     if (api_version >= 7) {
2930         proto_tree_add_item(tree, hf_kafka_fetch_session_id, tvb, offset, 4, ENC_BIG_ENDIAN);
2931         offset += 4;
2932     }
2933
2934     if (api_version >= 11) {
2935         proto_tree_add_item(tree, hf_kafka_replica, tvb, offset, 4, ENC_BIG_ENDIAN);
2936         offset += 4;
2937     }
2938
2939     return dissect_kafka_array(tree, tvb, pinfo, offset, api_version, &dissect_kafka_fetch_response_topic);
2940 }
2941
2942 /* PRODUCE REQUEST/RESPONSE */
2943
2944 static int
2945 dissect_kafka_produce_request_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2946                                         kafka_api_version_t api_version _U_)
2947 {
2948     proto_item *ti;
2949     proto_tree *subtree;
2950     guint      len;
2951     kafka_packet_values_t packet_values;
2952     memset(&packet_values, 0, sizeof(packet_values));
2953
2954     subtree = proto_tree_add_subtree(tree, tvb, offset, 14, ett_kafka_partition, &ti, "Partition");
2955
2956     offset = dissect_kafka_partition_id_ret(tvb, pinfo, subtree, offset, &packet_values.partition_id);
2957
2958     len = tvb_get_ntohl(tvb, offset);
2959     offset += 4;
2960
2961     if (len > 0) {
2962         offset = dissect_kafka_message_set(tvb, pinfo, subtree, offset, len, KAFKA_MESSAGE_CODEC_NONE);
2963     }
2964
2965     proto_item_append_text(ti, " (ID=%u)", packet_values.partition_id);
2966     proto_item_set_end(ti, tvb, offset);
2967
2968     return offset;
2969 }
2970
2971 static int
2972 dissect_kafka_produce_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
2973                                     kafka_api_version_t api_version)
2974 {
2975     proto_item *ti;
2976     proto_tree *subtree;
2977     int         offset = start_offset;
2978     int topic_off, topic_len;
2979
2980     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &ti, "Topic");
2981
2982     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_off, &topic_len);
2983     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
2984                                  &dissect_kafka_produce_request_partition);
2985
2986     proto_item_append_text(ti, " (Name=%s)",
2987                            tvb_get_string_enc(wmem_packet_scope(), tvb, topic_off, topic_len, ENC_UTF_8|ENC_NA));
2988     proto_item_set_end(ti, tvb, offset);
2989
2990     return offset;
2991 }
2992
2993 static int
2994 dissect_kafka_produce_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
2995                               kafka_api_version_t api_version)
2996 {
2997     if (api_version >= 3) {
2998         offset = dissect_kafka_string(tree, hf_kafka_transactional_id, tvb, pinfo, offset, NULL, NULL);
2999     }
3000
3001     proto_tree_add_item(tree, hf_kafka_required_acks, tvb, offset, 2, ENC_BIG_ENDIAN);
3002     offset += 2;
3003
3004     proto_tree_add_item(tree, hf_kafka_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
3005     offset += 4;
3006
3007     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
3008                                  &dissect_kafka_produce_request_topic);
3009
3010     return offset;
3011 }
3012
3013 static int
3014 dissect_kafka_produce_response_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3015                                          kafka_api_version_t api_version _U_)
3016 {
3017     proto_item *ti;
3018     proto_tree *subtree;
3019     kafka_packet_values_t packet_values;
3020     memset(&packet_values, 0, sizeof(packet_values));
3021
3022     subtree = proto_tree_add_subtree(tree, tvb, offset, 14, ett_kafka_partition, &ti, "Partition");
3023
3024     offset = dissect_kafka_partition_id_ret(tvb, pinfo, subtree, offset, &packet_values.partition_id);
3025
3026     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
3027
3028     offset = dissect_kafka_offset_ret(tvb, pinfo, subtree, offset, &packet_values.offset);
3029
3030     if (api_version >= 2) {
3031         offset = dissect_kafka_offset_time(tvb, pinfo, subtree, offset, api_version);
3032     }
3033
3034     if (api_version >= 5) {
3035         proto_tree_add_item(subtree, hf_kafka_log_start_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
3036         offset += 8;
3037     }
3038
3039     proto_item_append_text(ti, " (ID=%u, Offset=%" G_GINT64_MODIFIER "i)",
3040                            packet_values.partition_id, packet_values.offset);
3041
3042     return offset;
3043 }
3044
3045 static int
3046 dissect_kafka_produce_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
3047                                      kafka_api_version_t api_version)
3048 {
3049     proto_item *ti;
3050     proto_tree *subtree;
3051     int         offset = start_offset;
3052
3053     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &ti, "Topic");
3054
3055     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, NULL, NULL);
3056     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
3057                                  &dissect_kafka_produce_response_partition);
3058
3059     proto_item_set_len(ti, offset - start_offset);
3060
3061     return offset;
3062 }
3063
3064 static int
3065 dissect_kafka_produce_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3066                                kafka_api_version_t api_version)
3067 {
3068     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version, &dissect_kafka_produce_response_topic);
3069
3070     if (api_version >= 1) {
3071         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
3072     }
3073
3074     return offset;
3075 }
3076
3077 /* OFFSETS REQUEST/RESPONSE */
3078
3079 static int
3080 dissect_kafka_offsets_request_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3081                                         int start_offset, kafka_api_version_t api_version)
3082 {
3083     proto_item *ti;
3084     proto_tree *subtree;
3085     int         offset = start_offset;
3086     kafka_partition_t partition;
3087
3088     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &ti, "Partition");
3089
3090     offset = dissect_kafka_partition_id_ret(tvb, pinfo, subtree, offset, &partition);
3091
3092     if (api_version >= 4) {
3093         proto_tree_add_item(subtree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
3094         offset += 4;
3095     }
3096
3097     offset = dissect_kafka_offset_time(tvb, pinfo, subtree, offset, api_version);
3098
3099     if (api_version == 0) {
3100         proto_tree_add_item(subtree, hf_kafka_max_offsets, tvb, offset, 4, ENC_BIG_ENDIAN);
3101         offset += 4;
3102     }
3103
3104     proto_item_set_len(ti, offset - start_offset);
3105     proto_item_append_text(ti, " (ID=%u)", partition);
3106
3107     return offset;
3108 }
3109
3110 static int
3111 dissect_kafka_offsets_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
3112                                     kafka_api_version_t api_version)
3113 {
3114     proto_item *ti;
3115     proto_tree *subtree;
3116     int         offset = start_offset;
3117
3118     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &ti, "Topic");
3119
3120     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, NULL, NULL);
3121     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
3122                                  &dissect_kafka_offsets_request_partition);
3123
3124     proto_item_set_len(ti, offset - start_offset);
3125
3126     return offset;
3127 }
3128
3129 static int
3130 dissect_kafka_offsets_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3131                               kafka_api_version_t api_version)
3132 {
3133     proto_tree_add_item(tree, hf_kafka_replica, tvb, offset, 4, ENC_BIG_ENDIAN);
3134     offset += 4;
3135
3136     if (api_version >= 2) {
3137         proto_tree_add_item(tree, hf_kafka_isolation_level, tvb, offset, 1, ENC_BIG_ENDIAN);
3138         offset += 1;
3139     }
3140
3141     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version, &dissect_kafka_offsets_request_topic);
3142
3143     return offset;
3144 }
3145
3146 static int
3147 dissect_kafka_offsets_response_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3148                                          int start_offset, kafka_api_version_t api_version)
3149 {
3150     proto_item *ti;
3151     proto_tree *subtree;
3152     int         offset = start_offset;
3153     kafka_partition_t partition;
3154
3155     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &ti, "Partition");
3156
3157     offset = dissect_kafka_partition_id_ret(tvb, pinfo, subtree, offset, &partition);
3158
3159     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
3160
3161     if (api_version == 0) {
3162         offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version, &dissect_kafka_offset);
3163     }
3164     else if (api_version >= 1) {
3165         offset = dissect_kafka_offset_time(tvb, pinfo, subtree, offset, api_version);
3166
3167         offset = dissect_kafka_offset_ret(tvb, pinfo, subtree, offset, NULL);
3168     }
3169
3170     if (api_version >= 4) {
3171         proto_tree_add_item(subtree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
3172         offset += 4;
3173     }
3174
3175     proto_item_set_len(ti, offset - start_offset);
3176     proto_item_append_text(ti, " (ID=%u)", partition);
3177
3178     return offset;
3179 }
3180
3181 static int
3182 dissect_kafka_offsets_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
3183                                      kafka_api_version_t api_version)
3184 {
3185     proto_item *ti;
3186     proto_tree *subtree;
3187     int         offset = start_offset;
3188
3189     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &ti, "Topic");
3190
3191     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, NULL, NULL);
3192     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
3193                                  &dissect_kafka_offsets_response_partition);
3194
3195     proto_item_set_len(ti, offset - start_offset);
3196
3197     return offset;
3198 }
3199
3200 static int
3201 dissect_kafka_offsets_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset,
3202                                kafka_api_version_t api_version)
3203 {
3204     int offset = start_offset;
3205
3206     if (api_version >= 2) {
3207         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
3208     }
3209
3210     return dissect_kafka_array(tree, tvb, pinfo, offset, api_version, &dissect_kafka_offsets_response_topic);
3211 }
3212
3213 /* API_VERSIONS REQUEST/RESPONSE */
3214
3215 static int
3216 dissect_kafka_api_versions_request(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_,
3217                                    int offset _U_, kafka_api_version_t api_version _U_)
3218 {
3219     return offset;
3220 }
3221
3222 static int
3223 dissect_kafka_api_versions_response_api_version(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3224                                                 int offset, kafka_api_version_t api_version _U_)
3225 {
3226     proto_item *ti;
3227     proto_tree *subtree;
3228     kafka_api_key_t api_key;
3229     kafka_api_version_t min_version, max_version;
3230     const kafka_api_info_t *api_info;
3231
3232     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_api_version, &ti,
3233                                      "API Version");
3234
3235     api_key = tvb_get_ntohs(tvb, offset);
3236     proto_tree_add_item(subtree, hf_kafka_api_versions_api_key, tvb, offset, 2, ENC_BIG_ENDIAN);
3237     offset += 2;
3238
3239     min_version = tvb_get_ntohs(tvb, offset);
3240     proto_tree_add_item(subtree, hf_kafka_api_versions_min_version, tvb, offset, 2, ENC_BIG_ENDIAN);
3241     offset += 2;
3242
3243     max_version = tvb_get_ntohs(tvb, offset);
3244     proto_tree_add_item(subtree, hf_kafka_api_versions_max_version, tvb, offset, 2, ENC_BIG_ENDIAN);
3245     offset += 2;
3246
3247     proto_item_set_end(ti, tvb, offset);
3248     if (max_version != min_version) {
3249         /* Range of versions supported. */
3250         proto_item_append_text(subtree, " %s (v%d-%d)",
3251                                kafka_api_key_to_str(api_key),
3252                                min_version, max_version);
3253     }
3254     else {
3255         /* Only one version. */
3256         proto_item_append_text(subtree, " %s (v%d)",
3257                                kafka_api_key_to_str(api_key),
3258                                min_version);
3259     }
3260
3261     api_info = kafka_get_api_info(api_key);
3262     if (api_info == NULL) {
3263         proto_item_append_text(subtree, " [Unknown API key]");
3264         expert_add_info_format(pinfo, ti, &ei_kafka_unknown_api_key,
3265                                "%s API key", kafka_api_key_to_str(api_key));
3266     }
3267     else if (!kafka_is_api_version_supported(api_info, min_version) ||
3268              !kafka_is_api_version_supported(api_info, max_version)) {
3269         if (api_info->min_version == -1) {
3270             proto_item_append_text(subtree, " [Unsupported API version]");
3271             expert_add_info_format(pinfo, ti, &ei_kafka_unsupported_api_version,
3272                                    "Unsupported %s version.",
3273                                    kafka_api_key_to_str(api_key));
3274         }
3275         else if (api_info->min_version == api_info->max_version) {
3276             proto_item_append_text(subtree, " [Unsupported API version. Supports v%d]",
3277                                    api_info->min_version);
3278             expert_add_info_format(pinfo, ti, &ei_kafka_unsupported_api_version,
3279                                    "Unsupported %s version. Supports v%d.",
3280                                    kafka_api_key_to_str(api_key), api_info->min_version);
3281         } else {
3282             proto_item_append_text(subtree, " [Unsupported API version. Supports v%d-%d]",
3283                                    api_info->min_version, api_info->max_version);
3284             expert_add_info_format(pinfo, ti, &ei_kafka_unsupported_api_version,
3285                                    "Unsupported %s version. Supports v%d-%d.",
3286                                    kafka_api_key_to_str(api_key),
3287                                    api_info->min_version, api_info->max_version);
3288         }
3289     }
3290
3291     return offset;
3292 }
3293
3294 static int
3295 dissect_kafka_api_versions_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3296                                     kafka_api_version_t api_version)
3297 {
3298     /* error_code */
3299     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
3300
3301     /* [api_version] */
3302     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
3303                                  &dissect_kafka_api_versions_response_api_version);
3304
3305     if (api_version >= 1) {
3306         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
3307     }
3308     return offset;
3309 }
3310
3311 /* UPDATE_METADATA REQUEST/RESPONSE */
3312
3313 static int
3314 dissect_kafka_update_metadata_request_isr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3315                                           int offset, kafka_api_version_t api_version _U_)
3316 {
3317     /* isr */
3318     proto_tree_add_item(tree, hf_kafka_isr, tvb, offset, 4, ENC_BIG_ENDIAN);
3319     offset += 4;
3320
3321     return offset;
3322 }
3323
3324 static int
3325 dissect_kafka_update_metadata_request_replica(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3326                                               int offset, kafka_api_version_t api_version _U_)
3327 {
3328     /* replica */
3329     proto_tree_add_item(tree, hf_kafka_replica, tvb, offset, 4, ENC_BIG_ENDIAN);
3330     offset += 4;
3331
3332     return offset;
3333 }
3334
3335 static int
3336 dissect_kafka_update_metadata_request_partition_state(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3337                                                       int offset, kafka_api_version_t api_version)
3338 {
3339     proto_tree *subtree, *subsubtree;
3340     proto_item *subti, *subsubti;
3341     int topic_start, topic_len;
3342     kafka_partition_t partition;
3343
3344     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
3345                                      ett_kafka_partition,
3346                                      &subti, "Partition");
3347
3348     if (api_version < 5) {
3349         /* topic */
3350         offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset,
3351                                       &topic_start, &topic_len);
3352     }
3353
3354     /* partition */
3355     partition = (gint32) tvb_get_ntohl(tvb, offset);
3356     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
3357     offset += 4;
3358
3359     /* controller_epoch */
3360     proto_tree_add_item(subtree, hf_kafka_controller_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
3361     offset += 4;
3362
3363     /* leader */
3364     proto_tree_add_item(subtree, hf_kafka_leader_id, tvb, offset, 4, ENC_BIG_ENDIAN);
3365     offset += 4;
3366
3367     /* leader_epoch */
3368     proto_tree_add_item(subtree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
3369     offset += 4;
3370
3371     /* [isr] */
3372     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
3373                                         ett_kafka_isrs,
3374                                         &subsubti, "ISRs");
3375     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
3376                                  &dissect_kafka_update_metadata_request_isr);
3377     proto_item_set_end(subsubti, tvb, offset);
3378
3379     /* zk_version */
3380     proto_tree_add_item(subtree, hf_kafka_zk_version, tvb, offset, 4, ENC_BIG_ENDIAN);
3381     offset += 4;
3382
3383     /* [replica] */
3384     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
3385                                         ett_kafka_replicas,
3386                                         &subsubti, "Replicas");
3387     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
3388                                  &dissect_kafka_update_metadata_request_replica);
3389     proto_item_set_end(subsubti, tvb, offset);
3390
3391     proto_item_set_end(subti, tvb, offset);
3392
3393     if (api_version >= 5) {
3394         proto_item_append_text(subti, " (Partition-ID=%u)",
3395                                partition);
3396     } else {
3397         proto_item_append_text(subti, " (Topic=%s, Partition-ID=%u)",
3398                                tvb_get_string_enc(wmem_packet_scope(), tvb,
3399                                                   topic_start, topic_len, ENC_UTF_8|ENC_NA),
3400                                partition);
3401     }
3402     return offset;
3403 }
3404
3405 static int
3406 dissect_kafka_update_metadata_request_topic_state(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3407                                                       int offset, kafka_api_version_t api_version)
3408 {
3409     proto_tree *subtree;
3410     proto_item *subti;
3411     int topic_start, topic_len;
3412
3413     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
3414                                      ett_kafka_topic,
3415                                      &subti, "Topic");
3416     /* topic */
3417     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset,
3418                                   &topic_start, &topic_len);
3419
3420     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
3421                                  &dissect_kafka_update_metadata_request_partition_state);
3422
3423     proto_item_set_end(subti, tvb, offset);
3424     proto_item_append_text(subti, " (Topic=%s)",
3425                            tvb_get_string_enc(wmem_packet_scope(), tvb,
3426                                     topic_start, topic_len, ENC_UTF_8|ENC_NA));
3427
3428     return offset;
3429 }
3430
3431 static int
3432 dissect_kafka_update_metadata_request_end_point(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3433                                                 int offset, kafka_api_version_t api_version _U_)
3434 {
3435     proto_item *subti;
3436     proto_tree *subtree;
3437     int host_start, host_len;
3438     gint32 broker_port;
3439     gint16 security_protocol_type;
3440
3441     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_broker_end_point,
3442                                      &subti, "End Point");
3443
3444     /* port */
3445     broker_port = (gint32) tvb_get_ntohl(tvb, offset);
3446     proto_tree_add_item(subtree, hf_kafka_broker_port, tvb, offset, 4, ENC_BIG_ENDIAN);
3447     offset += 4;
3448
3449     /* host */
3450     offset = dissect_kafka_string(subtree, hf_kafka_broker_host, tvb, pinfo, offset, &host_start, &host_len);
3451
3452     if (api_version >= 3) {
3453         /* listener_name */
3454         offset = dissect_kafka_string(subtree, hf_kafka_listener_name, tvb, pinfo, offset, NULL, NULL);
3455     }
3456
3457     /* security_protocol_type */
3458     security_protocol_type = (gint16) tvb_get_ntohs(tvb, offset);
3459     proto_tree_add_item(subtree, hf_kafka_broker_security_protocol_type, tvb, offset, 2, ENC_BIG_ENDIAN);
3460     offset += 2;
3461
3462     proto_item_set_end(subti, tvb, offset);
3463     proto_item_append_text(subti, " (%s://%s:%d)",
3464                            val_to_str_const(security_protocol_type,
3465                                             kafka_security_protocol_types, "UNKNOWN"),
3466                            tvb_get_string_enc(wmem_packet_scope(), tvb, host_start, host_len,
3467                                               ENC_UTF_8|ENC_NA),
3468                            broker_port);
3469
3470     return offset;
3471 }
3472
3473 static int
3474 dissect_kafka_update_metadata_request_live_leader(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3475                                                   int offset, kafka_api_version_t api_version)
3476 {
3477     proto_item *subti;
3478     proto_tree *subtree;
3479     gint32 nodeid;
3480
3481     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_broker,
3482                                      &subti, "Live Leader");
3483
3484     /* id */
3485     nodeid = (gint32) tvb_get_ntohl(tvb, offset);
3486     proto_tree_add_item(subtree, hf_kafka_broker_nodeid, tvb, offset, 4, ENC_BIG_ENDIAN);
3487     offset += 4;
3488
3489     if (api_version == 0) {
3490         int host_start, host_len;
3491         gint32 broker_port;
3492
3493         /* host */
3494         offset = dissect_kafka_string(subtree, hf_kafka_broker_host, tvb, pinfo, offset, &host_start, &host_len);
3495
3496         /* port */
3497         broker_port = (gint32) tvb_get_ntohl(tvb, offset);
3498         proto_tree_add_item(subtree, hf_kafka_broker_port, tvb, offset, 4, ENC_BIG_ENDIAN);
3499         offset += 4;
3500
3501         proto_item_append_text(subti, " (node %u: %s:%u)",
3502                                nodeid,
3503                                tvb_get_string_enc(wmem_packet_scope(), tvb, host_start, host_len,
3504                                                   ENC_UTF_8|ENC_NA),
3505                                broker_port);
3506     } else if (api_version >= 1) {
3507         /* [end_point] */
3508         offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
3509                                      &dissect_kafka_update_metadata_request_end_point);
3510
3511         if (api_version >= 2) {
3512             /* rack */
3513             offset = dissect_kafka_string(subtree, hf_kafka_rack, tvb, pinfo, offset, NULL, NULL);
3514         }
3515
3516         proto_item_append_text(subti, " (node %d)",
3517                                nodeid);
3518     }
3519
3520     proto_item_set_end(subti, tvb, offset);
3521
3522     return offset;
3523 }
3524
3525 static int
3526 dissect_kafka_update_metadata_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3527                                       kafka_api_version_t api_version)
3528 {
3529     gint32 controller_id;
3530
3531     /* controller_id */
3532     controller_id = (gint32) tvb_get_ntohl(tvb, offset);
3533     proto_tree_add_item(tree, hf_kafka_controller_id, tvb, offset, 4, ENC_BIG_ENDIAN);
3534     offset += 4;
3535
3536     /* controller_epoch */
3537     proto_tree_add_item(tree, hf_kafka_controller_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
3538     offset += 4;
3539
3540     if (api_version >= 5) {
3541         /* controller_epoch */
3542         proto_tree_add_item(tree, hf_kafka_broker_epoch, tvb, offset, 8, ENC_BIG_ENDIAN);
3543         offset += 8;
3544     }
3545
3546     if (api_version >= 5) {
3547         /* [topic_state] */
3548         offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
3549                                      &dissect_kafka_update_metadata_request_topic_state);
3550     } else {
3551         /* [partition_state] */
3552         offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
3553                                      &dissect_kafka_update_metadata_request_partition_state);
3554     }
3555
3556     /* [live_leader] */
3557     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
3558                                  &dissect_kafka_update_metadata_request_live_leader);
3559
3560     col_append_fstr(pinfo->cinfo, COL_INFO, " (Controller-ID=%d)", controller_id);
3561
3562     return offset;
3563 }
3564
3565 static int
3566 dissect_kafka_update_metadata_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3567                                        kafka_api_version_t api_version _U_)
3568 {
3569     /* error_code */
3570     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
3571
3572     return offset;
3573 }
3574
3575 /* CONTROLLED_SHUTDOWN REQUEST/RESPONSE */
3576
3577 static int
3578 dissect_kafka_controlled_shutdown_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3579                                           kafka_api_version_t api_version _U_)
3580 {
3581     gint32 broker_id;
3582
3583     /* broker_id */
3584     broker_id = (gint32) tvb_get_ntohl(tvb, offset);
3585     proto_tree_add_item(tree, hf_kafka_broker_nodeid, tvb, offset, 4, ENC_BIG_ENDIAN);
3586     offset += 4;
3587
3588     if (api_version >= 2) {
3589         proto_tree_add_item(tree, hf_kafka_broker_epoch, tvb, offset, 8, ENC_BIG_ENDIAN);
3590         offset += 8;
3591     }
3592
3593     col_append_fstr(pinfo->cinfo, COL_INFO, " (Broker-ID=%d)", broker_id);
3594
3595     return offset;
3596 }
3597
3598 static int
3599 dissect_kafka_controlled_shutdown_response_partition_remaining(tvbuff_t *tvb, packet_info *pinfo,
3600                                                                proto_tree *tree, int offset,
3601                                                                kafka_api_version_t api_version _U_)
3602 {
3603     proto_item *subti;
3604     proto_tree *subtree;
3605     int topic_start, topic_len;
3606     kafka_partition_t partition;
3607
3608     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti,
3609                                      "Partition Remaining");
3610
3611     /* topic */
3612     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset,
3613                                   &topic_start, &topic_len);
3614
3615     /* partition */
3616     partition = (gint32) tvb_get_ntohl(tvb, offset);
3617     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
3618     offset += 4;
3619
3620     proto_item_set_end(subti, tvb, offset);
3621     proto_item_append_text(subti, " (Topic=%s, Partition-ID=%d)",
3622                            tvb_get_string_enc(wmem_packet_scope(), tvb,
3623                                               topic_start, topic_len, ENC_UTF_8|ENC_NA),
3624                            partition);
3625
3626     return offset;
3627 }
3628
3629 static int
3630 dissect_kafka_controlled_shutdown_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3631                                            kafka_api_version_t api_version)
3632 {
3633     /* error_code */
3634     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
3635
3636     /* [partition_remaining] */
3637     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
3638                                  &dissect_kafka_controlled_shutdown_response_partition_remaining);
3639
3640     return offset;
3641 }
3642
3643 /* OFFSET_COMMIT REQUEST/RESPONSE */
3644
3645 static int
3646 dissect_kafka_offset_commit_request_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3647                                               int offset, kafka_api_version_t api_version _U_)
3648 {
3649     proto_item *subti;
3650     proto_tree *subtree;
3651     kafka_partition_t partition_id;
3652     kafka_offset_t partition_offset;
3653
3654     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti,
3655                                      "Partition");
3656
3657     /* partition */
3658     partition_id = (gint32) tvb_get_ntohl(tvb, offset);
3659     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
3660     offset += 4;
3661
3662     /* offset */
3663     partition_offset = (gint64) tvb_get_ntoh64(tvb, offset);
3664     proto_tree_add_item(subtree, hf_kafka_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
3665     offset += 8;
3666
3667     if (api_version >= 6) {
3668         proto_tree_add_item(subtree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
3669         offset += 4;
3670     }
3671
3672     if (api_version == 1) {
3673         /* timestamp */
3674         proto_tree_add_item(subtree, hf_kafka_commit_timestamp, tvb, offset, 8, ENC_TIME_MSECS|ENC_BIG_ENDIAN);
3675         offset += 8;
3676     }
3677
3678     /* metadata */
3679     offset = dissect_kafka_string(subtree, hf_kafka_metadata, tvb, pinfo, offset, NULL, NULL);
3680
3681     proto_item_set_end(subti, tvb, offset);
3682     proto_item_append_text(subti, " (ID=%u, Offset=%" G_GINT64_MODIFIER "i)",
3683                            partition_id, partition_offset);
3684
3685     return offset;
3686 }
3687
3688 static int
3689 dissect_kafka_offset_commit_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3690                                           int offset, kafka_api_version_t api_version)
3691 {
3692     proto_item *subti;
3693     proto_tree *subtree;
3694     int topic_start, topic_len;
3695
3696     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
3697
3698     /* topic */
3699     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset,
3700                                   &topic_start, &topic_len);
3701
3702     /* [partition] */
3703     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
3704                                  &dissect_kafka_offset_commit_request_partition);
3705
3706     proto_item_set_end(subti, tvb, offset);
3707     proto_item_append_text(subti, " (Topic=%s)",
3708                            tvb_get_string_enc(wmem_packet_scope(), tvb,
3709                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
3710
3711     return offset;
3712 }
3713
3714 static int
3715 dissect_kafka_offset_commit_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3716                                     kafka_api_version_t api_version)
3717 {
3718     int group_start, group_len;
3719
3720     /* group_id */
3721     offset = dissect_kafka_string(tree, hf_kafka_consumer_group, tvb, pinfo, offset,
3722                                   &group_start, &group_len);
3723
3724     if (api_version >= 1) {
3725         /* group_generation_id */
3726         proto_tree_add_item(tree, hf_kafka_generation_id, tvb, offset, 4, ENC_BIG_ENDIAN);
3727         offset += 4;
3728
3729         /* member_id */
3730         offset = dissect_kafka_string(tree, hf_kafka_member_id, tvb, pinfo, offset, NULL, NULL);
3731
3732         if (api_version >= 7){
3733             /* instance_id */
3734             offset = dissect_kafka_string(tree, hf_kafka_consumer_group_instance, tvb, pinfo, offset, NULL, NULL);
3735         }
3736
3737         if (api_version >= 2 && api_version < 5) {
3738             /* retention_time */
3739             proto_tree_add_item(tree, hf_kafka_retention_time, tvb, offset, 8, ENC_BIG_ENDIAN);
3740             offset += 8;
3741         }
3742     }
3743
3744     /* [topic] */
3745     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
3746                                  &dissect_kafka_offset_commit_request_topic);
3747
3748     col_append_fstr(pinfo->cinfo, COL_INFO,
3749                     " (Group=%s)",
3750                     tvb_get_string_enc(wmem_packet_scope(), tvb,
3751                                        group_start, group_len, ENC_UTF_8|ENC_NA));
3752
3753     return offset;
3754 }
3755
3756 static int
3757 dissect_kafka_offset_commit_response_partition_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3758                                                         int offset, kafka_api_version_t api_version _U_)
3759 {
3760     proto_item *subti;
3761     proto_tree *subtree;
3762     kafka_partition_t partition;
3763     kafka_error_t error;
3764
3765     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti,
3766                                      "Partition");
3767
3768     /* partition */
3769     partition = (gint32) tvb_get_ntohl(tvb, offset);
3770     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
3771     offset += 4;
3772
3773     /* error_code */
3774     offset = dissect_kafka_error_ret(tvb, pinfo, subtree, offset, &error);
3775
3776     proto_item_set_end(subti, tvb, offset);
3777     proto_item_append_text(subti, " (Partition-ID=%d, Error=%s)",
3778                            partition, kafka_error_to_str(error));
3779
3780     return offset;
3781 }
3782
3783 static int
3784 dissect_kafka_offset_commit_response_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3785                                               int offset, kafka_api_version_t api_version)
3786 {
3787     proto_item *subti;
3788     proto_tree *subtree;
3789     int topic_start, topic_len;
3790
3791     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
3792
3793     /* topic */
3794     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset,
3795                                   &topic_start, &topic_len);
3796
3797     /* [partition_response] */
3798     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
3799                                  &dissect_kafka_offset_commit_response_partition_response);
3800
3801     proto_item_set_end(subti, tvb, offset);
3802     proto_item_append_text(subti, " (Name=%s)",
3803                            tvb_get_string_enc(wmem_packet_scope(), tvb,
3804                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
3805
3806     return offset;
3807 }
3808
3809 static int
3810 dissect_kafka_offset_commit_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3811                                      kafka_api_version_t api_version)
3812 {
3813     if (api_version >= 3) {
3814         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
3815     }
3816
3817     /* [responses] */
3818     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
3819                                  &dissect_kafka_offset_commit_response_response);
3820
3821     return offset;
3822 }
3823
3824 /* GROUP_COORDINATOR REQUEST/RESPONSE */
3825
3826 static int
3827 dissect_kafka_find_coordinator_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3828                                         kafka_api_version_t api_version _U_)
3829 {
3830     int group_start, group_len;
3831
3832     if (api_version == 0) {
3833         /* group_id */
3834         offset = dissect_kafka_string(tree, hf_kafka_consumer_group, tvb, pinfo, offset,
3835                                       &group_start, &group_len);
3836
3837         col_append_fstr(pinfo->cinfo, COL_INFO,
3838                         " (Group=%s)",
3839                         tvb_get_string_enc(wmem_packet_scope(), tvb,
3840                                            group_start, group_len, ENC_UTF_8|ENC_NA));
3841     } else {
3842
3843         offset = dissect_kafka_string(tree, hf_kafka_coordinator_key, tvb, pinfo, offset,
3844                                       NULL, NULL);
3845
3846         proto_tree_add_item(tree, hf_kafka_coordinator_type, tvb, offset, 1, ENC_NA);
3847         offset += 4;
3848
3849     }
3850
3851     return offset;
3852 }
3853
3854 static int
3855 dissect_kafka_find_coordinator_response_coordinator(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3856                                                      int offset, kafka_api_version_t api_version _U_)
3857 {
3858     proto_item *subti;
3859     proto_tree *subtree;
3860     gint32 node_id;
3861     int host_start, host_len;
3862     gint32 port;
3863
3864     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_broker, &subti, "Coordinator");
3865
3866     /* node_id */
3867     node_id = (gint32) tvb_get_ntohl(tvb, offset);
3868     proto_tree_add_item(subtree, hf_kafka_broker_nodeid, tvb, offset, 4, ENC_BIG_ENDIAN);
3869     offset += 4;
3870
3871     /* host */
3872     offset = dissect_kafka_string(subtree, hf_kafka_broker_host, tvb, pinfo, offset,
3873                                   &host_start, &host_len);
3874
3875     /* port */
3876     port = (gint32) tvb_get_ntohl(tvb, offset);
3877     proto_tree_add_item(subtree, hf_kafka_broker_port, tvb, offset, 4, ENC_BIG_ENDIAN);
3878     offset += 4;
3879
3880     proto_item_set_end(subti, tvb, offset);
3881
3882     if (node_id >= 0) {
3883         proto_item_append_text(subti, " (node %d: %s:%d)",
3884                                node_id,
3885                                tvb_get_string_enc(wmem_packet_scope(), tvb,
3886                                                   host_start, host_len, ENC_UTF_8|ENC_NA),
3887                                port);
3888     } else {
3889         proto_item_append_text(subti, " (none)");
3890     }
3891
3892     return offset;
3893 }
3894
3895 static int
3896 dissect_kafka_find_coordinator_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3897                                          kafka_api_version_t api_version)
3898 {
3899     if (api_version >= 1) {
3900         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
3901     }
3902
3903     /* error_code */
3904     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
3905
3906     if (api_version >= 1) {
3907         offset = dissect_kafka_string(tree, hf_kafka_error_message, tvb, pinfo, offset,
3908                                       NULL, NULL);
3909     }
3910
3911     /* coordinator */
3912     offset = dissect_kafka_find_coordinator_response_coordinator(tvb, pinfo, tree, offset, api_version);
3913
3914     return offset;
3915 }
3916
3917 /* JOIN_GROUP REQUEST/RESPONSE */
3918
3919 static int
3920 dissect_kafka_join_group_request_group_protocols(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
3921                                                  int offset, kafka_api_version_t api_version _U_)
3922 {
3923     proto_item *subti;
3924     proto_tree *subtree;
3925     int protocol_start, protocol_len;
3926
3927     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group_protocol, &subti,
3928                                      "Group Protocol");
3929
3930     /* protocol_name */
3931     offset = dissect_kafka_string(subtree, hf_kafka_protocol_name, tvb, pinfo, offset,
3932                                   &protocol_start, &protocol_len);
3933
3934     /* protocol_metadata */
3935     offset = dissect_kafka_bytes(subtree, hf_kafka_protocol_metadata, tvb, pinfo, offset, NULL, NULL);
3936
3937     proto_item_set_end(subti, tvb, offset);
3938     proto_item_append_text(subti, " (Group-ID=%s)",
3939                            tvb_get_string_enc(wmem_packet_scope(), tvb,
3940                                               protocol_start, protocol_len, ENC_UTF_8|ENC_NA));
3941
3942     return offset;
3943 }
3944
3945 static int
3946 dissect_kafka_join_group_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
3947                                  kafka_api_version_t api_version)
3948 {
3949     proto_item *subti;
3950     proto_tree *subtree;
3951     int group_start, group_len;
3952     int member_start, member_len;
3953
3954     /* group_id */
3955     offset = dissect_kafka_string(tree, hf_kafka_consumer_group, tvb, pinfo, offset,
3956                                   &group_start, &group_len);
3957
3958     /* session_timeout */
3959     proto_tree_add_item(tree, hf_kafka_session_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
3960     offset += 4;
3961
3962     if (api_version > 0) {
3963         /* rebalance_timeout */
3964         proto_tree_add_item(tree, hf_kafka_rebalance_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
3965         offset += 4;
3966     }
3967
3968     /* member_id */
3969     offset = dissect_kafka_string(tree, hf_kafka_member_id, tvb, pinfo, offset,
3970                                   &member_start, &member_len);
3971
3972     if (api_version >= 5) {
3973         /* instance id */
3974         offset = dissect_kafka_string(tree, hf_kafka_consumer_group_instance, tvb, pinfo, offset,
3975                                       NULL, NULL);
3976     }
3977
3978     /* protocol_type */
3979     offset = dissect_kafka_string(tree, hf_kafka_protocol_type, tvb, pinfo, offset, NULL, NULL);
3980
3981     /* [group_protocols] */
3982     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group_protocols, &subti,
3983                                      "Group Protocols");
3984     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
3985                                  &dissect_kafka_join_group_request_group_protocols);
3986     proto_item_set_end(subti, tvb, offset);
3987
3988     col_append_fstr(pinfo->cinfo, COL_INFO,
3989                     " (Group=%s, Member=%s)",
3990                     tvb_get_string_enc(wmem_packet_scope(), tvb,
3991                                        group_start, group_len, ENC_UTF_8|ENC_NA),
3992                     tvb_get_string_enc(wmem_packet_scope(), tvb,
3993                                        member_start, member_len, ENC_UTF_8|ENC_NA));
3994
3995     return offset;
3996 }
3997
3998 static int
3999 dissect_kafka_join_group_response_member(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4000                                          int offset, kafka_api_version_t api_version)
4001 {
4002     proto_item *subti;
4003     proto_tree *subtree;
4004     int member_start, member_len;
4005
4006     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group_member, &subti, "Member");
4007
4008     /* member_id */
4009     offset = dissect_kafka_string(subtree, hf_kafka_member_id, tvb, pinfo, offset,
4010                                   &member_start, &member_len);
4011
4012     if (api_version >= 5) {
4013         /* instance id */
4014         offset = dissect_kafka_string(subtree, hf_kafka_consumer_group_instance, tvb, pinfo, offset,
4015                                       NULL, NULL);
4016     }
4017
4018     /* member_metadata */
4019     offset = dissect_kafka_bytes(subtree, hf_kafka_member_metadata, tvb, pinfo, offset, NULL, NULL);
4020
4021     proto_item_set_end(subti, tvb, offset);
4022     proto_item_append_text(subti, " (Member=%s)",
4023                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4024                                               member_start, member_len, ENC_UTF_8|ENC_NA));
4025
4026     return offset;
4027 }
4028
4029 static int
4030 dissect_kafka_join_group_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4031                                   kafka_api_version_t api_version)
4032 {
4033     proto_item *subti;
4034     proto_tree *subtree;
4035     int member_start, member_len;
4036
4037     if (api_version >= 2) {
4038         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
4039     }
4040
4041     /* error_code */
4042     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
4043
4044     /* generation_id */
4045     proto_tree_add_item(tree, hf_kafka_generation_id, tvb, offset, 4, ENC_BIG_ENDIAN);
4046     offset += 4;
4047
4048     /* group_protocol */
4049     offset = dissect_kafka_string(tree, hf_kafka_protocol_name, tvb, pinfo, offset, NULL, NULL);
4050
4051     /* leader_id */
4052     offset = dissect_kafka_string(tree, hf_kafka_group_leader_id, tvb, pinfo, offset, NULL, NULL);
4053
4054     /* member_id */
4055     offset = dissect_kafka_string(tree, hf_kafka_member_id, tvb, pinfo, offset,
4056                                   &member_start, &member_len);
4057
4058     /* [member] */
4059     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group_members, &subti, "Members");
4060     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
4061                                  &dissect_kafka_join_group_response_member);
4062     proto_item_set_end(subti, tvb, offset);
4063
4064     col_append_fstr(pinfo->cinfo, COL_INFO,
4065                     " (Member=%s)",
4066                     tvb_get_string_enc(wmem_packet_scope(), tvb,
4067                                        member_start, member_len, ENC_UTF_8|ENC_NA));
4068
4069     return offset;
4070 }
4071
4072 /* HEARTBEAT REQUEST/RESPONSE */
4073
4074 static int
4075 dissect_kafka_heartbeat_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4076                                 kafka_api_version_t api_version _U_)
4077 {
4078     int group_start, group_len;
4079     int member_start, member_len;
4080
4081     /* group_id */
4082     offset = dissect_kafka_string(tree, hf_kafka_consumer_group, tvb, pinfo, offset,
4083                                   &group_start, &group_len);
4084
4085     /* group_generation_id */
4086     proto_tree_add_item(tree, hf_kafka_generation_id, tvb, offset, 4, ENC_BIG_ENDIAN);
4087     offset += 4;
4088
4089     /* member_id */
4090     offset = dissect_kafka_string(tree, hf_kafka_member_id, tvb, pinfo, offset,
4091                                   &member_start, &member_len);
4092
4093     if (api_version >= 3) {
4094         /* instance_id */
4095         offset = dissect_kafka_string(tree, hf_kafka_consumer_group_instance, tvb, pinfo, offset,
4096                                       NULL, NULL);
4097     }
4098
4099     col_append_fstr(pinfo->cinfo, COL_INFO,
4100                     " (Group=%s, Member=%s)",
4101                     tvb_get_string_enc(wmem_packet_scope(), tvb,
4102                                        group_start, group_len, ENC_UTF_8|ENC_NA),
4103                     tvb_get_string_enc(wmem_packet_scope(), tvb,
4104                                        member_start, member_len, ENC_UTF_8|ENC_NA));
4105
4106     return offset;
4107 }
4108
4109 static int
4110 dissect_kafka_heartbeat_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4111                                  kafka_api_version_t api_version _U_)
4112 {
4113     if (api_version >= 1) {
4114         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
4115     }
4116
4117     /* error_code */
4118     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
4119
4120     return offset;
4121 }
4122
4123 /* LEAVE_GROUP REQUEST/RESPONSE */
4124
4125 static int
4126 dissect_kafka_leave_group_request_member(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4127                                   kafka_api_version_t api_version _U_)
4128 {
4129     proto_item *subti;
4130     proto_tree *subtree;
4131     int member_start, member_len;
4132     int instance_start, instance_len;
4133
4134     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group_member, &subti, "Member");
4135
4136     /* member_id */
4137     offset = dissect_kafka_string(subtree, hf_kafka_member_id, tvb, pinfo, offset,
4138                                   &member_start, &member_len);
4139
4140     /* instance_id */
4141     offset = dissect_kafka_string(subtree, hf_kafka_consumer_group_instance, tvb, pinfo, offset,
4142                                   &instance_start, &instance_len);
4143
4144     proto_item_set_end(subti, tvb, offset);
4145     proto_item_append_text(subti, " (Member=%s, Group-Instance=%s)",
4146                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4147                                               member_start, member_len, ENC_UTF_8|ENC_NA),
4148                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4149                                               instance_start, instance_len, ENC_UTF_8|ENC_NA)
4150                            );
4151
4152     return offset;
4153 }
4154
4155 static int
4156 dissect_kafka_leave_group_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4157                                   kafka_api_version_t api_version)
4158 {
4159     int group_start, group_len;
4160     int member_start, member_len;
4161     proto_item *subti;
4162     proto_tree *subtree;
4163
4164     /* group_id */
4165     offset = dissect_kafka_string(tree, hf_kafka_consumer_group, tvb, pinfo, offset,
4166                                   &group_start, &group_len);
4167
4168     if (api_version >= 0 && api_version <= 2) {
4169
4170         /* member_id */
4171         offset = dissect_kafka_string(tree, hf_kafka_member_id, tvb, pinfo, offset,
4172                                       &member_start, &member_len);
4173
4174         col_append_fstr(pinfo->cinfo, COL_INFO,
4175                         " (Group=%s, Member=%s)",
4176                         tvb_get_string_enc(wmem_packet_scope(), tvb,
4177                                            group_start, group_len, ENC_UTF_8|ENC_NA),
4178                         tvb_get_string_enc(wmem_packet_scope(), tvb,
4179                                            member_start, member_len, ENC_UTF_8|ENC_NA));
4180
4181     } else if (api_version >= 3) {
4182
4183         // KIP-345
4184         subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group_members, &subti, "Members");
4185         offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
4186                                      &dissect_kafka_leave_group_request_member);
4187         proto_item_set_end(subti, tvb, offset);
4188
4189         col_append_fstr(pinfo->cinfo, COL_INFO,
4190                         " (Group=%s)",
4191                         tvb_get_string_enc(wmem_packet_scope(), tvb,
4192                                            group_start, group_len, ENC_UTF_8|ENC_NA));
4193
4194     }
4195
4196     return offset;
4197 }
4198
4199 static int
4200 dissect_kafka_leave_group_response_member(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4201                                                   kafka_api_version_t api_version _U_)
4202 {
4203     proto_item *subti;
4204     proto_tree *subtree;
4205     int member_start, member_len;
4206     int instance_start, instance_len;
4207
4208     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group_member, &subti, "Member");
4209
4210     /* member_id */
4211     offset = dissect_kafka_string(subtree, hf_kafka_member_id, tvb, pinfo, offset,
4212                                   &member_start, &member_len);
4213
4214     /* instance_id */
4215     offset = dissect_kafka_string(subtree, hf_kafka_consumer_group_instance, tvb, pinfo, offset,
4216                                   &instance_start, &instance_len);
4217
4218     /* error_code */
4219     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
4220
4221     proto_item_set_end(subti, tvb, offset);
4222     proto_item_append_text(subti, " (Member=%s, Group-Instance=%s)",
4223                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4224                                               member_start, member_len, ENC_UTF_8|ENC_NA),
4225                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4226                                               instance_start, instance_len, ENC_UTF_8|ENC_NA)
4227                            );
4228
4229     return offset;
4230 }
4231
4232 static int
4233 dissect_kafka_leave_group_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4234                                    kafka_api_version_t api_version _U_)
4235 {
4236     proto_item *subti;
4237     proto_tree *subtree;
4238
4239     if (api_version >= 1) {
4240         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
4241     }
4242
4243     /* error_code */
4244     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
4245
4246     if (api_version >= 3) {
4247
4248         // KIP-345
4249         subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group_members, &subti, "Members");
4250         offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
4251                                      &dissect_kafka_leave_group_response_member);
4252         proto_item_set_end(subti, tvb, offset);
4253
4254     }
4255
4256
4257     return offset;
4258 }
4259
4260 /* SYNC_GROUP REQUEST/RESPONSE */
4261
4262 static int
4263 dissect_kafka_sync_group_request_group_assignment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4264                                                   int offset, kafka_api_version_t api_version _U_)
4265 {
4266     proto_item *subti;
4267     proto_tree *subtree;
4268     int member_start, member_len;
4269
4270     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group_assignment, &subti,
4271                                      "Group Assignment");
4272
4273     /* member_id */
4274     offset = dissect_kafka_string(subtree, hf_kafka_member_id, tvb, pinfo, offset,
4275                                   &member_start, &member_len);
4276
4277     /* member_assigment */
4278     offset = dissect_kafka_bytes(subtree, hf_kafka_member_assignment, tvb, pinfo, offset, NULL, NULL);
4279
4280     proto_item_set_end(subti, tvb, offset);
4281     proto_item_append_text(subti, " (Member=%s)",
4282                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4283                                               member_start, member_len, ENC_UTF_8|ENC_NA));
4284
4285     return offset;
4286 }
4287
4288 static int
4289 dissect_kafka_sync_group_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4290                                  kafka_api_version_t api_version)
4291 {
4292     proto_item *subti;
4293     proto_tree *subtree;
4294     int group_start, group_len;
4295     int member_start, member_len;
4296
4297     /* group_id */
4298     offset = dissect_kafka_string(tree, hf_kafka_consumer_group, tvb, pinfo, offset,
4299                                   &group_start, &group_len);
4300
4301     /* generation_id */
4302     proto_tree_add_item(tree, hf_kafka_generation_id, tvb, offset, 4, ENC_BIG_ENDIAN);
4303     offset += 4;
4304
4305     /* member_id */
4306     offset = dissect_kafka_string(tree, hf_kafka_member_id, tvb, pinfo, offset,
4307                                   &member_start, &member_len);
4308
4309     if (api_version >= 3) {
4310         /* instance_id */
4311         offset = dissect_kafka_string(tree, hf_kafka_consumer_group_instance, tvb, pinfo, offset,
4312                                   NULL, NULL);
4313     }
4314
4315     /* [group_assignment] */
4316     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group_assignments, &subti,
4317                                      "Group Assignments");
4318     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
4319                                  &dissect_kafka_sync_group_request_group_assignment);
4320     proto_item_set_end(subti, tvb, offset);
4321
4322     col_append_fstr(pinfo->cinfo, COL_INFO,
4323                     " (Group=%s, Member=%s)",
4324                     tvb_get_string_enc(wmem_packet_scope(), tvb,
4325                                        group_start, group_len, ENC_UTF_8|ENC_NA),
4326                     tvb_get_string_enc(wmem_packet_scope(), tvb,
4327                                        member_start, member_len, ENC_UTF_8|ENC_NA));
4328
4329     return offset;
4330 }
4331
4332 static int
4333 dissect_kafka_sync_group_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4334                                   kafka_api_version_t api_version _U_)
4335 {
4336     if (api_version >= 1) {
4337         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
4338     }
4339
4340     /* error_code */
4341     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
4342
4343     /* member_assignment */
4344     offset = dissect_kafka_bytes(tree, hf_kafka_member_assignment, tvb, pinfo, offset, NULL, NULL);
4345
4346     return offset;
4347 }
4348
4349 /* DESCRIBE_GROUPS REQUEST/RESPONSE */
4350
4351 static int
4352 dissect_kafka_describe_groups_request_group_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4353                                               int offset, kafka_api_version_t api_version _U_)
4354 {
4355     /* group_id */
4356     offset = dissect_kafka_string(tree, hf_kafka_consumer_group, tvb, pinfo, offset, NULL, NULL);
4357
4358     return offset;
4359 }
4360
4361 static int
4362 dissect_kafka_describe_groups_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4363                                       kafka_api_version_t api_version)
4364 {
4365     /* [group_id] */
4366     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
4367                                  &dissect_kafka_describe_groups_request_group_id);
4368
4369     if (api_version >= 3) {
4370         proto_tree_add_item(tree, hf_kafka_include_group_authorized_ops, tvb, offset, 1, ENC_BIG_ENDIAN);
4371         offset += 1;
4372     }
4373
4374     return offset;
4375 }
4376
4377 static int
4378 dissect_kafka_describe_groups_response_member(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4379                                               kafka_api_version_t api_version _U_)
4380 {
4381     proto_item *subti;
4382     proto_tree *subtree;
4383     int member_start, member_len;
4384     int instance_start, instance_len;
4385
4386     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group_member, &subti, "Member");
4387
4388     /* member_id */
4389     offset = dissect_kafka_string(subtree, hf_kafka_member_id, tvb, pinfo, offset,
4390                                   &member_start, &member_len);
4391
4392     if (api_version >= 4) {
4393         /* instance_id */
4394         offset = dissect_kafka_string(subtree, hf_kafka_consumer_group_instance, tvb, pinfo, offset,
4395                                       &instance_start, &instance_len);
4396     }
4397
4398     /* client_id */
4399     offset = dissect_kafka_string(subtree, hf_kafka_client_id, tvb, pinfo, offset, NULL, NULL);
4400
4401     /* client_host */
4402     offset = dissect_kafka_string(subtree, hf_kafka_client_host, tvb, pinfo, offset, NULL, NULL);
4403
4404     /* member_metadata */
4405     offset = dissect_kafka_bytes(subtree, hf_kafka_member_metadata, tvb, pinfo, offset, NULL, NULL);
4406
4407     /* member_assignment */
4408     offset = dissect_kafka_bytes(subtree, hf_kafka_member_assignment, tvb, pinfo, offset, NULL, NULL);
4409
4410     proto_item_set_end(subti, tvb, offset);
4411
4412     if (api_version < 4) {
4413         proto_item_append_text(subti, " (Member=%s)",
4414                                tvb_get_string_enc(wmem_packet_scope(), tvb,
4415                                                   member_start, member_len, ENC_UTF_8|ENC_NA));
4416     } else {
4417         proto_item_append_text(subti, " (Member=%s, Instance=%s)",
4418                                tvb_get_string_enc(wmem_packet_scope(), tvb,
4419                                                   member_start, member_len, ENC_UTF_8|ENC_NA),
4420                                tvb_get_string_enc(wmem_packet_scope(), tvb,
4421                                                   instance_start, instance_len, ENC_UTF_8|ENC_NA));
4422     }
4423     return offset;
4424 }
4425
4426 static int
4427 dissect_kafka_describe_groups_response_group(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4428                                              kafka_api_version_t api_version)
4429 {
4430     proto_item *subti, *subsubti;
4431     proto_tree *subtree, *subsubtree;
4432     int group_start, group_len;
4433
4434     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group, &subti, "Group");
4435
4436     /* error_code */
4437     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
4438
4439     /* group_id */
4440     offset = dissect_kafka_string(subtree, hf_kafka_consumer_group, tvb, pinfo, offset,
4441                                   &group_start, &group_len);
4442
4443     /* state */
4444     offset = dissect_kafka_string(subtree, hf_kafka_group_state, tvb, pinfo, offset, NULL, NULL);
4445
4446     /* protocol_type */
4447     offset = dissect_kafka_string(subtree, hf_kafka_protocol_type, tvb, pinfo, offset, NULL, NULL);
4448
4449     /* protocol */
4450     offset = dissect_kafka_string(subtree, hf_kafka_protocol_name, tvb, pinfo, offset, NULL, NULL);
4451
4452     /* [member] */
4453     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_group_members,
4454                                         &subsubti, "Members");
4455     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
4456                                  &dissect_kafka_describe_groups_response_member);
4457     proto_item_set_end(subsubti, tvb, offset);
4458
4459     if (api_version >= 3) {
4460         proto_tree_add_item(subtree, hf_kafka_group_authorized_ops, tvb, offset, 4, ENC_BIG_ENDIAN);
4461         offset += 4;
4462     }
4463
4464     proto_item_set_end(subti, tvb, offset);
4465     proto_item_append_text(subti, " (Group=%s)",
4466                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4467                                               group_start, group_len, ENC_UTF_8|ENC_NA));
4468
4469     return offset;
4470 }
4471
4472 static int
4473 dissect_kafka_describe_groups_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4474                                        kafka_api_version_t api_version)
4475 {
4476     if (api_version >= 1) {
4477         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
4478     }
4479
4480     /* [group] */
4481     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
4482                                  &dissect_kafka_describe_groups_response_group);
4483
4484     return offset;
4485 }
4486
4487 /* LIST_GROUPS REQUEST/RESPONSE */
4488
4489 static int
4490 dissect_kafka_list_groups_request(tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_, int offset,
4491                                   kafka_api_version_t api_version _U_)
4492 {
4493     return offset;
4494 }
4495
4496 static int
4497 dissect_kafka_list_groups_response_group(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4498                                          kafka_api_version_t api_version _U_)
4499 {
4500     proto_item *subti;
4501     proto_tree *subtree;
4502     int group_start, group_len;
4503     int protocol_type_start, protocol_type_len;
4504
4505     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group, &subti, "Group");
4506
4507     /* group_id */
4508     offset = dissect_kafka_string(subtree, hf_kafka_consumer_group, tvb, pinfo, offset,
4509                                   &group_start, &group_len);
4510
4511     /* protocol_type */
4512     offset = dissect_kafka_string(subtree, hf_kafka_protocol_type, tvb, pinfo, offset,
4513                                   &protocol_type_start, &protocol_type_len);
4514
4515     proto_item_set_end(subti, tvb, offset);
4516     proto_item_append_text(subti, " (Group-ID=%s, Protocol-Type=%s)",
4517                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4518                                               group_start, group_len, ENC_UTF_8|ENC_NA),
4519                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4520                                               protocol_type_start, protocol_type_len, ENC_UTF_8|ENC_NA));
4521
4522     return offset;
4523 }
4524
4525 static int
4526 dissect_kafka_list_groups_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4527                                    kafka_api_version_t api_version)
4528 {
4529     if (api_version >= 1) {
4530         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
4531     }
4532
4533     /* error_code */
4534     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
4535
4536     /* [group] */
4537     offset = dissect_kafka_array(tree, tvb, pinfo, offset, api_version,
4538                                  &dissect_kafka_list_groups_response_group);
4539
4540     return offset;
4541 }
4542
4543 /* SASL_HANDSHAKE REQUEST/RESPONSE */
4544
4545 static int
4546 dissect_kafka_sasl_handshake_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4547                                      kafka_api_version_t api_version _U_)
4548 {
4549     /* mechanism */
4550     offset = dissect_kafka_string(tree, hf_kafka_sasl_mechanism, tvb, pinfo, offset, NULL, NULL);
4551
4552     return offset;
4553 }
4554
4555 static int
4556 dissect_kafka_sasl_handshake_response_enabled_mechanism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4557                                                         int offset, kafka_api_version_t api_version _U_)
4558 {
4559     /* enabled_mechanism */
4560     offset = dissect_kafka_string(tree, hf_kafka_sasl_mechanism, tvb, pinfo, offset, NULL, NULL);
4561
4562     return offset;
4563 }
4564
4565 static int
4566 dissect_kafka_sasl_handshake_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4567                                       kafka_api_version_t api_version)
4568 {
4569     proto_item *subti;
4570     proto_tree *subtree;
4571
4572     /* error_code */
4573     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
4574
4575     /* [enabled_mechanism] */
4576     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
4577                                      ett_kafka_sasl_enabled_mechanisms,
4578                                      &subti, "Enabled SASL Mechanisms");
4579     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
4580                                  &dissect_kafka_sasl_handshake_response_enabled_mechanism);
4581     proto_item_set_end(subti, tvb, offset);
4582
4583     return offset;
4584 }
4585
4586 /* CREATE_TOPICS REQUEST/RESPONSE */
4587
4588 static int
4589 dissect_kafka_create_topics_request_replica(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
4590                                             int offset, kafka_api_version_t api_version _U_)
4591 {
4592     /* replica */
4593     proto_tree_add_item(tree, hf_kafka_replica, tvb, offset, 4, ENC_BIG_ENDIAN);
4594     offset += 4;
4595
4596     return offset;
4597 }
4598
4599 static int
4600 dissect_kafka_create_topics_request_replica_assignment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4601                                                        int offset, kafka_api_version_t api_version _U_)
4602 {
4603     proto_item *subti;
4604     proto_tree *subtree;
4605     kafka_partition_t partition;
4606
4607     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
4608                                      ett_kafka_replica_assignment,
4609                                      &subti, "Replica Assignment");
4610
4611     /* partition_id */
4612     partition = (gint32) tvb_get_ntohl(tvb, offset);
4613     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
4614     offset += 4;
4615
4616     /* [replica] */
4617     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
4618                                  &dissect_kafka_create_topics_request_replica);
4619
4620     proto_item_set_end(subti, tvb, offset);
4621     proto_item_append_text(subti, " (Partition-ID=%d)",
4622                            partition);
4623
4624     return offset;
4625 }
4626
4627 static int
4628 dissect_kafka_create_topics_request_config(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4629                                            int offset, kafka_api_version_t api_version _U_)
4630 {
4631     proto_item *subti;
4632     proto_tree *subtree;
4633     int key_start, key_len;
4634     int val_start, val_len;
4635
4636     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
4637                                      ett_kafka_config,
4638                                      &subti, "Config");
4639
4640     /* key */
4641     offset = dissect_kafka_string(subtree, hf_kafka_config_key, tvb, pinfo, offset, &key_start, &key_len);
4642
4643     /* value */
4644     offset = dissect_kafka_string(subtree, hf_kafka_config_value, tvb, pinfo, offset, &val_start, &val_len);
4645
4646     proto_item_set_end(subti, tvb, offset);
4647     proto_item_append_text(subti, " (Key=%s, Value=%s)",
4648                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4649                                               key_start, key_len, ENC_UTF_8|ENC_NA),
4650                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4651                                               val_start, val_len, ENC_UTF_8|ENC_NA));
4652
4653     return offset;
4654 }
4655
4656 static int
4657 dissect_kafka_create_topics_request_create_topic_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4658                                                          int offset, kafka_api_version_t api_version)
4659 {
4660     proto_item *subti, *subsubti;
4661     proto_tree *subtree, *subsubtree;
4662     int topic_start, topic_len;
4663
4664     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
4665                                      ett_kafka_topic,
4666                                      &subti, "Create Topic Request");
4667
4668     /* topic */
4669     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
4670
4671     /* num_partitions */
4672     proto_tree_add_item(subtree, hf_kafka_num_partitions, tvb, offset, 4, ENC_BIG_ENDIAN);
4673     offset += 4;
4674
4675     /* replication_factor */
4676     proto_tree_add_item(subtree, hf_kafka_replication_factor, tvb, offset, 2, ENC_BIG_ENDIAN);
4677     offset += 2;
4678
4679     /* [replica_assignment] */
4680     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
4681                                         ett_kafka_replica_assignment,
4682                                         &subsubti, "Replica Assignments");
4683     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
4684                                  &dissect_kafka_create_topics_request_replica_assignment);
4685     proto_item_set_end(subsubti, tvb, offset);
4686
4687     /* [config] */
4688     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
4689                                         ett_kafka_config,
4690                                         &subsubti, "Configs");
4691     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
4692                                  &dissect_kafka_create_topics_request_config);
4693     proto_item_set_end(subsubti, tvb, offset);
4694
4695     proto_item_set_end(subti, tvb, offset);
4696     proto_item_append_text(subti, " (Topic=%s)",
4697                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4698                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
4699
4700     return offset;
4701 }
4702
4703 static int
4704 dissect_kafka_create_topics_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4705                                     kafka_api_version_t api_version)
4706 {
4707     proto_item *subti;
4708     proto_tree *subtree;
4709
4710     /* [topic] */
4711     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
4712                                      ett_kafka_topics,
4713                                      &subti, "Create Topic Requests");
4714     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
4715                                  &dissect_kafka_create_topics_request_create_topic_request);
4716     proto_item_set_end(subti, tvb, offset);
4717
4718     /* timeout */
4719     proto_tree_add_item(tree, hf_kafka_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
4720     offset += 4;
4721
4722     if (api_version >= 1) {
4723         /* validate */
4724         proto_tree_add_item(tree, hf_kafka_validate_only, tvb, offset, 1, ENC_NA);
4725         offset += 1;
4726     }
4727
4728     return offset;
4729 }
4730
4731 static int
4732 dissect_kafka_create_topics_response_topic_error_code(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4733                                                       int offset, kafka_api_version_t api_version _U_)
4734 {
4735     proto_item *subti;
4736     proto_tree *subtree;
4737     int topic_start, topic_len;
4738     kafka_error_t error;
4739
4740     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
4741                                      ett_kafka_topic,
4742                                      &subti, "Topic Error Code");
4743
4744     /* topic */
4745     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
4746
4747     /* error_code */
4748     offset = dissect_kafka_error_ret(tvb, pinfo, subtree, offset, &error);
4749
4750     proto_item_set_end(subti, tvb, offset);
4751     proto_item_append_text(subti, " (Topic=%s, Error=%s)",
4752                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4753                                               topic_start, topic_len, ENC_UTF_8|ENC_NA),
4754                            kafka_error_to_str(error));
4755
4756     return offset;
4757 }
4758
4759 static int
4760 dissect_kafka_create_topics_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4761                                      kafka_api_version_t api_version)
4762 {
4763     proto_item *subti;
4764     proto_tree *subtree;
4765
4766     if (api_version >= 2) {
4767         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
4768     }
4769
4770     /* [topic_error_code] */
4771     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
4772                                      ett_kafka_topics,
4773                                      &subti, "Topic Error Codes");
4774     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
4775                                  &dissect_kafka_create_topics_response_topic_error_code);
4776     proto_item_set_end(subti, tvb, offset);
4777
4778     return offset;
4779 }
4780
4781 /* DELETE_TOPICS REQUEST/RESPONSE */
4782
4783 static int
4784 dissect_kafka_delete_topics_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4785                                           int offset, kafka_api_version_t api_version _U_)
4786 {
4787     /* topic */
4788     offset = dissect_kafka_string(tree, hf_kafka_topic_name, tvb, pinfo, offset, NULL, NULL);
4789
4790     return offset;
4791 }
4792
4793 static int
4794 dissect_kafka_delete_topics_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4795                                     kafka_api_version_t api_version)
4796 {
4797     proto_item *subti;
4798     proto_tree *subtree;
4799
4800     /* [topic] */
4801     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
4802                                      ett_kafka_topics,
4803                                      &subti, "Topics");
4804     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
4805                                  &dissect_kafka_delete_topics_request_topic);
4806     proto_item_set_end(subti, tvb, offset);
4807
4808     /* timeout */
4809     proto_tree_add_item(tree, hf_kafka_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
4810     offset += 4;
4811
4812     return offset;
4813 }
4814
4815 static int
4816 dissect_kafka_delete_topics_response_topic_error_code(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4817                                                       int offset, kafka_api_version_t api_version _U_)
4818 {
4819     proto_item *subti;
4820     proto_tree *subtree;
4821     int topic_start, topic_len;
4822     kafka_error_t error;
4823
4824     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
4825                                      ett_kafka_topic,
4826                                      &subti, "Topic Error Code");
4827
4828     /* topic */
4829     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
4830
4831     /* error_code */
4832     offset = dissect_kafka_error_ret(tvb, pinfo, subtree, offset, &error);
4833
4834     proto_item_set_end(subti, tvb, offset);
4835     proto_item_append_text(subti, " (Topic=%s, Error=%s)",
4836                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4837                                               topic_start, topic_len, ENC_UTF_8|ENC_NA),
4838                            kafka_error_to_str(error));
4839
4840     return offset;
4841 }
4842
4843 static int
4844 dissect_kafka_delete_topics_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4845                                      kafka_api_version_t api_version)
4846 {
4847     proto_item *subti;
4848     proto_tree *subtree;
4849
4850     if (api_version >= 3) {
4851         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
4852     }
4853
4854     /* [topic_error_code] */
4855     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
4856                                      ett_kafka_topics,
4857                                      &subti, "Topic Error Codes");
4858     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
4859                                  &dissect_kafka_delete_topics_response_topic_error_code);
4860     proto_item_set_end(subti, tvb, offset);
4861
4862     return offset;
4863 }
4864
4865 /* DELETE_RECORDS REQUEST/RESPONSE */
4866
4867 static int
4868 dissect_kafka_delete_records_request_topic_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
4869                                            int offset, kafka_api_version_t api_version _U_)
4870 {
4871     guint32 partition_id;
4872     gint64 partition_offset;
4873     proto_item *subti;
4874     proto_tree *subtree;
4875
4876     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
4877
4878     partition_id = tvb_get_ntohl(tvb, offset);
4879     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
4880     offset += 4;
4881
4882     partition_offset = tvb_get_ntohi64(tvb, offset);
4883     proto_tree_add_item(subtree, hf_kafka_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
4884     offset += 8;
4885
4886     proto_item_set_end(subti, tvb, offset);
4887
4888     if (partition_offset == -1) {
4889         proto_item_append_text(subti, " (ID=%u, Offset=HWM)", partition_id);
4890     } else {
4891         proto_item_append_text(subti, " (ID=%u, Offset=%" G_GINT64_MODIFIER "i)", partition_id, partition_offset);
4892     }
4893
4894     return offset;
4895 }
4896
4897 static int
4898 dissect_kafka_delete_records_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4899                                           int offset, kafka_api_version_t api_version _U_)
4900 {
4901     int topic_start, topic_len;
4902     proto_item *subti, *subsubti;
4903     proto_tree *subtree, *subsubtree;
4904
4905     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
4906
4907     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
4908
4909     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
4910     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
4911                                  &dissect_kafka_delete_records_request_topic_partition);
4912     proto_item_set_end(subsubti, tvb, offset);
4913
4914     proto_item_set_end(subti, tvb, offset);
4915     proto_item_append_text(subti, " (Topic=%s)",
4916                            tvb_get_string_enc(wmem_packet_scope(), tvb,
4917                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
4918
4919     return offset;
4920 }
4921
4922 static int
4923 dissect_kafka_delete_records_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
4924                                     kafka_api_version_t api_version)
4925 {
4926     proto_item *subti;
4927     proto_tree *subtree;
4928
4929     /* [topic] */
4930     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
4931                                      ett_kafka_topics,
4932                                      &subti, "Topics");
4933     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
4934                                  &dissect_kafka_delete_records_request_topic);
4935     proto_item_set_end(subti, tvb, offset);
4936
4937     /* timeout */
4938     proto_tree_add_item(tree, hf_kafka_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
4939     offset += 4;
4940
4941     return offset;
4942 }
4943
4944 static int
4945 dissect_kafka_delete_records_response_topic_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
4946                                                      int offset, kafka_api_version_t api_version _U_)
4947 {
4948     guint32 partition_id;
4949     gint64 partition_offset; // low watermark
4950     kafka_error_t partition_error_code;
4951
4952     proto_item *subti;
4953     proto_tree *subtree;
4954
4955     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
4956
4957     partition_id = tvb_get_ntohl(tvb, offset);
4958     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
4959     offset += 4;
4960
4961     partition_offset = tvb_get_ntohi64(tvb, offset);
4962     proto_tree_add_item(subtree, hf_kafka_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
4963     offset += 8;
4964
4965     partition_error_code = (kafka_error_t) tvb_get_ntohs(tvb, offset);
4966     proto_tree_add_item(subtree, hf_kafka_error, tvb, offset, 2, ENC_BIG_ENDIAN);
4967     offset += 2;
4968
4969     proto_item_set_end(subti, tvb, offset);
4970
4971     if (partition_error_code == 0) {
4972         proto_item_append_text(subti, " (ID=%u, Offset=%" G_GINT64_MODIFIER "i)", partition_id, partition_offset);
4973     } else {
4974         proto_item_append_text(subti, " (ID=%u, Error=%s)", partition_id, kafka_error_to_str(partition_error_code));
4975     }
4976
4977     return offset;
4978 }
4979
4980 static int
4981 dissect_kafka_delete_records_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4982                                            int offset, kafka_api_version_t api_version _U_)
4983 {
4984     int topic_start, topic_len;
4985     proto_item *subti, *subsubti;
4986     proto_tree *subtree, *subsubtree;
4987
4988     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
4989
4990     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
4991
4992     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
4993     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
4994                                  &dissect_kafka_delete_records_response_topic_partition);
4995     proto_item_set_end(subsubti, tvb, offset);
4996
4997     proto_item_set_end(subti, tvb, offset);
4998     proto_item_append_text(subti, " (Topic=%s)",
4999                            tvb_get_string_enc(wmem_packet_scope(), tvb,
5000                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
5001
5002     return offset;
5003 }
5004
5005
5006 static int
5007 dissect_kafka_delete_records_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5008                                      kafka_api_version_t api_version)
5009 {
5010     proto_item *subti;
5011     proto_tree *subtree;
5012
5013     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
5014
5015     /* [topic_error_code] */
5016     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5017                                      ett_kafka_topics,
5018                                      &subti, "Topics");
5019     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5020                                  &dissect_kafka_delete_records_response_topic);
5021
5022     proto_item_set_end(subti, tvb, offset);
5023
5024     return offset;
5025 }
5026
5027 /* INIT_PRODUCER_ID REQUEST/RESPONSE */
5028
5029 static int
5030 dissect_kafka_init_producer_id_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5031                               kafka_api_version_t api_version _U_)
5032 {
5033     offset = dissect_kafka_string(tree, hf_kafka_transactional_id, tvb, pinfo, offset, NULL, NULL);
5034
5035     proto_tree_add_item(tree, hf_kafka_transaction_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
5036     offset += 4;
5037
5038     return offset;
5039 }
5040
5041
5042 static int
5043 dissect_kafka_init_producer_id_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5044                                kafka_api_version_t api_version _U_)
5045 {
5046     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
5047
5048     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
5049
5050     proto_tree_add_item(tree, hf_kafka_producer_id, tvb, offset, 8, ENC_BIG_ENDIAN);
5051     offset += 8;
5052
5053     proto_tree_add_item(tree, hf_kafka_producer_epoch, tvb, offset, 2, ENC_BIG_ENDIAN);
5054     offset += 2;
5055
5056     return offset;
5057 }
5058
5059 /* OFFSET_FOR_LEADER_EPOCH REQUEST/RESPONSE */
5060
5061 static int
5062 dissect_kafka_offset_for_leader_epoch_request_topic_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5063                                                             int offset, kafka_api_version_t api_version)
5064 {
5065     guint32 partition_id;
5066     proto_item *subti;
5067     proto_tree *subtree;
5068
5069     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
5070
5071     partition_id = tvb_get_ntohl(tvb, offset);
5072     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
5073     offset += 4;
5074
5075     if (api_version >= 2) {
5076         proto_tree_add_item(subtree, hf_kafka_current_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
5077         offset += 4;
5078     }
5079
5080     proto_tree_add_item(subtree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
5081     offset += 4;
5082
5083     proto_item_set_end(subti, tvb, offset);
5084
5085     proto_item_append_text(subti, " (ID=%u)", partition_id);
5086
5087     return offset;
5088 }
5089
5090 static int
5091 dissect_kafka_offset_for_leader_epoch_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5092                                                   int offset, kafka_api_version_t api_version _U_)
5093 {
5094     int topic_start, topic_len;
5095     proto_item *subti, *subsubti;
5096     proto_tree *subtree, *subsubtree;
5097
5098     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
5099
5100     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
5101
5102     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
5103     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
5104                                  &dissect_kafka_offset_for_leader_epoch_request_topic_partition);
5105     proto_item_set_end(subsubti, tvb, offset);
5106
5107     proto_item_set_end(subti, tvb, offset);
5108     proto_item_append_text(subti, " (Name=%s)",
5109                            tvb_get_string_enc(wmem_packet_scope(), tvb,
5110                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
5111
5112     return offset;
5113 }
5114
5115 static int
5116 dissect_kafka_offset_for_leader_epoch_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5117                                             kafka_api_version_t api_version)
5118 {
5119     proto_item *subti;
5120     proto_tree *subtree;
5121     gint32 replica_id;
5122
5123     if (api_version >= 3) {
5124         replica_id = tvb_get_ntohl(tvb, offset);
5125         subti = proto_tree_add_item(tree, hf_kafka_replica, tvb, offset, 4, ENC_BIG_ENDIAN);
5126         if (replica_id==-2) {
5127             proto_item_append_text(subti, " (debug)");
5128         } else if (replica_id==-1) {
5129             proto_item_append_text(subti, " (consumer)");
5130         }
5131         offset += 4;
5132     }
5133
5134     /* [topic] */
5135     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5136                                      ett_kafka_topics,
5137                                      &subti, "Topics");
5138     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5139                                  &dissect_kafka_offset_for_leader_epoch_request_topic);
5140     proto_item_set_end(subti, tvb, offset);
5141
5142     return offset;
5143 }
5144
5145 static int
5146 dissect_kafka_offset_for_leader_epoch_response_topic_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5147                                                              int offset, kafka_api_version_t api_version _U_)
5148 {
5149     guint32 partition_id;
5150     kafka_error_t partition_error_code;
5151
5152     proto_item *subti;
5153     proto_tree *subtree;
5154
5155     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
5156
5157     partition_error_code = (kafka_error_t) tvb_get_ntohs(tvb, offset);
5158     proto_tree_add_item(subtree, hf_kafka_error, tvb, offset, 2, ENC_BIG_ENDIAN);
5159     offset += 2;
5160
5161     partition_id = tvb_get_ntohl(tvb, offset);
5162     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
5163     offset += 4;
5164
5165     if (api_version >= 1) {
5166         proto_tree_add_item(subtree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
5167         offset += 4;
5168     }
5169
5170     proto_tree_add_item(subtree, hf_kafka_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
5171     offset += 8;
5172
5173     proto_item_set_end(subti, tvb, offset);
5174
5175     if (partition_error_code == 0) {
5176         proto_item_append_text(subti, " (ID=%u)", partition_id);
5177     } else {
5178         proto_item_append_text(subti, " (ID=%u, Error=%s)", partition_id, kafka_error_to_str(partition_error_code));
5179     }
5180
5181     return offset;
5182 }
5183
5184 static int
5185 dissect_kafka_offset_for_leader_epoch_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5186                                                    int offset, kafka_api_version_t api_version _U_)
5187 {
5188     int topic_start, topic_len;
5189     proto_item *subti, *subsubti;
5190     proto_tree *subtree, *subsubtree;
5191
5192     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
5193
5194     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
5195
5196     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
5197     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
5198                                  &dissect_kafka_offset_for_leader_epoch_response_topic_partition);
5199     proto_item_set_end(subsubti, tvb, offset);
5200
5201     proto_item_set_end(subti, tvb, offset);
5202     proto_item_append_text(subti, " (Name=%s)",
5203                            tvb_get_string_enc(wmem_packet_scope(), tvb,
5204                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
5205
5206     return offset;
5207 }
5208
5209
5210 static int
5211 dissect_kafka_offset_for_leader_epoch_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5212                                              kafka_api_version_t api_version)
5213 {
5214     proto_item *subti;
5215     proto_tree *subtree;
5216
5217     if (api_version >= 2) {
5218         offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
5219     }
5220
5221     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5222                                      ett_kafka_topics,
5223                                      &subti, "Topics");
5224     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5225                                  &dissect_kafka_offset_for_leader_epoch_response_topic);
5226
5227     proto_item_set_end(subti, tvb, offset);
5228
5229     return offset;
5230 }
5231
5232 /* ADD_PARTITIONS_TO_TXN REQUEST/RESPONSE */
5233
5234 static int
5235 dissect_kafka_add_partitions_to_txn_request_topic_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5236                                                      int offset, kafka_api_version_t api_version _U_)
5237 {
5238     proto_tree_add_item(tree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
5239
5240     return offset+4;
5241 }
5242
5243 static int
5244 dissect_kafka_add_partitions_to_txn_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5245                                            int offset, kafka_api_version_t api_version _U_)
5246 {
5247     int topic_start, topic_len;
5248     proto_item *subti, *subsubti;
5249     proto_tree *subtree, *subsubtree;
5250
5251     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
5252
5253     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
5254
5255     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
5256     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
5257                                  &dissect_kafka_add_partitions_to_txn_request_topic_partition);
5258     proto_item_set_end(subsubti, tvb, offset);
5259
5260     proto_item_set_end(subti, tvb, offset);
5261     proto_item_append_text(subti, " (Topic=%s)",
5262                            tvb_get_string_enc(wmem_packet_scope(), tvb,
5263                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
5264
5265     return offset;
5266 }
5267
5268 static int
5269 dissect_kafka_add_partitions_to_txn_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5270                                      kafka_api_version_t api_version)
5271 {
5272     proto_item *subti;
5273     proto_tree *subtree;
5274
5275     offset = dissect_kafka_string(tree, hf_kafka_transactional_id, tvb, pinfo, offset, NULL, NULL);
5276
5277     proto_tree_add_item(tree, hf_kafka_producer_id, tvb, offset, 8, ENC_BIG_ENDIAN);
5278     offset += 8;
5279
5280     proto_tree_add_item(tree, hf_kafka_producer_epoch, tvb, offset, 2, ENC_BIG_ENDIAN);
5281     offset += 2;
5282
5283     /* [topic] */
5284     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5285                                      ett_kafka_topics,
5286                                      &subti, "Topics");
5287     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5288                                  &dissect_kafka_add_partitions_to_txn_request_topic);
5289     proto_item_set_end(subti, tvb, offset);
5290
5291     return offset;
5292 }
5293
5294 static int
5295 dissect_kafka_add_partitions_to_txn_response_topic_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5296                                                       int offset, kafka_api_version_t api_version _U_)
5297 {
5298     guint32 partition_id;
5299     kafka_error_t partition_error_code;
5300
5301     proto_item *subti;
5302     proto_tree *subtree;
5303
5304     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
5305
5306     partition_id = tvb_get_ntohl(tvb, offset);
5307     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
5308     offset += 4;
5309
5310     partition_error_code = (kafka_error_t) tvb_get_ntohs(tvb, offset);
5311     proto_tree_add_item(subtree, hf_kafka_error, tvb, offset, 2, ENC_BIG_ENDIAN);
5312     offset += 2;
5313
5314     proto_item_set_end(subti, tvb, offset);
5315
5316     if (partition_error_code == 0) {
5317         proto_item_append_text(subti, " (ID=%u)", partition_id);
5318     } else {
5319         proto_item_append_text(subti, " (ID=%u, Error=%s)", partition_id, kafka_error_to_str(partition_error_code));
5320     }
5321
5322     return offset;
5323 }
5324
5325 static int
5326 dissect_kafka_add_partitions_to_txn_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5327                                             int offset, kafka_api_version_t api_version _U_)
5328 {
5329     int topic_start, topic_len;
5330     proto_item *subti, *subsubti;
5331     proto_tree *subtree, *subsubtree;
5332
5333     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
5334
5335     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
5336
5337     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
5338     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
5339                                  &dissect_kafka_add_partitions_to_txn_response_topic_partition);
5340     proto_item_set_end(subsubti, tvb, offset);
5341
5342     proto_item_set_end(subti, tvb, offset);
5343     proto_item_append_text(subti, " (Topic=%s)",
5344                            tvb_get_string_enc(wmem_packet_scope(), tvb,
5345                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
5346
5347     return offset;
5348 }
5349
5350
5351 static int
5352 dissect_kafka_add_partitions_to_txn_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5353                                       kafka_api_version_t api_version)
5354 {
5355     proto_item *subti;
5356     proto_tree *subtree;
5357
5358     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
5359
5360     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5361                                      ett_kafka_topics,
5362                                      &subti, "Topics");
5363     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5364                                  &dissect_kafka_add_partitions_to_txn_response_topic);
5365
5366     proto_item_set_end(subti, tvb, offset);
5367
5368     return offset;
5369 }
5370
5371 /* ADD_OFFSETS_TO_TXN REQUEST/RESPONSE */
5372
5373 static int
5374 dissect_kafka_add_offsets_to_txn_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5375                               kafka_api_version_t api_version _U_)
5376 {
5377     offset = dissect_kafka_string(tree, hf_kafka_transactional_id, tvb, pinfo, offset, NULL, NULL);
5378
5379     proto_tree_add_item(tree, hf_kafka_producer_id, tvb, offset, 8, ENC_BIG_ENDIAN);
5380     offset += 8;
5381
5382     proto_tree_add_item(tree, hf_kafka_producer_epoch, tvb, offset, 2, ENC_BIG_ENDIAN);
5383     offset += 2;
5384
5385     offset = dissect_kafka_string(tree, hf_kafka_consumer_group, tvb, pinfo, offset, NULL, NULL);
5386
5387     return offset;
5388 }
5389
5390
5391 static int
5392 dissect_kafka_add_offsets_to_txn_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5393                                kafka_api_version_t api_version _U_)
5394 {
5395     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
5396
5397     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
5398
5399     return offset;
5400 }
5401
5402 /* END_TXN REQUEST/RESPONSE */
5403
5404 static int
5405 dissect_kafka_end_txn_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5406                                             kafka_api_version_t api_version _U_)
5407 {
5408     offset = dissect_kafka_string(tree, hf_kafka_transactional_id, tvb, pinfo, offset, NULL, NULL);
5409
5410     proto_tree_add_item(tree, hf_kafka_producer_id, tvb, offset, 8, ENC_BIG_ENDIAN);
5411     offset += 8;
5412
5413     proto_tree_add_item(tree, hf_kafka_producer_epoch, tvb, offset, 2, ENC_BIG_ENDIAN);
5414     offset += 2;
5415
5416     proto_tree_add_item(tree, hf_kafka_transaction_result, tvb, offset, 1, ENC_BIG_ENDIAN);
5417     offset += 1;
5418
5419     return offset;
5420 }
5421
5422
5423 static int
5424 dissect_kafka_end_txn_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5425                                              kafka_api_version_t api_version _U_)
5426 {
5427     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
5428
5429     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
5430
5431     return offset;
5432 }
5433
5434 /* WRITE_TXN_MARKERS REQUEST/RESPONSE */
5435
5436 static int
5437 dissect_kafka_write_txn_markers_request_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5438                                                      int offset, kafka_api_version_t api_version _U_)
5439 {
5440     proto_tree_add_item(tree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
5441     offset += 4;
5442
5443     return offset;
5444 }
5445
5446 static int
5447 dissect_kafka_write_txn_markers_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5448                                            int offset, kafka_api_version_t api_version _U_)
5449 {
5450     int topic_start, topic_len;
5451     proto_item *subti, *subsubti;
5452     proto_tree *subtree, *subsubtree;
5453
5454     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
5455
5456     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
5457
5458     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
5459     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
5460                                  &dissect_kafka_write_txn_markers_request_partition);
5461     proto_item_set_end(subsubti, tvb, offset);
5462
5463     proto_item_set_end(subti, tvb, offset);
5464     proto_item_append_text(subti, " (Topic=%s)",
5465                            tvb_get_string_enc(wmem_packet_scope(), tvb,
5466                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
5467
5468     return offset;
5469 }
5470
5471 static int
5472 dissect_kafka_write_txn_markers_request_marker(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5473                                      kafka_api_version_t api_version)
5474 {
5475     guint64 producer_id;
5476     proto_item *subti, *subsubti;
5477     proto_tree *subtree, *subsubtree;
5478
5479     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5480                                      ett_kafka_marker,
5481                                      &subti, "Marker");
5482
5483     producer_id = tvb_get_ntoh64(tvb, offset);
5484     proto_tree_add_item(subtree, hf_kafka_producer_id, tvb, offset, 8, ENC_BIG_ENDIAN);
5485     offset += 8;
5486
5487     proto_tree_add_item(subtree, hf_kafka_producer_epoch, tvb, offset, 2, ENC_BIG_ENDIAN);
5488     offset += 2;
5489
5490     proto_tree_add_item(subtree, hf_kafka_transaction_result, tvb, offset, 1, ENC_BIG_ENDIAN);
5491     offset += 1;
5492
5493     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
5494                                      ett_kafka_topics,
5495                                      &subsubti, "Topics");
5496     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
5497                                  &dissect_kafka_write_txn_markers_request_topic);
5498
5499     proto_tree_add_item(subsubtree, hf_kafka_coordinator_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
5500     offset += 4;
5501
5502     proto_item_set_end(subsubti, tvb, offset);
5503     proto_item_set_end(subti, tvb, offset);
5504     proto_item_append_text(subti, " (Producer=%" G_GINT64_MODIFIER "u)", producer_id);
5505
5506     return offset;
5507 }
5508
5509 static int
5510 dissect_kafka_write_txn_markers_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5511                                                 kafka_api_version_t api_version)
5512 {
5513     proto_item *subti;
5514     proto_tree *subtree;
5515
5516     /* [topic] */
5517     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5518                                      ett_kafka_markers,
5519                                      &subti, "Markers");
5520     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5521                                  &dissect_kafka_write_txn_markers_request_marker);
5522     proto_item_set_end(subti, tvb, offset);
5523
5524     return offset;
5525 }
5526
5527 static int
5528 dissect_kafka_write_txn_markers_response_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5529                                                       int offset, kafka_api_version_t api_version _U_)
5530 {
5531     guint32 partition_id;
5532     kafka_error_t partition_error_code;
5533
5534     proto_item *subti;
5535     proto_tree *subtree;
5536
5537     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
5538
5539     partition_id = tvb_get_ntohl(tvb, offset);
5540     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
5541     offset += 4;
5542
5543     partition_error_code = (kafka_error_t) tvb_get_ntohs(tvb, offset);
5544     proto_tree_add_item(subtree, hf_kafka_error, tvb, offset, 2, ENC_BIG_ENDIAN);
5545     offset += 2;
5546
5547     proto_item_set_end(subti, tvb, offset);
5548
5549     if (partition_error_code == 0) {
5550         proto_item_append_text(subti, " (ID=%u", partition_id);
5551     } else {
5552         proto_item_append_text(subti, " (ID=%u, Error=%s)", partition_id, kafka_error_to_str(partition_error_code));
5553     }
5554
5555     return offset;
5556 }
5557
5558 static int
5559 dissect_kafka_write_txn_markers_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5560                                             int offset, kafka_api_version_t api_version _U_)
5561 {
5562     int topic_start, topic_len;
5563     proto_item *subti, *subsubti;
5564     proto_tree *subtree, *subsubtree;
5565
5566     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
5567
5568     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
5569
5570     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
5571     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
5572                                  &dissect_kafka_write_txn_markers_response_partition);
5573     proto_item_set_end(subsubti, tvb, offset);
5574
5575     proto_item_set_end(subti, tvb, offset);
5576     proto_item_append_text(subti, " (Topic=%s)",
5577                            tvb_get_string_enc(wmem_packet_scope(), tvb,
5578                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
5579
5580     return offset;
5581 }
5582
5583 static int
5584 dissect_kafka_write_txn_markers_response_marker(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5585                                                int offset, kafka_api_version_t api_version _U_)
5586 {
5587     guint64 producer_id;
5588     proto_item *subti, *subsubti;
5589     proto_tree *subtree, *subsubtree;
5590
5591     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_marker, &subti, "Marker");
5592
5593     producer_id = tvb_get_ntoh64(tvb, offset);
5594     proto_tree_add_item(subtree, hf_kafka_producer_id, tvb, offset, 8, ENC_BIG_ENDIAN);
5595     offset += 8;
5596
5597     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Topics");
5598     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
5599                                  &dissect_kafka_write_txn_markers_response_topic);
5600     proto_item_set_end(subsubti, tvb, offset);
5601
5602     proto_item_set_end(subti, tvb, offset);
5603     proto_item_append_text(subti, " (Producer=%" G_GINT64_MODIFIER "u)", producer_id);
5604
5605     return offset;
5606 }
5607
5608 static int
5609 dissect_kafka_write_txn_markers_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5610                                       kafka_api_version_t api_version)
5611 {
5612     proto_item *subti;
5613     proto_tree *subtree;
5614
5615     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
5616
5617     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5618                                      ett_kafka_markers,
5619                                      &subti, "Markers");
5620     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5621                                  &dissect_kafka_write_txn_markers_response_marker);
5622
5623     proto_item_set_end(subti, tvb, offset);
5624
5625     return offset;
5626 }
5627
5628 /* TXN_OFFSET_COMMIT REQUEST/RESPONSE */
5629
5630 static int
5631 dissect_kafka_txn_offset_commit_request_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5632                                                      int offset, kafka_api_version_t api_version _U_)
5633 {
5634     guint32 partition_id;
5635     gint64 partition_offset;
5636     proto_item *subti;
5637     proto_tree *subtree;
5638
5639     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
5640
5641     partition_id = tvb_get_ntohl(tvb, offset);
5642     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
5643     offset += 4;
5644
5645     partition_offset = tvb_get_ntohi64(tvb, offset);
5646     proto_tree_add_item(subtree, hf_kafka_offset, tvb, offset, 8, ENC_BIG_ENDIAN);
5647     offset += 8;
5648
5649     if (api_version >= 2) {
5650         proto_tree_add_item(subtree, hf_kafka_leader_epoch, tvb, offset, 4, ENC_BIG_ENDIAN);
5651         offset += 4;
5652     }
5653
5654     offset = dissect_kafka_string(subtree, hf_kafka_metadata, tvb, pinfo, offset, NULL, NULL);
5655     proto_item_set_end(subti, tvb, offset);
5656
5657     proto_item_append_text(subti, " (ID=%u, Offset=%" G_GINT64_MODIFIER "i)", partition_id, partition_offset);
5658
5659     return offset;
5660 }
5661
5662 static int
5663 dissect_kafka_txn_offset_commit_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5664                                            int offset, kafka_api_version_t api_version _U_)
5665 {
5666     int topic_start, topic_len;
5667     proto_item *subti, *subsubti;
5668     proto_tree *subtree, *subsubtree;
5669
5670     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
5671
5672     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
5673
5674     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
5675     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
5676                                  &dissect_kafka_txn_offset_commit_request_partition);
5677     proto_item_set_end(subsubti, tvb, offset);
5678
5679     proto_item_set_end(subti, tvb, offset);
5680     proto_item_append_text(subti, " (Topic=%s)",
5681                            tvb_get_string_enc(wmem_packet_scope(), tvb,
5682                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
5683
5684     return offset;
5685 }
5686
5687 static int
5688 dissect_kafka_txn_offset_commit_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5689                                      kafka_api_version_t api_version)
5690 {
5691     proto_item *subti;
5692     proto_tree *subtree;
5693
5694     offset = dissect_kafka_string(tree, hf_kafka_transactional_id, tvb, pinfo, offset, NULL, NULL);
5695
5696     offset = dissect_kafka_string(tree, hf_kafka_consumer_group, tvb, pinfo, offset, NULL, NULL);
5697
5698     proto_tree_add_item(tree, hf_kafka_producer_id, tvb, offset, 8, ENC_BIG_ENDIAN);
5699     offset += 8;
5700
5701     proto_tree_add_item(tree, hf_kafka_producer_epoch, tvb, offset, 2, ENC_BIG_ENDIAN);
5702     offset += 2;
5703
5704     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5705                                      ett_kafka_topics,
5706                                      &subti, "Topics");
5707     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5708                                  &dissect_kafka_txn_offset_commit_request_topic);
5709     proto_item_set_end(subti, tvb, offset);
5710
5711     return offset;
5712 }
5713
5714 static int
5715 dissect_kafka_txn_offset_commit_response_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5716                                                       int offset, kafka_api_version_t api_version _U_)
5717 {
5718     guint32 partition_id;
5719     kafka_error_t partition_error_code;
5720
5721     proto_item *subti;
5722     proto_tree *subtree;
5723
5724     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
5725
5726     partition_id = tvb_get_ntohl(tvb, offset);
5727     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
5728     offset += 4;
5729
5730     partition_error_code = (kafka_error_t) tvb_get_ntohs(tvb, offset);
5731     proto_tree_add_item(subtree, hf_kafka_error, tvb, offset, 2, ENC_BIG_ENDIAN);
5732     offset += 2;
5733
5734     proto_item_set_end(subti, tvb, offset);
5735
5736     if (partition_error_code == 0) {
5737         proto_item_append_text(subti, " (ID=%u)", partition_id);
5738     } else {
5739         proto_item_append_text(subti, " (ID=%u, Error=%s)", partition_id, kafka_error_to_str(partition_error_code));
5740     }
5741
5742     return offset;
5743 }
5744
5745 static int
5746 dissect_kafka_txn_offset_commit_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5747                                             int offset, kafka_api_version_t api_version _U_)
5748 {
5749     int topic_start, topic_len;
5750     proto_item *subti, *subsubti;
5751     proto_tree *subtree, *subsubtree;
5752
5753     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
5754
5755     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
5756
5757     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
5758     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
5759                                  &dissect_kafka_txn_offset_commit_response_partition);
5760     proto_item_set_end(subsubti, tvb, offset);
5761
5762     proto_item_set_end(subti, tvb, offset);
5763     proto_item_append_text(subti, " (Topic=%s)",
5764                            tvb_get_string_enc(wmem_packet_scope(), tvb,
5765                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
5766
5767     return offset;
5768 }
5769
5770
5771 static int
5772 dissect_kafka_txn_offset_commit_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5773                                       kafka_api_version_t api_version)
5774 {
5775     proto_item *subti;
5776     proto_tree *subtree;
5777
5778     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
5779
5780     /* [topic_error_code] */
5781     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5782                                      ett_kafka_topics,
5783                                      &subti, "Topics");
5784     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5785                                  &dissect_kafka_txn_offset_commit_response_topic);
5786
5787     proto_item_set_end(subti, tvb, offset);
5788
5789     return offset;
5790 }
5791
5792 /* DESCRIBE_ACLS REQUEST/RESPONSE */
5793
5794 static int
5795 dissect_kafka_describe_acls_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5796                                         kafka_api_version_t api_version)
5797 {
5798     proto_tree_add_item(tree, hf_kafka_acl_resource_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5799     offset += 1;
5800
5801     offset = dissect_kafka_string(tree, hf_kafka_acl_resource_name, tvb, pinfo, offset, NULL, NULL);
5802
5803     if (api_version >= 1) {
5804         proto_tree_add_item(tree, hf_kafka_acl_resource_pattern_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5805         offset += 1;
5806     }
5807
5808     offset = dissect_kafka_string(tree, hf_kafka_acl_principal, tvb, pinfo, offset, NULL, NULL);
5809
5810     offset = dissect_kafka_string(tree, hf_kafka_acl_host, tvb, pinfo, offset, NULL, NULL);
5811
5812     proto_tree_add_item(tree, hf_kafka_acl_operation, tvb, offset, 1, ENC_BIG_ENDIAN);
5813     offset += 1;
5814
5815     proto_tree_add_item(tree, hf_kafka_acl_permission_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5816     offset += 1;
5817
5818     return offset;
5819 }
5820
5821 static int
5822 dissect_kafka_describe_acls_response_resource_acl(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5823                                                    int offset, kafka_api_version_t api_version _U_)
5824 {
5825     proto_item *subti;
5826     proto_tree *subtree;
5827
5828     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_acl, &subti, "ACL");
5829
5830     offset = dissect_kafka_string(subtree, hf_kafka_acl_principal, tvb, pinfo, offset, NULL, NULL);
5831
5832     offset = dissect_kafka_string(subtree, hf_kafka_acl_host, tvb, pinfo, offset, NULL, NULL);
5833
5834     proto_tree_add_item(subtree, hf_kafka_acl_operation, tvb, offset, 1, ENC_BIG_ENDIAN);
5835     offset += 1;
5836
5837     proto_tree_add_item(subtree, hf_kafka_acl_permission_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5838     offset += 1;
5839
5840     return offset;
5841 }
5842
5843 static int
5844 dissect_kafka_describe_acls_response_resource(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5845                                                int offset, kafka_api_version_t api_version _U_)
5846 {
5847     proto_item *subti, *subsubti;
5848     proto_tree *subtree, *subsubtree;
5849
5850     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_resource, &subti, "Resource");
5851
5852     proto_tree_add_item(subtree, hf_kafka_acl_resource_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5853     offset += 1;
5854
5855     offset = dissect_kafka_string(subtree, hf_kafka_acl_resource_name, tvb, pinfo, offset, NULL, NULL);
5856
5857     if (api_version >= 1) {
5858         proto_tree_add_item(subtree, hf_kafka_acl_resource_pattern_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5859         offset += 1;
5860     }
5861
5862     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_acls, &subsubti, "ACLs");
5863     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
5864                                  &dissect_kafka_describe_acls_response_resource_acl);
5865     proto_item_set_end(subsubti, tvb, offset);
5866
5867     proto_item_set_end(subti, tvb, offset);
5868
5869     return offset;
5870 }
5871
5872
5873 static int
5874 dissect_kafka_describe_acls_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5875                                          kafka_api_version_t api_version)
5876 {
5877     proto_item *subti;
5878     proto_tree *subtree;
5879
5880     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
5881
5882     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
5883
5884     offset = dissect_kafka_string(tree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
5885
5886     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5887                                      ett_kafka_resources,
5888                                      &subti, "Resources");
5889     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5890                                  &dissect_kafka_describe_acls_response_resource);
5891
5892     proto_item_set_end(subti, tvb, offset);
5893
5894     return offset;
5895 }
5896
5897 /* CREATE_ACLS REQUEST/RESPONSE */
5898
5899 static int
5900 dissect_kafka_create_acls_request_creation(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5901                                                   int offset, kafka_api_version_t api_version _U_)
5902 {
5903     proto_item *subti;
5904     proto_tree *subtree;
5905
5906     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_acl_creation, &subti, "Creation");
5907
5908     proto_tree_add_item(subtree, hf_kafka_acl_resource_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5909     offset += 1;
5910
5911     offset = dissect_kafka_string(subtree, hf_kafka_acl_resource_name, tvb, pinfo, offset, NULL, NULL);
5912
5913     if (api_version >= 1) {
5914         proto_tree_add_item(subtree, hf_kafka_acl_resource_pattern_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5915         offset += 1;
5916     }
5917
5918     offset = dissect_kafka_string(subtree, hf_kafka_acl_principal, tvb, pinfo, offset, NULL, NULL);
5919
5920     offset = dissect_kafka_string(subtree, hf_kafka_acl_host, tvb, pinfo, offset, NULL, NULL);
5921
5922     proto_tree_add_item(subtree, hf_kafka_acl_operation, tvb, offset, 1, ENC_BIG_ENDIAN);
5923     offset += 1;
5924
5925     proto_tree_add_item(subtree, hf_kafka_acl_permission_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5926     offset += 1;
5927
5928     proto_item_set_end(subti, tvb, offset);
5929
5930     return offset;
5931 }
5932
5933 static int
5934 dissect_kafka_create_acls_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5935                                         kafka_api_version_t api_version)
5936 {
5937     proto_item *subti;
5938     proto_tree *subtree;
5939
5940     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5941                                      ett_kafka_acl_creations,
5942                                      &subti, "Creations");
5943     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5944                                  &dissect_kafka_create_acls_request_creation);
5945     proto_item_set_end(subti, tvb, offset);
5946
5947     return offset;
5948 }
5949
5950 static int
5951 dissect_kafka_create_acls_response_creation(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5952                                                    int offset, kafka_api_version_t api_version _U_)
5953 {
5954     proto_item *subti;
5955     proto_tree *subtree;
5956
5957     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_acl_creation, &subti, "Creation");
5958
5959     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
5960
5961     offset = dissect_kafka_string(subtree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
5962
5963     return offset;
5964 }
5965
5966 static int
5967 dissect_kafka_create_acls_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
5968                                          kafka_api_version_t api_version)
5969 {
5970     proto_item *subti;
5971     proto_tree *subtree;
5972
5973     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
5974
5975     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
5976                                      ett_kafka_acl_creations,
5977                                      &subti, "Creations");
5978     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
5979                                  &dissect_kafka_create_acls_response_creation);
5980
5981     proto_item_set_end(subti, tvb, offset);
5982
5983     return offset;
5984 }
5985
5986 /* DELETE_ACLS REQUEST/RESPONSE */
5987
5988 static int
5989 dissect_kafka_delete_acls_request_filter(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
5990                                            int offset, kafka_api_version_t api_version _U_)
5991 {
5992     proto_item *subti;
5993     proto_tree *subtree;
5994
5995     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_acl_filter, &subti, "Filter");
5996
5997     proto_tree_add_item(subtree, hf_kafka_acl_resource_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5998     offset += 1;
5999
6000     offset = dissect_kafka_string(subtree, hf_kafka_acl_resource_name, tvb, pinfo, offset, NULL, NULL);
6001
6002     if (api_version >= 1) {
6003         proto_tree_add_item(subtree, hf_kafka_acl_resource_pattern_type, tvb, offset, 1, ENC_BIG_ENDIAN);
6004         offset += 1;
6005     }
6006
6007     offset = dissect_kafka_string(subtree, hf_kafka_acl_principal, tvb, pinfo, offset, NULL, NULL);
6008
6009     offset = dissect_kafka_string(subtree, hf_kafka_acl_host, tvb, pinfo, offset, NULL, NULL);
6010
6011     proto_tree_add_item(subtree, hf_kafka_acl_operation, tvb, offset, 1, ENC_BIG_ENDIAN);
6012     offset += 1;
6013
6014     proto_tree_add_item(subtree, hf_kafka_acl_permission_type, tvb, offset, 1, ENC_BIG_ENDIAN);
6015     offset += 1;
6016
6017     proto_item_set_end(subti, tvb, offset);
6018
6019     return offset;
6020 }
6021
6022 static int
6023 dissect_kafka_delete_acls_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6024                                   kafka_api_version_t api_version)
6025 {
6026     proto_item *subti;
6027     proto_tree *subtree;
6028
6029     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6030                                      ett_kafka_acl_filter,
6031                                      &subti, "Filters");
6032     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6033                                  &dissect_kafka_delete_acls_request_filter);
6034     proto_item_set_end(subti, tvb, offset);
6035
6036     return offset;
6037 }
6038
6039 static int
6040 dissect_kafka_delete_acls_response_match(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6041                                           int offset, kafka_api_version_t api_version _U_)
6042 {
6043     proto_item *subti;
6044     proto_tree *subtree;
6045
6046     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_acl_filter_match, &subti, "Match");
6047
6048     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
6049
6050     offset = dissect_kafka_string(subtree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
6051
6052     proto_tree_add_item(subtree, hf_kafka_acl_resource_type, tvb, offset, 1, ENC_BIG_ENDIAN);
6053     offset += 1;
6054
6055     offset = dissect_kafka_string(subtree, hf_kafka_acl_resource_name, tvb, pinfo, offset, NULL, NULL);
6056
6057     if (api_version >= 1) {
6058         proto_tree_add_item(subtree, hf_kafka_acl_resource_pattern_type, tvb, offset, 1, ENC_BIG_ENDIAN);
6059         offset += 1;
6060     }
6061
6062     offset = dissect_kafka_string(subtree, hf_kafka_acl_principal, tvb, pinfo, offset, NULL, NULL);
6063
6064     offset = dissect_kafka_string(subtree, hf_kafka_acl_host, tvb, pinfo, offset, NULL, NULL);
6065
6066     proto_tree_add_item(subtree, hf_kafka_acl_operation, tvb, offset, 1, ENC_BIG_ENDIAN);
6067     offset += 1;
6068
6069     proto_tree_add_item(subtree, hf_kafka_acl_permission_type, tvb, offset, 1, ENC_BIG_ENDIAN);
6070     offset += 1;
6071
6072     proto_item_set_end(subti, tvb, offset);
6073
6074     return offset;
6075 }
6076
6077 static int
6078 dissect_kafka_delete_acls_response_filter(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6079                                             int offset, kafka_api_version_t api_version _U_)
6080 {
6081     proto_item *subti, *subsubti;
6082     proto_tree *subtree, *subsubtree;
6083
6084     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_acl_creation, &subti, "Filter");
6085
6086     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
6087
6088     offset = dissect_kafka_string(subtree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
6089
6090     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
6091                                      ett_kafka_acl_filter_matches,
6092                                      &subsubti, "Matches");
6093     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6094                                  &dissect_kafka_delete_acls_response_match);
6095
6096     proto_item_set_end(subsubti, tvb, offset);
6097     proto_item_set_end(subti, tvb, offset);
6098
6099     return offset;
6100 }
6101
6102 static int
6103 dissect_kafka_delete_acls_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6104                                    kafka_api_version_t api_version)
6105 {
6106     proto_item *subti;
6107     proto_tree *subtree;
6108
6109     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
6110
6111     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6112                                      ett_kafka_acl_creations,
6113                                      &subti, "Filters");
6114     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6115                                  &dissect_kafka_delete_acls_response_filter);
6116
6117     proto_item_set_end(subti, tvb, offset);
6118
6119     return offset;
6120 }
6121
6122 /* DESCRIBE_CONFIGS REQUEST/RESPONSE */
6123
6124 static int
6125 dissect_kafka_describe_config_request_entry(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6126                                                int offset, kafka_api_version_t api_version _U_)
6127 {
6128     offset = dissect_kafka_string(tree, hf_kafka_config_key, tvb, pinfo, offset, NULL, NULL);
6129
6130     return offset;
6131 }
6132
6133 static int
6134 dissect_kafka_describe_config_request_resource(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6135                                          int offset, kafka_api_version_t api_version _U_)
6136 {
6137     proto_item *subti, *subsubti;
6138     proto_tree *subtree, *subsubtree;
6139
6140     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_resource, &subti, "Resource");
6141
6142     proto_tree_add_item(subtree, hf_kafka_config_resource_type, tvb, offset, 1, ENC_BIG_ENDIAN);
6143     offset += 1;
6144
6145     offset = dissect_kafka_string(subtree, hf_kafka_config_resource_name, tvb, pinfo, offset, NULL, NULL);
6146
6147     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_config_entries, &subsubti, "Entries");
6148
6149     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6150                                  &dissect_kafka_describe_config_request_entry);
6151
6152     proto_item_set_end(subti, tvb, offset);
6153
6154     return offset;
6155 }
6156
6157 static int
6158 dissect_kafka_describe_configs_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6159                                   kafka_api_version_t api_version)
6160 {
6161     proto_item *subti;
6162     proto_tree *subtree;
6163
6164     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6165                                      ett_kafka_resources,
6166                                      &subti, "Resources");
6167     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6168                                  &dissect_kafka_describe_config_request_resource);
6169
6170     if (api_version >= 1) {
6171         proto_tree_add_item(subtree, hf_kafka_config_include_synonyms, tvb, offset, 1, ENC_BIG_ENDIAN);
6172         offset += 1;
6173     }
6174
6175     proto_item_set_end(subti, tvb, offset);
6176
6177     return offset;
6178 }
6179
6180 static int
6181 dissect_kafka_describe_configs_response_synonym(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6182                                               int offset, kafka_api_version_t api_version _U_)
6183 {
6184     proto_item *subti;
6185     proto_tree *subtree;
6186     int key_start, key_len;
6187
6188     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_config_synonym, &subti, "Synonym");
6189
6190     offset = dissect_kafka_string(subtree, hf_kafka_config_key, tvb, pinfo, offset, &key_start, &key_len);
6191     offset = dissect_kafka_string(subtree, hf_kafka_config_value, tvb, pinfo, offset, NULL, NULL);
6192
6193     proto_tree_add_item(subtree, hf_kafka_config_source, tvb, offset, 1, ENC_BIG_ENDIAN);
6194     offset += 1;
6195
6196     proto_item_set_end(subti, tvb, offset);
6197     proto_item_append_text(subti, " (Key=%s)",
6198                            tvb_get_string_enc(wmem_packet_scope(), tvb,
6199                                               key_start, key_len, ENC_UTF_8|ENC_NA));
6200
6201     return offset;
6202 }
6203
6204 static int
6205 dissect_kafka_describe_configs_response_entry(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6206                                          int offset, kafka_api_version_t api_version _U_)
6207 {
6208     proto_item *subti, *subsubti;
6209     proto_tree *subtree, *subsubtree;
6210     int key_start, key_len;
6211
6212     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_config_entry, &subti, "Entry");
6213
6214     offset = dissect_kafka_string(subtree, hf_kafka_config_key, tvb, pinfo, offset, &key_start, &key_len);
6215     offset = dissect_kafka_string(subtree, hf_kafka_config_value, tvb, pinfo, offset, NULL, NULL);
6216
6217     proto_tree_add_item(subtree, hf_kafka_config_readonly, tvb, offset, 1, ENC_BIG_ENDIAN);
6218     offset += 1;
6219
6220     if (api_version == 0) {
6221         proto_tree_add_item(subtree, hf_kafka_config_default, tvb, offset, 1, ENC_BIG_ENDIAN);
6222         offset += 1;
6223     } else {
6224         proto_tree_add_item(subtree, hf_kafka_config_source, tvb, offset, 1, ENC_BIG_ENDIAN);
6225         offset += 1;
6226     }
6227
6228     proto_tree_add_item(subtree, hf_kafka_config_sensitive, tvb, offset, 1, ENC_BIG_ENDIAN);
6229     offset += 1;
6230
6231     if (api_version >= 1) {
6232         subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
6233                                             ett_kafka_config_synonyms,
6234                                             &subsubti, "Synonyms");
6235         offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6236                                      &dissect_kafka_describe_configs_response_synonym);
6237
6238         proto_item_set_end(subsubti, tvb, offset);
6239     }
6240
6241     proto_item_set_end(subti, tvb, offset);
6242     proto_item_append_text(subti, " (Key=%s)",
6243                            tvb_get_string_enc(wmem_packet_scope(), tvb,
6244                                               key_start, key_len, ENC_UTF_8|ENC_NA));
6245
6246     return offset;
6247 }
6248
6249 static int
6250 dissect_kafka_describe_configs_response_resource(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6251                                           int offset, kafka_api_version_t api_version _U_)
6252 {
6253     proto_item *subti, *subsubti;
6254     proto_tree *subtree, *subsubtree;
6255
6256     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_resource, &subti, "Resource");
6257
6258     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
6259
6260     offset = dissect_kafka_string(subtree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
6261
6262     proto_tree_add_item(subtree, hf_kafka_config_resource_type, tvb, offset, 1, ENC_BIG_ENDIAN);
6263     offset += 1;
6264
6265     offset = dissect_kafka_string(subtree, hf_kafka_config_resource_name, tvb, pinfo, offset, NULL, NULL);
6266
6267     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
6268                                         ett_kafka_config_entries,
6269                                         &subsubti, "Entries");
6270     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6271                                  &dissect_kafka_describe_configs_response_entry);
6272
6273     proto_item_set_end(subsubti, tvb, offset);
6274     proto_item_set_end(subti, tvb, offset);
6275
6276     return offset;
6277 }
6278
6279 static int
6280 dissect_kafka_describe_configs_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6281                                    kafka_api_version_t api_version)
6282 {
6283     proto_item *subti;
6284     proto_tree *subtree;
6285
6286     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
6287
6288     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6289                                      ett_kafka_resources,
6290                                      &subti, "Resources");
6291     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6292                                  &dissect_kafka_describe_configs_response_resource);
6293
6294     proto_item_set_end(subti, tvb, offset);
6295
6296     return offset;
6297 }
6298
6299 /* ALTER_CONFIGS REQUEST/RESPONSE */
6300
6301 static int
6302 dissect_kafka_alter_config_request_entry(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6303                                             int offset, kafka_api_version_t api_version _U_)
6304 {
6305     proto_item *subti;
6306     proto_tree *subtree;
6307
6308     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_config_entry, &subti, "Entry");
6309
6310     offset = dissect_kafka_string(subtree, hf_kafka_config_key, tvb, pinfo, offset, NULL, NULL);
6311     offset = dissect_kafka_string(subtree, hf_kafka_config_value, tvb, pinfo, offset, NULL, NULL);
6312
6313     proto_item_set_end(subti, tvb, offset);
6314
6315     return offset;
6316 }
6317
6318 static int
6319 dissect_kafka_alter_config_request_resource(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6320                                                int offset, kafka_api_version_t api_version _U_)
6321 {
6322     proto_item *subti, *subsubti;
6323     proto_tree *subtree, *subsubtree;
6324
6325     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_resource, &subti, "Resource");
6326
6327     proto_tree_add_item(subtree, hf_kafka_config_resource_type, tvb, offset, 1, ENC_BIG_ENDIAN);
6328     offset += 1;
6329
6330     offset = dissect_kafka_string(subtree, hf_kafka_config_resource_name, tvb, pinfo, offset, NULL, NULL);
6331
6332     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_config_entries, &subsubti, "Entries");
6333
6334     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6335                                  &dissect_kafka_alter_config_request_entry);
6336
6337     proto_item_set_end(subti, tvb, offset);
6338
6339     return offset;
6340 }
6341
6342 static int
6343 dissect_kafka_alter_configs_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6344                                        kafka_api_version_t api_version)
6345 {
6346     proto_item *subti;
6347     proto_tree *subtree;
6348
6349     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6350                                      ett_kafka_resources,
6351                                      &subti, "Resources");
6352     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6353                                  &dissect_kafka_alter_config_request_resource);
6354
6355     proto_tree_add_item(subtree, hf_kafka_validate_only, tvb, offset, 1, ENC_BIG_ENDIAN);
6356     offset += 1;
6357
6358     proto_item_set_end(subti, tvb, offset);
6359
6360     return offset;
6361 }
6362
6363 static int
6364 dissect_kafka_alter_configs_response_resource(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6365                                                  int offset, kafka_api_version_t api_version _U_)
6366 {
6367     proto_item *subti;
6368     proto_tree *subtree;
6369
6370     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_resource, &subti, "Resource");
6371
6372     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
6373
6374     offset = dissect_kafka_string(subtree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
6375
6376     proto_tree_add_item(subtree, hf_kafka_config_resource_type, tvb, offset, 1, ENC_BIG_ENDIAN);
6377     offset += 1;
6378
6379     offset = dissect_kafka_string(subtree, hf_kafka_config_resource_name, tvb, pinfo, offset, NULL, NULL);
6380
6381     proto_item_set_end(subti, tvb, offset);
6382
6383     return offset;
6384 }
6385
6386 static int
6387 dissect_kafka_alter_configs_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6388                                         kafka_api_version_t api_version)
6389 {
6390     proto_item *subti;
6391     proto_tree *subtree;
6392
6393     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
6394
6395     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6396                                      ett_kafka_resources,
6397                                      &subti, "Resources");
6398     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6399                                  &dissect_kafka_alter_configs_response_resource);
6400
6401     proto_item_set_end(subti, tvb, offset);
6402
6403     return offset;
6404 }
6405
6406 /* ALTER_REPLICA_LOG_DIRS REQUEST/RESPONSE */
6407
6408 static int
6409 dissect_kafka_alter_replica_log_dirs_request_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6410                                          int offset, kafka_api_version_t api_version _U_)
6411 {
6412     proto_tree_add_item(tree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
6413     offset += 4;
6414
6415     return offset;
6416 }
6417
6418 static int
6419 dissect_kafka_alter_replica_log_dirs_request_topic(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6420                                                  int offset, kafka_api_version_t api_version _U_)
6421 {
6422     proto_item *subti, *subsubti;
6423     proto_tree *subtree, *subsubtree;
6424     int topic_start, topic_len;
6425
6426     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_resource, &subti, "Topic");
6427
6428     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
6429
6430     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topics, &subsubti, "Partitions");
6431
6432     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6433                                  &dissect_kafka_alter_replica_log_dirs_request_partition);
6434
6435     proto_item_set_end(subti, tvb, offset);
6436     proto_item_append_text(subti, " (Name=%s)",
6437                            tvb_get_string_enc(wmem_packet_scope(), tvb,
6438                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
6439
6440     return offset;
6441 }
6442
6443 static int
6444 dissect_kafka_alter_replica_log_dirs_request_log_dir(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6445                                             int offset, kafka_api_version_t api_version _U_)
6446 {
6447     proto_item *subti, *subsubti;
6448     proto_tree *subtree, *subsubtree;
6449
6450     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_log_dir, &subti, "Log Directory");
6451
6452     offset = dissect_kafka_string(subtree, hf_kafka_log_dir, tvb, pinfo, offset, NULL, NULL);
6453
6454     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topics, &subsubti, "Topics");
6455
6456     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6457                                  &dissect_kafka_alter_replica_log_dirs_request_topic);
6458
6459     proto_item_set_end(subti, tvb, offset);
6460
6461     return offset;
6462 }
6463
6464 static int
6465 dissect_kafka_alter_replica_log_dirs_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6466                                     kafka_api_version_t api_version)
6467 {
6468     proto_item *subti;
6469     proto_tree *subtree;
6470
6471     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6472                                      ett_kafka_log_dirs,
6473                                      &subti, "Log Directories");
6474     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6475                                  &dissect_kafka_alter_replica_log_dirs_request_log_dir);
6476
6477     proto_item_set_end(subti, tvb, offset);
6478
6479     return offset;
6480 }
6481
6482 static int
6483 dissect_kafka_alter_replica_log_dirs_response_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6484                                        int offset, kafka_api_version_t api_version _U_)
6485 {
6486     proto_item *subti;
6487     proto_tree *subtree;
6488     int partition_id;
6489
6490     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
6491
6492     partition_id = tvb_get_ntohl(tvb, offset);
6493     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
6494     offset += 4;
6495
6496     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
6497
6498     proto_item_append_text(subti, " (ID=%u)", partition_id);
6499
6500     proto_item_set_end(subti, tvb, offset);
6501
6502     return offset;
6503 }
6504
6505 static int
6506 dissect_kafka_alter_replica_log_dirs_response_topic(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6507                                               int offset, kafka_api_version_t api_version)
6508 {
6509     proto_item *subti, *subsubti;
6510     proto_tree *subtree, *subsubtree;
6511     int topic_start, topic_len;
6512
6513     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
6514
6515     offset = dissect_kafka_string(subtree, hf_kafka_log_dir, tvb, pinfo, offset, &topic_start, &topic_len);
6516
6517     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partition");
6518
6519     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6520                                  &dissect_kafka_alter_replica_log_dirs_response_partition);
6521
6522     proto_item_set_end(subti, tvb, offset);
6523     proto_item_append_text(subti, " (Name=%s)",
6524                            tvb_get_string_enc(wmem_packet_scope(), tvb,
6525                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
6526
6527     return offset;
6528 }
6529
6530 static int
6531 dissect_kafka_alter_replica_log_dirs_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6532                                      kafka_api_version_t api_version)
6533 {
6534     proto_item *subti;
6535     proto_tree *subtree;
6536
6537     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
6538
6539     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6540                                      ett_kafka_topics,
6541                                      &subti, "Topics");
6542     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6543                                  &dissect_kafka_alter_replica_log_dirs_response_topic);
6544
6545     proto_item_set_end(subti, tvb, offset);
6546
6547     return offset;
6548 }
6549
6550 /* DESCRIBE_LOG_DIRS REQUEST/RESPONSE */
6551
6552 static int
6553 dissect_kafka_describe_log_dirs_request_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6554                                                        int offset, kafka_api_version_t api_version _U_)
6555 {
6556     proto_tree_add_item(tree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
6557     offset += 4;
6558
6559     return offset;
6560 }
6561
6562 static int
6563 dissect_kafka_describe_log_dirs_request_topic(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6564                                                    int offset, kafka_api_version_t api_version _U_)
6565 {
6566     proto_item *subti, *subsubti;
6567     proto_tree *subtree, *subsubtree;
6568     int topic_start, topic_len;
6569
6570     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_resource, &subti, "Topic");
6571
6572     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
6573
6574     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
6575
6576     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6577                                  &dissect_kafka_describe_log_dirs_request_partition);
6578
6579     proto_item_set_end(subti, tvb, offset);
6580     proto_item_append_text(subti, " (Name=%s)",
6581                            tvb_get_string_enc(wmem_packet_scope(), tvb,
6582                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
6583
6584     return offset;
6585 }
6586
6587 static int
6588 dissect_kafka_describe_log_dirs_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6589                                              kafka_api_version_t api_version)
6590 {
6591     proto_item *subti;
6592     proto_tree *subtree;
6593
6594     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6595                                      ett_kafka_topics,
6596                                      &subti, "Topics");
6597     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6598                                  &dissect_kafka_describe_log_dirs_request_topic);
6599
6600     proto_item_set_end(subti, tvb, offset);
6601
6602     return offset;
6603 }
6604
6605 static int
6606 dissect_kafka_describe_log_dirs_response_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6607                                                         int offset, kafka_api_version_t api_version _U_)
6608 {
6609     proto_item *subti;
6610     proto_tree *subtree;
6611
6612     int partition_id;
6613
6614     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
6615
6616     partition_id = tvb_get_ntohl(tvb, offset);
6617     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
6618     offset += 4;
6619
6620     proto_tree_add_item(subtree, hf_kafka_segment_size, tvb, offset, 8, ENC_BIG_ENDIAN);
6621     offset += 8;
6622
6623     proto_tree_add_item(subtree, hf_kafka_offset_lag, tvb, offset, 8, ENC_BIG_ENDIAN);
6624     offset += 8;
6625
6626     proto_tree_add_item(subtree, hf_kafka_future, tvb, offset, 1, ENC_BIG_ENDIAN);
6627     offset += 1;
6628
6629     proto_item_set_end(subti, tvb, offset);
6630     proto_item_append_text(subti, " (ID=%u)", partition_id);
6631
6632     return offset;
6633 }
6634
6635 static int
6636 dissect_kafka_describe_log_dirs_response_topic(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6637                                                     int offset, kafka_api_version_t api_version)
6638 {
6639     proto_item *subti, *subsubti;
6640     proto_tree *subtree, *subsubtree;
6641     int topic_start, topic_len;
6642
6643     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
6644
6645     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
6646
6647     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
6648
6649     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6650                                  &dissect_kafka_describe_log_dirs_response_partition);
6651
6652     proto_item_set_end(subti, tvb, offset);
6653     proto_item_append_text(subti, " (Name=%s)",
6654                            tvb_get_string_enc(wmem_packet_scope(), tvb,
6655                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
6656
6657     return offset;
6658 }
6659
6660 static int
6661 dissect_kafka_describe_log_dirs_response_log_dir(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6662                                                     int offset, kafka_api_version_t api_version)
6663 {
6664     proto_item *subti, *subsubti;
6665     proto_tree *subtree, *subsubtree;
6666     int dir_start, dir_len;
6667
6668     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_log_dir, &subti, "Log Directory");
6669
6670     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
6671
6672     offset = dissect_kafka_string(subtree, hf_kafka_log_dir, tvb, pinfo, offset, &dir_start, &dir_len);
6673
6674     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_topics, &subsubti, "Topics");
6675
6676     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6677                                  &dissect_kafka_describe_log_dirs_response_topic);
6678
6679     proto_item_set_end(subti, tvb, offset);
6680     proto_item_append_text(subti, " (Dir=%s)",
6681                            tvb_get_string_enc(wmem_packet_scope(), tvb,
6682                                               dir_start, dir_len, ENC_UTF_8|ENC_NA));
6683
6684     return offset;
6685 }
6686
6687 static int
6688 dissect_kafka_describe_log_dirs_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6689                                               kafka_api_version_t api_version)
6690 {
6691     proto_item *subti;
6692     proto_tree *subtree;
6693
6694     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
6695
6696     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6697                                      ett_kafka_log_dirs,
6698                                      &subti, "Log Directories");
6699     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6700                                  &dissect_kafka_describe_log_dirs_response_log_dir);
6701
6702     proto_item_set_end(subti, tvb, offset);
6703
6704     return offset;
6705 }
6706
6707 /* CREATE_PARTITIONS REQUEST/RESPONSE */
6708
6709 static int
6710 dissect_kafka_create_partitions_request_broker(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6711                                                   int offset, kafka_api_version_t api_version _U_)
6712 {
6713     proto_tree_add_item(tree, hf_kafka_broker_nodeid, tvb, offset, 4, ENC_BIG_ENDIAN);
6714     offset += 4;
6715
6716     return offset;
6717 }
6718
6719 static int
6720 dissect_kafka_create_partitions_request_topic(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6721                                               int offset, kafka_api_version_t api_version _U_)
6722 {
6723     proto_item *subti, *subsubti;
6724     proto_tree *subtree, *subsubtree;
6725     int topic_start, topic_len;
6726
6727     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_resource, &subti, "Topic");
6728
6729     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
6730
6731     proto_tree_add_item(subtree, hf_kafka_partition_count, tvb, offset, 4, ENC_BIG_ENDIAN);
6732     offset += 4;
6733
6734     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1, ett_kafka_brokers, &subsubti, "Brokers");
6735
6736     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
6737                                  &dissect_kafka_create_partitions_request_broker);
6738
6739     proto_item_set_end(subti, tvb, offset);
6740     proto_item_append_text(subti, " (Name=%s)",
6741                            tvb_get_string_enc(wmem_packet_scope(), tvb,
6742                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
6743
6744     return offset;
6745 }
6746
6747 static int
6748 dissect_kafka_create_partitions_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6749                                         kafka_api_version_t api_version)
6750 {
6751     proto_item *subti;
6752     proto_tree *subtree;
6753
6754     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6755                                      ett_kafka_topics,
6756                                      &subti, "Topics");
6757
6758     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6759                                  &dissect_kafka_create_partitions_request_topic);
6760
6761     proto_item_set_end(subti, tvb, offset);
6762
6763     proto_tree_add_item(tree, hf_kafka_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
6764     offset += 4;
6765
6766     proto_tree_add_item(tree, hf_kafka_validate_only, tvb, offset, 1, ENC_BIG_ENDIAN);
6767     offset += 1;
6768
6769     return offset;
6770 }
6771
6772 static int
6773 dissect_kafka_create_partitions_response_topic(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6774                                                int offset, kafka_api_version_t api_version _U_)
6775 {
6776     proto_item *subti;
6777     proto_tree *subtree;
6778     int topic_start, topic_len;
6779
6780     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
6781
6782     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, &topic_start, &topic_len);
6783
6784     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
6785
6786     offset = dissect_kafka_string(subtree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
6787
6788     proto_item_set_end(subti, tvb, offset);
6789     proto_item_append_text(subti, " (Name=%s)",
6790                            tvb_get_string_enc(wmem_packet_scope(), tvb,
6791                                               topic_start, topic_len, ENC_UTF_8|ENC_NA));
6792
6793     return offset;
6794 }
6795
6796 static int
6797 dissect_kafka_create_partitions_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6798                                          kafka_api_version_t api_version)
6799 {
6800     proto_item *subti;
6801     proto_tree *subtree;
6802
6803     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
6804
6805     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6806                                      ett_kafka_topics,
6807                                      &subti, "Topics");
6808     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6809                                  &dissect_kafka_create_partitions_response_topic);
6810
6811     proto_item_set_end(subti, tvb, offset);
6812
6813     return offset;
6814 }
6815
6816 /* SASL_AUTHENTICATE REQUEST/RESPONSE */
6817
6818 static int
6819 dissect_kafka_sasl_authenticate_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6820                                          kafka_api_version_t api_version _U_)
6821 {
6822     offset = dissect_kafka_bytes(tree, hf_kafka_sasl_auth_bytes, tvb, pinfo, offset, NULL, NULL);
6823
6824     return offset;
6825 }
6826
6827
6828 static int
6829 dissect_kafka_sasl_authenticate_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6830                                           kafka_api_version_t api_version _U_)
6831 {
6832     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
6833
6834     offset = dissect_kafka_string(tree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
6835
6836     offset = dissect_kafka_bytes(tree, hf_kafka_sasl_auth_bytes, tvb, pinfo, offset, NULL, NULL);
6837
6838     if (api_version >= 1) {
6839         proto_tree_add_item(tree, hf_kafka_session_lifetime_ms, tvb, offset, 8, ENC_BIG_ENDIAN);
6840         offset += 8;
6841     }
6842
6843     return offset;
6844 }
6845
6846 /* CREATE_DELEGATION_TOKEN REQUEST/RESPONSE */
6847
6848 static int
6849 dissect_kafka_create_delegation_token_request_renewer(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6850                                               int offset, kafka_api_version_t api_version _U_)
6851 {
6852     proto_item *subti;
6853     proto_tree *subtree;
6854
6855     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_renewer, &subti, "Renewer");
6856
6857     offset = dissect_kafka_string(subtree, hf_kafka_token_principal_type, tvb, pinfo, offset, NULL, NULL);
6858
6859     offset = dissect_kafka_string(subtree, hf_kafka_token_principal_name, tvb, pinfo, offset, NULL, NULL);
6860
6861     proto_item_set_end(subti, tvb, offset);
6862
6863     return offset;
6864 }
6865
6866 static int
6867 dissect_kafka_create_delegation_token_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6868                                         kafka_api_version_t api_version)
6869 {
6870     proto_item *subti;
6871     proto_tree *subtree;
6872
6873     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6874                                      ett_kafka_renewers,
6875                                      &subti, "Renewers");
6876
6877     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6878                                  &dissect_kafka_create_delegation_token_request_renewer);
6879
6880     proto_item_set_end(subti, tvb, offset);
6881
6882     proto_tree_add_item(tree, hf_kafka_token_max_life_time, tvb, offset, 8, ENC_BIG_ENDIAN);
6883     offset += 8;
6884
6885     return offset;
6886 }
6887
6888 static int
6889 dissect_kafka_create_delegation_token_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6890                                          kafka_api_version_t api_version _U_)
6891 {
6892     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
6893
6894     offset = dissect_kafka_string(tree, hf_kafka_token_principal_type, tvb, pinfo, offset, NULL, NULL);
6895     offset = dissect_kafka_string(tree, hf_kafka_token_principal_name, tvb, pinfo, offset, NULL, NULL);
6896
6897     proto_tree_add_item(tree, hf_kafka_token_issue_timestamp, tvb, offset, 8, ENC_TIME_MSECS | ENC_BIG_ENDIAN);
6898     offset += 8;
6899     proto_tree_add_item(tree, hf_kafka_token_expiry_timestamp, tvb, offset, 8, ENC_TIME_MSECS | ENC_BIG_ENDIAN);
6900     offset += 8;
6901     proto_tree_add_item(tree, hf_kafka_token_max_timestamp, tvb, offset, 8, ENC_TIME_MSECS | ENC_BIG_ENDIAN);
6902     offset += 8;
6903
6904     offset = dissect_kafka_string(tree, hf_kafka_token_id, tvb, pinfo, offset, NULL, NULL);
6905     offset = dissect_kafka_bytes(tree, hf_kafka_token_hmac, tvb, pinfo, offset, NULL, NULL);
6906
6907     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
6908
6909     return offset;
6910 }
6911
6912 /* RENEW_DELEGATION_TOKEN REQUEST/RESPONSE */
6913
6914 static int
6915 dissect_kafka_renew_delegation_token_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6916                                               kafka_api_version_t api_version _U_)
6917 {
6918     offset = dissect_kafka_bytes(tree, hf_kafka_token_hmac, tvb, pinfo, offset, NULL, NULL);
6919
6920     proto_tree_add_item(tree, hf_kafka_token_renew_time, tvb, offset, 8, ENC_BIG_ENDIAN);
6921     offset += 8;
6922
6923     return offset;
6924 }
6925
6926 static int
6927 dissect_kafka_renew_delegation_token_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6928                                                kafka_api_version_t api_version _U_)
6929 {
6930     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
6931     proto_tree_add_item(tree, hf_kafka_token_expiry_timestamp, tvb, offset, 8, ENC_TIME_MSECS | ENC_BIG_ENDIAN);
6932     offset += 8;
6933     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
6934
6935     return offset;
6936 }
6937
6938 /* EXPIRE_DELEGATION_TOKEN REQUEST/RESPONSE */
6939
6940 static int
6941 dissect_kafka_expire_delegation_token_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6942                                              kafka_api_version_t api_version _U_)
6943 {
6944     offset = dissect_kafka_bytes(tree, hf_kafka_token_hmac, tvb, pinfo, offset, NULL, NULL);
6945
6946     proto_tree_add_item(tree, hf_kafka_token_expiry_time, tvb, offset, 8, ENC_BIG_ENDIAN);
6947     offset += 8;
6948
6949     return offset;
6950 }
6951
6952 static int
6953 dissect_kafka_expire_delegation_token_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6954                                               kafka_api_version_t api_version _U_)
6955 {
6956     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
6957     proto_tree_add_item(tree, hf_kafka_token_expiry_timestamp, tvb, offset, 8, ENC_TIME_MSECS | ENC_BIG_ENDIAN);
6958     offset += 8;
6959     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
6960
6961     return offset;
6962 }
6963
6964 /* DESCRIBE_DELEGATION_TOKEN REQUEST/RESPONSE */
6965
6966 static int
6967 dissect_kafka_describe_delegation_token_request_owner(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
6968                                                       int offset, kafka_api_version_t api_version _U_)
6969 {
6970     proto_item *subti;
6971     proto_tree *subtree;
6972
6973     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_owner, &subti, "Owner");
6974
6975     offset = dissect_kafka_string(subtree, hf_kafka_token_principal_type, tvb, pinfo, offset, NULL, NULL);
6976
6977     offset = dissect_kafka_string(subtree, hf_kafka_token_principal_name, tvb, pinfo, offset, NULL, NULL);
6978
6979     proto_item_set_end(subti, tvb, offset);
6980
6981     return offset;
6982 }
6983
6984 static int
6985 dissect_kafka_describe_delegation_token_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
6986                                               kafka_api_version_t api_version _U_)
6987 {
6988     proto_item *subti;
6989     proto_tree *subtree;
6990
6991     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
6992                                      ett_kafka_owners,
6993                                      &subti, "Owners");
6994
6995     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
6996                                  &dissect_kafka_describe_delegation_token_request_owner);
6997
6998     proto_item_set_end(subti, tvb, offset);
6999
7000     return offset;
7001 }
7002
7003 static int
7004 dissect_kafka_describe_delegation_token_response_renewer(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
7005                                                      int offset, kafka_api_version_t api_version _U_)
7006 {
7007     proto_item *subti;
7008     proto_tree *subtree;
7009
7010     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_renewer, &subti, "Renewer");
7011
7012     offset = dissect_kafka_string(subtree, hf_kafka_token_principal_type, tvb, pinfo, offset, NULL, NULL);
7013     offset = dissect_kafka_string(subtree, hf_kafka_token_principal_name, tvb, pinfo, offset, NULL, NULL);
7014
7015     proto_item_set_end(subti, tvb, offset);
7016
7017     return offset;
7018 }
7019
7020 static int
7021 dissect_kafka_describe_delegation_token_response_token(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7022                                                       int offset, kafka_api_version_t api_version)
7023 {
7024     proto_item *subti, *subsubti;
7025     proto_tree *subtree, *subsubtree;
7026
7027     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_token, &subti, "Token");
7028
7029     offset = dissect_kafka_string(subtree, hf_kafka_token_principal_type, tvb, pinfo, offset, NULL, NULL);
7030     offset = dissect_kafka_string(subtree, hf_kafka_token_principal_name, tvb, pinfo, offset, NULL, NULL);
7031
7032     proto_tree_add_item(subtree, hf_kafka_token_issue_timestamp, tvb, offset, 8, ENC_TIME_MSECS | ENC_BIG_ENDIAN);
7033     offset += 8;
7034     proto_tree_add_item(subtree, hf_kafka_token_expiry_timestamp, tvb, offset, 8, ENC_TIME_MSECS | ENC_BIG_ENDIAN);
7035     offset += 8;
7036     proto_tree_add_item(subtree, hf_kafka_token_max_timestamp, tvb, offset, 8, ENC_TIME_MSECS | ENC_BIG_ENDIAN);
7037     offset += 8;
7038
7039     offset = dissect_kafka_string(subtree, hf_kafka_token_id, tvb, pinfo, offset, NULL, NULL);
7040     offset = dissect_kafka_bytes(subtree, hf_kafka_token_hmac, tvb, pinfo, offset, NULL, NULL);
7041
7042
7043     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
7044                                      ett_kafka_renewers,
7045                                      &subsubti, "Renewers");
7046
7047     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7048                                  &dissect_kafka_describe_delegation_token_response_renewer);
7049
7050     proto_item_set_end(subsubti, tvb, offset);
7051
7052     proto_item_set_end(subti, tvb, offset);
7053
7054     return offset;
7055 }
7056
7057 static int
7058 dissect_kafka_describe_delegation_token_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7059                                                kafka_api_version_t api_version _U_)
7060 {
7061     proto_item *subti;
7062     proto_tree *subtree;
7063
7064     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
7065
7066     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7067                                      ett_kafka_tokens,
7068                                      &subti, "Tokens");
7069
7070     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
7071                                  &dissect_kafka_describe_delegation_token_response_token);
7072
7073     proto_item_set_end(subti, tvb, offset);
7074
7075     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
7076
7077     return offset;
7078 }
7079
7080 /* DELETE_GROUPS REQUEST/RESPONSE */
7081
7082 static int
7083 dissect_kafka_delete_groups_request_group(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
7084                                                       int offset, kafka_api_version_t api_version _U_)
7085 {
7086     offset = dissect_kafka_string(tree, hf_kafka_consumer_group, tvb, pinfo, offset, NULL, NULL);
7087
7088     return offset;
7089 }
7090
7091 static int
7092 dissect_kafka_delete_groups_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7093                                                 kafka_api_version_t api_version _U_)
7094 {
7095     proto_item *subti;
7096     proto_tree *subtree;
7097
7098     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7099                                      ett_kafka_groups,
7100                                      &subti, "Groups");
7101
7102     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
7103                                  &dissect_kafka_delete_groups_request_group);
7104
7105     proto_item_set_end(subti, tvb, offset);
7106
7107     return offset;
7108 }
7109
7110 static int
7111 dissect_kafka_delete_groups_response_group(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
7112                                                          int offset, kafka_api_version_t api_version _U_)
7113 {
7114     proto_item *subti;
7115     proto_tree *subtree;
7116
7117     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_group, &subti, "Group");
7118
7119     offset = dissect_kafka_string(subtree, hf_kafka_consumer_group, tvb, pinfo, offset, NULL, NULL);
7120     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
7121
7122     proto_item_set_end(subti, tvb, offset);
7123
7124     return offset;
7125 }
7126
7127 static int
7128 dissect_kafka_delete_groups_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7129                                                  kafka_api_version_t api_version _U_)
7130 {
7131     proto_item *subti;
7132     proto_tree *subtree;
7133
7134     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
7135
7136     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7137                                      ett_kafka_groups,
7138                                      &subti, "Groups");
7139
7140     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
7141                                  &dissect_kafka_delete_groups_response_group);
7142
7143     proto_item_set_end(subti, tvb, offset);
7144
7145     return offset;
7146 }
7147
7148 /* ELECT_LEADERS REQUEST/RESPONSE */
7149
7150 static int
7151 dissect_kafka_elect_leaders_request_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
7152                                           int offset, kafka_api_version_t api_version _U_)
7153 {
7154     proto_tree_add_item(tree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
7155     offset += 4;
7156
7157     return offset;
7158 }
7159
7160 static int
7161 dissect_kafka_elect_leaders_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7162                                     kafka_api_version_t api_version)
7163 {
7164     proto_item *subti, *subsubti;
7165     proto_tree *subtree, *subsubtree;
7166
7167     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7168                                      ett_kafka_topic,
7169                                      &subti, "Topic");
7170
7171     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
7172                                      ett_kafka_partitions,
7173                                      &subsubti, "Partitions");
7174
7175     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7176                                  &dissect_kafka_elect_leaders_request_partition);
7177
7178     proto_item_set_end(subsubti, tvb, offset);
7179     proto_item_set_end(subti, tvb, offset);
7180
7181     return offset;
7182 }
7183
7184 static int
7185 dissect_kafka_elect_leaders_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7186                                     kafka_api_version_t api_version)
7187 {
7188     proto_item *subti;
7189     proto_tree *subtree;
7190
7191     if (api_version >= 1) {
7192         proto_tree_add_item(tree, hf_kafka_election_type, tvb, offset, 4, ENC_BIG_ENDIAN);
7193         offset += 1;
7194     }
7195
7196     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7197                                      ett_kafka_topics,
7198                                      &subti, "Topics");
7199
7200     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
7201                                  &dissect_kafka_elect_leaders_request_topic);
7202
7203     proto_item_set_end(subti, tvb, offset);
7204
7205     proto_tree_add_item(tree, hf_kafka_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
7206     offset += 4;
7207
7208     return offset;
7209 }
7210
7211 static int
7212 dissect_kafka_elect_leaders_response_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
7213                                                   int offset, kafka_api_version_t api_version _U_)
7214 {
7215     proto_tree_add_item(tree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
7216     offset += 4;
7217
7218     proto_item *subti;
7219     proto_tree *subtree;
7220
7221     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7222                                      ett_kafka_partition,
7223                                      &subti, "Partition");
7224
7225     proto_tree_add_item(subtree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
7226     offset += 4;
7227
7228     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
7229
7230     offset = dissect_kafka_string(subtree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
7231
7232     proto_item_set_end(subti, tvb, offset);
7233
7234     return offset;
7235 }
7236
7237 static int
7238 dissect_kafka_elect_leaders_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7239                                               kafka_api_version_t api_version)
7240 {
7241     proto_item *subti, *subsubti;
7242     proto_tree *subtree, *subsubtree;
7243
7244     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7245                                      ett_kafka_topic,
7246                                      &subti, "Topic");
7247
7248     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
7249                                         ett_kafka_partitions,
7250                                         &subsubti, "Partitions");
7251
7252     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7253                                  &dissect_kafka_elect_leaders_response_partition);
7254
7255     proto_item_set_end(subsubti, tvb, offset);
7256     proto_item_set_end(subti, tvb, offset);
7257
7258     return offset;
7259 }
7260
7261 static int
7262 dissect_kafka_elect_leaders_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7263                                         kafka_api_version_t api_version)
7264 {
7265     proto_item *subti;
7266     proto_tree *subtree;
7267
7268     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
7269
7270     if (api_version >= 1) {
7271         offset = dissect_kafka_error(tvb, pinfo, tree, offset);
7272     }
7273
7274     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7275                                      ett_kafka_topics,
7276                                      &subti, "Topics");
7277
7278     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
7279                                  &dissect_kafka_elect_leaders_response_topic);
7280
7281     proto_item_set_end(subti, tvb, offset);
7282
7283     return offset;
7284 }
7285
7286 /* INCREMENTAL_ALTER_CONFIGS REQUEST/RESPONSE */
7287
7288 static int
7289 dissect_kafka_inc_alter_config_request_entry(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
7290                                          int offset, kafka_api_version_t api_version _U_)
7291 {
7292     proto_item *subti;
7293     proto_tree *subtree;
7294
7295     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_config_entry, &subti, "Entry");
7296
7297     offset = dissect_kafka_string(subtree, hf_kafka_config_key, tvb, pinfo, offset, NULL, NULL);
7298
7299     proto_tree_add_item(subtree, hf_kafka_config_operation, tvb, offset, 1, ENC_BIG_ENDIAN);
7300     offset += 1;
7301
7302     offset = dissect_kafka_string(subtree, hf_kafka_config_value, tvb, pinfo, offset, NULL, NULL);
7303
7304     proto_item_set_end(subti, tvb, offset);
7305
7306     return offset;
7307 }
7308
7309 static int
7310 dissect_kafka_inc_alter_config_request_resource(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
7311                                             int offset, kafka_api_version_t api_version _U_)
7312 {
7313     proto_item *subti, *subsubti;
7314     proto_tree *subtree, *subsubtree;
7315
7316     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_resource, &subti, "Resource");
7317
7318     proto_tree_add_item(subtree, hf_kafka_config_resource_type, tvb, offset, 1, ENC_BIG_ENDIAN);
7319     offset += 1;
7320
7321     offset = dissect_kafka_string(subtree, hf_kafka_config_resource_name, tvb, pinfo, offset, NULL, NULL);
7322
7323     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_config_entries, &subsubti, "Entries");
7324
7325     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7326                                  &dissect_kafka_inc_alter_config_request_entry);
7327
7328     proto_item_set_end(subti, tvb, offset);
7329
7330     return offset;
7331 }
7332
7333 static int
7334 dissect_kafka_inc_alter_configs_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7335                                     kafka_api_version_t api_version)
7336 {
7337     proto_item *subti;
7338     proto_tree *subtree;
7339
7340     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7341                                      ett_kafka_resources,
7342                                      &subti, "Resources");
7343     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
7344                                  &dissect_kafka_inc_alter_config_request_resource);
7345
7346     proto_tree_add_item(subtree, hf_kafka_validate_only, tvb, offset, 1, ENC_BIG_ENDIAN);
7347     offset += 1;
7348
7349     proto_item_set_end(subti, tvb, offset);
7350
7351     return offset;
7352 }
7353
7354 static int
7355 dissect_kafka_inc_alter_configs_response_resource(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
7356                                               int offset, kafka_api_version_t api_version _U_)
7357 {
7358     proto_item *subti;
7359     proto_tree *subtree;
7360
7361     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_resource, &subti, "Resource");
7362
7363     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
7364
7365     offset = dissect_kafka_string(subtree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
7366
7367     proto_tree_add_item(subtree, hf_kafka_config_resource_type, tvb, offset, 1, ENC_BIG_ENDIAN);
7368     offset += 1;
7369
7370     offset = dissect_kafka_string(subtree, hf_kafka_config_resource_name, tvb, pinfo, offset, NULL, NULL);
7371
7372     proto_item_set_end(subti, tvb, offset);
7373
7374     return offset;
7375 }
7376
7377 static int
7378 dissect_kafka_inc_alter_configs_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7379                                      kafka_api_version_t api_version)
7380 {
7381     proto_item *subti;
7382     proto_tree *subtree;
7383
7384     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
7385
7386     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7387                                      ett_kafka_resources,
7388                                      &subti, "Resources");
7389     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
7390                                  &dissect_kafka_inc_alter_configs_response_resource);
7391
7392     proto_item_set_end(subti, tvb, offset);
7393
7394     return offset;
7395 }
7396
7397 /* ALTER_PARTITION_REASSIGNMENTS REQUEST/RESPONSE */
7398
7399 static int
7400 dissect_kafka_alter_partition_reassignments_request_replica(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
7401                                              int offset, kafka_api_version_t api_version _U_)
7402 {
7403     proto_tree_add_item(tree, hf_kafka_replica, tvb, offset, 4, ENC_BIG_ENDIAN);
7404     offset += 4;
7405
7406     return offset;
7407 }
7408
7409 static int
7410 dissect_kafka_alter_partition_reassignments_request_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7411                                                           int offset, kafka_api_version_t api_version)
7412 {
7413     proto_item *subti, *subsubti;
7414     proto_tree *subtree, *subsubtree;
7415     kafka_partition_t partition;
7416
7417     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
7418
7419     offset = dissect_kafka_partition_id_ret(tvb, pinfo, subtree, offset, &partition);
7420
7421     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Replicas");
7422
7423     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7424                                  &dissect_kafka_alter_partition_reassignments_request_replica);
7425
7426     proto_item_set_end(subti, tvb, offset);
7427
7428     return offset;
7429 }
7430
7431 static int
7432 dissect_kafka_alter_partition_reassignments_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7433                                                 int offset, kafka_api_version_t api_version)
7434 {
7435     proto_item *subti, *subsubti;
7436     proto_tree *subtree, *subsubtree;
7437
7438     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
7439
7440     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, NULL, NULL);
7441
7442     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
7443
7444     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7445                                  &dissect_kafka_alter_partition_reassignments_request_partition);
7446
7447     proto_item_set_end(subti, tvb, offset);
7448
7449     return offset;
7450 }
7451
7452 static int
7453 dissect_kafka_alter_partition_reassignments_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7454                                         kafka_api_version_t api_version)
7455 {
7456     proto_item *subti;
7457     proto_tree *subtree;
7458
7459     proto_tree_add_item(tree, hf_kafka_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
7460     offset += 4;
7461
7462     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7463                                      ett_kafka_topics,
7464                                      &subti, "Topics");
7465     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
7466                                  &dissect_kafka_alter_partition_reassignments_request_topic);
7467
7468     proto_item_set_end(subti, tvb, offset);
7469
7470     return offset;
7471 }
7472
7473 static int
7474 dissect_kafka_alter_partition_reassignments_response_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7475                                                               int offset, kafka_api_version_t api_version _U_)
7476 {
7477     proto_item *subti;
7478     proto_tree *subtree;
7479     kafka_partition_t partition;
7480
7481     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
7482
7483     offset = dissect_kafka_partition_id_ret(tvb, pinfo, subtree, offset, &partition);
7484
7485     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
7486
7487     offset = dissect_kafka_string(subtree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
7488
7489     proto_item_set_end(subti, tvb, offset);
7490
7491     return offset;
7492 }
7493
7494 static int
7495 dissect_kafka_alter_partition_reassignments_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7496                                                           int offset, kafka_api_version_t api_version)
7497 {
7498     proto_item *subti, *subsubti;
7499     proto_tree *subtree, *subsubtree;
7500
7501     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
7502
7503     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, NULL, NULL);
7504
7505     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
7506
7507     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7508                                  &dissect_kafka_alter_partition_reassignments_response_partition);
7509
7510     proto_item_set_end(subti, tvb, offset);
7511
7512     return offset;
7513 }
7514
7515 static int
7516 dissect_kafka_alter_partition_reassignments_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7517                                                     kafka_api_version_t api_version)
7518 {
7519     proto_item *subti;
7520     proto_tree *subtree;
7521
7522     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
7523
7524     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
7525
7526     offset = dissect_kafka_string(tree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
7527
7528     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7529                                      ett_kafka_topics,
7530                                      &subti, "Topics");
7531     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
7532                                  &dissect_kafka_alter_partition_reassignments_response_topic);
7533
7534     proto_item_set_end(subti, tvb, offset);
7535
7536     return offset;
7537 }
7538
7539 /* LIST_PARTITION_REASSIGNMENTS REQUEST/RESPONSE */
7540
7541 static int
7542 dissect_kafka_list_partition_reassignments_request_partition(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
7543                                                               int offset, kafka_api_version_t api_version _U_)
7544 {
7545     proto_tree_add_item(tree, hf_kafka_partition_id, tvb, offset, 4, ENC_BIG_ENDIAN);
7546     offset += 4;
7547
7548     return offset;
7549 }
7550
7551 static int
7552 dissect_kafka_list_partition_reassignments_request_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7553                                                           int offset, kafka_api_version_t api_version)
7554 {
7555     proto_item *subti, *subsubti;
7556     proto_tree *subtree, *subsubtree;
7557
7558     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
7559
7560     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, NULL, NULL);
7561
7562     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
7563
7564     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7565                                  &dissect_kafka_list_partition_reassignments_request_partition);
7566
7567     proto_item_set_end(subti, tvb, offset);
7568
7569     return offset;
7570 }
7571
7572 static int
7573 dissect_kafka_list_partition_reassignments_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7574                                                     kafka_api_version_t api_version)
7575 {
7576     proto_item *subti;
7577     proto_tree *subtree;
7578
7579     proto_tree_add_item(tree, hf_kafka_timeout, tvb, offset, 4, ENC_BIG_ENDIAN);
7580     offset += 4;
7581
7582     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7583                                      ett_kafka_topics,
7584                                      &subti, "Topics");
7585     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
7586                                  &dissect_kafka_list_partition_reassignments_request_topic);
7587
7588     proto_item_set_end(subti, tvb, offset);
7589
7590     return offset;
7591 }
7592
7593 static int
7594 dissect_kafka_list_partition_reassignments_response_replica(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
7595                                                              int offset, kafka_api_version_t api_version _U_)
7596 {
7597     proto_tree_add_item(tree, hf_kafka_replica, tvb, offset, 4, ENC_BIG_ENDIAN);
7598     offset += 4;
7599
7600     return offset;
7601 }
7602
7603 static int
7604 dissect_kafka_list_partition_reassignments_response_partition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7605                                                                int offset, kafka_api_version_t api_version)
7606 {
7607     proto_item *subti, *subsubti;
7608     proto_tree *subtree, *subsubtree;
7609     kafka_partition_t partition;
7610
7611     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partition, &subti, "Partition");
7612
7613     offset = dissect_kafka_partition_id_ret(tvb, pinfo, subtree, offset, &partition);
7614
7615     offset = dissect_kafka_error(tvb, pinfo, subtree, offset);
7616
7617     offset = dissect_kafka_string(subtree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
7618
7619     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
7620                                         ett_kafka_replicas,
7621                                         &subsubti, "Current Replicas");
7622     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7623                                  &dissect_kafka_list_partition_reassignments_response_replica);
7624     proto_item_set_end(subsubti, tvb, offset);
7625
7626     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
7627                                         ett_kafka_replicas,
7628                                         &subsubti, "Adding Replicas");
7629     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7630                                  &dissect_kafka_list_partition_reassignments_response_replica);
7631     proto_item_set_end(subsubti, tvb, offset);
7632
7633     subsubtree = proto_tree_add_subtree(subtree, tvb, offset, -1,
7634                                         ett_kafka_replicas,
7635                                         &subsubti, "Removing Replicas");
7636     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7637                                  &dissect_kafka_list_partition_reassignments_response_replica);
7638     proto_item_set_end(subsubti, tvb, offset);
7639
7640     proto_item_set_end(subti, tvb, offset);
7641
7642     return offset;
7643 }
7644
7645 static int
7646 dissect_kafka_list_partition_reassignments_response_topic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7647                                                            int offset, kafka_api_version_t api_version)
7648 {
7649     proto_item *subti, *subsubti;
7650     proto_tree *subtree, *subsubtree;
7651
7652     subtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_topic, &subti, "Topic");
7653
7654     offset = dissect_kafka_string(subtree, hf_kafka_topic_name, tvb, pinfo, offset, NULL, NULL);
7655
7656     subsubtree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_kafka_partitions, &subsubti, "Partitions");
7657
7658     offset = dissect_kafka_array(subsubtree, tvb, pinfo, offset, api_version,
7659                                  &dissect_kafka_list_partition_reassignments_response_partition);
7660
7661     proto_item_set_end(subti, tvb, offset);
7662
7663     return offset;
7664 }
7665
7666 static int
7667 dissect_kafka_list_partition_reassignments_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
7668                                                      kafka_api_version_t api_version)
7669 {
7670     proto_item *subti;
7671     proto_tree *subtree;
7672
7673     offset = dissect_kafka_throttle_time(tvb, pinfo, tree, offset);
7674
7675     offset = dissect_kafka_error(tvb, pinfo, tree, offset);
7676
7677     offset = dissect_kafka_string(tree, hf_kafka_error_message, tvb, pinfo, offset, NULL, NULL);
7678
7679     subtree = proto_tree_add_subtree(tree, tvb, offset, -1,
7680                                      ett_kafka_topics,
7681                                      &subti, "Topics");
7682     offset = dissect_kafka_array(subtree, tvb, pinfo, offset, api_version,
7683                                  &dissect_kafka_list_partition_reassignments_response_topic);
7684
7685     proto_item_set_end(subti, tvb, offset);
7686
7687     return offset;
7688 }
7689
7690 /* MAIN */
7691
7692 static int
7693 dissect_kafka(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
7694 {
7695     proto_item             *root_ti, *ti;
7696     proto_tree             *kafka_tree;
7697     int                     offset  = 0;
7698     kafka_query_response_t *matcher = NULL;
7699     conversation_t         *conversation;
7700     wmem_queue_t           *match_queue;
7701
7702     col_set_str(pinfo->cinfo, COL_PROTOCOL, "Kafka");
7703     col_clear(pinfo->cinfo, COL_INFO);
7704
7705     root_ti = proto_tree_add_item(tree, proto_kafka, tvb, 0, -1, ENC_NA);
7706
7707     kafka_tree = proto_item_add_subtree(root_ti, ett_kafka);
7708
7709     proto_tree_add_item(kafka_tree, hf_kafka_len, tvb, offset, 4, ENC_BIG_ENDIAN);
7710     offset += 4;
7711
7712     conversation = find_or_create_conversation(pinfo);
7713     /* Create match_queue for this conversation */
7714     match_queue  = (wmem_queue_t *) conversation_get_proto_data(conversation, proto_kafka);
7715     if (match_queue == NULL) {
7716         match_queue = wmem_queue_new(wmem_file_scope());
7717         conversation_add_proto_data(conversation, proto_kafka, match_queue);
7718     }
7719
7720     if (PINFO_FD_VISITED(pinfo)) {
7721         matcher = (kafka_query_response_t *) p_get_proto_data(wmem_file_scope(), pinfo, proto_kafka, 0);
7722     }
7723
7724     if (pinfo->destport == pinfo->match_uint) {
7725         /* Request (as directed towards server port) */
7726         if (matcher == NULL) {
7727             matcher = wmem_new(wmem_file_scope(), kafka_query_response_t);
7728
7729             matcher->api_key        = tvb_get_ntohs(tvb, offset);
7730             matcher->api_version    = tvb_get_ntohs(tvb, offset+2);
7731             matcher->request_frame  = pinfo->num;
7732             matcher->response_found = FALSE;
7733
7734             p_add_proto_data(wmem_file_scope(), pinfo, proto_kafka, 0, matcher);
7735
7736             /* The kafka server always responds, except in the case of a produce
7737              * request whose RequiredAcks field is 0. This field is at a dynamic
7738              * offset into the request, so to avoid too much prefetch logic we
7739              * simply don't queue produce requests here. If it is a produce
7740              * request with a non-zero RequiredAcks field it gets queued later.
7741              */
7742             if (matcher->api_key != KAFKA_PRODUCE) {
7743                 wmem_queue_push(match_queue, matcher);
7744             }
7745         }
7746
7747         col_add_fstr(pinfo->cinfo, COL_INFO, "Kafka %s v%d Request",
7748                      kafka_api_key_to_str(matcher->api_key),
7749                      matcher->api_version);
7750         /* Also add to protocol root */
7751         proto_item_append_text(root_ti, " (%s v%d Request)",
7752                                kafka_api_key_to_str(matcher->api_key),
7753                                matcher->api_version);
7754
7755         if (matcher->response_found) {
7756             ti = proto_tree_add_uint(kafka_tree, hf_kafka_response_frame, tvb,
7757                     0, 0, matcher->response_frame);
7758             proto_item_set_generated(ti);
7759         }
7760
7761
7762         ti = proto_tree_add_item(kafka_tree, hf_kafka_request_api_key, tvb, offset, 2, ENC_BIG_ENDIAN);
7763         proto_item_set_hidden(ti);
7764
7765         ti = proto_tree_add_item(kafka_tree, hf_kafka_api_key, tvb, offset, 2, ENC_BIG_ENDIAN);
7766         offset += 2;
7767         kafka_check_supported_api_key(pinfo, ti, matcher);
7768
7769         ti = proto_tree_add_item(kafka_tree, hf_kafka_request_api_version, tvb, offset, 2, ENC_BIG_ENDIAN);
7770         proto_item_set_hidden(ti);
7771
7772         ti = proto_tree_add_item(kafka_tree, hf_kafka_api_version, tvb, offset, 2, ENC_BIG_ENDIAN);
7773         offset += 2;
7774         kafka_check_supported_api_version(pinfo, ti, matcher);
7775
7776         proto_tree_add_item(kafka_tree, hf_kafka_correlation_id, tvb, offset, 4, ENC_BIG_ENDIAN);
7777         offset += 4;
7778
7779         offset = dissect_kafka_string(kafka_tree, hf_kafka_client_id, tvb, pinfo, offset, NULL, NULL);
7780
7781         switch (matcher->api_key) {
7782             case KAFKA_PRODUCE:
7783                 /* Produce requests may need delayed queueing, see the more
7784                  * detailed comment above. */
7785                 if (tvb_get_ntohs(tvb, offset) != KAFKA_ACK_NOT_REQUIRED && !PINFO_FD_VISITED(pinfo)) {
7786                     wmem_queue_push(match_queue, matcher);
7787                 }
7788                 /*offset =*/ dissect_kafka_produce_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7789                 break;
7790             case KAFKA_FETCH:
7791                 /*offset =*/ dissect_kafka_fetch_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7792                 break;
7793             case KAFKA_OFFSETS:
7794                 /*offset =*/ dissect_kafka_offsets_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7795                 break;
7796             case KAFKA_METADATA:
7797                 /*offset =*/ dissect_kafka_metadata_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7798                 break;
7799             case KAFKA_LEADER_AND_ISR:
7800                 /*offset =*/ dissect_kafka_leader_and_isr_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7801                 break;
7802             case KAFKA_STOP_REPLICA:
7803                 /*offset =*/ dissect_kafka_stop_replica_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7804                 break;
7805             case KAFKA_UPDATE_METADATA:
7806                 /*offset =*/ dissect_kafka_update_metadata_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7807                 break;
7808             case KAFKA_CONTROLLED_SHUTDOWN:
7809                 /*offset =*/ dissect_kafka_controlled_shutdown_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7810                 break;
7811             case KAFKA_OFFSET_COMMIT:
7812                 /*offset =*/ dissect_kafka_offset_commit_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7813                 break;
7814             case KAFKA_OFFSET_FETCH:
7815                 /*offset =*/ dissect_kafka_offset_fetch_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7816                 break;
7817             case KAFKA_FIND_COORDINATOR:
7818                 /*offset =*/ dissect_kafka_find_coordinator_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7819                 break;
7820             case KAFKA_JOIN_GROUP:
7821                 /*offset =*/ dissect_kafka_join_group_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7822                 break;
7823             case KAFKA_HEARTBEAT:
7824                 /*offset =*/ dissect_kafka_heartbeat_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7825                 break;
7826             case KAFKA_LEAVE_GROUP:
7827                 /*offset =*/ dissect_kafka_leave_group_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7828                 break;
7829             case KAFKA_SYNC_GROUP:
7830                 /*offset =*/ dissect_kafka_sync_group_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7831                 break;
7832             case KAFKA_DESCRIBE_GROUPS:
7833                 /*offset =*/ dissect_kafka_describe_groups_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7834                 break;
7835             case KAFKA_LIST_GROUPS:
7836                 /*offset =*/ dissect_kafka_list_groups_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7837                 break;
7838             case KAFKA_SASL_HANDSHAKE:
7839                 /*offset =*/ dissect_kafka_sasl_handshake_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7840                 break;
7841             case KAFKA_API_VERSIONS:
7842                 /*offset =*/ dissect_kafka_api_versions_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7843                 break;
7844             case KAFKA_CREATE_TOPICS:
7845                 /*offset =*/ dissect_kafka_create_topics_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7846                 break;
7847             case KAFKA_DELETE_TOPICS:
7848                 /*offset =*/ dissect_kafka_delete_topics_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7849                 break;
7850             case KAFKA_DELETE_RECORDS:
7851                 /*offset =*/ dissect_kafka_delete_records_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7852                 break;
7853             case KAFKA_INIT_PRODUCER_ID:
7854                 /*offset =*/ dissect_kafka_init_producer_id_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7855                 break;
7856             case KAFKA_OFFSET_FOR_LEADER_EPOCH:
7857                 /*offset =*/ dissect_kafka_offset_for_leader_epoch_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7858                 break;
7859             case KAFKA_ADD_PARTITIONS_TO_TXN:
7860                 /*offset =*/ dissect_kafka_add_partitions_to_txn_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7861                 break;
7862             case KAFKA_ADD_OFFSETS_TO_TXN:
7863                 /*offset =*/ dissect_kafka_add_offsets_to_txn_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7864                 break;
7865             case KAFKA_END_TXN:
7866                 /*offset =*/ dissect_kafka_end_txn_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7867                 break;
7868             case KAFKA_WRITE_TXN_MARKERS:
7869                 /*offset =*/ dissect_kafka_write_txn_markers_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7870                 break;
7871             case KAFKA_TXN_OFFSET_COMMIT:
7872                 /*offset =*/ dissect_kafka_txn_offset_commit_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7873                 break;
7874             case KAFKA_DESCRIBE_ACLS:
7875                 /*offset =*/ dissect_kafka_describe_acls_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7876                 break;
7877             case KAFKA_CREATE_ACLS:
7878                 /*offset =*/ dissect_kafka_create_acls_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7879                 break;
7880             case KAFKA_DELETE_ACLS:
7881                 /*offset =*/ dissect_kafka_delete_acls_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7882                 break;
7883             case KAFKA_DESCRIBE_CONFIGS:
7884                 /*offset =*/ dissect_kafka_describe_configs_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7885                 break;
7886             case KAFKA_ALTER_CONFIGS:
7887                 /*offset =*/ dissect_kafka_alter_configs_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7888                 break;
7889             case KAFKA_ALTER_REPLICA_LOG_DIRS:
7890                 /*offset =*/ dissect_kafka_alter_replica_log_dirs_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7891                 break;
7892             case KAFKA_DESCRIBE_LOG_DIRS:
7893                 /*offset =*/ dissect_kafka_describe_log_dirs_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7894                 break;
7895             case KAFKA_CREATE_PARTITIONS:
7896                 /*offset =*/ dissect_kafka_create_partitions_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7897                 break;
7898             case KAFKA_SASL_AUTHENTICATE:
7899                 /*offset =*/ dissect_kafka_sasl_authenticate_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7900                 break;
7901             case KAFKA_CREATE_DELEGATION_TOKEN:
7902                 /*offset =*/ dissect_kafka_create_delegation_token_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7903                 break;
7904             case KAFKA_RENEW_DELEGATION_TOKEN:
7905                 /*offset =*/ dissect_kafka_renew_delegation_token_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7906                 break;
7907             case KAFKA_EXPIRE_DELEGATION_TOKEN:
7908                 /*offset =*/ dissect_kafka_expire_delegation_token_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7909                 break;
7910             case KAFKA_DESCRIBE_DELEGATION_TOKEN:
7911                 /*offset =*/ dissect_kafka_describe_delegation_token_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7912                 break;
7913             case KAFKA_DELETE_GROUPS:
7914                 /*offset =*/ dissect_kafka_delete_groups_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7915                 break;
7916             case KAFKA_ELECT_LEADERS:
7917                 /*offset =*/ dissect_kafka_elect_leaders_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7918                 break;
7919             case KAFKA_INC_ALTER_CONFIGS:
7920                 /*offset =*/ dissect_kafka_inc_alter_configs_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7921                 break;
7922             case KAFKA_ALTER_PARTITION_REASSIGNMENTS:
7923                 /*offset =*/ dissect_kafka_alter_partition_reassignments_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7924                 break;
7925             case KAFKA_LIST_PARTITION_REASSIGNMENTS:
7926                 /*offset =*/ dissect_kafka_list_partition_reassignments_request(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7927                 break;
7928         }
7929     }
7930     else {
7931         /* Response */
7932
7933         proto_tree_add_item(kafka_tree, hf_kafka_correlation_id, tvb, offset, 4, ENC_BIG_ENDIAN);
7934         offset += 4;
7935
7936         if (matcher == NULL) {
7937             if (wmem_queue_count(match_queue) > 0) {
7938                 matcher = (kafka_query_response_t *) wmem_queue_peek(match_queue);
7939             }
7940             if (matcher == NULL || matcher->request_frame >= pinfo->num) {
7941                 col_set_str(pinfo->cinfo, COL_INFO, "Kafka Response (Undecoded, Request Missing)");
7942                 expert_add_info(pinfo, root_ti, &ei_kafka_request_missing);
7943                 return tvb_captured_length(tvb);
7944             }
7945
7946             wmem_queue_pop(match_queue);
7947
7948             matcher->response_frame = pinfo->num;
7949             matcher->response_found = TRUE;
7950
7951             p_add_proto_data(wmem_file_scope(), pinfo, proto_kafka, 0, matcher);
7952         }
7953
7954         col_add_fstr(pinfo->cinfo, COL_INFO, "Kafka %s v%d Response",
7955                      kafka_api_key_to_str(matcher->api_key),
7956                      matcher->api_version);
7957         /* Also add to protocol root */
7958         proto_item_append_text(root_ti, " (%s v%d Response)",
7959                                kafka_api_key_to_str(matcher->api_key),
7960                                matcher->api_version);
7961
7962
7963         /* Show request frame */
7964         ti = proto_tree_add_uint(kafka_tree, hf_kafka_request_frame, tvb,
7965                 0, 0, matcher->request_frame);
7966         proto_item_set_generated(ti);
7967
7968         /* Show api key (message type) */
7969         ti = proto_tree_add_int(kafka_tree, hf_kafka_response_api_key, tvb,
7970                 0, 0, matcher->api_key);
7971         proto_item_set_generated(ti);
7972         proto_item_set_hidden(ti);
7973         ti = proto_tree_add_int(kafka_tree, hf_kafka_api_key, tvb,
7974                                 0, 0, matcher->api_key);
7975         proto_item_set_generated(ti);
7976         kafka_check_supported_api_key(pinfo, ti, matcher);
7977
7978         /* Also show api version from request */
7979         ti = proto_tree_add_int(kafka_tree, hf_kafka_response_api_version, tvb,
7980                 0, 0, matcher->api_version);
7981         proto_item_set_generated(ti);
7982         proto_item_set_hidden(ti);
7983         ti = proto_tree_add_int(kafka_tree, hf_kafka_response_api_version, tvb,
7984                                 0, 0, matcher->api_version);
7985         proto_item_set_generated(ti);
7986         kafka_check_supported_api_version(pinfo, ti, matcher);
7987
7988         switch (matcher->api_key) {
7989             case KAFKA_PRODUCE:
7990                 /*offset =*/ dissect_kafka_produce_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7991                 break;
7992             case KAFKA_FETCH:
7993                 /*offset =*/ dissect_kafka_fetch_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7994                 break;
7995             case KAFKA_OFFSETS:
7996                 /*offset =*/ dissect_kafka_offsets_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
7997                 break;
7998             case KAFKA_METADATA:
7999                 /*offset =*/ dissect_kafka_metadata_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8000                 break;
8001             case KAFKA_LEADER_AND_ISR:
8002                 /*offset =*/ dissect_kafka_leader_and_isr_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8003                 break;
8004             case KAFKA_STOP_REPLICA:
8005                 /*offset =*/ dissect_kafka_stop_replica_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8006                 break;
8007             case KAFKA_UPDATE_METADATA:
8008                 /*offset =*/ dissect_kafka_update_metadata_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8009                 break;
8010             case KAFKA_CONTROLLED_SHUTDOWN:
8011                 /*offset =*/ dissect_kafka_controlled_shutdown_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8012                 break;
8013             case KAFKA_OFFSET_COMMIT:
8014                 /*offset =*/ dissect_kafka_offset_commit_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8015                 break;
8016             case KAFKA_OFFSET_FETCH:
8017                 /*offset =*/ dissect_kafka_offset_fetch_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8018                 break;
8019             case KAFKA_FIND_COORDINATOR:
8020                 /*offset =*/ dissect_kafka_find_coordinator_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8021                 break;
8022             case KAFKA_JOIN_GROUP:
8023                 /*offset =*/ dissect_kafka_join_group_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8024                 break;
8025             case KAFKA_HEARTBEAT:
8026                 /*offset =*/ dissect_kafka_heartbeat_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8027                 break;
8028             case KAFKA_LEAVE_GROUP:
8029                 /*offset =*/ dissect_kafka_leave_group_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8030                 break;
8031             case KAFKA_SYNC_GROUP:
8032                 /*offset =*/ dissect_kafka_sync_group_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8033                 break;
8034             case KAFKA_DESCRIBE_GROUPS:
8035                 /*offset =*/ dissect_kafka_describe_groups_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8036                 break;
8037             case KAFKA_LIST_GROUPS:
8038                 /*offset =*/ dissect_kafka_list_groups_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8039                 break;
8040             case KAFKA_SASL_HANDSHAKE:
8041                 /*offset =*/ dissect_kafka_sasl_handshake_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8042                 break;
8043             case KAFKA_API_VERSIONS:
8044                 /*offset =*/ dissect_kafka_api_versions_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8045                 break;
8046             case KAFKA_CREATE_TOPICS:
8047                 /*offset =*/ dissect_kafka_create_topics_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8048                 break;
8049             case KAFKA_DELETE_TOPICS:
8050                 /*offset =*/ dissect_kafka_delete_topics_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8051                 break;
8052             case KAFKA_DELETE_RECORDS:
8053                 /*offset =*/ dissect_kafka_delete_records_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8054                 break;
8055             case KAFKA_INIT_PRODUCER_ID:
8056                 /*offset =*/ dissect_kafka_init_producer_id_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8057                 break;
8058             case KAFKA_OFFSET_FOR_LEADER_EPOCH:
8059                 /*offset =*/ dissect_kafka_offset_for_leader_epoch_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8060                 break;
8061             case KAFKA_ADD_PARTITIONS_TO_TXN:
8062                 /*offset =*/ dissect_kafka_add_partitions_to_txn_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8063                 break;
8064             case KAFKA_ADD_OFFSETS_TO_TXN:
8065                 /*offset =*/ dissect_kafka_add_offsets_to_txn_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8066                 break;
8067             case KAFKA_END_TXN:
8068                 /*offset =*/ dissect_kafka_end_txn_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8069                 break;
8070             case KAFKA_WRITE_TXN_MARKERS:
8071                 /*offset =*/ dissect_kafka_write_txn_markers_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8072                 break;
8073             case KAFKA_TXN_OFFSET_COMMIT:
8074                 /*offset =*/ dissect_kafka_txn_offset_commit_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8075                 break;
8076             case KAFKA_DESCRIBE_ACLS:
8077                 /*offset =*/ dissect_kafka_describe_acls_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8078                 break;
8079             case KAFKA_CREATE_ACLS:
8080                 /*offset =*/ dissect_kafka_create_acls_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8081                 break;
8082             case KAFKA_DELETE_ACLS:
8083                 /*offset =*/ dissect_kafka_delete_acls_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8084                 break;
8085             case KAFKA_DESCRIBE_CONFIGS:
8086                 /*offset =*/ dissect_kafka_describe_configs_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8087                 break;
8088             case KAFKA_ALTER_CONFIGS:
8089                 /*offset =*/ dissect_kafka_alter_configs_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8090                 break;
8091             case KAFKA_ALTER_REPLICA_LOG_DIRS:
8092                 /*offset =*/ dissect_kafka_alter_replica_log_dirs_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8093                 break;
8094             case KAFKA_DESCRIBE_LOG_DIRS:
8095                 /*offset =*/ dissect_kafka_describe_log_dirs_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8096                 break;
8097             case KAFKA_CREATE_PARTITIONS:
8098                 /*offset =*/ dissect_kafka_create_partitions_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8099                 break;
8100             case KAFKA_SASL_AUTHENTICATE:
8101                 /*offset =*/ dissect_kafka_sasl_authenticate_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8102                 break;
8103             case KAFKA_CREATE_DELEGATION_TOKEN:
8104                 /*offset =*/ dissect_kafka_create_delegation_token_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8105                 break;
8106             case KAFKA_RENEW_DELEGATION_TOKEN:
8107                 /*offset =*/ dissect_kafka_renew_delegation_token_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8108                 break;
8109             case KAFKA_EXPIRE_DELEGATION_TOKEN:
8110                 /*offset =*/ dissect_kafka_expire_delegation_token_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8111                 break;
8112             case KAFKA_DESCRIBE_DELEGATION_TOKEN:
8113                 /*offset =*/ dissect_kafka_describe_delegation_token_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8114                 break;
8115             case KAFKA_DELETE_GROUPS:
8116                 /*offset =*/ dissect_kafka_delete_groups_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8117                 break;
8118             case KAFKA_ELECT_LEADERS:
8119                 /*offset =*/ dissect_kafka_elect_leaders_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8120                 break;
8121             case KAFKA_INC_ALTER_CONFIGS:
8122                 /*offset =*/ dissect_kafka_inc_alter_configs_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8123                 break;
8124             case KAFKA_ALTER_PARTITION_REASSIGNMENTS:
8125                 /*offset =*/ dissect_kafka_alter_partition_reassignments_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8126                 break;
8127             case KAFKA_LIST_PARTITION_REASSIGNMENTS:
8128                 /*offset =*/ dissect_kafka_list_partition_reassignments_response(tvb, pinfo, kafka_tree, offset, matcher->api_version);
8129                 break;
8130         }
8131
8132     }
8133
8134     return tvb_captured_length(tvb);
8135 }
8136
8137 static int
8138 dissect_kafka_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
8139         void *data)
8140 {
8141     tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 4,
8142             get_kafka_pdu_len, dissect_kafka, data);
8143
8144     return tvb_captured_length(tvb);
8145 }
8146
8147 static void
8148 compute_kafka_api_names(void)
8149 {
8150     guint i;
8151     guint len = array_length(kafka_apis);
8152
8153     for (i = 0; i < len; ++i) {
8154         kafka_api_names[i].value  = kafka_apis[i].api_key;
8155         kafka_api_names[i].strptr = kafka_apis[i].name;
8156     }
8157
8158     kafka_api_names[len].value  = 0;
8159     kafka_api_names[len].strptr = NULL;
8160 }
8161
8162 void
8163 proto_register_kafka(void)
8164 {
8165     static hf_register_info hf[] = {
8166         { &hf_kafka_len,
8167             { "Length", "kafka.len",
8168                FT_INT32, BASE_DEC, 0, 0,
8169               "The length of this Kafka packet.", HFILL }
8170         },
8171         { &hf_kafka_offset,
8172             { "Offset", "kafka.offset",
8173                FT_INT64, BASE_DEC, 0, 0,
8174                NULL, HFILL }
8175         },
8176         { &hf_kafka_offset_time,
8177             { "Time", "kafka.offset_time",
8178                FT_INT64, BASE_DEC, 0, 0,
8179                NULL, HFILL }
8180         },
8181         { &hf_kafka_log_start_offset,
8182             { "Log Start Offset", "kafka.log_start_offset",
8183                FT_INT64, BASE_DEC, 0, 0,
8184                NULL, HFILL }
8185         },
8186         { &hf_kafka_last_stable_offset,
8187             { "Last Stable Offset", "kafka.last_stable_offset",
8188                FT_INT64, BASE_DEC, 0, 0,
8189                NULL, HFILL }
8190         },
8191         { &hf_kafka_first_offset,
8192             { "First Offset", "kafka.first_offset",
8193                FT_INT64, BASE_DEC, 0, 0,
8194                NULL, HFILL }
8195         },
8196         { &hf_kafka_max_offsets,
8197             { "Max Offsets", "kafka.max_offsets",
8198                FT_INT32, BASE_DEC, 0, 0,
8199                NULL, HFILL }
8200         },
8201         { &hf_kafka_metadata,
8202             { "Metadata", "kafka.metadata",
8203                FT_STRING, STR_ASCII, 0, 0,
8204                NULL, HFILL }
8205         },
8206         { &hf_kafka_error,
8207             { "Error", "kafka.error",
8208                FT_INT16, BASE_DEC, VALS(kafka_errors), 0,
8209                NULL, HFILL }
8210         },
8211         { &hf_kafka_error_message,
8212             { "Error Message", "kafka.error_message",
8213                FT_STRING, STR_ASCII, 0, 0,
8214                NULL, HFILL }
8215         },
8216         { &hf_kafka_api_key,
8217             { "API Key", "kafka.api_key",
8218                 FT_INT16, BASE_DEC, VALS(kafka_api_names), 0,
8219                 "Request API Key.", HFILL }
8220         },
8221         { &hf_kafka_api_version,
8222             { "API Version", "kafka.api_version",
8223                 FT_INT16, BASE_DEC, 0, 0,
8224                 "Request API Version.", HFILL }
8225         },
8226         // these should be deprecated
8227         // --- begin ---
8228         { &hf_kafka_request_api_key,
8229             { "API Key", "kafka.request_key",
8230                FT_INT16, BASE_DEC, VALS(kafka_api_names), 0,
8231               "Request API.", HFILL }
8232         },
8233         { &hf_kafka_response_api_key,
8234             { "API Key", "kafka.response_key",
8235                FT_INT16, BASE_DEC, VALS(kafka_api_names), 0,
8236               "Response API.", HFILL }
8237         },
8238         { &hf_kafka_request_api_version,
8239             { "API Version", "kafka.request.version",
8240                FT_INT16, BASE_DEC, 0, 0,
8241               "Request API Version.", HFILL }
8242         },
8243         { &hf_kafka_response_api_version,
8244             { "API Version", "kafka.response.version",
8245                FT_INT16, BASE_DEC, 0, 0,
8246               "Response API Version.", HFILL }
8247         },
8248         // --- end ---
8249         { &hf_kafka_correlation_id,
8250             { "Correlation ID", "kafka.correlation_id",
8251                FT_INT32, BASE_DEC, 0, 0,
8252                NULL, HFILL }
8253         },
8254         { &hf_kafka_client_id,
8255             { "Client ID", "kafka.client_id",
8256                FT_STRING, STR_ASCII, 0, 0,
8257               "The ID of the sending client.", HFILL }
8258         },
8259         { &hf_kafka_client_host,
8260             { "Client Host", "kafka.client_host",
8261                FT_STRING, STR_ASCII, 0, 0,
8262                NULL, HFILL }
8263         },
8264         { &hf_kafka_transactional_id,
8265             { "Transactional ID", "kafka.transactional_id",
8266                FT_STRING, STR_ASCII, 0, 0,
8267                NULL, HFILL }
8268         },
8269         { &hf_kafka_transaction_result,
8270             { "Transaction Result", "kafka.transaction_result",
8271                FT_INT8, BASE_DEC, VALS(kafka_transaction_results), 0,
8272                NULL, HFILL }
8273         },
8274         { &hf_kafka_transaction_timeout,
8275             { "Transaction Timeout", "kafka.transaction_timeout",
8276                FT_INT32, BASE_DEC, 0, 0,
8277                NULL, HFILL }
8278         },
8279         { &hf_kafka_string_len,
8280             { "String Length", "kafka.string_len",
8281                FT_INT16, BASE_DEC, 0, 0,
8282               "Generic length for kafka-encoded string.", HFILL }
8283         },
8284         { &hf_kafka_bytes_len,
8285             { "Bytes Length", "kafka.bytes_len",
8286                FT_INT32, BASE_DEC, 0, 0,
8287               "Generic length for kafka-encoded bytes.", HFILL }
8288         },
8289         { &hf_kafka_required_acks,
8290             { "Required Acks", "kafka.required_acks",
8291                FT_INT16, BASE_DEC, VALS(kafka_acks), 0,
8292                NULL, HFILL }
8293         },
8294         { &hf_kafka_timeout,
8295             { "Timeout", "kafka.timeout",
8296                FT_INT32, BASE_DEC, 0, 0,
8297                NULL, HFILL }
8298         },
8299         { &hf_kafka_topic_name,
8300             { "Topic Name", "kafka.topic_name",
8301                FT_STRING, STR_UNICODE, 0, 0,
8302                NULL, HFILL }
8303         },
8304         { &hf_kafka_producer_id,
8305             { "Producer ID", "kafka.producer_id",
8306                FT_INT64, BASE_DEC, 0, 0,
8307                NULL, HFILL }
8308         },
8309         { &hf_kafka_producer_epoch,
8310             { "Producer Epoch", "kafka.producer_epoch",
8311                 FT_INT16, BASE_DEC, 0, 0,
8312                 NULL, HFILL }
8313         },
8314         { &hf_kafka_partition_id,
8315             { "Partition ID", "kafka.partition_id",
8316                FT_INT32, BASE_DEC, 0, 0,
8317                NULL, HFILL }
8318         },
8319         { &hf_kafka_replica,
8320             { "Replica ID", "kafka.replica_id",
8321                FT_INT32, BASE_DEC, 0, 0,
8322                NULL, HFILL }
8323         },
8324         { &hf_kafka_replication_factor,
8325             { "Replication Factor", "kafka.replication_factor",
8326                FT_INT16, BASE_DEC, 0, 0,
8327                NULL, HFILL }
8328         },
8329         { &hf_kafka_isr,
8330             { "Caught-Up Replica ID", "kafka.isr_id",
8331                FT_INT32, BASE_DEC, 0, 0,
8332                NULL, HFILL }
8333         },
8334         { &hf_kafka_offline,
8335             { "Offline Replica ID", "kafka.offline_id",
8336                 FT_INT32, BASE_DEC, 0, 0,
8337                 NULL, HFILL }
8338         },
8339         { &hf_kafka_message_size,
8340             { "Message Size", "kafka.message_size",
8341                FT_INT32, BASE_DEC, 0, 0,
8342                NULL, HFILL }
8343         },
8344         { &hf_kafka_message_crc,
8345             { "CRC32", "kafka.message_crc",
8346                FT_UINT32, BASE_HEX, 0, 0,
8347                NULL, HFILL }
8348         },
8349         { &hf_kafka_message_magic,
8350             { "Magic Byte", "kafka.message_magic",
8351                FT_INT8, BASE_DEC, 0, 0,
8352                NULL, HFILL }
8353         },
8354         { &hf_kafka_message_codec,
8355             { "Compression Codec", "kafka.message_codec",
8356                FT_UINT8, BASE_DEC, VALS(kafka_message_codecs), KAFKA_MESSAGE_CODEC_MASK,
8357                NULL, HFILL }
8358         },
8359         { &hf_kafka_message_timestamp_type,
8360             { "Timestamp Type", "kafka.message_timestamp_type",
8361                FT_UINT8, BASE_DEC, VALS(kafka_message_timestamp_types), KAFKA_MESSAGE_TIMESTAMP_MASK,
8362                NULL, HFILL }
8363         },
8364         { &hf_kafka_batch_crc,
8365             { "CRC32", "kafka.batch_crc",
8366                 FT_UINT32, BASE_HEX, 0, 0,
8367                 NULL, HFILL }
8368         },
8369         { &hf_kafka_batch_codec,
8370             { "Compression Codec", "kafka.batch_codec",
8371                 FT_UINT16, BASE_DEC, VALS(kafka_message_codecs), KAFKA_MESSAGE_CODEC_MASK,
8372                 NULL, HFILL }
8373         },
8374         { &hf_kafka_batch_timestamp_type,
8375             { "Timestamp Type", "kafka.batch_timestamp_type",
8376                 FT_UINT16, BASE_DEC, VALS(kafka_message_timestamp_types), KAFKA_MESSAGE_TIMESTAMP_MASK,
8377                 NULL, HFILL }
8378         },
8379         { &hf_kafka_batch_transactional,
8380             { "Transactional", "kafka.batch_transactional",
8381                 FT_UINT16, BASE_DEC, VALS(kafka_batch_transactional_values), KAFKA_BATCH_TRANSACTIONAL_MASK,
8382                 NULL, HFILL }
8383         },
8384         { &hf_kafka_batch_control_batch,
8385             { "Control Batch", "kafka.batch_control_batch",
8386                 FT_UINT16, BASE_DEC, VALS(kafka_batch_control_batch_values), KAFKA_BATCH_CONTROL_BATCH_MASK,
8387                 NULL, HFILL }
8388         },
8389         { &hf_kafka_batch_last_offset_delta,
8390             { "Last Offset Delta", "kafka.batch_last_offset_delta",
8391                FT_UINT32, BASE_DEC, 0, 0,
8392                NULL, HFILL }
8393         },
8394         { &hf_kafka_batch_first_timestamp,
8395             { "First Timestamp", "kafka.batch_first_timestamp",
8396                 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
8397                 NULL, HFILL }
8398         },
8399         { &hf_kafka_batch_last_timestamp,
8400             { "Last Timestamp", "kafka.batch_last_timestamp",
8401                 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
8402                 NULL, HFILL }
8403         },
8404         { &hf_kafka_batch_base_sequence,
8405             { "Base Sequence", "kafka.batch_base_sequence",
8406                 FT_INT32, BASE_DEC, 0, 0,
8407                 NULL, HFILL }
8408         },
8409         { &hf_kafka_batch_size,
8410             { "Size", "kafka.batch_size",
8411                 FT_UINT32, BASE_DEC, 0, 0,
8412                 NULL, HFILL }
8413         },
8414         { &hf_kafka_message_timestamp,
8415             { "Timestamp", "kafka.message_timestamp",
8416                FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
8417                NULL, HFILL }
8418         },
8419         { &hf_kafka_message_key,
8420             { "Key", "kafka.message_key",
8421                FT_BYTES, BASE_SHOW_ASCII_PRINTABLE, 0, 0,
8422                NULL, HFILL }
8423         },
8424         { &hf_kafka_message_value,
8425             { "Value", "kafka.message_value",
8426                FT_BYTES, BASE_SHOW_ASCII_PRINTABLE, 0, 0,
8427                NULL, HFILL }
8428         },
8429         { &hf_kafka_message_compression_reduction,
8430             { "Compression Reduction (compressed/uncompressed)", "kafka.message_compression_reduction",
8431                FT_FLOAT, BASE_NONE, 0, 0,
8432                NULL, HFILL }
8433         },
8434         { &hf_kafka_consumer_group,
8435             { "Consumer Group", "kafka.consumer_group",
8436                FT_STRING, STR_ASCII, 0, 0,
8437                NULL, HFILL }
8438         },
8439         { &hf_kafka_consumer_group_instance,
8440             { "Consumer Group Instance", "kafka.consumer_group_instance",
8441                FT_STRING, STR_ASCII, 0, 0,
8442                NULL, HFILL }
8443         },
8444         { &hf_kafka_coordinator_key,
8445             { "Coordinator Key", "kafka.coordinator_key",
8446                FT_STRING, STR_ASCII, 0, 0,
8447                NULL, HFILL }
8448         },
8449         { &hf_kafka_coordinator_type,
8450             { "Coordinator Type", "kafka.coordinator_type",
8451                FT_INT8, BASE_DEC, VALS(kafka_coordinator_types), 0,
8452                NULL, HFILL }
8453         },
8454         { &hf_kafka_request_frame,
8455             { "Request Frame", "kafka.request_frame",
8456                FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0,
8457                NULL, HFILL }
8458         },
8459         { &hf_kafka_broker_nodeid,
8460             { "Node ID", "kafka.node_id",
8461                FT_INT32, BASE_DEC, 0, 0,
8462                NULL, HFILL }
8463         },
8464         { &hf_kafka_broker_epoch,
8465             { "Broker Epoch", "kafka.broker_epoch",
8466                FT_INT64, BASE_DEC, 0, 0,
8467                NULL, HFILL }
8468         },
8469         { &hf_kafka_broker_host,
8470             { "Host", "kafka.host",
8471                FT_STRING, STR_ASCII, 0, 0,
8472                NULL, HFILL }
8473         },
8474         { &hf_kafka_listener_name,
8475             { "Listener", "kafka.listener_name",
8476                FT_STRING, STR_ASCII, 0, 0,
8477                NULL, HFILL }
8478         },
8479         { &hf_kafka_broker_port,
8480             { "Port", "kafka.port",
8481                FT_INT32, BASE_DEC, 0, 0,
8482                NULL, HFILL }
8483         },
8484         { &hf_kafka_rack,
8485             { "Rack", "kafka.rack",
8486                FT_STRING, STR_ASCII, 0, 0,
8487                NULL, HFILL }
8488         },
8489         { &hf_kafka_broker_security_protocol_type,
8490             { "Security Protocol Type", "kafka.broker_security_protocol_type",
8491                FT_INT16, BASE_DEC, VALS(kafka_security_protocol_types), 0,
8492                NULL, HFILL }
8493         },
8494         { &hf_kafka_cluster_id,
8495             { "Cluster ID", "kafka.cluster_id",
8496                FT_STRING, STR_ASCII, 0, 0,
8497                NULL, HFILL }
8498         },
8499         { &hf_kafka_controller_id,
8500             { "Controller ID", "kafka.node_id",
8501                FT_INT32, BASE_DEC, 0, 0,
8502                NULL, HFILL }
8503         },
8504         { &hf_kafka_controller_epoch,
8505             { "Controller Epoch", "kafka.controller_epoch",
8506                FT_INT32, BASE_DEC, 0, 0,
8507                NULL, HFILL }
8508         },
8509         { &hf_kafka_delete_partitions,
8510             { "Delete Partitions", "kafka.delete_partitions",
8511                FT_BOOLEAN, BASE_NONE, 0, 0,
8512                NULL, HFILL }
8513         },
8514         { &hf_kafka_group_leader_id,
8515             { "Leader ID", "kafka.group_leader_id",
8516                FT_STRING, STR_ASCII, 0, 0,
8517                NULL, HFILL }
8518         },
8519         { &hf_kafka_leader_id,
8520             { "Leader ID", "kafka.leader_id",
8521                FT_INT32, BASE_DEC, 0, 0,
8522                NULL, HFILL }
8523         },
8524         { &hf_kafka_leader_epoch,
8525             { "Leader Epoch", "kafka.leader_epoch",
8526                FT_INT32, BASE_DEC, 0, 0,
8527                NULL, HFILL }
8528         },
8529         { &hf_kafka_current_leader_epoch,
8530             { "Leader Epoch", "kafka.current_leader_epoch",
8531                FT_INT32, BASE_DEC, 0, 0,
8532                NULL, HFILL }
8533         },
8534         { &hf_kafka_is_internal,
8535             { "Is Internal", "kafka.is_internal",
8536                FT_BOOLEAN, BASE_NONE, 0, 0,
8537                NULL, HFILL }
8538         },
8539         { &hf_kafka_min_bytes,
8540             { "Min Bytes", "kafka.min_bytes",
8541                FT_INT32, BASE_DEC, 0, 0,
8542                "The minimum number of bytes of messages that must be available"
8543                    " to give a response.",
8544                HFILL }
8545         },
8546         { &hf_kafka_max_bytes,
8547             { "Max Bytes", "kafka.max_bytes",
8548                FT_INT32, BASE_DEC, 0, 0,
8549                "The maximum bytes to include in the message set for this"
8550                    " partition. This helps bound the size of the response.",
8551                HFILL }
8552         },
8553         { &hf_kafka_isolation_level,
8554             { "Isolation Level", "kafka.isolation_level",
8555                FT_INT8, BASE_DEC, VALS(kafka_isolation_levels), 0,
8556                NULL, HFILL }
8557         },
8558         { &hf_kafka_max_wait_time,
8559             { "Max Wait Time", "kafka.max_wait_time",
8560                FT_INT32, BASE_DEC, 0, 0,
8561                "The maximum amount of time in milliseconds to block waiting if"
8562                    " insufficient data is available at the time the request is"
8563                    " issued.",
8564                HFILL }
8565         },
8566         { &hf_kafka_throttle_time,
8567             { "Throttle time", "kafka.throttle_time",
8568                FT_INT32, BASE_DEC, 0, 0,
8569                "Duration in milliseconds for which the request was throttled"
8570                    " due to quota violation."
8571                    " (Zero if the request did not violate any quota.)",
8572                HFILL }
8573         },
8574         { &hf_kafka_response_frame,
8575             { "Response Frame", "kafka.response_frame",
8576                FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0,
8577                NULL, HFILL }
8578         },
8579         { &hf_kafka_api_versions_api_key,
8580             { "API Key", "kafka.api_versions.api_key",
8581                FT_INT16, BASE_DEC, VALS(kafka_api_names), 0,
8582               "API Key.", HFILL }
8583         },
8584         { &hf_kafka_api_versions_min_version,
8585             { "Min Version", "kafka.api_versions.min_version",
8586                FT_INT16, BASE_DEC, 0, 0,
8587               "Minimal version which supports api key.", HFILL }
8588         },
8589         { &hf_kafka_api_versions_max_version,
8590             { "Max Version", "kafka.api_versions.max_version",
8591               FT_INT16, BASE_DEC, 0, 0,
8592               "Maximal version which supports api key.", HFILL }
8593         },
8594         { &hf_kafka_session_timeout,
8595             { "Session Timeout", "kafka.session_timeout",
8596                FT_INT32, BASE_DEC, 0, 0,
8597                NULL, HFILL }
8598         },
8599         { &hf_kafka_rebalance_timeout,
8600             { "Rebalance Timeout", "kafka.rebalance_timeout",
8601                FT_INT32, BASE_DEC, 0, 0,
8602                NULL, HFILL }
8603         },
8604         { &hf_kafka_group_state,
8605             { "State", "kafka.group_state",
8606                FT_STRING, STR_ASCII, 0, 0,
8607                NULL, HFILL }
8608         },
8609         { &hf_kafka_member_id,
8610             { "Consumer Group Member ID", "kafka.member_id",
8611                FT_STRING, STR_ASCII, 0, 0,
8612                NULL, HFILL }
8613         },
8614         { &hf_kafka_protocol_type,
8615             { "Protocol Type", "kafka.protocol_type",
8616                FT_STRING, STR_ASCII, 0, 0,
8617                NULL, HFILL }
8618         },
8619         { &hf_kafka_protocol_name,
8620             { "Protocol Name", "kafka.protocol_name",
8621                FT_STRING, STR_ASCII, 0, 0,
8622                NULL, HFILL }
8623         },
8624         { &hf_kafka_protocol_metadata,
8625             { "Protocol Metadata", "kafka.protocol_metadata",
8626                FT_BYTES, BASE_NONE, 0, 0,
8627                NULL, HFILL }
8628         },
8629         { &hf_kafka_member_metadata,
8630             { "Member Metadata", "kafka.member_metadata",
8631                FT_BYTES, BASE_NONE, 0, 0,
8632                NULL, HFILL }
8633         },
8634         { &hf_kafka_generation_id,
8635             { "Generation ID", "kafka.generation_id",
8636                FT_INT32, BASE_DEC, 0, 0,
8637                NULL, HFILL }
8638         },
8639         { &hf_kafka_member_assignment,
8640             { "Member Assignment", "kafka.member_assignment",
8641                FT_BYTES, BASE_NONE, 0, 0,
8642                NULL, HFILL }
8643         },
8644         { &hf_kafka_sasl_mechanism,
8645             { "SASL Mechanism", "kafka.sasl_mechanism",
8646                FT_STRING, STR_ASCII, 0, 0,
8647                NULL, HFILL }
8648         },
8649         { &hf_kafka_num_partitions,
8650             { "Number of Partitions", "kafka.num_partitions",
8651                FT_INT32, BASE_DEC, 0, 0,
8652                NULL, HFILL }
8653         },
8654         { &hf_kafka_zk_version,
8655             { "Zookeeper Version", "kafka.zk_version",
8656                FT_INT32, BASE_DEC, 0, 0,
8657                NULL, HFILL }
8658         },
8659         { &hf_kafka_config_key,
8660             { "Key", "kafka.config_key",
8661                FT_STRING, STR_ASCII, 0, 0,
8662                NULL, HFILL }
8663         },
8664         { &hf_kafka_config_value,
8665             { "Value", "kafka.config_value",
8666                FT_STRING, STR_ASCII, 0, 0,
8667                NULL, HFILL }
8668         },
8669         { &hf_kafka_config_operation,
8670             { "Operation", "kafka.config_operation",
8671                FT_INT8, BASE_DEC, VALS(config_operations), 0,
8672                NULL, HFILL }
8673         },
8674         { &hf_kafka_commit_timestamp,
8675             { "Timestamp", "kafka.commit_timestamp",
8676                FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
8677                NULL, HFILL }
8678         },
8679         { &hf_kafka_retention_time,
8680             { "Retention Time", "kafka.retention_time",
8681                FT_INT64, BASE_DEC, 0, 0,
8682                NULL, HFILL }
8683         },
8684         { &hf_kafka_forgotten_topic_name,
8685             { "Forgotten Topic Name", "kafka.forgotten_topic_name",
8686                 FT_STRING, STR_ASCII, 0, 0,
8687                 NULL, HFILL }
8688         },
8689         { &hf_kafka_forgotten_topic_partition,
8690             { "Forgotten Topic Partition", "kafka.forgotten_topic_partition",
8691                 FT_INT64, BASE_DEC, 0, 0,
8692                 NULL, HFILL }
8693         },
8694         { &hf_kafka_fetch_session_id,
8695             { "Fetch Session ID", "kafka.fetch_session_id",
8696                 FT_INT64, BASE_DEC, 0, 0,
8697                 NULL, HFILL }
8698         },
8699         { &hf_kafka_fetch_session_epoch,
8700             { "Fetch Session Epoch", "kafka.fetch_session_epoch",
8701                 FT_INT64, BASE_DEC, 0, 0,
8702                 NULL, HFILL }
8703         },
8704         { &hf_kafka_record_header_key,
8705             { "Header Key", "kafka.header_key",
8706                 FT_STRING, STR_UNICODE, 0, 0,
8707                 NULL, HFILL }
8708         },
8709         { &hf_kafka_record_header_value,
8710             { "Header Value", "kafka.header_value",
8711                 FT_BYTES, BASE_SHOW_ASCII_PRINTABLE, 0, 0,
8712                 NULL, HFILL }
8713         },
8714         { &hf_kafka_record_attributes,
8715             { "Record Attributes (reserved)", "kafka.record_attributes",
8716                 FT_INT8, BASE_DEC, 0, 0,
8717                 NULL, HFILL }
8718         },
8719         { &hf_kafka_allow_auto_topic_creation,
8720             { "Allow Auto Topic Creation", "kafka.allow_auto_topic_creation",
8721                 FT_BOOLEAN, BASE_NONE, 0, 0,
8722                 NULL, HFILL }
8723         },
8724         { &hf_kafka_validate_only,
8725             { "Only Validate the Request", "kafka.validate_only",
8726                 FT_BOOLEAN, BASE_NONE, 0, 0,
8727                 NULL, HFILL }
8728         },
8729         { &hf_kafka_coordinator_epoch,
8730             { "Coordinator Epoch", "kafka.coordinator_epoch",
8731                 FT_INT32, BASE_DEC, 0, 0,
8732                 NULL, HFILL }
8733         },
8734         { &hf_kafka_sasl_auth_bytes,
8735             { "SASL Authentication Bytes", "kafka.sasl_authentication",
8736                 FT_BYTES, BASE_NONE, 0, 0,
8737                 NULL, HFILL }
8738         },
8739         { &hf_kafka_session_lifetime_ms,
8740             { "Session Lifetime (ms)", "kafka.session_lifetime_ms",
8741                 FT_INT64, BASE_DEC, 0, 0,
8742                 NULL, HFILL }
8743         },
8744         { &hf_kafka_acl_resource_type,
8745             { "Resource Type", "kafka.acl_resource_type",
8746                 FT_INT8, BASE_DEC, VALS(acl_resource_types), 0,
8747                 NULL, HFILL }
8748         },
8749         { &hf_kafka_acl_resource_name,
8750             { "Resource Name", "kafka.acl_resource_name",
8751                 FT_STRING, STR_ASCII, 0, 0,
8752                 NULL, HFILL }
8753         },
8754         { &hf_kafka_acl_resource_pattern_type,
8755             { "Resource Pattern Type", "kafka.acl_resource_pattern_type",
8756                 FT_INT8, BASE_DEC, VALS(acl_resource_pattern_types), 0,
8757                 NULL, HFILL }
8758         },
8759         { &hf_kafka_acl_principal,
8760             { "Principal", "kafka.acl_principal",
8761                 FT_STRING, STR_ASCII, 0, 0,
8762                 NULL, HFILL }
8763         },
8764         { &hf_kafka_acl_host,
8765             { "Host", "kafka.acl_host",
8766                 FT_STRING, STR_ASCII, 0, 0,
8767                 NULL, HFILL }
8768         },
8769         { &hf_kafka_acl_operation,
8770             { "Operation", "kafka.acl_operation",
8771                 FT_INT8, BASE_DEC, VALS(acl_operations), 0,
8772                 NULL, HFILL }
8773         },
8774         { &hf_kafka_acl_permission_type,
8775             { "Permission Type", "kafka.acl_permission_type",
8776                 FT_INT8, BASE_DEC, VALS(acl_permission_types), 0,
8777                 NULL, HFILL }
8778         },
8779         { &hf_kafka_config_resource_type,
8780             { "Resource Type", "kafka.config_resource_type",
8781                 FT_INT8, BASE_DEC, VALS(config_resource_types), 0,
8782                 NULL, HFILL }
8783         },
8784         { &hf_kafka_config_resource_name,
8785             { "Resource Name", "kafka.config_resource_name",
8786                 FT_STRING, STR_ASCII, 0, 0,
8787                 NULL, HFILL }
8788         },
8789         { &hf_kafka_config_include_synonyms,
8790             { "Include Synonyms", "kafka.config_include_synonyms",
8791                 FT_BOOLEAN, BASE_NONE, 0, 0,
8792                 NULL, HFILL }
8793         },
8794         { &hf_kafka_config_default,
8795             { "Default", "kafka.config_default",
8796                 FT_BOOLEAN, BASE_NONE, 0, 0,
8797                 NULL, HFILL }
8798         },
8799         { &hf_kafka_config_readonly,
8800             { "Readonly", "kafka.config_readonly",
8801                 FT_BOOLEAN, BASE_NONE, 0, 0,
8802                 NULL, HFILL }
8803         },
8804         { &hf_kafka_config_sensitive,
8805             { "Sensitive", "kafka.config_sensitive",
8806                 FT_BOOLEAN, BASE_NONE, 0, 0,
8807                 NULL, HFILL }
8808         },
8809         { &hf_kafka_config_source,
8810             { "Source", "kafka.config_source",
8811                 FT_INT8, BASE_DEC, VALS(config_sources), 0,
8812                 NULL, HFILL }
8813         },
8814         { &hf_kafka_log_dir,
8815             { "Log Directory", "kafka.log_dir",
8816                 FT_STRING, STR_ASCII, 0, 0,
8817                 NULL, HFILL }
8818         },
8819         { &hf_kafka_segment_size,
8820             { "Segment Size", "kafka.segment_size",
8821                 FT_UINT64, BASE_DEC, 0, 0,
8822                 NULL, HFILL }
8823         },
8824         { &hf_kafka_offset_lag,
8825             { "Offset Lag", "kafka.offset_lag",
8826                 FT_UINT64, BASE_DEC, 0, 0,
8827                 NULL, HFILL }
8828         },
8829         { &hf_kafka_future,
8830             { "Future", "kafka.future",
8831                 FT_BOOLEAN, BASE_NONE, 0, 0,
8832                 NULL, HFILL }
8833         },
8834         { &hf_kafka_partition_count,
8835             { "Partition Count", "kafka.partition_count",
8836                 FT_UINT32, BASE_DEC, 0, 0,
8837                 NULL, HFILL }
8838         },
8839         { &hf_kafka_token_max_life_time,
8840             { "Max Life Time", "kafka.token_max_life_time",
8841                 FT_INT64, BASE_DEC, 0, 0,
8842                 NULL, HFILL }
8843         },
8844         { &hf_kafka_token_renew_time,
8845             { "Renew Time", "kafka.renew_time",
8846                 FT_INT64, BASE_DEC, 0, 0,
8847                 NULL, HFILL }
8848         },
8849         { &hf_kafka_token_expiry_time,
8850             { "Expiry Time", "kafka.expiry_time",
8851                 FT_INT64, BASE_DEC, 0, 0,
8852                 NULL, HFILL }
8853         },
8854         { &hf_kafka_token_principal_type,
8855             { "Principal Type", "kafka.principal_type",
8856                 FT_STRING, STR_ASCII, 0, 0,
8857                 NULL, HFILL }
8858         },
8859         { &hf_kafka_token_principal_name,
8860             { "Principal Name", "kafka.principal_name",
8861                 FT_STRING, STR_ASCII, 0, 0,
8862                 NULL, HFILL }
8863         },
8864         { &hf_kafka_token_issue_timestamp,
8865             { "Issue Timestamp", "kafka.token_issue_timestamp",
8866                 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
8867                 NULL, HFILL }
8868         },
8869         { &hf_kafka_token_expiry_timestamp,
8870             { "Expiry Timestamp", "kafka.token_expiry_timestamp",
8871                 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
8872                 NULL, HFILL }
8873         },
8874         { &hf_kafka_token_max_timestamp,
8875             { "Max Timestamp", "kafka.token_max_timestamp",
8876                 FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0,
8877                 NULL, HFILL }
8878         },
8879         { &hf_kafka_token_id,
8880             { "ID", "kafka.token_id",
8881                 FT_STRING, STR_ASCII, 0, 0,
8882                 NULL, HFILL }
8883         },
8884         { &hf_kafka_token_hmac,
8885             { "HMAC", "kafka.token_hmac",
8886                 FT_BYTES, BASE_NONE, 0, 0,
8887                 NULL, HFILL }
8888         },
8889         { &hf_kafka_include_cluster_authorized_ops,
8890             { "Include Cluster Authorized Operations", "kafka.include_cluster_authorized_ops",
8891                 FT_BOOLEAN, BASE_NONE, 0, 0,
8892                 NULL, HFILL }
8893         },
8894         { &hf_kafka_include_topic_authorized_ops,
8895             { "Include Topic Authorized Operations", "kafka.include_topic_authorized_ops",
8896                 FT_BOOLEAN, BASE_NONE, 0, 0,
8897                 NULL, HFILL }
8898         },
8899         { &hf_kafka_cluster_authorized_ops,
8900             { "Cluster Authorized Operations", "kafka.cluster_authorized_ops",
8901                 FT_UINT32, BASE_HEX, 0, 0,
8902                 NULL, HFILL }
8903         },
8904         { &hf_kafka_topic_authorized_ops,
8905             { "Topic Authorized Operations", "kafka.topic_authorized_ops",
8906                 FT_UINT32, BASE_HEX, 0, 0,
8907                 NULL, HFILL }
8908         },
8909         { &hf_kafka_include_group_authorized_ops,
8910             { "Include Group Authorized Operations", "kafka.include_group_authorized_ops",
8911                 FT_BOOLEAN, BASE_NONE, 0, 0,
8912                 NULL, HFILL }
8913         },
8914         { &hf_kafka_group_authorized_ops,
8915             { "Group Authorized Operations", "kafka.group_authorized_ops",
8916                 FT_UINT32, BASE_HEX, 0, 0,
8917                 NULL, HFILL }
8918         },
8919         { &hf_kafka_election_type,
8920             { "ElectionType", "kafka.election_type",
8921                 FT_INT8, BASE_DEC, VALS(election_types), 0,
8922                 NULL, HFILL }
8923         },
8924     };
8925
8926     static int *ett[] = {
8927         &ett_kafka,
8928         &ett_kafka_batch,
8929         &ett_kafka_message,
8930         &ett_kafka_message_set,
8931         &ett_kafka_offline,
8932         &ett_kafka_isrs,
8933         &ett_kafka_replicas,
8934         &ett_kafka_broker,
8935         &ett_kafka_brokers,
8936         &ett_kafka_broker_end_point,
8937         &ett_kafka_markers,
8938         &ett_kafka_marker,
8939         &ett_kafka_topics,
8940         &ett_kafka_topic,
8941         &ett_kafka_partitions,
8942         &ett_kafka_partition,
8943         &ett_kafka_api_version,
8944         &ett_kafka_group_protocols,
8945         &ett_kafka_group_protocol,
8946         &ett_kafka_group_members,
8947         &ett_kafka_group_member,
8948         &ett_kafka_group_assignments,
8949         &ett_kafka_group_assignment,
8950         &ett_kafka_groups,
8951         &ett_kafka_group,
8952         &ett_kafka_sasl_enabled_mechanisms,
8953         &ett_kafka_replica_assignment,
8954         &ett_kafka_configs,
8955         &ett_kafka_config,
8956         &ett_kafka_request_forgotten_topic,
8957         &ett_kafka_record,
8958         &ett_kafka_record_headers,
8959         &ett_kafka_record_headers_header,
8960         &ett_kafka_aborted_transactions,
8961         &ett_kafka_aborted_transaction,
8962         &ett_kafka_resources,
8963         &ett_kafka_resource,
8964         &ett_kafka_acls,
8965         &ett_kafka_acl,
8966         &ett_kafka_acl_creations,
8967         &ett_kafka_acl_creation,
8968         &ett_kafka_acl_filters,
8969         &ett_kafka_acl_filter,
8970         &ett_kafka_acl_filter_matches,
8971         &ett_kafka_acl_filter_match,
8972         &ett_kafka_config_synonyms,
8973         &ett_kafka_config_synonym,
8974         &ett_kafka_config_entries,
8975         &ett_kafka_config_entry,
8976         &ett_kafka_log_dirs,
8977         &ett_kafka_log_dir,
8978         &ett_kafka_renewers,
8979         &ett_kafka_renewer,
8980         &ett_kafka_owners,
8981         &ett_kafka_owner,
8982         &ett_kafka_tokens,
8983         &ett_kafka_token,
8984     };
8985
8986     static ei_register_info ei[] = {
8987         { &ei_kafka_request_missing,
8988           { "kafka.request_missing", PI_UNDECODED, PI_WARN, "Request missing", EXPFILL }},
8989         { &ei_kafka_unknown_api_key,
8990           { "kafka.unknown_api_key", PI_UNDECODED, PI_WARN, "Unknown API key", EXPFILL }},
8991         { &ei_kafka_unsupported_api_version,
8992           { "kafka.unsupported_api_version", PI_UNDECODED, PI_WARN, "Unsupported API version", EXPFILL }},
8993         { &ei_kafka_bad_string_length,
8994           { "kafka.bad_string_length", PI_MALFORMED, PI_WARN, "Invalid string length field", EXPFILL }},
8995         { &ei_kafka_bad_bytes_length,
8996           { "kafka.bad_bytes_length", PI_MALFORMED, PI_WARN, "Invalid byte length field", EXPFILL }},
8997         { &ei_kafka_bad_array_length,
8998           { "kafka.bad_array_length", PI_MALFORMED, PI_WARN, "Invalid array length field", EXPFILL }},
8999         { &ei_kafka_bad_record_length,
9000           { "kafka.bad_record_length", PI_MALFORMED, PI_WARN, "Invalid record length field", EXPFILL }},
9001         { &ei_kafka_bad_varint,
9002           { "kafka.bad_varint", PI_MALFORMED, PI_WARN, "Invalid varint bytes", EXPFILL }},
9003         { &ei_kafka_bad_message_set_length,
9004           { "kafka.ei_kafka_bad_message_set_length", PI_MALFORMED, PI_WARN, "Message set size does not match content", EXPFILL }},
9005         { &ei_kafka_unknown_message_magic,
9006           { "kafka.unknown_message_magic", PI_MALFORMED, PI_WARN, "Invalid message magic field", EXPFILL }},
9007     };
9008
9009     module_t *kafka_module;
9010     expert_module_t* expert_kafka;
9011
9012     proto_kafka = proto_register_protocol("Kafka", "Kafka", "kafka");
9013
9014     compute_kafka_api_names();
9015     proto_register_field_array(proto_kafka, hf, array_length(hf));
9016     proto_register_subtree_array(ett, array_length(ett));
9017     expert_kafka = expert_register_protocol(proto_kafka);
9018     expert_register_field_array(expert_kafka, ei, array_length(ei));
9019
9020     kafka_module = prefs_register_protocol(proto_kafka, NULL);
9021     kafka_handle = register_dissector("kafka", dissect_kafka_tcp, proto_kafka);
9022
9023     prefs_register_bool_preference(kafka_module, "show_string_bytes_lengths",
9024         "Show length for string and bytes fields in the protocol tree",
9025         "",
9026         &kafka_show_string_bytes_lengths);
9027 }
9028
9029 void
9030 proto_reg_handoff_kafka(void)
9031 {
9032     dissector_add_uint_range_with_preference("tcp.port", KAFKA_TCP_DEFAULT_RANGE, kafka_handle);
9033     ssl_dissector_add(0, kafka_handle);
9034 }
9035
9036 /*
9037  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
9038  *
9039  * Local variables:
9040  * c-basic-offset: 4
9041  * tab-width: 8
9042  * indent-tabs-mode: nil
9043  * End:
9044  *
9045  * vi: set shiftwidth=4 tabstop=8 expandtab:
9046  * :indentSize=4:tabSize=8:noTabs=true:
9047  */