Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-zabbix.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-zabbix.c
2
 * Routines for Zabbix protocol dissection
3
 * Copyright 2023, Markku Leiniƶ <markku.leinio@gmail.com>
4
 *
5
 * Wireshark - Network traffic analyzer
6
 * By Gerald Combs <gerald@wireshark.org>
7
 * Copyright 1998 Gerald Combs
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
/*
13
 * Zabbix protocol specifications can be found in Zabbix documentation:
14
 * https://www.zabbix.com/documentation/current/en/manual/appendix/protocols
15
 */
16
17
#include "config.h"
18
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"
29
30
void proto_register_zabbix(void);
31
void proto_reg_handoff_zabbix(void);
32
33
static dissector_handle_t zabbix_handle;
34
35
/* Desegmentation of Zabbix protocol over TCP */
36
static bool zabbix_desegment = true;
37
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;
99
100
/* Subtree pointers */
101
static int ett_zabbix;
102
static int ett_zabbix_flags;
103
104
/* Expert fields */
105
static expert_field ei_zabbix_packet_too_large;
106
static expert_field ei_zabbix_json_error;
107
108
/* Other dissector-specifics */
109
static range_t *zabbix_port_range;
110
111
static const char ZABBIX_HDR_SIGNATURE[] = "ZBXD";
112
static const char ZABBIX_UNKNOWN[] = "<unknown>";
113
static const char ZABBIX_ZBX_NOTSUPPORTED[] = "ZBX_NOTSUPPORTED";
114
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;
121
122
6
#define ZABBIX_HDR_MIN_LEN          13              /* When not large packet */
123
0
#define ZABBIX_HDR_MAX_LEN          21              /* When large packet */
124
0
#define ZABBIX_MAX_LENGTH_ALLOWED   1024*1024*1024  /* 1 GB */
125
14
#define ZABBIX_TCP_PORTS            "10050,10051"   /* IANA registered ports */
126
127
14
#define ZABBIX_FLAG_ZABBIX_COMMUNICATIONS   0x01
128
14
#define ZABBIX_FLAG_COMPRESSED              0x02
129
14
#define ZABBIX_FLAG_LARGEPACKET             0x04
130
14
#define ZABBIX_FLAG_RESERVED                0xf8
131
132
/* Response flags are not saved in the conversations */
133
0
#define ZABBIX_RESPONSE_SUCCESS     0x01
134
0
#define ZABBIX_RESPONSE_FAILED      0x02
135
0
#define ZABBIX_RESPONSE_FULLSYNC    0x04
136
0
#define ZABBIX_RESPONSE_INCREMENTAL 0x08
137
0
#define ZABBIX_RESPONSE_NOCHANGE    0x10
138
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
163
164
0
#define ADD_ZABBIX_T_FLAGS(flags)       (zabbix_info->oper_flags |= (flags))
165
0
#define CLEAR_ZABBIX_T_FLAGS(flags)     (zabbix_info->oper_flags &= (0xffffffff-(flags)))
166
0
#define IS_ZABBIX_T_FLAGS(flags)        ((zabbix_info->oper_flags & (flags)) == (flags))
167
168
0
#define CONV_IS_ZABBIX_REQUEST(zabbix_info,pinfo)           ((zabbix_info)->req_framenum == (pinfo)->fd->num)
169
0
#define CONV_IS_ZABBIX_RESPONSE(zabbix_info,pinfo)          ((zabbix_info)->req_framenum != (pinfo)->fd->num)
170
171
0
#define ZABBIX_NAME_OR_UNKNOWN(name)       ((name) ? (name) : ZABBIX_UNKNOWN)
172
173
174
static zabbix_conv_info_t*
175
zabbix_find_conversation_and_get_conv_data(packet_info *pinfo)
176
0
{
177
0
    conversation_t *conversation;
178
0
    zabbix_conv_info_t *zabbix_info = NULL;
179
180
0
    conversation = find_conversation_pinfo(pinfo, 0);
181
0
    if (conversation) {
182
0
        zabbix_info = (zabbix_conv_info_t *)conversation_get_proto_data(conversation, proto_zabbix);
183
0
    } else {
184
0
        conversation = conversation_new(pinfo->num, &pinfo->src, &pinfo->dst,
185
0
            conversation_pt_to_conversation_type(pinfo->ptype),
186
0
            pinfo->srcport, pinfo->destport, 0);
187
0
    }
188
0
    if (!zabbix_info) {
189
        /* New conversation, or there was no Zabbix data yet in the existing conv */
190
0
        zabbix_info = wmem_alloc(wmem_file_scope(), sizeof(zabbix_conv_info_t));
191
0
        if (value_is_in_range(zabbix_port_range, pinfo->destport)) {
192
            /* Let's assume this is the first Zabbix packet (request) */
193
0
            zabbix_info->req_framenum = pinfo->fd->num;
194
0
            zabbix_info->req_timestamp = pinfo->abs_ts;
195
0
        }
196
0
        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
199
             */
200
0
            zabbix_info->req_framenum = 0;
201
0
            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;
204
            */
205
0
        }
206
0
        zabbix_info->oper_flags = 0;
207
0
        zabbix_info->host_name = NULL;
208
0
        conversation_add_proto_data(conversation, proto_zabbix, (void *)zabbix_info);
209
0
    }
210
0
    return zabbix_info;
