replace SPDX identifier GPL-2.0+ with GPL-2.0-or-later.
[metze/wireshark/wip.git] / epan / dissectors / packet-artemis.c
1 /* packet-artemis.c
2  * Dissector of ActiveMQ Artemis Core Protocol, so far just the message headers
3  * Implemented: 2017, Pavel Moravec, Red Hat <pmoravec@redhat.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  * Protocol information:
12  * https://github.com/apache/activemq-artemis/blob/master/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/PacketImpl.java#L309-L326
13  */
14
15 #include "config.h"
16
17 #include <epan/packet.h>
18 #include <epan/expert.h>
19 #include "packet-tcp.h"
20 #include "stdio.h"
21
22 #define ARTEMIS_PORT 5445 /* Not IANA registered */
23
24 static int proto_artemis = -1;
25
26 /* handles */
27 static int hf_artemis_len = -1;
28 static int hf_artemis_type = -1;
29 static int hf_artemis_channel = -1;
30 static int hf_artemis_buffer = -1;
31
32 static gint ett_artemis = -1;
33
34 static expert_field ei_artemis_len_short = EI_INIT;
35
36
37 static dissector_handle_t artemis_tcp_handle = NULL;
38
39 void proto_register_artemis(void);
40 void proto_reg_handoff_artemis(void);
41 static int dissect_artemis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data _U_);
42
43 static guint
44 get_artemis_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
45                          int offset, void *data _U_)
46 {
47     /* The 4bytes length doesn't include the actual length byte, that's why the "+4" */
48     return (guint) tvb_get_ntohl(tvb, offset) + 4;
49 }
50
51 static int
52 dissect_artemis_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
53 {
54
55     proto_item  *ti, *len_item;
56     proto_tree  *artemis_tree;
57     guint32     length;
58
59     ti = proto_tree_add_item(tree, proto_artemis, tvb, 0, -1, ENC_NA);
60     artemis_tree = proto_item_add_subtree(ti, ett_artemis);
61
62     len_item = proto_tree_add_item_ret_uint(artemis_tree, hf_artemis_len, tvb, 0, 4, ENC_BIG_ENDIAN, &length);
63     if (length < 9) {    /* 9 = 1(type) + channel(8), if length is smaller, we cant read even type+channel */
64         expert_add_info(pinfo, len_item, &ei_artemis_len_short);
65         return tvb_captured_length(tvb);
66     }
67
68     proto_tree_add_item(artemis_tree, hf_artemis_type, tvb, 4, 1, ENC_BIG_ENDIAN);
69     proto_tree_add_item(artemis_tree, hf_artemis_channel, tvb, 5, 8, ENC_BIG_ENDIAN);
70     proto_tree_add_item(artemis_tree, hf_artemis_buffer,  tvb, 13, length-9, ENC_NA);
71
72     return tvb_captured_length(tvb);
73 }
74
75 static int
76 dissect_artemis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree _U_, void *data _U_)
77 {
78     col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARTEMIS");
79     /* Clear out stuff in the info column */
80     col_clear(pinfo->cinfo, COL_INFO);
81
82     /* fixed_len = 4(len) + 1(type) + 8(channel) */
83     tcp_dissect_pdus(tvb, pinfo, tree, TRUE, 4, get_artemis_message_len,
84                          dissect_artemis_frame, data);
85
86     return tvb_captured_length(tvb);
87 }
88
89 void
90 proto_register_artemis(void)
91 {
92     static hf_register_info hf[] = {
93         {&hf_artemis_len, {
94             "Length", "artemis.length",
95             FT_UINT32, BASE_DEC, NULL, 0x0,
96             "Length of the frame", HFILL}},
97         {&hf_artemis_type, {
98             "Type", "artemis.type",
99             FT_UINT8, BASE_DEC, NULL, 0x0,
100             "Type of the frame", HFILL}},
101         {&hf_artemis_channel, {
102             "Channel", "artemis.channel",
103             FT_UINT64, BASE_DEC, NULL, 0x0,
104             "Channel ID of the frame", HFILL}},
105         {&hf_artemis_buffer, {
106             "Buffer", "artemis.buffer",
107             FT_BYTES, BASE_NONE, NULL, 0,
108             "Binary buffer", HFILL}}
109     };
110
111     static gint *ett [] = {
112          &ett_artemis
113     };
114
115     static ei_register_info ei[] = {
116         { &ei_artemis_len_short, { "artemis.len_short", PI_PROTOCOL, PI_ERROR, "Frame length is too short", EXPFILL }}
117     };
118
119     expert_module_t* expert_artemis;
120
121     proto_artemis = proto_register_protocol ( "Artemis Core Protocol", "Artemis", "artemis" );
122
123     artemis_tcp_handle = register_dissector("artemis", dissect_artemis, proto_artemis);
124     proto_register_field_array(proto_artemis, hf, array_length(hf));
125     proto_register_subtree_array(ett, array_length(ett));
126
127     expert_artemis = expert_register_protocol(proto_artemis);
128     expert_register_field_array(expert_artemis, ei, array_length(ei));
129 }
130
131 void
132 proto_reg_handoff_artemis(void)
133 {
134     static gboolean initialize = FALSE;
135
136     if (!initialize) {
137         /* Register TCP port for dissection */
138         dissector_add_uint_with_preference("tcp.port", ARTEMIS_PORT, artemis_tcp_handle);
139         initialize = TRUE;
140     }
141 }
142
143 /*
144  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
145  *
146  * Local variables:
147  * c-basic-offset: 4
148  * tab-width: 8
149  * indent-tabs-mode: nil
150  * End:
151  *
152  * vi: set shiftwidth=4 tabstop=8 expandtab:
153  * :indentSize=4:tabSize=8:noTabs=true:
154  */