Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-zabbix.c
blob572753ea3bf0b25951caac2d6f979642a9f704fd
1 /* packet-zabbix.c
2 * Routines for Zabbix protocol dissection
3 * Copyright 2023, Markku Leiniƶ <markku.leinio@gmail.com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * Zabbix protocol specifications can be found in Zabbix documentation:
14 * https://www.zabbix.com/documentation/current/en/manual/appendix/protocols
17 #include "config.h"
19 #include <epan/conversation.h>
20 #include <epan/expert.h>
21 #include <epan/packet.h>
22 #include <epan/prefs.h>
23 #include <epan/tfs.h>
24 #include <wsutil/array.h>
25 #include <wsutil/inet_addr.h>
26 #include <wsutil/nstime.h>
27 #include <wsutil/wsjson.h>
28 #include "packet-tcp.h"
30 void proto_register_zabbix(void);
31 void proto_reg_handoff_zabbix(void);
33 static dissector_handle_t zabbix_handle;
35 /* Desegmentation of Zabbix protocol over TCP */
36 static bool zabbix_desegment = true;
38 /* The protocol and registered fields */
39 static int proto_zabbix;
40 static int hf_zabbix_header;
41 static int hf_zabbix_flags;
42 static int hf_zabbix_flag_zabbix_communications;
43 static int hf_zabbix_flag_compressed;
44 static int hf_zabbix_flag_largepacket;
45 static int hf_zabbix_flag_reserved;
46 static int hf_zabbix_length;
47 static int hf_zabbix_reserved;
48 static int hf_zabbix_uncompressed_length;
49 static int hf_zabbix_large_length;
50 static int hf_zabbix_large_reserved;
51 static int hf_zabbix_large_uncompressed_length;
52 static int hf_zabbix_data;
53 static int hf_zabbix_error;
54 static int hf_zabbix_time;
55 static int hf_zabbix_agent;
56 static int hf_zabbix_agent_commands;
57 static int hf_zabbix_agent_config;
58 static int hf_zabbix_agent_data;
59 static int hf_zabbix_agent_redirection;
60 static int hf_zabbix_agent_passive;
61 static int hf_zabbix_agent_name;
62 static int hf_zabbix_agent_hb;
63 static int hf_zabbix_agent_hb_freq;
64 static int hf_zabbix_agent_hostmetadata;
65 static int hf_zabbix_agent_hostinterface;
66 static int hf_zabbix_agent_listenipv4;
67 static int hf_zabbix_agent_listenipv6;
68 static int hf_zabbix_agent_listenport;
69 static int hf_zabbix_agent_variant;
70 static int hf_zabbix_proxy;
71 static int hf_zabbix_proxy_hb;
72 static int hf_zabbix_proxy_name;
73 static int hf_zabbix_proxy_data;
74 static int hf_zabbix_proxy_config;
75 static int hf_zabbix_proxy_fullsync;
76 static int hf_zabbix_proxy_incr_config;
77 static int hf_zabbix_proxy_no_config_change;
78 static int hf_zabbix_proxy_tasks;
79 static int hf_zabbix_sender;
80 static int hf_zabbix_sender_name;
81 static int hf_zabbix_frontend;
82 static int hf_zabbix_frontend_sysinfo;
83 static int hf_zabbix_frontend_queueinfo;
84 static int hf_zabbix_frontend_historypush;
85 static int hf_zabbix_frontend_itemtest;
86 static int hf_zabbix_frontend_mediatest;
87 static int hf_zabbix_frontend_reporttest;
88 static int hf_zabbix_frontend_expressioneval;
89 static int hf_zabbix_frontend_scriptexec;
90 static int hf_zabbix_metrics;
91 static int hf_zabbix_request;
92 static int hf_zabbix_response;
93 static int hf_zabbix_success;
94 static int hf_zabbix_failed;
95 static int hf_zabbix_config_revision;
96 static int hf_zabbix_hostmap_revision;
97 static int hf_zabbix_session;
98 static int hf_zabbix_version;
100 /* Subtree pointers */
101 static int ett_zabbix;
102 static int ett_zabbix_flags;
104 /* Expert fields */
105 static expert_field ei_zabbix_packet_too_large;
106 static expert_field ei_zabbix_json_error;
108 /* Other dissector-specifics */
109 static range_t *zabbix_port_range;
111 static const char ZABBIX_HDR_SIGNATURE[] = "ZBXD";
112 static const char ZABBIX_UNKNOWN[] = "<unknown>";
113 static const char ZABBIX_ZBX_NOTSUPPORTED[] = "ZBX_NOTSUPPORTED";
115 typedef struct _zabbix_conv_info_t {
116 uint32_t req_framenum;
117 nstime_t req_timestamp;
118 uint32_t oper_flags; /* ZABBIX_T_XXX macros below */
119 const char *host_name;
120 } zabbix_conv_info_t;
122 #define ZABBIX_HDR_MIN_LEN 13 /* When not large packet */
123 #define ZABBIX_HDR_MAX_LEN 21 /* When large packet */
124 #define ZABBIX_MAX_LENGTH_ALLOWED 1024*1024*1024 /* 1 GB */
125 #define ZABBIX_TCP_PORTS "10050,10051" /* IANA registered ports */
127 #define ZABBIX_FLAG_ZABBIX_COMMUNICATIONS 0x01
128 #define ZABBIX_FLAG_COMPRESSED 0x02
129 #define ZABBIX_FLAG_LARGEPACKET 0x04
130 #define ZABBIX_FLAG_RESERVED 0xf8
132 /* Response flags are not saved in the conversations */
133 #define ZABBIX_RESPONSE_SUCCESS 0x01
134 #define ZABBIX_RESPONSE_FAILED 0x02
135 #define ZABBIX_RESPONSE_FULLSYNC 0x04
136 #define ZABBIX_RESPONSE_INCREMENTAL 0x08
137 #define ZABBIX_RESPONSE_NOCHANGE 0x10
139 /* Flags for saving and comparing operation types,
140 * max 32 bits as defined in zabbix_conv_info_t above */
141 #define ZABBIX_T_REQUEST 0x00000001
142 #define ZABBIX_T_RESPONSE 0x00000002
143 #define ZABBIX_T_ACTIVE 0x00000004
144 #define ZABBIX_T_PASSIVE 0x00000008
145 #define ZABBIX_T_AGENT 0x00000010
146 #define ZABBIX_T_PROXY 0x00000020
147 #define ZABBIX_T_SENDER 0x00000040
148 #define ZABBIX_T_CONFIG 0x00000080
149 #define ZABBIX_T_DATA 0x00000100
150 #define ZABBIX_T_TASKS 0x00000200
151 #define ZABBIX_T_HEARTBEAT 0x00000400
152 #define ZABBIX_T_LEGACY 0x00000800 /* pre-7.0 non-JSON protocol */
153 #define ZABBIX_T_FRONTEND 0x00001000
154 #define ZABBIX_T_SYSINFO 0x00002000
155 #define ZABBIX_T_QUEUEINFO 0x00004000
156 #define ZABBIX_T_HISTORYPUSH 0x00008000
157 #define ZABBIX_T_ITEMTEST 0x00010000
158 #define ZABBIX_T_MEDIATEST 0x00020000
159 #define ZABBIX_T_REPORTTEST 0x00040000
160 #define ZABBIX_T_METRICS 0x00080000
161 #define ZABBIX_T_EXPRESSIONEVAL 0x00100000
162 #define ZABBIX_T_SCRIPTEXEC 0x00200000
164 #define ADD_ZABBIX_T_FLAGS(flags) (zabbix_info->oper_flags |= (flags))
165 #define CLEAR_ZABBIX_T_FLAGS(flags) (zabbix_info->oper_flags &= (0xffffffff-(flags)))
166 #define IS_ZABBIX_T_FLAGS(flags) ((zabbix_info->oper_flags & (flags)) == (flags))
168 #define CONV_IS_ZABBIX_REQUEST(zabbix_info,pinfo) ((zabbix_info)->req_framenum == (pinfo)->fd->num)
169 #define CONV_IS_ZABBIX_RESPONSE(zabbix_info,pinfo) ((zabbix_info)->req_framenum != (pinfo)->fd->num)
171 #define ZABBIX_NAME_OR_UNKNOWN(name) ((name) ? (name) : ZABBIX_UNKNOWN)
174 static zabbix_conv_info_t*
175 zabbix_find_conversation_and_get_conv_data(packet_info *pinfo)
177 conversation_t *conversation;
178 zabbix_conv_info_t *zabbix_info = NULL;
180 conversation = find_conversation_pinfo(pinfo, 0);
181 if (conversation) {
182 zabbix_info = (zabbix_conv_info_t *)conversation_get_proto_data(conversation, proto_zabbix);
183 } else {
184 conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst,
185 conversation_pt_to_conversation_type(pinfo->ptype),
186 pinfo->srcport, pinfo->destport, 0);
188 if (!zabbix_info) {
189 /* New conversation, or there was no Zabbix data yet in the existing conv */
190 zabbix_info = wmem_alloc(wmem_file_scope(), sizeof(zabbix_conv_info_t));
191 if (value_is_in_range(zabbix_port_range, pinfo->destport)) {
192 /* Let's assume this is the first Zabbix packet (request) */
193 zabbix_info->req_framenum = pinfo->fd->num;
194 zabbix_info->req_timestamp = pinfo->abs_ts;
196 else {
197 /* For any reason we didn't have Zabbix data yet but this is not
198 * the first packet for the connection, so don't save it as a request
200 zabbix_info->req_framenum = 0;
201 nstime_set_unset(&zabbix_info->req_timestamp);
202 /* For some reason this produces "syntax error: '{'" when compiling:
203 zabbix_info->req_timestamp = NSTIME_INIT_UNSET;
206 zabbix_info->oper_flags = 0;
207 zabbix_info->host_name = NULL;
208 conversation_add_proto_data(conversation, proto_zabbix, (void *)zabbix_info);
210 return zabbix_info;
213 static void
214 zabbix_add_expert_info_if_too_large(packet_info *pinfo, proto_tree *tree_item,
215 uint64_t length, bool *is_too_large)
217 if (length > ZABBIX_MAX_LENGTH_ALLOWED) {
218 expert_add_info(pinfo, tree_item, &ei_zabbix_packet_too_large);
219 *is_too_large = true;
221 return;
224 static int
225 dissect_zabbix_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
227 int offset = 0;
228 int agent_hb_freq = 0;
229 unsigned oper_response = 0;
230 proto_item *ti;
231 proto_item *pi;
232 proto_tree *temp_ti;
233 proto_tree *zabbix_tree = NULL;
234 uint8_t flags;
235 uint16_t agent_listenport = 0;
236 uint64_t length;
237 uint64_t uncompressed_length;
238 uint64_t datalen;
239 int64_t agent_variant = 0;
240 int64_t config_revision = -1;
241 int64_t hostmap_revision = -1;
242 bool is_compressed;
243 bool is_large_packet;
244 bool is_too_large = false;
245 bool is_redirection = false;
246 char *json_str;
247 char *passive_agent_data_str = NULL;
248 jsmntok_t *commands_array = NULL;
249 jsmntok_t *data_array = NULL;
250 jsmntok_t *data_object = NULL;
251 const char *agent_name = NULL;
252 const char *agent_hostmetadata = NULL;
253 const char *agent_hostinterface = NULL;
254 const char *agent_listenip = NULL;
255 const char *proxy_name = NULL;
256 const char *sender_name = NULL;
257 const char *session = NULL;
258 const char *request_type = NULL;
259 const char *response_status = NULL;
260 const char *version = NULL;
261 double temp_double;
262 tvbuff_t *next_tvb;
263 zabbix_conv_info_t *zabbix_info;
264 static int* const flagbits[] = {
265 &hf_zabbix_flag_reserved,
266 &hf_zabbix_flag_largepacket,
267 &hf_zabbix_flag_compressed,
268 &hf_zabbix_flag_zabbix_communications,
269 NULL
272 /* Make entries in Protocol column and Info column on summary display */
273 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Zabbix");
274 col_clear(pinfo->cinfo, COL_INFO);
276 if ((tvb_reported_length(tvb) < ZABBIX_HDR_MIN_LEN) ||
277 (tvb_memeql(tvb, offset, ZABBIX_HDR_SIGNATURE, 4) == -1)) {
278 /* Encrypted or not Zabbix at all */
279 return 0;
281 flags = tvb_get_uint8(tvb, offset+4);
282 if (!(flags & ZABBIX_FLAG_ZABBIX_COMMUNICATIONS)) {
283 return 0;
286 zabbix_info = zabbix_find_conversation_and_get_conv_data(pinfo);
288 is_compressed = (flags & ZABBIX_FLAG_COMPRESSED) > 0;
289 is_large_packet = (flags & ZABBIX_FLAG_LARGEPACKET) > 0;
291 /* create display subtree for the protocol */
292 ti = proto_tree_add_item(tree, proto_zabbix, tvb, 0, -1, ENC_NA);
293 zabbix_tree = proto_item_add_subtree(ti, ett_zabbix);
294 proto_tree_add_item(zabbix_tree, hf_zabbix_header, tvb, offset, 4, ENC_UTF_8);
295 offset += 4;
296 proto_tree_add_bitmask(zabbix_tree, tvb, offset, hf_zabbix_flags, ett_zabbix_flags, flagbits, ENC_BIG_ENDIAN);
297 offset += 1;
298 if (is_large_packet) {
299 /* 8-byte values */
300 temp_ti = proto_tree_add_item_ret_uint64(zabbix_tree,
301 hf_zabbix_large_length, tvb, offset, 8, ENC_LITTLE_ENDIAN, &length);
302 zabbix_add_expert_info_if_too_large(pinfo, temp_ti, length, &is_too_large);
303 offset += 8;
304 if (is_compressed) {
305 temp_ti = proto_tree_add_item_ret_uint64(zabbix_tree,
306 hf_zabbix_large_uncompressed_length, tvb, offset, 8, ENC_LITTLE_ENDIAN, &uncompressed_length);
307 zabbix_add_expert_info_if_too_large(pinfo, temp_ti, uncompressed_length, &is_too_large);
308 } else {
309 proto_tree_add_item(zabbix_tree, hf_zabbix_large_reserved, tvb, offset, 8, ENC_LITTLE_ENDIAN);
311 offset += 8;
312 } else {
313 /* 4-byte values */
314 uint32_t temp_uint32;
315 temp_ti = proto_tree_add_item_ret_uint(zabbix_tree,
316 hf_zabbix_length, tvb, offset, 4, ENC_LITTLE_ENDIAN, &temp_uint32);
317 length = (uint64_t)temp_uint32;
318 zabbix_add_expert_info_if_too_large(pinfo, temp_ti, length, &is_too_large);
319 offset += 4;
320 if (is_compressed) {
321 temp_ti = proto_tree_add_item_ret_uint(zabbix_tree,
322 hf_zabbix_uncompressed_length, tvb, offset, 4, ENC_LITTLE_ENDIAN, &temp_uint32);
323 uncompressed_length = (uint64_t)temp_uint32;
324 zabbix_add_expert_info_if_too_large(pinfo, temp_ti, uncompressed_length, &is_too_large);
325 } else {
326 proto_tree_add_item(zabbix_tree, hf_zabbix_reserved, tvb, offset, 4, ENC_LITTLE_ENDIAN);
328 offset += 4;
330 if (is_too_large) {
331 /* Set next_tvb for response time calculation to work later */
332 next_tvb = tvb_new_subset_remaining(tvb, offset);
333 /* ... but don't do any content-based inspection, just skip to the end */
334 goto final_outputs;
335 } else if (is_compressed) {
336 next_tvb = tvb_uncompress_zlib(tvb, offset, tvb_reported_length_remaining(tvb, offset));
337 if (next_tvb) {
338 tvb_set_child_real_data_tvbuff(tvb, next_tvb);
339 add_new_data_source(pinfo, next_tvb, "Uncompressed data");
340 datalen = uncompressed_length;
341 } else {
342 /* Handle uncompressed */
343 next_tvb = tvb_new_subset_remaining(tvb, offset);
344 datalen = length;
346 } else {
347 next_tvb = tvb_new_subset_remaining(tvb, offset);
348 datalen = length;
351 /* Use only next_tvb and datalen for data extraction from here on! */
352 offset = 0;
354 /* Rewrite the default texts in the protocol tree and initialize request/response flags */
355 if (CONV_IS_ZABBIX_REQUEST(zabbix_info, pinfo)) {
356 proto_item_set_text(ti, "Zabbix Protocol request");
357 ADD_ZABBIX_T_FLAGS(ZABBIX_T_REQUEST);
358 CLEAR_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE);
360 else if (CONV_IS_ZABBIX_RESPONSE(zabbix_info, pinfo)) {
361 proto_item_set_text(ti, "Zabbix Protocol response");
362 ADD_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE);
363 CLEAR_ZABBIX_T_FLAGS(ZABBIX_T_REQUEST);
367 * Note that json_str is modified when using json_get_xxx() functions below!
368 * So don't use it to anything else (make a wmem_strdup() if needed, see below)
370 json_str = tvb_get_string_enc(pinfo->pool, next_tvb, offset, (int)datalen, ENC_UTF_8);
371 /* First check if this is a pre-7.0 passive agent.
372 * Note that even pre-7.0 passive agent *responses* can be JSON, so don't just check
373 * for JSON validation but check the conversation data!
375 if (
376 !json_validate(json_str, datalen) ||
378 CONV_IS_ZABBIX_RESPONSE(zabbix_info, pinfo) &&
379 IS_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_PASSIVE | ZABBIX_T_LEGACY)
382 /* The only non-JSON Zabbix request/response is passive agent before Zabbix 7.0,
383 * ensure the conversation data is set, then set the texts
385 ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_PASSIVE | ZABBIX_T_LEGACY);
386 if (CONV_IS_ZABBIX_REQUEST(zabbix_info, pinfo)) {
387 proto_item_set_text(ti, "Zabbix Server/proxy request for passive agent checks");
388 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Server/proxy request for passive agent checks");
389 } else if (CONV_IS_ZABBIX_RESPONSE(zabbix_info, pinfo)) {
390 proto_item_set_text(ti, "Zabbix Agent response for passive checks");
391 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Agent response for passive checks");
393 /* Make a copy of the data string for later error message lookup use */
394 passive_agent_data_str = wmem_strndup(pinfo->pool, json_str, (size_t)datalen);
395 /* Don't do content-based searches for pre-7.0 passive agents */
396 goto show_agent_outputs;
398 /* Parse JSON, first get the token count */
399 int token_count = json_parse(json_str, NULL, 0);
400 if (token_count <= 0) {
401 temp_ti = proto_tree_add_item(zabbix_tree, hf_zabbix_data, next_tvb, 0, (int)datalen, ENC_UTF_8);
402 expert_add_info_format(pinfo, temp_ti, &ei_zabbix_json_error, "Error in initial JSON parse");
403 goto final_outputs;
405 jsmntok_t *tokens = wmem_alloc_array(pinfo->pool, jsmntok_t, token_count);
406 int ret = json_parse(json_str, tokens, token_count);
407 if (ret <= 0) {
408 temp_ti = proto_tree_add_item(zabbix_tree, hf_zabbix_data, next_tvb, 0, (int)datalen, ENC_UTF_8);
409 expert_add_info_format(pinfo, temp_ti, &ei_zabbix_json_error, "Error parsing JSON tokens");
410 goto final_outputs;
414 * Now we have JSON tokens analyzed, let's do all the logic to populate the fields.
415 * Also set Zabbix tree item and Info column texts, Len= and ports will be added later below.
418 /* First populate common fields */
419 version = json_get_string(json_str, tokens, "version");
420 if (json_get_double(json_str, tokens, "variant", &temp_double)) {
421 agent_variant = (int64_t)temp_double;
423 session = json_get_string(json_str, tokens, "session");
424 if (json_get_double(json_str, tokens, "config_revision", &temp_double)) {
425 config_revision = (int64_t)temp_double;
427 if (json_get_double(json_str, tokens, "hostmap_revision", &temp_double)) {
428 hostmap_revision = (int64_t)temp_double;
429 } else {
430 jsmntok_t *proxy_group_object = json_get_object(json_str, tokens, "proxy_group");
431 if (proxy_group_object) {
432 if (json_get_double(json_str, proxy_group_object, "hostmap_revision", &temp_double)) {
433 hostmap_revision = (int64_t)temp_double;
437 request_type = json_get_string(json_str, tokens, "request");
438 response_status = json_get_string(json_str, tokens, "response");
439 commands_array = json_get_array(json_str, tokens, "commands");
440 data_array = json_get_array(json_str, tokens, "data");
441 data_object = json_get_object(json_str, tokens, "data");
442 /* Find the packet type primarily based on "request" field */
443 if (request_type) {
444 if (strcmp(request_type, "active checks") == 0) {
445 /* Active agent requesting configs */
446 ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_CONFIG | ZABBIX_T_ACTIVE);
447 agent_name = json_get_string(json_str, tokens, "host");
448 if (agent_name && !PINFO_FD_VISITED(pinfo)) {
449 zabbix_info->host_name = wmem_strdup(wmem_file_scope(), agent_name);
451 proto_item_set_text(ti,
452 "Zabbix Agent request for active checks for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
453 col_add_fstr(pinfo->cinfo, COL_INFO,
454 "Zabbix Agent request for active checks for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
455 agent_hostmetadata = json_get_string(json_str, tokens, "host_metadata");
456 agent_hostinterface = json_get_string(json_str, tokens, "interface");
457 agent_listenip = json_get_string(json_str, tokens, "ip");
458 if (json_get_double(json_str, tokens, "port", &temp_double)) {
459 agent_listenport = (uint16_t)temp_double;
462 else if (strcmp(request_type, "agent data") == 0) {
463 /* Active agent sending data */
464 ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_DATA | ZABBIX_T_ACTIVE);
465 /* Zabbix Agent 2 has Host in the top level */
466 agent_name = json_get_string(json_str, tokens, "host");
467 if (!agent_name) {
468 /* For Zabbix Agent try parsing agent name inside data array */
469 jsmntok_t *tok = json_get_array(json_str, tokens, "data");
470 if (tok && json_get_array_len(tok) > 0) {
471 jsmntok_t *datatok = json_get_array_index(tok, 0);
472 agent_name = json_get_string(json_str, datatok, "host");
475 if (agent_name && !PINFO_FD_VISITED(pinfo)) {
476 zabbix_info->host_name = wmem_strdup(wmem_file_scope(), agent_name);
478 proto_item_set_text(ti,
479 "Zabbix Agent data from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
480 col_add_fstr(pinfo->cinfo, COL_INFO,
481 "Zabbix Agent data from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
483 else if (strcmp(request_type, "active check heartbeat") == 0) {
484 /* Active agent sending heartbeat */
485 ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_HEARTBEAT | ZABBIX_T_ACTIVE);
486 agent_name = json_get_string(json_str, tokens, "host");
487 if (agent_name && !PINFO_FD_VISITED(pinfo)) {
488 zabbix_info->host_name = wmem_strdup(wmem_file_scope(), agent_name);
490 if (json_get_double(json_str, tokens, "heartbeat_freq", &temp_double)) {
491 agent_hb_freq = (int)temp_double;
493 proto_item_set_text(ti,
494 "Zabbix Agent heartbeat from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
495 col_add_fstr(pinfo->cinfo, COL_INFO,
496 "Zabbix Agent heartbeat from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
498 else if (strcmp(request_type, "passive checks") == 0) {
499 /* Passive agent checks since Zabbix 7.0 */
500 ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_PASSIVE);
501 proto_item_set_text(ti, "Zabbix Server/proxy request for passive agent checks");
502 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Server/proxy request for passive agent checks");
504 else if (strcmp(request_type, "zabbix.stats") == 0) {
505 /* Agent requesting server/proxy internal metrics, since Zabbix 4.0.5 */
506 ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_METRICS);
507 proto_item_set_text(ti, "Zabbix Server/proxy internal metrics request");
508 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Server/proxy internal metrics request");
510 else if (strcmp(request_type, "sender data") == 0) {
511 /* Sender/trapper */
512 ADD_ZABBIX_T_FLAGS(ZABBIX_T_SENDER);
513 /* Try to get the sender name from the first data array item */
514 jsmntok_t *tok = json_get_array(json_str, tokens, "data");
515 if (tok && json_get_array_len(tok) > 0) {
516 jsmntok_t *datatok = json_get_array_index(tok, 0);
517 sender_name = json_get_string(json_str, datatok, "host");
518 if (sender_name && !PINFO_FD_VISITED(pinfo)) {
519 zabbix_info->host_name = wmem_strdup(wmem_file_scope(), sender_name);
522 proto_item_set_text(ti,
523 "Zabbix Sender data from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(sender_name));
524 col_add_fstr(pinfo->cinfo, COL_INFO,
525 "Zabbix Sender data from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(sender_name));
527 else if ((strcmp(request_type, "proxy data") == 0) ||
528 (strcmp(request_type, "host availability") == 0) ||
529 (strcmp(request_type, "history data") == 0) ||
530 (strcmp(request_type, "discovery data") == 0) ||
531 (strcmp(request_type, "auto registration") == 0)) {
532 /* Either active or passive proxy; "proxy data" = Zabbix 3.4+,
533 * others = Zabbix 3.2 or older */
534 proxy_name = json_get_string(json_str, tokens, "host");
535 if (token_count == 3) { /* Only '{"request":"xxx"}' */
536 /* This is Zabbix server connecting to passive proxy */
537 ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_DATA | ZABBIX_T_PASSIVE);
538 proto_item_set_text(ti, "Zabbix Proxy data request to passive proxy");
539 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Proxy data request to passive proxy");
541 else if (proxy_name) {
542 /* This is an active proxy connecting to server */
543 ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_DATA | ZABBIX_T_ACTIVE);
544 if (proxy_name && !PINFO_FD_VISITED(pinfo)) {
545 zabbix_info->host_name = wmem_strdup(wmem_file_scope(), proxy_name);
547 proto_item_set_text(ti, "Zabbix Proxy data from \"%s\"", proxy_name);
548 col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Proxy data from \"%s\"", proxy_name);
551 else if (strcmp(request_type, "proxy config") == 0) {
552 /* Either active or passive proxy */
553 proxy_name = json_get_string(json_str, tokens, "host");
554 if (token_count == 3) { /* Only '{"request":"proxy config"}' */
555 /* This is Zabbix 6.4+ server connecting to passive proxy */
556 ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG | ZABBIX_T_PASSIVE);
557 proto_item_set_text(ti, "Zabbix Proxy config request to passive proxy");
558 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Proxy config request to passive proxy");
560 else if (proxy_name) {
561 /* This is an active proxy connecting to server */
562 ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG | ZABBIX_T_ACTIVE);
563 if (proxy_name && !PINFO_FD_VISITED(pinfo)) {
564 zabbix_info->host_name = wmem_strdup(wmem_file_scope(), proxy_name);
566 proto_item_set_text(ti, "Zabbix Request proxy config for \"%s\"", proxy_name);
567 col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Request proxy config for \"%s\"", proxy_name);
570 else if (strcmp(request_type, "proxy tasks") == 0) {
571 /* Zabbix server connecting to passive proxy, only '{"request":"proxy tasks"}' */
572 ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_TASKS | ZABBIX_T_PASSIVE);
573 proto_item_set_text(ti, "Zabbix Proxy tasks request to passive proxy");
574 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Proxy tasks request to passive proxy");
576 else if (strcmp(request_type, "proxy heartbeat") == 0) {
577 /* Heartbeat from active proxy, not used in Zabbix 6.4+ */
578 ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_HEARTBEAT | ZABBIX_T_ACTIVE);
579 proxy_name = json_get_string(json_str, tokens, "host");
580 if (proxy_name && !PINFO_FD_VISITED(pinfo)) {
581 zabbix_info->host_name = wmem_strdup(wmem_file_scope(), proxy_name);
583 proto_item_set_text(ti, "Zabbix Proxy heartbeat from \"%s\"", proxy_name);
584 col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Proxy heartbeat from \"%s\"", proxy_name);
586 /* UI/API-specific requests */
587 else if (strcmp(request_type, "status.get") == 0) {
588 /* System information report */
589 ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_SYSINFO);
590 proto_item_set_text(ti, "Zabbix System information request");
591 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix System information request");
593 else if (strcmp(request_type, "queue.get") == 0) {
594 /* Queue information request */
595 ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_QUEUEINFO);
596 proto_item_set_text(ti, "Zabbix Queue information request");
597 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Queue information request");
599 else if (strcmp(request_type, "history.push") == 0) {
600 /* history.push API call, since Zabbix 7.0 */
601 ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_HISTORYPUSH);
602 proto_item_set_text(ti, "Zabbix History push request");
603 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix History push request");
605 else if (strcmp(request_type, "item.test") == 0) {
606 /* Item test in the frontend */
607 ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_ITEMTEST);
608 proto_item_set_text(ti, "Zabbix Item test request");
609 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Item test request");
611 else if (strcmp(request_type, "alert.send") == 0) {
612 /* Media test in the frontend */
613 ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_MEDIATEST);
614 proto_item_set_text(ti, "Zabbix Media test request");
615 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Media test request");
617 else if (strcmp(request_type, "report.test") == 0) {
618 /* Report test in the frontend */
619 ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_REPORTTEST);
620 proto_item_set_text(ti, "Zabbix Report test request");
621 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Report test request");
623 else if (strcmp(request_type, "expressions.evaluate") == 0) {
624 /* Trigger expression evaluation test in the frontend */
625 ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_EXPRESSIONEVAL);
626 proto_item_set_text(ti, "Zabbix Expression evaluation request");
627 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Expression evaluation request");
629 else if (strcmp(request_type, "command") == 0) {
630 /* Script execution from the frontend */
631 ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_SCRIPTEXEC);
632 proto_item_set_text(ti, "Zabbix Script execution request");
633 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Script execution request");
636 /* There was no "request" field match, continue with other ways to recognize the packet */
637 else if (json_get_object(json_str, tokens, "globalmacro")) {
638 /* This is Zabbix server before 6.4 sending configurations to active proxy */
639 ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG | ZABBIX_T_ACTIVE);
640 proxy_name = zabbix_info->host_name;
641 proto_item_set_text(ti,
642 "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
643 col_add_fstr(pinfo->cinfo, COL_INFO,
644 "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
646 else if (json_get_double(json_str, tokens, "full_sync", &temp_double)) {
647 /* This is Zabbix 6.4+ server sending proxy config to active or passive proxy */
648 /* Only present when value is 1 */
649 ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG);
650 oper_response |= ZABBIX_RESPONSE_FULLSYNC;
651 /* Active/passive flag was set in the earlier packet */
652 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PASSIVE)) {
653 /* There is no proxy name anywhere to use */
654 proto_item_set_text(ti, "Zabbix Passive proxy config");
655 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Passive proxy config");
657 else {
658 /* Active proxy */
659 proxy_name = zabbix_info->host_name;
660 proto_item_set_text(ti,
661 "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
662 col_add_fstr(pinfo->cinfo, COL_INFO,
663 "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
666 else if (response_status) {
667 if (strcmp(response_status, "success") == 0) {
668 oper_response |= ZABBIX_RESPONSE_SUCCESS;
670 else if (strcmp(response_status, "failed") == 0) {
671 oper_response |= ZABBIX_RESPONSE_FAILED;
673 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_AGENT)) {
674 agent_name = zabbix_info->host_name;
675 if (json_get_object(json_str, tokens, "redirect")) {
676 /* Agent redirection response from a Zabbix 7.0+ proxy in load balancing configuration.
677 * Not added in the conversation flags to prevent it from showing in the request packet,
678 * just set a local variable for later usage.
680 is_redirection = true;
681 proto_item_set_text(ti,
682 "Zabbix Agent redirection for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
683 col_add_fstr(pinfo->cinfo, COL_INFO,
684 "Zabbix Agent redirection for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
686 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_CONFIG | ZABBIX_T_ACTIVE)) {
687 proto_item_set_text(ti,
688 "Zabbix Server/proxy response for active checks for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(agent_name), response_status);
689 col_add_fstr(pinfo->cinfo, COL_INFO,
690 "Zabbix Server/proxy response for active checks for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(agent_name), response_status);
692 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_DATA | ZABBIX_T_ACTIVE)) {
693 proto_item_set_text(ti,
694 "Zabbix Server/proxy response for agent data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(agent_name), response_status);
695 col_add_fstr(pinfo->cinfo, COL_INFO,
696 "Zabbix Server/proxy response for agent data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(agent_name), response_status);
698 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_METRICS)) {
699 proto_item_set_text(ti, "Zabbix Server/proxy internal metrics response");
700 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Server/proxy internal metrics response");
703 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY)) {
704 proxy_name = zabbix_info->host_name;
705 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_CONFIG | ZABBIX_T_ACTIVE)) {
706 proto_item_set_text(ti,
707 "Zabbix Response for active proxy config request for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
708 col_add_fstr(pinfo->cinfo, COL_INFO,
709 "Zabbix Response for active proxy config request for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
711 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_DATA | ZABBIX_T_ACTIVE)) {
712 proto_item_set_text(ti,
713 "Zabbix Server response for active proxy data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
714 col_add_fstr(pinfo->cinfo, COL_INFO,
715 "Zabbix Server response for active proxy data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
717 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_CONFIG | ZABBIX_T_PASSIVE)) {
718 proto_item_set_text(ti,
719 "Zabbix Proxy response for passive proxy config (%s)", response_status);
720 col_add_fstr(pinfo->cinfo, COL_INFO,
721 "Zabbix Proxy response for passive proxy config (%s)", response_status);
723 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_DATA | ZABBIX_T_PASSIVE)) {
724 proto_item_set_text(ti,
725 "Zabbix Server response for passive proxy data (%s)", response_status);
726 col_add_fstr(pinfo->cinfo, COL_INFO,
727 "Zabbix Server response for passive proxy data (%s)", response_status);
729 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_TASKS | ZABBIX_T_PASSIVE)) {
730 proto_item_set_text(ti,
731 "Zabbix Server response for passive proxy tasks (%s)", response_status);
732 col_add_fstr(pinfo->cinfo, COL_INFO,
733 "Zabbix Server response for passive proxy tasks (%s)", response_status);
735 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_HEARTBEAT | ZABBIX_T_ACTIVE)) {
736 proto_item_set_text(ti,
737 "Zabbix Server response for active proxy heartbeat for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
738 col_add_fstr(pinfo->cinfo, COL_INFO,
739 "Zabbix Server response for active proxy heartbeat for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
742 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SENDER)) {
743 sender_name = zabbix_info->host_name;
744 proto_item_set_text(ti,
745 "Zabbix Server/proxy response for sender data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(sender_name), response_status);
746 col_add_fstr(pinfo->cinfo, COL_INFO,
747 "Zabbix Server/proxy response for sender data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(sender_name), response_status);
749 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND)) {
750 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SYSINFO)) {
751 proto_item_set_text(ti, "Zabbix System information response");
752 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix System information response");
754 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_QUEUEINFO)) {
755 proto_item_set_text(ti, "Zabbix Queue information response");
756 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Queue information response");
758 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_HISTORYPUSH)) {
759 proto_item_set_text(ti, "Zabbix History push response");
760 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix History push response");
762 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_ITEMTEST)) {
763 proto_item_set_text(ti, "Zabbix Item test response");
764 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Item test response");
766 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_MEDIATEST)) {
767 proto_item_set_text(ti, "Zabbix Media test response");
768 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Media test response");
770 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_REPORTTEST)) {
771 proto_item_set_text(ti, "Zabbix Report test response");
772 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Report test response");
774 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_EXPRESSIONEVAL)) {
775 proto_item_set_text(ti, "Zabbix Expression evaluation response");
776 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Expression evaluation response");
778 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SCRIPTEXEC)) {
779 proto_item_set_text(ti, "Zabbix Script execution response");
780 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Script execution response");
784 else if (version && data_array) {
785 /* This looks like passive agent response in Zabbix 7.0+ */
786 ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_PASSIVE);
787 proto_item_set_text(ti, "Zabbix Agent response for passive checks");
788 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Agent response for passive checks");
790 else if (data_object || data_array || tokens->size == 0) {
791 /* No other match above, let's assume this is server sending incremental
792 * configuration to a proxy
794 ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG);
795 if ((data_object && (data_object->size == 0)) || tokens->size == 0) {
796 /* Empty data object or the whole JSON is empty */
797 oper_response |= ZABBIX_RESPONSE_NOCHANGE;
799 else if (data_array) {
800 /* This was not a "full_sync" but data array exists */
801 oper_response |= ZABBIX_RESPONSE_INCREMENTAL;
803 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PASSIVE)) {
804 /* There is no proxy name anywhere to use */
805 proto_item_set_text(ti, "Zabbix Passive proxy config");
806 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Passive proxy config");
808 else {
809 proxy_name = zabbix_info->host_name;
810 proto_item_set_text(ti,
811 "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
812 col_add_fstr(pinfo->cinfo, COL_INFO,
813 "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
816 /* Final guesses to provide customized packet information */
817 else if (session && version) {
818 /* Config or data responses from passive proxy */
819 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG | ZABBIX_T_PASSIVE)) {
820 proto_item_set_text(ti, "Zabbix Passive proxy response for config push");
821 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Passive proxy response for config push");
823 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_DATA | ZABBIX_T_PASSIVE)) {
824 proto_item_set_text(ti, "Zabbix Passive proxy data response");
825 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Passive proxy data response");
828 else if (version) {
829 /* Tasks response from passive proxy */
830 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_TASKS | ZABBIX_T_PASSIVE)) {
831 proto_item_set_text(ti, "Zabbix Passive proxy response for tasks request");
832 col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Passive proxy response for tasks request");
837 /* Add all relevant fields to the tree */
839 show_agent_outputs:
840 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_AGENT)) {
841 temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent, NULL, 0, 0, true);
842 proto_item_set_text(temp_ti, "This is an agent connection");
843 proto_item_set_generated(temp_ti);
844 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_DATA)) {
845 temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_data, NULL, 0, 0, true);
846 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE)) {
847 /* Set as generated, not seen in data */
848 proto_item_set_generated(temp_ti);
851 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_CONFIG)) {
852 temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_config, NULL, 0, 0, true);
853 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE)) {
854 /* Set as generated, not seen in data */
855 proto_item_set_generated(temp_ti);
858 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_HEARTBEAT)) {
859 proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_hb, NULL, 0, 0, true);
861 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PASSIVE)) {
862 temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_passive, NULL, 0, 0, true);
863 proto_item_set_text(temp_ti, "Agent is in passive mode");
864 proto_item_set_generated(temp_ti);
866 if (is_redirection) {
867 proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_redirection, NULL, 0, 0, true);
870 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY)) {
871 temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy, NULL, 0, 0, true);
872 proto_item_set_text(temp_ti, "This is a proxy connection");
873 proto_item_set_generated(temp_ti);
875 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SENDER)) {
876 temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_sender, NULL, 0, 0, true);
877 proto_item_set_text(temp_ti, "This is a sender connection");
878 proto_item_set_generated(temp_ti);
880 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND)) {
881 temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend, NULL, 0, 0, true);
882 proto_item_set_text(temp_ti, "This is a frontend connection");
883 proto_item_set_generated(temp_ti);
885 if (oper_response & ZABBIX_RESPONSE_SUCCESS) {
886 proto_tree_add_boolean(zabbix_tree, hf_zabbix_success, NULL, 0, 0, true);
888 else if (oper_response & ZABBIX_RESPONSE_FAILED) {
889 proto_tree_add_boolean(zabbix_tree, hf_zabbix_failed, NULL, 0, 0, true);
891 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_AGENT)) {
892 if (agent_name) {
893 temp_ti = proto_tree_add_string(zabbix_tree, hf_zabbix_agent_name, NULL, 0, 0, agent_name);
894 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE)) {
895 /* agent_name was populated from the conversation */
896 proto_item_set_generated(temp_ti);
897 proto_item_append_text(temp_ti, " (from the request)");
900 if (agent_variant) {
901 proto_tree_add_int64(zabbix_tree, hf_zabbix_agent_variant, NULL, 0, 0, agent_variant);
903 if (agent_hb_freq) {
904 proto_tree_add_int(zabbix_tree, hf_zabbix_agent_hb_freq, NULL, 0, 0, agent_hb_freq);
906 if (agent_hostmetadata) {
907 proto_tree_add_string(zabbix_tree, hf_zabbix_agent_hostmetadata, NULL, 0, 0, agent_hostmetadata);
909 if (agent_hostinterface) {
910 proto_tree_add_string(zabbix_tree, hf_zabbix_agent_hostinterface, NULL, 0, 0, agent_hostinterface);
912 if (agent_listenip) {
913 if (strstr(agent_listenip, ":") != NULL) {
914 ws_in6_addr addr6;
915 if (ws_inet_pton6(agent_listenip, &addr6)) {
916 proto_tree_add_ipv6(zabbix_tree, hf_zabbix_agent_listenipv6, NULL, 0, 0, &addr6);
919 else {
920 ws_in4_addr addr4;
921 if (ws_inet_pton4(agent_listenip, &addr4)) {
922 proto_tree_add_ipv4(zabbix_tree, hf_zabbix_agent_listenipv4, NULL, 0, 0, addr4);
926 if (agent_listenport) {
927 proto_tree_add_uint(zabbix_tree, hf_zabbix_agent_listenport, NULL, 0, 0, agent_listenport);
929 if (commands_array) {
930 proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_commands, NULL, 0, 0, true);
932 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_METRICS)) {
933 proto_tree_add_boolean(zabbix_tree, hf_zabbix_metrics, NULL, 0, 0, true);
936 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY)) {
937 if (proxy_name) {
938 temp_ti = proto_tree_add_string(zabbix_tree, hf_zabbix_proxy_name, NULL, 0, 0, proxy_name);
939 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE)) {
940 /* proxy_name was populated from the conversation */
941 proto_item_set_generated(temp_ti);
942 proto_item_append_text(temp_ti, " (from the request)");
945 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_DATA)) {
946 proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_data, NULL, 0, 0, true);
948 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_CONFIG)) {
949 proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_config, NULL, 0, 0, true);
950 if (oper_response & ZABBIX_RESPONSE_FULLSYNC) {
951 proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_fullsync, NULL, 0, 0, true);
953 else if (oper_response & ZABBIX_RESPONSE_INCREMENTAL) {
954 proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_incr_config, NULL, 0, 0, true);
956 else if (oper_response & ZABBIX_RESPONSE_NOCHANGE) {
957 proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_no_config_change, NULL, 0, 0, true);
960 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_TASKS)) {
961 proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_tasks, NULL, 0, 0, true);
963 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_HEARTBEAT)) {
964 proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_hb, NULL, 0, 0, true);
967 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND)) {
968 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SYSINFO)) {
969 proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_sysinfo, NULL, 0, 0, true);
971 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_QUEUEINFO)) {
972 proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_queueinfo, NULL, 0, 0, true);
974 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_HISTORYPUSH)) {
975 proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_historypush, NULL, 0, 0, true);
977 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_ITEMTEST)) {
978 proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_itemtest, NULL, 0, 0, true);
980 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_MEDIATEST)) {
981 proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_mediatest, NULL, 0, 0, true);
983 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_REPORTTEST)) {
984 proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_reporttest, NULL, 0, 0, true);
986 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_EXPRESSIONEVAL)) {
987 proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_expressioneval, NULL, 0, 0, true);
989 else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SCRIPTEXEC)) {
990 proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_scriptexec, NULL, 0, 0, true);
993 else if (sender_name) {
994 temp_ti = proto_tree_add_string(zabbix_tree, hf_zabbix_sender_name, NULL, 0, 0, sender_name);
995 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE)) {
996 /* sender_name was populated from the conversation */
997 proto_item_set_generated(temp_ti);
998 proto_item_append_text(temp_ti, " (from the request)");
1001 if (version) {
1002 proto_tree_add_string(zabbix_tree, hf_zabbix_version, NULL, 0, 0, version);
1004 if (config_revision > -1) {
1005 proto_tree_add_int64(zabbix_tree, hf_zabbix_config_revision, NULL, 0, 0, config_revision);
1007 if (hostmap_revision > -1) {
1008 proto_tree_add_int64(zabbix_tree, hf_zabbix_hostmap_revision, NULL, 0, 0, hostmap_revision);
1010 if (session) {
1011 proto_tree_add_string(zabbix_tree, hf_zabbix_session, NULL, 0, 0, session);
1013 /* Show also the full JSON, or pre-7.0 passive agent request/response (or error message).
1014 * Note that ZABBIX_ZBX_NOTSUPPORTED does not include the \0 that is in the
1015 * protocol specification! Therefore +1/-1's are present
1017 if (passive_agent_data_str &&
1018 strlen(passive_agent_data_str) >= strlen(ZABBIX_ZBX_NOTSUPPORTED) &&
1019 strncmp(passive_agent_data_str, ZABBIX_ZBX_NOTSUPPORTED, strlen(ZABBIX_ZBX_NOTSUPPORTED)) == 0) {
1020 /* Pre-7.0 passive agent error, first ZBX_NOTSUPPORTED\0 and then the error message */
1021 proto_tree_add_item(zabbix_tree, hf_zabbix_data,
1022 next_tvb, 0, (int)strlen(ZABBIX_ZBX_NOTSUPPORTED)+1, ENC_UTF_8);
1023 proto_tree_add_item(zabbix_tree, hf_zabbix_error,
1024 next_tvb, (int)strlen(ZABBIX_ZBX_NOTSUPPORTED)+1, (int)datalen-(int)strlen(ZABBIX_ZBX_NOTSUPPORTED)-1, ENC_UTF_8);
1025 } else {
1026 /* JSON or pre-7.0 passive agent without error */
1027 proto_tree_add_item(zabbix_tree, hf_zabbix_data, next_tvb, 0, (int)datalen, ENC_UTF_8);
1030 final_outputs:
1032 /* These are common for all cases, too large or not */
1034 /* Check the ZABBIX_T_REQUEST flag (and not CONV_IS_ZABBIX_REQUEST macro) because
1035 * heartbeats are not marked as requests */
1036 if (IS_ZABBIX_T_FLAGS(ZABBIX_T_REQUEST)) {
1037 temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_request, NULL, 0, 0, true);
1038 proto_item_set_text(temp_ti, "This is Zabbix request");
1039 } else if (CONV_IS_ZABBIX_RESPONSE(zabbix_info, pinfo)) {
1040 temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_response, NULL, 0, 0, true);
1041 proto_item_set_text(temp_ti, "This is Zabbix response");
1042 if (!nstime_is_unset(&zabbix_info->req_timestamp)) {
1043 nstime_t delta;
1044 nstime_delta(&delta, &pinfo->abs_ts, &zabbix_info->req_timestamp);
1045 pi = proto_tree_add_time(zabbix_tree, hf_zabbix_time, next_tvb, 0, 0, &delta);
1046 proto_item_set_generated(pi);
1050 /* Add length to the Zabbix tree text */
1051 proto_item_append_text(ti, ", Len=%u", (unsigned)length);
1052 /* Add/set Info column texts */
1053 const char *info_text = col_get_text(pinfo->cinfo, COL_INFO);
1054 if (!info_text || !strlen(info_text)) {
1055 /* Info column is still empty, set the default text */
1056 if (CONV_IS_ZABBIX_REQUEST(zabbix_info, pinfo)) {
1057 col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Protocol request, Flags=0x%02x", flags);
1058 } else if (CONV_IS_ZABBIX_RESPONSE(zabbix_info, pinfo)) {
1059 col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Protocol response, Flags=0x%02x", flags);
1060 } else {
1061 col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Protocol, Flags=0x%02x", flags);
1064 col_append_fstr(pinfo->cinfo, COL_INFO, ", Len=%u (", (unsigned)length);
1065 col_append_ports(pinfo->cinfo, COL_INFO, PT_TCP, pinfo->srcport, pinfo->destport);
1066 col_append_str(pinfo->cinfo, COL_INFO, ")");
1068 return tvb_reported_length(tvb);
1071 /* Determine PDU length of Zabbix protocol */
1072 static unsigned
1073 get_zabbix_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1075 uint8_t flags;
1076 uint64_t length;
1078 flags = tvb_get_uint8(tvb, offset+4);
1079 if (flags & ZABBIX_FLAG_LARGEPACKET) {
1080 /* 8-byte length field
1081 * Note that ZABBIX_HDR_MIN_LEN check (in dissect_zabbix()) is still enough
1082 * due to the header structure (there are reserved bytes)
1084 length = tvb_get_uint64(tvb, offset+5, ENC_LITTLE_ENDIAN) + ZABBIX_HDR_MAX_LEN;
1085 } else {
1086 /* 4-byte length */
1087 length = tvb_get_uint32(tvb, offset+5, ENC_LITTLE_ENDIAN) + ZABBIX_HDR_MIN_LEN;
1089 return (unsigned)length;
1092 /* The main dissecting routine */
1093 static int
1094 dissect_zabbix(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1096 uint8_t flags;
1098 if (tvb_captured_length(tvb) < ZABBIX_HDR_MIN_LEN) {
1099 /* Not enough data */
1100 return 0;
1102 if (tvb_memeql(tvb, 0, ZABBIX_HDR_SIGNATURE, 4)) {
1103 /* Encrypted or not Zabbix at all */
1104 return 0;
1106 flags = tvb_get_uint8(tvb, 4);
1107 if (!(flags & ZABBIX_FLAG_ZABBIX_COMMUNICATIONS)) {
1108 return 0;
1110 /* This is unencrypted Zabbix protocol, continue with dissecting it */
1111 tcp_dissect_pdus(tvb, pinfo, tree, zabbix_desegment, ZABBIX_HDR_MIN_LEN,
1112 get_zabbix_pdu_len, dissect_zabbix_pdu, data);
1113 return tvb_reported_length(tvb);
1116 /* Register the protocol with Wireshark */
1118 void
1119 proto_register_zabbix(void)
1121 static hf_register_info hf[] = {
1122 { &hf_zabbix_header,
1123 { "Header", "zabbix.header",
1124 FT_STRING, BASE_NONE, NULL, 0,
1125 NULL, HFILL }
1127 { &hf_zabbix_flags,
1128 { "Flags", "zabbix.flags",
1129 FT_UINT8, BASE_HEX, NULL, 0,
1130 NULL, HFILL }
1132 { &hf_zabbix_flag_zabbix_communications,
1133 { "Zabbix communications protocol", "zabbix.flags.zabbix",
1134 FT_BOOLEAN, 8, TFS(&tfs_yes_no), ZABBIX_FLAG_ZABBIX_COMMUNICATIONS,
1135 NULL, HFILL }
1137 { &hf_zabbix_flag_compressed,
1138 { "Compressed", "zabbix.flags.compressed",
1139 FT_BOOLEAN, 8, TFS(&tfs_yes_no), ZABBIX_FLAG_COMPRESSED,
1140 NULL, HFILL }
1142 { &hf_zabbix_flag_largepacket,
1143 { "Large packet", "zabbix.flags.large_packet",
1144 FT_BOOLEAN, 8, TFS(&tfs_yes_no), ZABBIX_FLAG_LARGEPACKET,
1145 NULL, HFILL }
1147 { &hf_zabbix_flag_reserved,
1148 { "Reserved bits", "zabbix.flags.reserved",
1149 FT_UINT8, BASE_DEC, NULL, ZABBIX_FLAG_RESERVED,
1150 NULL, HFILL }
1152 { &hf_zabbix_length,
1153 { "Length", "zabbix.len",
1154 FT_UINT32, BASE_DEC, NULL, 0,
1155 NULL, HFILL }
1157 { &hf_zabbix_reserved,
1158 { "Reserved", "zabbix.reserved",
1159 FT_UINT32, BASE_DEC, NULL, 0,
1160 NULL, HFILL }
1162 { &hf_zabbix_uncompressed_length,
1163 { "Uncompressed length", "zabbix.uncompressed_len",
1164 FT_UINT32, BASE_DEC, NULL, 0,
1165 NULL, HFILL }
1167 { &hf_zabbix_large_length,
1168 { "Large length", "zabbix.large.len",
1169 FT_UINT64, BASE_DEC, NULL, 0,
1170 NULL, HFILL }
1172 { &hf_zabbix_large_reserved,
1173 { "Large reserved", "zabbix.large.reserved",
1174 FT_UINT64, BASE_DEC, NULL, 0,
1175 NULL, HFILL }
1177 { &hf_zabbix_large_uncompressed_length,
1178 { "Large uncompressed length", "zabbix.large.uncompressed_len",
1179 FT_UINT64, BASE_DEC, NULL, 0,
1180 NULL, HFILL }
1182 { &hf_zabbix_data,
1183 { "Data", "zabbix.data",
1184 FT_STRING, BASE_NONE, NULL, 0,
1185 NULL, HFILL }
1187 { &hf_zabbix_error,
1188 { "Error message", "zabbix.error",
1189 FT_STRING, BASE_NONE, NULL, 0,
1190 NULL, HFILL }
1192 { &hf_zabbix_time,
1193 { "Response time", "zabbix.time",
1194 FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
1195 NULL, HFILL }
1197 { &hf_zabbix_request,
1198 { "Zabbix protocol request", "zabbix.request",
1199 FT_BOOLEAN, BASE_NONE, NULL, 0,
1200 NULL, HFILL }
1202 { &hf_zabbix_response,
1203 { "Zabbix protocol response", "zabbix.response",
1204 FT_BOOLEAN, BASE_NONE, NULL, 0,
1205 NULL, HFILL }
1207 { &hf_zabbix_success,
1208 { "Success", "zabbix.success",
1209 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1210 NULL, HFILL }
1212 { &hf_zabbix_failed,
1213 { "Failed", "zabbix.failed",
1214 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1215 NULL, HFILL }
1217 { &hf_zabbix_agent,
1218 { "Zabbix agent connection", "zabbix.agent",
1219 FT_BOOLEAN, BASE_NONE, NULL, 0,
1220 NULL, HFILL }
1222 { &hf_zabbix_agent_commands,
1223 { "Zabbix agent commands", "zabbix.agent.commands",
1224 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1225 NULL, HFILL }
1227 { &hf_zabbix_agent_config,
1228 { "Zabbix agent config", "zabbix.agent.config",
1229 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1230 NULL, HFILL }
1232 { &hf_zabbix_agent_data,
1233 { "Zabbix agent data", "zabbix.agent.data",
1234 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1235 NULL, HFILL }
1237 { &hf_zabbix_agent_redirection,
1238 { "Agent redirection", "zabbix.agent.redirection",
1239 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1240 NULL, HFILL }
1242 { &hf_zabbix_agent_passive,
1243 { "Passive agent", "zabbix.agent.passive",
1244 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1245 NULL, HFILL }
1247 { &hf_zabbix_agent_name,
1248 { "Agent name", "zabbix.agent.name",
1249 FT_STRING, BASE_NONE, NULL, 0,
1250 NULL, HFILL }
1252 { &hf_zabbix_agent_hb,
1253 { "Agent heartbeat", "zabbix.agent.heartbeat",
1254 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1255 NULL, HFILL }
1257 { &hf_zabbix_agent_hb_freq,
1258 { "Agent heartbeat frequency", "zabbix.agent.heartbeat_freq",
1259 FT_INT32, BASE_DEC, NULL, 0,
1260 NULL, HFILL }
1262 { &hf_zabbix_agent_hostmetadata,
1263 { "Agent host metadata", "zabbix.agent.host_metadata",
1264 FT_STRING, BASE_NONE, NULL, 0,
1265 NULL, HFILL }
1267 { &hf_zabbix_agent_hostinterface,
1268 { "Agent host interface", "zabbix.agent.host_interface",
1269 FT_STRING, BASE_NONE, NULL, 0,
1270 NULL, HFILL }
1272 { &hf_zabbix_agent_listenipv4,
1273 { "Agent listen IPv4", "zabbix.agent.listen_ipv4",
1274 FT_IPv4, BASE_NONE, NULL, 0,
1275 NULL, HFILL }
1277 { &hf_zabbix_agent_listenipv6,
1278 { "Agent listen IPv6", "zabbix.agent.listen_ipv6",
1279 FT_IPv6, BASE_NONE, NULL, 0,
1280 NULL, HFILL }
1282 { &hf_zabbix_agent_listenport,
1283 { "Agent listen port", "zabbix.agent.listen_port",
1284 FT_UINT16, BASE_DEC, NULL, 0,
1285 NULL, HFILL }
1287 { &hf_zabbix_agent_variant,
1288 { "Agent variant", "zabbix.agent.variant",
1289 FT_INT64, BASE_DEC, NULL, 0,
1290 NULL, HFILL }
1292 { &hf_zabbix_proxy,
1293 { "Proxy connection", "zabbix.proxy",
1294 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1295 NULL, HFILL }
1297 { &hf_zabbix_proxy_name,
1298 { "Proxy name", "zabbix.proxy.name",
1299 FT_STRING, BASE_NONE, NULL, 0,
1300 NULL, HFILL }
1302 { &hf_zabbix_proxy_hb,
1303 { "Proxy heartbeat", "zabbix.proxy.heartbeat",
1304 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1305 NULL, HFILL }
1307 { &hf_zabbix_proxy_data,
1308 { "Proxy data", "zabbix.proxy.data",
1309 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1310 NULL, HFILL }
1312 { &hf_zabbix_proxy_config,
1313 { "Proxy config", "zabbix.proxy.config",
1314 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1315 NULL, HFILL }
1317 { &hf_zabbix_proxy_fullsync,
1318 { "Proxy config full sync", "zabbix.proxy.full_sync",
1319 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1320 NULL, HFILL }
1322 { &hf_zabbix_proxy_incr_config,
1323 { "Proxy incremental config", "zabbix.proxy.incremental_config",
1324 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1325 NULL, HFILL }
1327 { &hf_zabbix_proxy_no_config_change,
1328 { "Proxy no config changes", "zabbix.proxy.no_config_changes",
1329 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1330 NULL, HFILL }
1332 { &hf_zabbix_proxy_tasks,
1333 { "Proxy tasks", "zabbix.proxy.tasks",
1334 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1335 NULL, HFILL }
1337 { &hf_zabbix_sender,
1338 { "Sender connection", "zabbix.sender",
1339 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1340 NULL, HFILL }
1342 { &hf_zabbix_sender_name,
1343 { "Sender name", "zabbix.sender.name",
1344 FT_STRING, BASE_NONE, NULL, 0,
1345 NULL, HFILL }
1347 { &hf_zabbix_version,
1348 { "Version", "zabbix.version",
1349 FT_STRING, BASE_NONE, NULL, 0,
1350 NULL, HFILL }
1352 { &hf_zabbix_session,
1353 { "Session", "zabbix.session",
1354 FT_STRING, BASE_NONE, NULL, 0,
1355 NULL, HFILL }
1357 { &hf_zabbix_config_revision,
1358 { "Config revision", "zabbix.config_revision",
1359 FT_INT64, BASE_DEC, NULL, 0,
1360 NULL, HFILL }
1362 { &hf_zabbix_hostmap_revision,
1363 { "Hostmap revision", "zabbix.hostmap_revision",
1364 FT_INT64, BASE_DEC, NULL, 0,
1365 NULL, HFILL }
1367 { &hf_zabbix_metrics,
1368 { "Server/proxy internal metrics", "zabbix.stats",
1369 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1370 NULL, HFILL }
1372 { &hf_zabbix_frontend,
1373 { "Zabbix frontend", "zabbix.frontend",
1374 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1375 NULL, HFILL }
1377 { &hf_zabbix_frontend_sysinfo,
1378 { "System information", "zabbix.frontend.sysinfo",
1379 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1380 NULL, HFILL }
1382 { &hf_zabbix_frontend_queueinfo,
1383 { "Queue information", "zabbix.frontend.queueinfo",
1384 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1385 NULL, HFILL }
1387 { &hf_zabbix_frontend_historypush,
1388 { "History push", "zabbix.frontend.historypush",
1389 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1390 NULL, HFILL }
1392 { &hf_zabbix_frontend_itemtest,
1393 { "Item test", "zabbix.frontend.itemtest",
1394 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1395 NULL, HFILL }
1397 { &hf_zabbix_frontend_mediatest,
1398 { "Media test", "zabbix.frontend.mediatest",
1399 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1400 NULL, HFILL }
1402 { &hf_zabbix_frontend_reporttest,
1403 { "Report test", "zabbix.frontend.reporttest",
1404 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1405 NULL, HFILL }
1407 { &hf_zabbix_frontend_expressioneval,
1408 { "Expression evaluation", "zabbix.frontend.expressioneval",
1409 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1410 NULL, HFILL }
1412 { &hf_zabbix_frontend_scriptexec,
1413 { "Script execution", "zabbix.frontend.scriptexec",
1414 FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1415 NULL, HFILL }
1419 static ei_register_info ei[] = {
1421 &ei_zabbix_packet_too_large,
1422 { "zabbix.packet_too_large", PI_UNDECODED, PI_WARN,
1423 "Packet is too large for detailed dissection", EXPFILL }
1426 &ei_zabbix_json_error,
1427 { "zabbix.json_error", PI_PROTOCOL, PI_ERROR,
1428 "Cannot parse JSON", EXPFILL }
1432 /* Setup protocol subtree array */
1433 static int *ett[] = {
1434 &ett_zabbix,
1435 &ett_zabbix_flags,
1438 module_t *zabbix_module;
1439 expert_module_t *expert_zabbix;
1441 /* Register the protocol name and description */
1442 proto_zabbix = proto_register_protocol("Zabbix Protocol", "Zabbix", "zabbix");
1444 /* Required function calls to register the header fields and subtrees used */
1445 proto_register_field_array(proto_zabbix, hf, array_length(hf));
1446 proto_register_subtree_array(ett, array_length(ett));
1448 zabbix_module = prefs_register_protocol(proto_zabbix, NULL);
1450 prefs_register_bool_preference(zabbix_module, "desegment",
1451 "Reassemble Zabbix messages spanning multiple TCP segments",
1452 "Whether the Zabbix protocol dissector should reassemble messages spanning multiple TCP segments."
1453 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1454 &zabbix_desegment);
1456 zabbix_handle = register_dissector("zabbix", dissect_zabbix, proto_zabbix);
1458 expert_zabbix = expert_register_protocol(proto_zabbix);
1459 expert_register_field_array(expert_zabbix, ei, array_length(ei));
1462 void
1463 proto_reg_handoff_zabbix(void)
1465 dissector_add_uint_range_with_preference("tcp.port", ZABBIX_TCP_PORTS, zabbix_handle);
1466 zabbix_port_range = prefs_get_range_value("Zabbix", "tcp.port");
1467 dissector_add_uint_range("tls.port", zabbix_port_range, zabbix_handle);