211
0
}
212
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)
216
0
{
217
0
    if (length > ZABBIX_MAX_LENGTH_ALLOWED) {
218
0
        expert_add_info(pinfo, tree_item, &ei_zabbix_packet_too_large);
219
0
        *is_too_large = true;
220
0
    }
221
0
    return;
222
0
}
223
224
static int
225
dissect_zabbix_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
226
0
{
227
0
    int offset = 0;
228
0
    int agent_hb_freq = 0;
229
0
    unsigned oper_response = 0;
230
0
    proto_item *ti;
231
0
    proto_item *pi;
232
0
    proto_tree *temp_ti;
233
0
    proto_tree *zabbix_tree = NULL;
234
0
    uint8_t flags;
235
0
    uint16_t agent_listenport = 0;
236
0
    uint64_t length;
237
0
    uint64_t uncompressed_length;
238
0
    uint64_t datalen;
239
0
    int64_t agent_variant = 0;
240
0
    int64_t config_revision = -1;
241
0
    int64_t hostmap_revision = -1;
242
0
    bool is_compressed;
243
0
    bool is_large_packet;
244
0
    bool is_too_large = false;
245
0
    bool is_redirection = false;
246
0
    char *json_str;
247
0
    char *passive_agent_data_str = NULL;
248
0
    jsmntok_t *commands_array = NULL;
249
0
    jsmntok_t *data_array = NULL;
250
0
    jsmntok_t *data_object = NULL;
251
0
    const char *agent_name = NULL;
252
0
    const char *agent_hostmetadata = NULL;
253
0
    const char *agent_hostinterface = NULL;
254
0
    const char *agent_listenip = NULL;
255
0
    const char *proxy_name = NULL;
256
0
    const char *sender_name = NULL;
257
0
    const char *session = NULL;
258
0
    const char *request_type = NULL;
259
0
    const char *response_status = NULL;
260
0
    const char *version = NULL;
261
0
    double temp_double;
262
0
    tvbuff_t *next_tvb;
263
0
    zabbix_conv_info_t *zabbix_info;
264
0
    static int* const flagbits[] = {
265
0
        &hf_zabbix_flag_reserved,
266
0
        &hf_zabbix_flag_largepacket,
267
0
        &hf_zabbix_flag_compressed,
268
0
        &hf_zabbix_flag_zabbix_communications,
269
0
        NULL
270
0
    };
271
272
    /* Make entries in Protocol column and Info column on summary display */
273
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Zabbix");
274
0
    col_clear(pinfo->cinfo, COL_INFO);
275
276
0
    if ((tvb_reported_length(tvb) < ZABBIX_HDR_MIN_LEN) ||
277
0
        (tvb_memeql(tvb, offset, ZABBIX_HDR_SIGNATURE, 4) == -1)) {
278
        /* Encrypted or not Zabbix at all */
279
0
        return 0;
280
0
    }
281
0
    flags = tvb_get_uint8(tvb, offset+4);
282
0
    if (!(flags & ZABBIX_FLAG_ZABBIX_COMMUNICATIONS)) {
283
0
        return 0;
284
0
    }
285
286
0
    zabbix_info = zabbix_find_conversation_and_get_conv_data(pinfo);
287
288
0
    is_compressed = (flags & ZABBIX_FLAG_COMPRESSED) > 0;
289
0
    is_large_packet = (flags & ZABBIX_FLAG_LARGEPACKET) > 0;
290
291
    /* create display subtree for the protocol */
292
0
    ti = proto_tree_add_item(tree, proto_zabbix, tvb, 0, -1, ENC_NA);
293
0
    zabbix_tree = proto_item_add_subtree(ti, ett_zabbix);
294
0
    proto_tree_add_item(zabbix_tree, hf_zabbix_header, tvb, offset, 4, ENC_UTF_8);
295
0
    offset += 4;
296
0
    proto_tree_add_bitmask(zabbix_tree, tvb, offset, hf_zabbix_flags, ett_zabbix_flags, flagbits, ENC_BIG_ENDIAN);
297
0
    offset += 1;
298
0
    if (is_large_packet) {
299
        /* 8-byte values */
300
0
        temp_ti = proto_tree_add_item_ret_uint64(zabbix_tree,
301
0
            hf_zabbix_large_length, tvb, offset, 8, ENC_LITTLE_ENDIAN, &length);
302
0
        zabbix_add_expert_info_if_too_large(pinfo, temp_ti, length, &is_too_large);
303
0
        offset += 8;
304
0
        if (is_compressed) {
305
0
            temp_ti = proto_tree_add_item_ret_uint64(zabbix_tree,
306
0
                hf_zabbix_large_uncompressed_length, tvb, offset, 8, ENC_LITTLE_ENDIAN, &uncompressed_length);
307
0
            zabbix_add_expert_info_if_too_large(pinfo, temp_ti, uncompressed_length, &is_too_large);
308
0
        } else {
309
0
            proto_tree_add_item(zabbix_tree, hf_zabbix_large_reserved, tvb, offset, 8, ENC_LITTLE_ENDIAN);
310
0
        }
311
0
        offset += 8;
312
0
    } else {
313
        /* 4-byte values */
314
0
        uint32_t temp_uint32;
315
0
        temp_ti = proto_tree_add_item_ret_uint(zabbix_tree,
316
0
            hf_zabbix_length, tvb, offset, 4, ENC_LITTLE_ENDIAN, &temp_uint32);
317
0
        length = (uint64_t)temp_uint32;
318
0
        zabbix_add_expert_info_if_too_large(pinfo, temp_ti, length, &is_too_large);
319
0
        offset += 4;
320
0
        if (is_compressed) {
321
0
            temp_ti = proto_tree_add_item_ret_uint(zabbix_tree,
322
0
                hf_zabbix_uncompressed_length, tvb, offset, 4, ENC_LITTLE_ENDIAN, &temp_uint32);
323
0
            uncompressed_length = (uint64_t)temp_uint32;
324
0
            zabbix_add_expert_info_if_too_large(pinfo, temp_ti, uncompressed_length, &is_too_large);
325
0
        } else {
326
0
            proto_tree_add_item(zabbix_tree, hf_zabbix_reserved, tvb, offset, 4, ENC_LITTLE_ENDIAN);
327
0
        }
328
0
        offset += 4;
329
0
    }
330
0
    if (is_too_large) {
331
        /* Set next_tvb for response time calculation to work later */
332
0
        next_tvb = tvb_new_subset_remaining(tvb, offset);
333
        /* ... but don't do any content-based inspection, just skip to the end */
334
0
        goto final_outputs;
335
0
    } else if (is_compressed) {
336
0
        next_tvb = tvb_uncompress_zlib(tvb, offset, tvb_reported_length_remaining(tvb, offset));
337
0
        if (next_tvb) {
338
0
            tvb_set_child_real_data_tvbuff(tvb, next_tvb);
339
0
            add_new_data_source(pinfo, next_tvb, "Uncompressed data");
340
0
            datalen = uncompressed_length;
341
0
        } else {
342
            /* Handle uncompressed */
343
0
            next_tvb = tvb_new_subset_remaining(tvb, offset);
344
0
            datalen = length;
345
0
        }
346
0
    } else {
347
0
        next_tvb = tvb_new_subset_remaining(tvb, offset);
348
0
        datalen = length;
349
0
    }
350
351
    /* Use only next_tvb and datalen for data extraction from here on! */
352
0
    offset = 0;
353
354
    /* Rewrite the default texts in the protocol tree and initialize request/response flags */
355
0
    if (CONV_IS_ZABBIX_REQUEST(zabbix_info, pinfo)) {
356
0
        proto_item_set_text(ti, "Zabbix Protocol request");
357
0
        ADD_ZABBIX_T_FLAGS(ZABBIX_T_REQUEST);
358
0
        CLEAR_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE);
359
0
    }
360
0
    else if (CONV_IS_ZABBIX_RESPONSE(zabbix_info, pinfo)) {
361
0
        proto_item_set_text(ti, "Zabbix Protocol response");
362
0
        ADD_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE);
363
0
        CLEAR_ZABBIX_T_FLAGS(ZABBIX_T_REQUEST);
364
0
    }
365
366
    /*
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)
369
     */
370
0
    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!
374
     */
375
0
    int token_count = json_parse(json_str, NULL, 0);
376
0
    if (
377
0
        token_count < 0 ||
378
0
        (
379
0
            CONV_IS_ZABBIX_RESPONSE(zabbix_info, pinfo) &&
380
0
            IS_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_PASSIVE | ZABBIX_T_LEGACY)
381
0
        )
382
0
    ) {
383
        /* The only non-JSON Zabbix request/response is passive agent before Zabbix 7.0,
384
         * ensure the conversation data is set, then set the texts
385
         */
386
0
        ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_PASSIVE | ZABBIX_T_LEGACY);
387
0
        if (CONV_IS_ZABBIX_REQUEST(zabbix_info, pinfo)) {
388
0
            proto_item_set_text(ti, "Zabbix Server/proxy request for passive agent checks");
389
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Server/proxy request for passive agent checks");
390
0
        } else if (CONV_IS_ZABBIX_RESPONSE(zabbix_info, pinfo)) {
391
0
            proto_item_set_text(ti, "Zabbix Agent response for passive checks");
392
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Agent response for passive checks");
393
0
        }
394
        /* Make a copy of the data string for later error message lookup use */
395
0
        passive_agent_data_str = wmem_strndup(pinfo->pool, json_str, (size_t)datalen);
396
        /* Don't do content-based searches for pre-7.0 passive agents */
397
0
        goto show_agent_outputs;
398
0
    }
399
0
    jsmntok_t *tokens = wmem_alloc_array(pinfo->pool, jsmntok_t, token_count);
400
0
    int ret = json_parse(json_str, tokens, token_count);
401
0
    if (ret <= 0) {
402
0
        temp_ti = proto_tree_add_item(zabbix_tree, hf_zabbix_data, next_tvb, 0, (int)datalen, ENC_UTF_8);
403
0
        expert_add_info_format(pinfo, temp_ti, &ei_zabbix_json_error, "Error parsing JSON tokens");
404
0
        goto final_outputs;
405
0
    }
406
407
    /*
408
     * Now we have JSON tokens analyzed, let's do all the logic to populate the fields.
409
     * Also set Zabbix tree item and Info column texts, Len= and ports will be added later below.
410
     */
411
412
    /* First populate common fields */
413
0
    version = json_get_string(json_str, tokens, "version");
414
0
    if (json_get_double(json_str, tokens, "variant", &temp_double)) {
415
0
        agent_variant = (int64_t)temp_double;
416
0
    }
417
0
    session = json_get_string(json_str, tokens, "session");
418
0
    if (json_get_double(json_str, tokens, "config_revision", &temp_double)) {
419
0
        config_revision = (int64_t)temp_double;
420
0
    }
421
0
    if (json_get_double(json_str, tokens, "hostmap_revision", &temp_double)) {
422
0
        hostmap_revision = (int64_t)temp_double;
423
0
    } else {
424
0
        jsmntok_t *proxy_group_object = json_get_object(json_str, tokens, "proxy_group");
425
0
        if (proxy_group_object) {
426
0
            if (json_get_double(json_str, proxy_group_object, "hostmap_revision", &temp_double)) {
427
0
                hostmap_revision = (int64_t)temp_double;
428
0
            }
429
0
        }
430
0
    }
431
0
    request_type = json_get_string(json_str, tokens, "request");
432
0
    response_status = json_get_string(json_str, tokens, "response");
433
0
    commands_array = json_get_array(json_str, tokens, "commands");
434
0
    data_array = json_get_array(json_str, tokens, "data");
435
0
    data_object = json_get_object(json_str, tokens, "data");
436
    /* Find the packet type primarily based on "request" field */
437
0
    if (request_type) {
438
0
        if (strcmp(request_type, "active checks") == 0) {
439
            /* Active agent requesting configs */
440
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_CONFIG | ZABBIX_T_ACTIVE);
441
0
            agent_name = json_get_string(json_str, tokens, "host");
442
0
            if (agent_name && !PINFO_FD_VISITED(pinfo)) {
443
0
                zabbix_info->host_name = wmem_strdup(wmem_file_scope(), agent_name);
444
0
            }
445
0
            proto_item_set_text(ti,
446
0
                "Zabbix Agent request for active checks for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
447
0
            col_add_fstr(pinfo->cinfo, COL_INFO,
448
0
                "Zabbix Agent request for active checks for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
449
0
            agent_hostmetadata = json_get_string(json_str, tokens, "host_metadata");
450
0
            agent_hostinterface = json_get_string(json_str, tokens, "interface");
451
0
            agent_listenip = json_get_string(json_str, tokens, "ip");
452
0
            if (json_get_double(json_str, tokens, "port", &temp_double)) {
453
0
                agent_listenport = (uint16_t)temp_double;
454
0
            }
455
0
        }
456
0
        else if (strcmp(request_type, "agent data") == 0) {
457
            /* Active agent sending data */
458
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_DATA | ZABBIX_T_ACTIVE);
459
            /* Zabbix Agent 2 has Host in the top level */
460
0
            agent_name = json_get_string(json_str, tokens, "host");
461
0
            if (!agent_name) {
462
                /* For Zabbix Agent try parsing agent name inside data array */
463
0
                jsmntok_t *tok = json_get_array(json_str, tokens, "data");
464
0
                if (tok && json_get_array_len(tok) > 0) {
465
0
                    jsmntok_t *datatok = json_get_array_index(tok, 0);
466
0
                    agent_name = json_get_string(json_str, datatok, "host");
467
0
                }
468
0
            }
469
0
            if (agent_name && !PINFO_FD_VISITED(pinfo)) {
470
0
                zabbix_info->host_name = wmem_strdup(wmem_file_scope(), agent_name);
471
0
            }
472
0
            proto_item_set_text(ti,
473
0
                "Zabbix Agent data from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
474
0
            col_add_fstr(pinfo->cinfo, COL_INFO,
475
0
                "Zabbix Agent data from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
476
0
        }
477
0
        else if (strcmp(request_type, "active check heartbeat") == 0) {
478
            /* Active agent sending heartbeat */
479
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_HEARTBEAT | ZABBIX_T_ACTIVE);
480
0
            agent_name = json_get_string(json_str, tokens, "host");
481
0
            if (agent_name && !PINFO_FD_VISITED(pinfo)) {
482
0
                zabbix_info->host_name = wmem_strdup(wmem_file_scope(), agent_name);
483
0
            }
484
0
            if (json_get_double(json_str, tokens, "heartbeat_freq", &temp_double)) {
485
0
                agent_hb_freq = (int)temp_double;
486
0
            }
487
0
            proto_item_set_text(ti,
488
0
                "Zabbix Agent heartbeat from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
489
0
            col_add_fstr(pinfo->cinfo, COL_INFO,
490
0
                "Zabbix Agent heartbeat from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
491
0
        }
492
0
        else if (strcmp(request_type, "passive checks") == 0) {
493
            /* Passive agent checks since Zabbix 7.0 */
494
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_PASSIVE);
495
0
            proto_item_set_text(ti, "Zabbix Server/proxy request for passive agent checks");
496
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Server/proxy request for passive agent checks");
497
0
        }
498
0
        else if (strcmp(request_type, "zabbix.stats") == 0) {
499
            /* Agent requesting server/proxy internal metrics, since Zabbix 4.0.5 */
500
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_METRICS);
501
0
            proto_item_set_text(ti, "Zabbix Server/proxy internal metrics request");
502
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Server/proxy internal metrics request");
503
0
        }
504
0
        else if (strcmp(request_type, "sender data") == 0) {
505
            /* Sender/trapper */
506
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_SENDER);
507
            /* Try to get the sender name from the first data array item */
508
0
            jsmntok_t *tok = json_get_array(json_str, tokens, "data");
509
0
            if (tok && json_get_array_len(tok) > 0) {
510
0
                jsmntok_t *datatok = json_get_array_index(tok, 0);
511
0
                sender_name = json_get_string(json_str, datatok, "host");
512
0
                if (sender_name && !PINFO_FD_VISITED(pinfo)) {
513
0
                    zabbix_info->host_name = wmem_strdup(wmem_file_scope(), sender_name);
514
0
                }
515
0
            }
516
0
            proto_item_set_text(ti,
517
0
                "Zabbix Sender data from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(sender_name));
518
0
            col_add_fstr(pinfo->cinfo, COL_INFO,
519
0
                "Zabbix Sender data from \"%s\"", ZABBIX_NAME_OR_UNKNOWN(sender_name));
520
0
        }
521
0
        else if ((strcmp(request_type, "proxy data") == 0) ||
522
0
                (strcmp(request_type, "host availability") == 0) ||
523
0
                (strcmp(request_type, "history data") == 0) ||
524
0
                (strcmp(request_type, "discovery data") == 0) ||
525
0
                (strcmp(request_type, "auto registration") == 0)) {
526
            /* Either active or passive proxy; "proxy data" = Zabbix 3.4+,
527
             * others = Zabbix 3.2 or older */
528
0
            proxy_name = json_get_string(json_str, tokens, "host");
529
0
            if (token_count == 3) {     /* Only '{"request":"xxx"}' */
530
                /* This is Zabbix server connecting to passive proxy */
531
0
                ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_DATA | ZABBIX_T_PASSIVE);
532
0
                proto_item_set_text(ti, "Zabbix Proxy data request to passive proxy");
533
0
                col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Proxy data request to passive proxy");
534
0
            }
535
0
            else if (proxy_name) {
536
                /* This is an active proxy connecting to server */
537
0
                ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_DATA | ZABBIX_T_ACTIVE);
538
0
                if (proxy_name && !PINFO_FD_VISITED(pinfo)) {
539
0
                    zabbix_info->host_name = wmem_strdup(wmem_file_scope(), proxy_name);
540
0
                }
541
0
                proto_item_set_text(ti, "Zabbix Proxy data from \"%s\"", proxy_name);
542
0
                col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Proxy data from \"%s\"", proxy_name);
543
0
            }
544
0
        }
545
0
        else if (strcmp(request_type, "proxy config") == 0) {
546
            /* Either active or passive proxy */
547
0
            proxy_name = json_get_string(json_str, tokens, "host");
548
0
            if (token_count == 3) {     /* Only '{"request":"proxy config"}' */
549
                /* This is Zabbix 6.4+ server connecting to passive proxy */
550
0
                ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG | ZABBIX_T_PASSIVE);
551
0
                proto_item_set_text(ti, "Zabbix Proxy config request to passive proxy");
552
0
                col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Proxy config request to passive proxy");
553
0
            }
554
0
            else if (proxy_name) {
555
                /* This is an active proxy connecting to server */
556
0
                ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG | ZABBIX_T_ACTIVE);
557
0
                if (proxy_name && !PINFO_FD_VISITED(pinfo)) {
558
0
                    zabbix_info->host_name = wmem_strdup(wmem_file_scope(), proxy_name);
559
0
                }
560
0
                proto_item_set_text(ti, "Zabbix Request proxy config for \"%s\"", proxy_name);
561
0
                col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Request proxy config for \"%s\"", proxy_name);
562
0
            }
563
0
        }
564
0
        else if (strcmp(request_type, "proxy tasks") == 0) {
565
            /* Zabbix server connecting to passive proxy, only '{"request":"proxy tasks"}' */
566
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_TASKS | ZABBIX_T_PASSIVE);
567
0
            proto_item_set_text(ti, "Zabbix Proxy tasks request to passive proxy");
568
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Proxy tasks request to passive proxy");
569
0
        }
570
0
        else if (strcmp(request_type, "proxy heartbeat") == 0) {
571
            /* Heartbeat from active proxy, not used in Zabbix 6.4+ */
572
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_HEARTBEAT | ZABBIX_T_ACTIVE);
573
0
            proxy_name = json_get_string(json_str, tokens, "host");
574
0
            if (proxy_name && !PINFO_FD_VISITED(pinfo)) {
575
0
                zabbix_info->host_name = wmem_strdup(wmem_file_scope(), proxy_name);
576
0
            }
577
0
            proto_item_set_text(ti, "Zabbix Proxy heartbeat from \"%s\"", proxy_name);
578
0
            col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Proxy heartbeat from \"%s\"", proxy_name);
579
0
        }
580
        /* UI/API-specific requests */
581
0
        else if (strcmp(request_type, "status.get") == 0) {
582
            /* System information report */
583
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_SYSINFO);
584
0
            proto_item_set_text(ti, "Zabbix System information request");
585
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix System information request");
586
0
        }
587
0
        else if (strcmp(request_type, "queue.get") == 0) {
588
            /* Queue information request */
589
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_QUEUEINFO);
590
0
            proto_item_set_text(ti, "Zabbix Queue information request");
591
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Queue information request");
592
0
        }
593
0
        else if (strcmp(request_type, "history.push") == 0) {
594
            /* history.push API call, since Zabbix 7.0 */
595
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_HISTORYPUSH);
596
0
            proto_item_set_text(ti, "Zabbix History push request");
597
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix History push request");
598
0
        }
599
0
        else if (strcmp(request_type, "item.test") == 0) {
600
            /* Item test in the frontend */
601
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_ITEMTEST);
602
0
            proto_item_set_text(ti, "Zabbix Item test request");
603
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Item test request");
604
0
        }
605
0
        else if (strcmp(request_type, "alert.send") == 0) {
606
            /* Media test in the frontend */
607
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_MEDIATEST);
608
0
            proto_item_set_text(ti, "Zabbix Media test request");
609
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Media test request");
610
0
        }
611
0
        else if (strcmp(request_type, "report.test") == 0) {
612
            /* Report test in the frontend */
613
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_REPORTTEST);
614
0
            proto_item_set_text(ti, "Zabbix Report test request");
615
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Report test request");
616
0
        }
617
0
        else if (strcmp(request_type, "expressions.evaluate") == 0) {
618
            /* Trigger expression evaluation test in the frontend */
619
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_EXPRESSIONEVAL);
620
0
            proto_item_set_text(ti, "Zabbix Expression evaluation request");
621
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Expression evaluation request");
622
0
        }
623
0
        else if (strcmp(request_type, "command") == 0) {
624
            /* Script execution from the frontend */
625
0
            ADD_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND | ZABBIX_T_SCRIPTEXEC);
626
0
            proto_item_set_text(ti, "Zabbix Script execution request");
627
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Script execution request");
628
0
        }
629
0
    }
630
    /* There was no "request" field match, continue with other ways to recognize the packet */
631
0
    else if (json_get_object(json_str, tokens, "globalmacro")) {
632
        /* This is Zabbix server before 6.4 sending configurations to active proxy */
633
0
        ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG | ZABBIX_T_ACTIVE);
634
0
        proxy_name = zabbix_info->host_name;
635
0
        proto_item_set_text(ti,
636
0
            "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
637
0
        col_add_fstr(pinfo->cinfo, COL_INFO,
638
0
            "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
639
0
    }
640
0
    else if (json_get_double(json_str, tokens, "full_sync", &temp_double)) {
641
        /* This is Zabbix 6.4+ server sending proxy config to active or passive proxy */
642
        /* Only present when value is 1 */
643
0
        ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG);
644
0
        oper_response |= ZABBIX_RESPONSE_FULLSYNC;
645
        /* Active/passive flag was set in the earlier packet */
646
0
        if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PASSIVE)) {
647
            /* There is no proxy name anywhere to use */
648
0
            proto_item_set_text(ti, "Zabbix Passive proxy config");
649
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Passive proxy config");
650
0
        }
651
0
        else {
652
            /* Active proxy */
653
0
            proxy_name = zabbix_info->host_name;
654
0
            proto_item_set_text(ti,
655
0
                "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
656
0
            col_add_fstr(pinfo->cinfo, COL_INFO,
657
0
                "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
658
0
        }
659
0
    }
660
0
    else if (response_status) {
661
0
        if (strcmp(response_status, "success") == 0) {
662
0
            oper_response |= ZABBIX_RESPONSE_SUCCESS;
663
0
        }
664
0
        else if (strcmp(response_status, "failed") == 0) {
665
0
            oper_response |= ZABBIX_RESPONSE_FAILED;
666
0
        }
667
0
        if (IS_ZABBIX_T_FLAGS(ZABBIX_T_AGENT)) {
668
0
            agent_name = zabbix_info->host_name;
669
0
            if (json_get_object(json_str, tokens, "redirect")) {
670
                /* Agent redirection response from a Zabbix 7.0+ proxy in load balancing configuration.
671
                 * Not added in the conversation flags to prevent it from showing in the request packet,
672
                 * just set a local variable for later usage.
673
                 */
674
0
                is_redirection = true;
675
0
                proto_item_set_text(ti,
676
0
                    "Zabbix Agent redirection for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
677
0
                col_add_fstr(pinfo->cinfo, COL_INFO,
678
0
                    "Zabbix Agent redirection for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(agent_name));
679
0
            }
680
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_CONFIG | ZABBIX_T_ACTIVE)) {
681
0
                proto_item_set_text(ti,
682
0
                    "Zabbix Server/proxy response for active checks for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(agent_name), response_status);
683
0
                col_add_fstr(pinfo->cinfo, COL_INFO,
684
0
                    "Zabbix Server/proxy response for active checks for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(agent_name), response_status);
685
0
            }
686
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_DATA | ZABBIX_T_ACTIVE)) {
687
0
                proto_item_set_text(ti,
688
0
                    "Zabbix Server/proxy response for agent data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(agent_name), response_status);
689
0
                col_add_fstr(pinfo->cinfo, COL_INFO,
690
0
                    "Zabbix Server/proxy response for agent data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(agent_name), response_status);
691
0
            }
692
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_METRICS)) {
693
0
                proto_item_set_text(ti, "Zabbix Server/proxy internal metrics response");
694
0
                col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Server/proxy internal metrics response");
695
0
            }
696
0
        }
697
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY)) {
698
0
            proxy_name = zabbix_info->host_name;
699
0
            if (IS_ZABBIX_T_FLAGS(ZABBIX_T_CONFIG | ZABBIX_T_ACTIVE)) {
700
0
                proto_item_set_text(ti,
701
0
                    "Zabbix Response for active proxy config request for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
702
0
                col_add_fstr(pinfo->cinfo, COL_INFO,
703
0
                    "Zabbix Response for active proxy config request for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
704
0
            }
705
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_DATA | ZABBIX_T_ACTIVE)) {
706
0
                proto_item_set_text(ti,
707
0
                    "Zabbix Server response for active proxy data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
708
0
                col_add_fstr(pinfo->cinfo, COL_INFO,
709
0
                    "Zabbix Server response for active proxy data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
710
0
            }
711
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_CONFIG | ZABBIX_T_PASSIVE)) {
712
0
                proto_item_set_text(ti,
713
0
                    "Zabbix Proxy response for passive proxy config (%s)", response_status);
714
0
                col_add_fstr(pinfo->cinfo, COL_INFO,
715
0
                    "Zabbix Proxy response for passive proxy config (%s)", response_status);
716
0
            }
717
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_DATA | ZABBIX_T_PASSIVE)) {
718
0
                proto_item_set_text(ti,
719
0
                    "Zabbix Server response for passive proxy data (%s)", response_status);
720
0
                col_add_fstr(pinfo->cinfo, COL_INFO,
721
0
                    "Zabbix Server response for passive proxy data (%s)", response_status);
722
0
            }
723
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_TASKS | ZABBIX_T_PASSIVE)) {
724
0
                proto_item_set_text(ti,
725
0
                    "Zabbix Server response for passive proxy tasks (%s)", response_status);
726
0
                col_add_fstr(pinfo->cinfo, COL_INFO,
727
0
                    "Zabbix Server response for passive proxy tasks (%s)", response_status);
728
0
            }
729
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_HEARTBEAT | ZABBIX_T_ACTIVE)) {
730
0
                proto_item_set_text(ti,
731
0
                    "Zabbix Server response for active proxy heartbeat for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
732
0
                col_add_fstr(pinfo->cinfo, COL_INFO,
733
0
                    "Zabbix Server response for active proxy heartbeat for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(proxy_name), response_status);
734
0
            }
735
0
        }
736
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SENDER)) {
737
0
            sender_name = zabbix_info->host_name;
738
0
            proto_item_set_text(ti,
739
0
                "Zabbix Server/proxy response for sender data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(sender_name), response_status);
740
0
            col_add_fstr(pinfo->cinfo, COL_INFO,
741
0
                "Zabbix Server/proxy response for sender data for \"%s\" (%s)", ZABBIX_NAME_OR_UNKNOWN(sender_name), response_status);
742
0
        }
743
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND)) {
744
0
            if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SYSINFO)) {
745
0
                proto_item_set_text(ti, "Zabbix System information response");
746
0
                col_set_str(pinfo->cinfo, COL_INFO, "Zabbix System information response");
747
0
            }
748
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_QUEUEINFO)) {
749
0
                proto_item_set_text(ti, "Zabbix Queue information response");
750
0
                col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Queue information response");
751
0
            }
752
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_HISTORYPUSH)) {
753
0
                proto_item_set_text(ti, "Zabbix History push response");
754
0
                col_set_str(pinfo->cinfo, COL_INFO, "Zabbix History push response");
755
0
            }
756
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_ITEMTEST)) {
757
0
                proto_item_set_text(ti, "Zabbix Item test response");
758
0
                col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Item test response");
759
0
            }
760
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_MEDIATEST)) {
761
0
                proto_item_set_text(ti, "Zabbix Media test response");
762
0
                col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Media test response");
763
0
            }
764
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_REPORTTEST)) {
765
0
                proto_item_set_text(ti, "Zabbix Report test response");
766
0
                col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Report test response");
767
0
            }
768
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_EXPRESSIONEVAL)) {
769
0
                proto_item_set_text(ti, "Zabbix Expression evaluation response");
770
0
                col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Expression evaluation response");
771
0
            }
772
0
            else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SCRIPTEXEC)) {
773
0
                proto_item_set_text(ti, "Zabbix Script execution response");
774
0
                col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Script execution response");
775
0
            }
776
0
        }
777
0
    }
778
0
    else if (version && data_array) {
779
        /* This looks like passive agent response in Zabbix 7.0+ */
780
0
        ADD_ZABBIX_T_FLAGS(ZABBIX_T_AGENT | ZABBIX_T_PASSIVE);
781
0
        proto_item_set_text(ti, "Zabbix Agent response for passive checks");
782
0
        col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Agent response for passive checks");
783
0
    }
784
0
    else if (data_object || data_array || tokens->size == 0) {
785
        /* No other match above, let's assume this is server sending incremental
786
         * configuration to a proxy
787
         */
788
0
        ADD_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG);
789
0
        if ((data_object && (data_object->size == 0)) || tokens->size == 0) {
790
            /* Empty data object or the whole JSON is empty */
791
0
            oper_response |= ZABBIX_RESPONSE_NOCHANGE;
792
0
        }
793
0
        else if (data_array) {
794
            /* This was not a "full_sync" but data array exists */
795
0
            oper_response |= ZABBIX_RESPONSE_INCREMENTAL;
796
0
        }
797
0
        if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PASSIVE)) {
798
            /* There is no proxy name anywhere to use */
799
0
            proto_item_set_text(ti, "Zabbix Passive proxy config");
800
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Passive proxy config");
801
0
        }
802
0
        else {
803
0
            proxy_name = zabbix_info->host_name;
804
0
            proto_item_set_text(ti,
805
0
                "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
806
0
            col_add_fstr(pinfo->cinfo, COL_INFO,
807
0
                "Zabbix Server response for proxy config for \"%s\"", ZABBIX_NAME_OR_UNKNOWN(proxy_name));
808
0
        }
809
0
    }
810
    /* Final guesses to provide customized packet information */
811
0
    else if (session && version) {
812
        /* Config or data responses from passive proxy */
813
0
        if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_CONFIG | ZABBIX_T_PASSIVE)) {
814
0
            proto_item_set_text(ti, "Zabbix Passive proxy response for config push");
815
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Passive proxy response for config push");
816
0
        }
817
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_DATA | ZABBIX_T_PASSIVE)) {
818
0
            proto_item_set_text(ti, "Zabbix Passive proxy data response");
819
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Passive proxy data response");
820
0
        }
821
0
    }
822
0
    else if (version) {
823
        /* Tasks response from passive proxy */
824
0
        if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY | ZABBIX_T_TASKS | ZABBIX_T_PASSIVE)) {
825
0
            proto_item_set_text(ti, "Zabbix Passive proxy response for tasks request");
826
0
            col_set_str(pinfo->cinfo, COL_INFO, "Zabbix Passive proxy response for tasks request");
827
0
        }
828
0
    }
829
830
831
    /* Add all relevant fields to the tree */
832
833
0
show_agent_outputs:
834
0
    if (IS_ZABBIX_T_FLAGS(ZABBIX_T_AGENT)) {
835
0
        temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent, NULL, 0, 0, true);
836
0
        proto_item_set_text(temp_ti, "This is an agent connection");
837
0
        proto_item_set_generated(temp_ti);
838
0
        if (IS_ZABBIX_T_FLAGS(ZABBIX_T_DATA)) {
839
0
            temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_data, NULL, 0, 0, true);
840
0
            if (IS_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE)) {
841
                /* Set as generated, not seen in data */
842
0
                proto_item_set_generated(temp_ti);
843
0
            }
844
0
        }
845
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_CONFIG)) {
846
0
            temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_config, NULL, 0, 0, true);
847
0
            if (IS_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE)) {
848
                /* Set as generated, not seen in data */
849
0
                proto_item_set_generated(temp_ti);
850
0
            }
851
0
        }
852
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_HEARTBEAT)) {
853
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_hb, NULL, 0, 0, true);
854
0
        }
855
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PASSIVE)) {
856
0
            temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_passive, NULL, 0, 0, true);
857
0
            proto_item_set_text(temp_ti, "Agent is in passive mode");
858
0
            proto_item_set_generated(temp_ti);
859
0
        }
860
0
        if (is_redirection) {
861
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_redirection, NULL, 0, 0, true);
862
0
        }
863
0
    }
864
0
    else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY)) {
865
0
        temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy, NULL, 0, 0, true);
866
0
        proto_item_set_text(temp_ti, "This is a proxy connection");
867
0
        proto_item_set_generated(temp_ti);
868
0
    }
869
0
    else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SENDER)) {
870
0
        temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_sender, NULL, 0, 0, true);
871
0
        proto_item_set_text(temp_ti, "This is a sender connection");
872
0
        proto_item_set_generated(temp_ti);
873
0
    }
874
0
    else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND)) {
875
0
        temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend, NULL, 0, 0, true);
876
0
        proto_item_set_text(temp_ti, "This is a frontend connection");
877
0
        proto_item_set_generated(temp_ti);
878
0
    }
879
0
    if (oper_response & ZABBIX_RESPONSE_SUCCESS) {
880
0
        proto_tree_add_boolean(zabbix_tree, hf_zabbix_success, NULL, 0, 0, true);
881
0
    }
882
0
    else if (oper_response & ZABBIX_RESPONSE_FAILED) {
883
0
        proto_tree_add_boolean(zabbix_tree, hf_zabbix_failed, NULL, 0, 0, true);
884
0
    }
885
0
    if (IS_ZABBIX_T_FLAGS(ZABBIX_T_AGENT)) {
886
0
        if (agent_name) {
887
0
            temp_ti = proto_tree_add_string(zabbix_tree, hf_zabbix_agent_name, NULL, 0, 0, agent_name);
888
0
            if (IS_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE)) {
889
                /* agent_name was populated from the conversation */
890
0
                proto_item_set_generated(temp_ti);
891
0
                proto_item_append_text(temp_ti, " (from the request)");
892
0
            }
893
0
        }
894
0
        if (agent_variant) {
895
0
            proto_tree_add_int64(zabbix_tree, hf_zabbix_agent_variant, NULL, 0, 0, agent_variant);
896
0
        }
897
0
        if (agent_hb_freq) {
898
0
            proto_tree_add_int(zabbix_tree, hf_zabbix_agent_hb_freq, NULL, 0, 0, agent_hb_freq);
899
0
        }
900
0
        if (agent_hostmetadata) {
901
0
            proto_tree_add_string(zabbix_tree, hf_zabbix_agent_hostmetadata, NULL, 0, 0, agent_hostmetadata);
902
0
        }
903
0
        if (agent_hostinterface) {
904
0
            proto_tree_add_string(zabbix_tree, hf_zabbix_agent_hostinterface, NULL, 0, 0, agent_hostinterface);
905
0
        }
906
0
        if (agent_listenip) {
907
0
            if (strstr(agent_listenip, ":") != NULL) {
908
0
                ws_in6_addr addr6;
909
0
                if (ws_inet_pton6(agent_listenip, &addr6)) {
910
0
                    proto_tree_add_ipv6(zabbix_tree, hf_zabbix_agent_listenipv6, NULL, 0, 0, &addr6);
911
0
                }
912
0
            }
913
0
            else {
914
0
                ws_in4_addr addr4;
915
0
                if (ws_inet_pton4(agent_listenip, &addr4)) {
916
0
                    proto_tree_add_ipv4(zabbix_tree, hf_zabbix_agent_listenipv4, NULL, 0, 0, addr4);
917
0
                }
918
0
            }
919
0
        }
920
0
        if (agent_listenport) {
921
0
            proto_tree_add_uint(zabbix_tree, hf_zabbix_agent_listenport, NULL, 0, 0, agent_listenport);
922
0
        }
923
0
        if (commands_array) {
924
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_agent_commands, NULL, 0, 0, true);
925
0
        }
926
0
        if (IS_ZABBIX_T_FLAGS(ZABBIX_T_METRICS)) {
927
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_metrics, NULL, 0, 0, true);
928
0
        }
929
0
    }
930
0
    else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_PROXY)) {
931
0
        if (proxy_name) {
932
0
            temp_ti = proto_tree_add_string(zabbix_tree, hf_zabbix_proxy_name, NULL, 0, 0, proxy_name);
933
0
            if (IS_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE)) {
934
                /* proxy_name was populated from the conversation */
935
0
                proto_item_set_generated(temp_ti);
936
0
                proto_item_append_text(temp_ti, " (from the request)");
937
0
            }
938
0
        }
939
0
        if (IS_ZABBIX_T_FLAGS(ZABBIX_T_DATA)) {
940
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_data, NULL, 0, 0, true);
941
0
        }
942
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_CONFIG)) {
943
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_config, NULL, 0, 0, true);
944
0
            if (oper_response & ZABBIX_RESPONSE_FULLSYNC) {
945
0
                proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_fullsync, NULL, 0, 0, true);
946
0
            }
947
0
            else if (oper_response & ZABBIX_RESPONSE_INCREMENTAL) {
948
0
                proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_incr_config, NULL, 0, 0, true);
949
0
            }
950
0
            else if (oper_response & ZABBIX_RESPONSE_NOCHANGE) {
951
0
                proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_no_config_change, NULL, 0, 0, true);
952
0
            }
953
0
        }
954
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_TASKS)) {
955
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_tasks, NULL, 0, 0, true);
956
0
        }
957
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_HEARTBEAT)) {
958
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_proxy_hb, NULL, 0, 0, true);
959
0
        }
960
0
    }
961
0
    else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_FRONTEND)) {
962
0
        if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SYSINFO)) {
963
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_sysinfo, NULL, 0, 0, true);
964
0
        }
965
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_QUEUEINFO)) {
966
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_queueinfo, NULL, 0, 0, true);
967
0
        }
968
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_HISTORYPUSH)) {
969
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_historypush, NULL, 0, 0, true);
970
0
        }
971
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_ITEMTEST)) {
972
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_itemtest, NULL, 0, 0, true);
973
0
        }
974
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_MEDIATEST)) {
975
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_mediatest, NULL, 0, 0, true);
976
0
        }
977
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_REPORTTEST)) {
978
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_reporttest, NULL, 0, 0, true);
979
0
        }
980
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_EXPRESSIONEVAL)) {
981
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_expressioneval, NULL, 0, 0, true);
982
0
        }
983
0
        else if (IS_ZABBIX_T_FLAGS(ZABBIX_T_SCRIPTEXEC)) {
984
0
            proto_tree_add_boolean(zabbix_tree, hf_zabbix_frontend_scriptexec, NULL, 0, 0, true);
985
0
        }
986
0
    }
987
0
    else if (sender_name) {
988
0
        temp_ti = proto_tree_add_string(zabbix_tree, hf_zabbix_sender_name, NULL, 0, 0, sender_name);
989
0
        if (IS_ZABBIX_T_FLAGS(ZABBIX_T_RESPONSE)) {
990
            /* sender_name was populated from the conversation */
991
0
            proto_item_set_generated(temp_ti);
992
0
            proto_item_append_text(temp_ti, " (from the request)");
993
0
        }
994
0
    }
995
0
    if (version) {
996
0
        proto_tree_add_string(zabbix_tree, hf_zabbix_version, NULL, 0, 0, version);
997
0
    }
998
0
    if (config_revision > -1) {
999
0
        proto_tree_add_int64(zabbix_tree, hf_zabbix_config_revision, NULL, 0, 0, config_revision);
1000
0
    }
1001
0
    if (hostmap_revision > -1) {
1002
0
        proto_tree_add_int64(zabbix_tree, hf_zabbix_hostmap_revision, NULL, 0, 0, hostmap_revision);
1003
0
    }
1004
0
    if (session) {
1005
0
        proto_tree_add_string(zabbix_tree, hf_zabbix_session, NULL, 0, 0, session);
1006
0
    }
1007
    /* Show also the full JSON, or pre-7.0 passive agent request/response (or error message).
1008
     * Note that ZABBIX_ZBX_NOTSUPPORTED does not include the \0 that is in the
1009
     * protocol specification! Therefore +1/-1's are present
1010
     */
1011
0
    if (passive_agent_data_str &&
1012
0
        strlen(passive_agent_data_str) >= strlen(ZABBIX_ZBX_NOTSUPPORTED) &&
1013
0
        strncmp(passive_agent_data_str, ZABBIX_ZBX_NOTSUPPORTED, strlen(ZABBIX_ZBX_NOTSUPPORTED)) == 0) {
1014
        /* Pre-7.0 passive agent error, first ZBX_NOTSUPPORTED\0 and then the error message */
1015
0
        proto_tree_add_item(zabbix_tree, hf_zabbix_data,
1016
0
            next_tvb, 0, (int)strlen(ZABBIX_ZBX_NOTSUPPORTED)+1, ENC_UTF_8);
1017
0
        proto_tree_add_item(zabbix_tree, hf_zabbix_error,
1018
0
            next_tvb, (int)strlen(ZABBIX_ZBX_NOTSUPPORTED)+1, (int)datalen-(int)strlen(ZABBIX_ZBX_NOTSUPPORTED)-1, ENC_UTF_8);
1019
0
    } else {
1020
        /* JSON or pre-7.0 passive agent without error */
1021
0
        proto_tree_add_item(zabbix_tree, hf_zabbix_data, next_tvb, 0, (int)datalen, ENC_UTF_8);
1022
0
    }
1023
1024
0
final_outputs:
1025
1026
    /* These are common for all cases, too large or not */
1027
1028
    /* Check the ZABBIX_T_REQUEST flag (and not CONV_IS_ZABBIX_REQUEST macro) because
1029
     * heartbeats are not marked as requests */
1030
0
    if (IS_ZABBIX_T_FLAGS(ZABBIX_T_REQUEST)) {
1031
0
        temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_request, NULL, 0, 0, true);
1032
0
        proto_item_set_text(temp_ti, "This is Zabbix request");
1033
0
    } else if (CONV_IS_ZABBIX_RESPONSE(zabbix_info, pinfo)) {
1034
0
        temp_ti = proto_tree_add_boolean(zabbix_tree, hf_zabbix_response, NULL, 0, 0, true);
1035
0
        proto_item_set_text(temp_ti, "This is Zabbix response");
1036
0
        if (!nstime_is_unset(&zabbix_info->req_timestamp)) {
1037
0
            nstime_t delta;
1038
0
            nstime_delta(&delta, &pinfo->abs_ts, &zabbix_info->req_timestamp);
1039
0
            pi = proto_tree_add_time(zabbix_tree, hf_zabbix_time, next_tvb, 0, 0, &delta);
1040
0
            proto_item_set_generated(pi);
1041
0
        }
1042
0
    }
1043
1044
    /* Add length to the Zabbix tree text */
1045
0
    proto_item_append_text(ti, ", Len=%u", (unsigned)length);
1046
    /* Add/set Info column texts */
1047
0
    const char *info_text = col_get_text(pinfo->cinfo, COL_INFO);
1048
0
    if (!info_text || !strlen(info_text)) {
1049
        /* Info column is still empty, set the default text */
1050
0
        if (CONV_IS_ZABBIX_REQUEST(zabbix_info, pinfo)) {
1051
0
            col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Protocol request, Flags=0x%02x", flags);
1052
0
        } else if (CONV_IS_ZABBIX_RESPONSE(zabbix_info, pinfo)) {
1053
0
            col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Protocol response, Flags=0x%02x", flags);
1054
0
        } else {
1055
0
            col_add_fstr(pinfo->cinfo, COL_INFO, "Zabbix Protocol, Flags=0x%02x", flags);
1056
0
        }
1057
0
    }
1058
0
    col_append_fstr(pinfo->cinfo, COL_INFO, ", Len=%u (", (unsigned)length);
1059
0
    col_append_ports(pinfo->cinfo, COL_INFO, PT_TCP, pinfo->srcport, pinfo->destport);
1060
0
    col_append_str(pinfo->cinfo, COL_INFO, ")");
1061
1062
0
    return tvb_reported_length(tvb);
1063
0
}
1064
1065
/* Determine PDU length of Zabbix protocol */
1066
static unsigned
1067
get_zabbix_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
1068
0
{
1069
0
    uint8_t flags;
1070
0
    uint64_t length;
1071
1072
0
    flags = tvb_get_uint8(tvb, offset+4);
1073
0
    if (flags & ZABBIX_FLAG_LARGEPACKET) {
1074
        /* 8-byte length field
1075
         * Note that ZABBIX_HDR_MIN_LEN check (in dissect_zabbix()) is still enough
1076
         * due to the header structure (there are reserved bytes)
1077
         */
1078
0
        length = tvb_get_uint64(tvb, offset+5, ENC_LITTLE_ENDIAN) + ZABBIX_HDR_MAX_LEN;
1079
0
    } else {
1080
        /* 4-byte length */
1081
0
        length = tvb_get_uint32(tvb, offset+5, ENC_LITTLE_ENDIAN) + ZABBIX_HDR_MIN_LEN;
1082
0
    }
1083
0
    return (unsigned)length;
1084
0
}
1085
1086
/* The main dissecting routine */
1087
static int
1088
dissect_zabbix(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
1089
6
{
1090
6
    uint8_t flags;
1091
1092
6
    if (tvb_captured_length(tvb) < ZABBIX_HDR_MIN_LEN) {
1093
        /* Not enough data */
1094
4
        return 0;
1095
4
    }
1096
2
    if (tvb_memeql(tvb, 0, ZABBIX_HDR_SIGNATURE, 4)) {
1097
        /* Encrypted or not Zabbix at all */
1098
2
        return 0;
1099
2
    }
1100
0
    flags = tvb_get_uint8(tvb, 4);
1101
0
    if (!(flags & ZABBIX_FLAG_ZABBIX_COMMUNICATIONS)) {
1102
0
        return 0;
1103
0
    }
1104
    /* This is unencrypted Zabbix protocol, continue with dissecting it */
1105
0
    tcp_dissect_pdus(tvb, pinfo, tree, zabbix_desegment, ZABBIX_HDR_MIN_LEN,
1106
0
        get_zabbix_pdu_len, dissect_zabbix_pdu, data);
1107
0
    return tvb_reported_length(tvb);
1108
0
}
1109
1110
/* Register the protocol with Wireshark */
1111
1112
void
1113
proto_register_zabbix(void)
1114
14
{
1115
14
    static hf_register_info hf[] = {
1116
14
        { &hf_zabbix_header,
1117
14
            { "Header", "zabbix.header",
1118
14
            FT_STRING, BASE_NONE, NULL, 0,
1119
14
            NULL, HFILL }
1120
14
        },
1121
14
        { &hf_zabbix_flags,
1122
14
            { "Flags", "zabbix.flags",
1123
14
            FT_UINT8, BASE_HEX, NULL, 0,
1124
14
            NULL, HFILL }
1125
14
        },
1126
14
        { &hf_zabbix_flag_zabbix_communications,
1127
14
            { "Zabbix communications protocol", "zabbix.flags.zabbix",
1128
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), ZABBIX_FLAG_ZABBIX_COMMUNICATIONS,
1129
14
            NULL, HFILL }
1130
14
        },
1131
14
        { &hf_zabbix_flag_compressed,
1132
14
            { "Compressed", "zabbix.flags.compressed",
1133
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), ZABBIX_FLAG_COMPRESSED,
1134
14
            NULL, HFILL }
1135
14
        },
1136
14
        { &hf_zabbix_flag_largepacket,
1137
14
            { "Large packet", "zabbix.flags.large_packet",
1138
14
            FT_BOOLEAN, 8, TFS(&tfs_yes_no), ZABBIX_FLAG_LARGEPACKET,
1139
14
            NULL, HFILL }
1140
14
        },
1141
14
        { &hf_zabbix_flag_reserved,
1142
14
            { "Reserved bits", "zabbix.flags.reserved",
1143
14
            FT_UINT8, BASE_DEC, NULL, ZABBIX_FLAG_RESERVED,
1144
14
            NULL, HFILL }
1145
14
        },
1146
14
        { &hf_zabbix_length,
1147
14
            { "Length", "zabbix.len",
1148
14
            FT_UINT32, BASE_DEC, NULL, 0,
1149
14
            NULL, HFILL }
1150
14
        },
1151
14
        { &hf_zabbix_reserved,
1152
14
            { "Reserved", "zabbix.reserved",
1153
14
            FT_UINT32, BASE_DEC, NULL, 0,
1154
14
            NULL, HFILL }
1155
14
        },
1156
14
        { &hf_zabbix_uncompressed_length,
1157
14
            { "Uncompressed length", "zabbix.uncompressed_len",
1158
14
            FT_UINT32, BASE_DEC, NULL, 0,
1159
14
            NULL, HFILL }
1160
14
        },
1161
14
        { &hf_zabbix_large_length,
1162
14
            { "Large length", "zabbix.large.len",
1163
14
            FT_UINT64, BASE_DEC, NULL, 0,
1164
14
            NULL, HFILL }
1165
14
        },
1166
14
        { &hf_zabbix_large_reserved,
1167
14
            { "Large reserved", "zabbix.large.reserved",
1168
14
            FT_UINT64, BASE_DEC, NULL, 0,
1169
14
            NULL, HFILL }
1170
14
        },
1171
14
        { &hf_zabbix_large_uncompressed_length,
1172
14
            { "Large uncompressed length", "zabbix.large.uncompressed_len",
1173
14
            FT_UINT64, BASE_DEC, NULL, 0,
1174
14
            NULL, HFILL }
1175
14
        },
1176
14
        { &hf_zabbix_data,
1177
14
            { "Data", "zabbix.data",
1178
14
            FT_STRING, BASE_NONE, NULL, 0,
1179
14
            NULL, HFILL }
1180
14
        },
1181
14
        { &hf_zabbix_error,
1182
14
            { "Error message", "zabbix.error",
1183
14
            FT_STRING, BASE_NONE, NULL, 0,
1184
14
            NULL, HFILL }
1185
14
        },
1186
14
        { &hf_zabbix_time,
1187
14
            { "Response time", "zabbix.time",
1188
14
            FT_RELATIVE_TIME, BASE_NONE, NULL, 0,
1189
14
            NULL, HFILL }
1190
14
        },
1191
14
        { &hf_zabbix_request,
1192
14
            { "Zabbix protocol request", "zabbix.request",
1193
14
            FT_BOOLEAN, BASE_NONE, NULL, 0,
1194
14
            NULL, HFILL }
1195
14
        },
1196
14
        { &hf_zabbix_response,
1197
14
            { "Zabbix protocol response", "zabbix.response",
1198
14
            FT_BOOLEAN, BASE_NONE, NULL, 0,
1199
14
            NULL, HFILL }
1200
14
        },
1201
14
        { &hf_zabbix_success,
1202
14
            { "Success", "zabbix.success",
1203
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1204
14
            NULL, HFILL }
1205
14
        },
1206
14
        { &hf_zabbix_failed,
1207
14
            { "Failed", "zabbix.failed",
1208
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1209
14
            NULL, HFILL }
1210
14
        },
1211
14
        { &hf_zabbix_agent,
1212
14
            { "Zabbix agent connection", "zabbix.agent",
1213
14
            FT_BOOLEAN, BASE_NONE, NULL, 0,
1214
14
            NULL, HFILL }
1215
14
        },
1216
14
        { &hf_zabbix_agent_commands,
1217
14
            { "Zabbix agent commands", "zabbix.agent.commands",
1218
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1219
14
            NULL, HFILL }
1220
14
        },
1221
14
        { &hf_zabbix_agent_config,
1222
14
            { "Zabbix agent config", "zabbix.agent.config",
1223
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1224
14
            NULL, HFILL }
1225
14
        },
1226
14
        { &hf_zabbix_agent_data,
1227
14
            { "Zabbix agent data", "zabbix.agent.data",
1228
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1229
14
            NULL, HFILL }
1230
14
        },
1231
14
        { &hf_zabbix_agent_redirection,
1232
14
            { "Agent redirection", "zabbix.agent.redirection",
1233
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1234
14
            NULL, HFILL }
1235
14
        },
1236
14
        { &hf_zabbix_agent_passive,
1237
14
            { "Passive agent", "zabbix.agent.passive",
1238
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1239
14
            NULL, HFILL }
1240
14
        },
1241
14
        { &hf_zabbix_agent_name,
1242
14
            { "Agent name", "zabbix.agent.name",
1243
14
            FT_STRING, BASE_NONE, NULL, 0,
1244
14
            NULL, HFILL }
1245
14
        },
1246
14
        { &hf_zabbix_agent_hb,
1247
14
            { "Agent heartbeat", "zabbix.agent.heartbeat",
1248
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1249
14
            NULL, HFILL }
1250
14
        },
1251
14
        { &hf_zabbix_agent_hb_freq,
1252
14
            { "Agent heartbeat frequency", "zabbix.agent.heartbeat_freq",
1253
14
            FT_INT32, BASE_DEC, NULL, 0,
1254
14
            NULL, HFILL }
1255
14
        },
1256
14
        { &hf_zabbix_agent_hostmetadata,
1257
14
            { "Agent host metadata", "zabbix.agent.host_metadata",
1258
14
            FT_STRING, BASE_NONE, NULL, 0,
1259
14
            NULL, HFILL }
1260
14
        },
1261
14
        { &hf_zabbix_agent_hostinterface,
1262
14
            { "Agent host interface", "zabbix.agent.host_interface",
1263
14
            FT_STRING, BASE_NONE, NULL, 0,
1264
14
            NULL, HFILL }
1265
14
        },
1266
14
        { &hf_zabbix_agent_listenipv4,
1267
14
            { "Agent listen IPv4", "zabbix.agent.listen_ipv4",
1268
14
            FT_IPv4, BASE_NONE, NULL, 0,
1269
14
            NULL, HFILL }
1270
14
        },
1271
14
        { &hf_zabbix_agent_listenipv6,
1272
14
            { "Agent listen IPv6", "zabbix.agent.listen_ipv6",
1273
14
            FT_IPv6, BASE_NONE, NULL, 0,
1274
14
            NULL, HFILL }
1275
14
        },
1276
14
        { &hf_zabbix_agent_listenport,
1277
14
            { "Agent listen port", "zabbix.agent.listen_port",
1278
14
            FT_UINT16, BASE_PT_TCP, NULL, 0,
1279
14
            NULL, HFILL }
1280
14
        },
1281
14
        { &hf_zabbix_agent_variant,
1282
14
            { "Agent variant", "zabbix.agent.variant",
1283
14
            FT_INT64, BASE_DEC, NULL, 0,
1284
14
            NULL, HFILL }
1285
14
        },
1286
14
        { &hf_zabbix_proxy,
1287
14
            { "Proxy connection", "zabbix.proxy",
1288
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1289
14
            NULL, HFILL }
1290
14
        },
1291
14
        { &hf_zabbix_proxy_name,
1292
14
            { "Proxy name", "zabbix.proxy.name",
1293
14
            FT_STRING, BASE_NONE, NULL, 0,
1294
14
            NULL, HFILL }
1295
14
        },
1296
14
        { &hf_zabbix_proxy_hb,
1297
14
            { "Proxy heartbeat", "zabbix.proxy.heartbeat",
1298
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1299
14
            NULL, HFILL }
1300
14
        },
1301
14
        { &hf_zabbix_proxy_data,
1302
14
            { "Proxy data", "zabbix.proxy.data",
1303
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1304
14
            NULL, HFILL }
1305
14
        },
1306
14
        { &hf_zabbix_proxy_config,
1307
14
            { "Proxy config", "zabbix.proxy.config",
1308
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1309
14
            NULL, HFILL }
1310
14
        },
1311
14
        { &hf_zabbix_proxy_fullsync,
1312
14
            { "Proxy config full sync", "zabbix.proxy.full_sync",
1313
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1314
14
            NULL, HFILL }
1315
14
        },
1316
14
        { &hf_zabbix_proxy_incr_config,
1317
14
            { "Proxy incremental config", "zabbix.proxy.incremental_config",
1318
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1319
14
            NULL, HFILL }
1320
14
        },
1321
14
        { &hf_zabbix_proxy_no_config_change,
1322
14
            { "Proxy no config changes", "zabbix.proxy.no_config_changes",
1323
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1324
14
            NULL, HFILL }
1325
14
        },
1326
14
        { &hf_zabbix_proxy_tasks,
1327
14
            { "Proxy tasks", "zabbix.proxy.tasks",
1328
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1329
14
            NULL, HFILL }
1330
14
        },
1331
14
        { &hf_zabbix_sender,
1332
14
            { "Sender connection", "zabbix.sender",
1333
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1334
14
            NULL, HFILL }
1335
14
        },
1336
14
        { &hf_zabbix_sender_name,
1337
14
            { "Sender name", "zabbix.sender.name",
1338
14
            FT_STRING, BASE_NONE, NULL, 0,
1339
14
            NULL, HFILL }
1340
14
        },
1341
14
        { &hf_zabbix_version,
1342
14
            { "Version", "zabbix.version",
1343
14
            FT_STRING, BASE_NONE, NULL, 0,
1344
14
            NULL, HFILL }
1345
14
        },
1346
14
        { &hf_zabbix_session,
1347
14
            { "Session", "zabbix.session",
1348
14
            FT_STRING, BASE_NONE, NULL, 0,
1349
14
            NULL, HFILL }
1350
14
        },
1351
14
        { &hf_zabbix_config_revision,
1352
14
            { "Config revision", "zabbix.config_revision",
1353
14
            FT_INT64, BASE_DEC, NULL, 0,
1354
14
            NULL, HFILL }
1355
14
        },
1356
14
        { &hf_zabbix_hostmap_revision,
1357
14
            { "Hostmap revision", "zabbix.hostmap_revision",
1358
14
            FT_INT64, BASE_DEC, NULL, 0,
1359
14
            NULL, HFILL }
1360
14
        },
1361
14
        { &hf_zabbix_metrics,
1362
14
            { "Server/proxy internal metrics", "zabbix.stats",
1363
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1364
14
            NULL, HFILL }
1365
14
        },
1366
14
        { &hf_zabbix_frontend,
1367
14
            { "Zabbix frontend", "zabbix.frontend",
1368
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1369
14
            NULL, HFILL }
1370
14
        },
1371
14
        { &hf_zabbix_frontend_sysinfo,
1372
14
            { "System information", "zabbix.frontend.sysinfo",
1373
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1374
14
            NULL, HFILL }
1375
14
        },
1376
14
        { &hf_zabbix_frontend_queueinfo,
1377
14
            { "Queue information", "zabbix.frontend.queueinfo",
1378
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1379
14
            NULL, HFILL }
1380
14
        },
1381
14
        { &hf_zabbix_frontend_historypush,
1382
14
            { "History push", "zabbix.frontend.historypush",
1383
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1384
14
            NULL, HFILL }
1385
14
        },
1386
14
        { &hf_zabbix_frontend_itemtest,
1387
14
            { "Item test", "zabbix.frontend.itemtest",
1388
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1389
14
            NULL, HFILL }
1390
14
        },
1391
14
        { &hf_zabbix_frontend_mediatest,
1392
14
            { "Media test", "zabbix.frontend.mediatest",
1393
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1394
14
            NULL, HFILL }
1395
14
        },
1396
14
        { &hf_zabbix_frontend_reporttest,
1397
14
            { "Report test", "zabbix.frontend.reporttest",
1398
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1399
14
            NULL, HFILL }
1400
14
        },
1401
14
        { &hf_zabbix_frontend_expressioneval,
1402
14
            { "Expression evaluation", "zabbix.frontend.expressioneval",
1403
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1404
14
            NULL, HFILL }
1405
14
        },
1406
14
        { &hf_zabbix_frontend_scriptexec,
1407
14
            { "Script execution", "zabbix.frontend.scriptexec",
1408
14
            FT_BOOLEAN, BASE_NONE, TFS(&tfs_yes_no), 0,
1409
14
            NULL, HFILL }
1410
14
        },
1411
14
    };
1412
1413
14
    static ei_register_info ei[] = {
1414
14
        {
1415
14
            &ei_zabbix_packet_too_large,
1416
14
                { "zabbix.packet_too_large", PI_UNDECODED, PI_WARN,
1417
14
                "Packet is too large for detailed dissection", EXPFILL }
1418
14
        },
1419
14
        {
1420
14
            &ei_zabbix_json_error,
1421
14
                { "zabbix.json_error", PI_PROTOCOL, PI_ERROR,
1422
14
                "Cannot parse JSON", EXPFILL }
1423
14
        },
1424
14
    };
1425
1426
    /* Setup protocol subtree array */
1427
14
    static int *ett[] = {
1428
14
        &ett_zabbix,
1429
14
        &ett_zabbix_flags,
1430
14
    };
1431
1432
14
    module_t *zabbix_module;
1433
14
    expert_module_t *expert_zabbix;
1434
1435
    /* Register the protocol name and description */
1436
14
    proto_zabbix = proto_register_protocol("Zabbix Protocol", "Zabbix", "zabbix");
1437
1438
    /* Required function calls to register the header fields and subtrees used */
1439
14
    proto_register_field_array(proto_zabbix, hf, array_length(hf));
1440
14
    proto_register_subtree_array(ett, array_length(ett));
1441
1442
14
    zabbix_module = prefs_register_protocol(proto_zabbix, NULL);
1443
1444
14
    prefs_register_bool_preference(zabbix_module, "desegment",
1445
14
        "Reassemble Zabbix messages spanning multiple TCP segments",
1446
14
        "Whether the Zabbix protocol dissector should reassemble messages spanning multiple TCP segments."
1447
14
        " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
1448
14
        &zabbix_desegment);
1449
1450
14
    zabbix_handle = register_dissector("zabbix", dissect_zabbix, proto_zabbix);
1451
1452
14
    expert_zabbix = expert_register_protocol(proto_zabbix);
1453
14
    expert_register_field_array(expert_zabbix, ei, array_length(ei));
1454
14
}
1455
1456
void
1457
proto_reg_handoff_zabbix(void)
1458
14
{
1459
14
    dissector_add_uint_range_with_preference("tcp.port", ZABBIX_TCP_PORTS, zabbix_handle);
1460
14
    zabbix_port_range = prefs_get_range_value("Zabbix", "tcp.port");
1461
14
    dissector_add_uint_range("tls.port", zabbix_port_range, zabbix_handle);
1462
14
}