/src/wireshark/epan/dissectors/packet-msgpack.c
Line | Count | Source |
1 | | /* packet-msgpack.c |
2 | | * |
3 | | * Routines for MsgPack dissection |
4 | | * References: |
5 | | * https://github.com/msgpack/msgpack/blob/master/spec.md |
6 | | * |
7 | | * Copyright 2018, Dario Lombardo <lomato@gmail.com> |
8 | | * |
9 | | * Wireshark - Network traffic analyzer |
10 | | * By Gerald Combs <gerald@wireshark.org> |
11 | | * Copyright 1998 Gerald Combs |
12 | | * |
13 | | * SPDX-License-Identifier: GPL-2.0-or-later |
14 | | */ |
15 | | |
16 | | #include "config.h" |
17 | | |
18 | | #include <wsutil/array.h> |
19 | | #include <epan/packet.h> |
20 | | #include <epan/expert.h> |
21 | | #include <epan/to_str.h> |
22 | | |
23 | | |
24 | | |
25 | | void proto_register_msgpack(void); |
26 | | void proto_reg_handoff_msgpack(void); |
27 | | |
28 | | static dissector_handle_t msgpack_handle; |
29 | | |
30 | | static int proto_msgpack; |
31 | | |
32 | | static int hf_msgpack_string; |
33 | | static int hf_msgpack_bin; |
34 | | static int hf_msgpack_type; |
35 | | static int hf_msgpack_string_len; |
36 | | static int hf_msgpack_bin_len; |
37 | | static int hf_msgpack_uint_fix; |
38 | | static int hf_msgpack_uint_8; |
39 | | static int hf_msgpack_uint_16; |
40 | | static int hf_msgpack_uint_32; |
41 | | static int hf_msgpack_uint_64; |
42 | | static int hf_msgpack_int_fix; |
43 | | static int hf_msgpack_int_8; |
44 | | static int hf_msgpack_int_16; |
45 | | static int hf_msgpack_int_32; |
46 | | static int hf_msgpack_int_64; |
47 | | static int hf_msgpack_bool; |
48 | | static int hf_msgpack_float; |
49 | | static int hf_msgpack_double; |
50 | | static int hf_msgpack_ext_type; |
51 | | static int hf_msgpack_ext_len; |
52 | | static int hf_msgpack_ext_bytes; |
53 | | |
54 | | static int ett_msgpack; |
55 | | static int ett_msgpack_num; |
56 | | static int ett_msgpack_string; |
57 | | static int ett_msgpack_bin; |
58 | | static int ett_msgpack_array; |
59 | | static int ett_msgpack_map; |
60 | | static int ett_msgpack_map_elem; |
61 | | static int ett_msgpack_ext; |
62 | | |
63 | | static expert_field ei_msgpack_unsupported; |
64 | | |
65 | | /* names and ranges from https://github.com/msgpack/msgpack/blob/master/spec.md#formats */ |
66 | | static const range_string msgpack_types[] = { |
67 | | {0x00, 0x7F, "positive fixint"}, |
68 | | {0x80, 0x8F, "fixmap"}, |
69 | | {0x90, 0x9F, "fixarray"}, |
70 | | {0xA0, 0xBF, "fixstr"}, |
71 | | {0xC0, 0xC0, "nil"}, |
72 | | {0xC1, 0xC1, "(never used)"}, |
73 | | {0xC2, 0xC2, "false"}, |
74 | | {0xC3, 0xC3, "true"}, |
75 | | {0xC4, 0xC4, "bin 8"}, |
76 | | {0xC5, 0xC5, "bin 16"}, |
77 | | {0xC6, 0xC6, "bin 32"}, |
78 | | {0xC7, 0xC7, "ext 8"}, |
79 | | {0xC8, 0xC8, "ext 16"}, |
80 | | {0xC9, 0xC9, "ext 32"}, |
81 | | {0xCA, 0xCA, "float 32"}, |
82 | | {0xCB, 0xCB, "flost 64"}, |
83 | | {0xCC, 0xCC, "uint 8"}, |
84 | | {0xCD, 0xCD, "uint 16"}, |
85 | | {0xCE, 0xCE, "uint 32"}, |
86 | | {0xCF, 0xCF, "uint 64"}, |
87 | | {0xD0, 0xD0, "int 8"}, |
88 | | {0xD1, 0xD1, "int 16"}, |
89 | | {0xD2, 0xD2, "int 32"}, |
90 | | {0xD3, 0xD3, "int 64"}, |
91 | | {0xD4, 0xD4, "fixext 1"}, |
92 | | {0xD5, 0xD5, "fixext 2"}, |
93 | | {0xD6, 0xD6, "fixext 4"}, |
94 | | {0xD7, 0xD7, "fixext 8"}, |
95 | | {0xD8, 0xD8, "fixext 16"}, |
96 | | {0xD9, 0xD9, "str 8"}, |
97 | | {0xDA, 0xDA, "str 16"}, |
98 | | {0xDB, 0xDB, "str 32"}, |
99 | | {0xDC, 0xDC, "array 16"}, |
100 | | {0xDD, 0xDD, "array 32"}, |
101 | | {0xDE, 0xDE, "map 16"}, |
102 | | {0xDF, 0xDF, "map 32"}, |
103 | | {0xE0, 0xFF, "negative fixint"}, |
104 | | {0x00, 0x00, NULL} |
105 | | }; |
106 | | |
107 | | static void dissect_msgpack_object(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data, unsigned* offset, char** value); |
108 | | |
109 | | static void dissect_msgpack_integer(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree, uint8_t type, void* data, unsigned* offset, char** value) |
110 | 0 | { |
111 | 0 | uint8_t uint8; |
112 | 0 | uint16_t uint16; |
113 | 0 | uint32_t uint32; |
114 | 0 | uint64_t uint64; |
115 | 0 | int8_t int8; |
116 | 0 | int16_t int16; |
117 | 0 | int32_t int32; |
118 | 0 | int64_t int64; |
119 | 0 | char* label; |
120 | 0 | proto_tree* subtree; |
121 | 0 | proto_item* ti; |
122 | 0 | int t_offset = *offset; |
123 | |
|
124 | 0 | label = (data ? (char*)data : "MsgPack Integer"); |
125 | |
|
126 | 0 | if (type >> 7 == 0) { |
127 | 0 | ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_fix, tvb, *offset, 1, type, "%s: %u", label, type); |
128 | 0 | subtree = proto_item_add_subtree(ti, ett_msgpack_num); |
129 | 0 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA); |
130 | |
|
131 | 0 | if (value) |
132 | 0 | *value = wmem_strdup_printf(pinfo->pool, "%u", type); |
133 | 0 | *offset += 1; |
134 | 0 | return; |
135 | 0 | } |
136 | | |
137 | 0 | if (type >> 5 == 7) { |
138 | 0 | int8_t stype = (int8_t)type; |
139 | 0 | ti = proto_tree_add_int_format(tree, hf_msgpack_int_fix, tvb, *offset, 1, stype, "%s: %d", label, stype); |
140 | 0 | subtree = proto_item_add_subtree(ti, ett_msgpack_num); |
141 | 0 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA); |
142 | |
|
143 | 0 | if (value) |
144 | 0 | *value = wmem_strdup_printf(pinfo->pool, "%d", stype); |
145 | 0 | *offset += 1; |
146 | 0 | return; |
147 | 0 | } |
148 | | |
149 | 0 | switch (type) { |
150 | 0 | case 0xcc: |
151 | 0 | uint8 = tvb_get_uint8(tvb, *offset + 1); |
152 | 0 | ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_8, tvb, *offset, 2, uint8, "%s: %u", label, uint8); |
153 | 0 | if (value) |
154 | 0 | *value = wmem_strdup_printf(pinfo->pool, "%u", uint8); |
155 | 0 | *offset += 2; |
156 | 0 | break; |
157 | 0 | case 0xcd: |
158 | 0 | uint16 = tvb_get_ntohs(tvb, *offset + 1); |
159 | 0 | ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_16, tvb, *offset, 3, uint16, "%s: %u", label, uint16); |
160 | 0 | if (value) |
161 | 0 | *value = wmem_strdup_printf(pinfo->pool, "%u", uint16); |
162 | 0 | *offset += 3; |
163 | 0 | break; |
164 | 0 | case 0xce: |
165 | 0 | uint32 = tvb_get_ntohl(tvb, *offset + 1); |
166 | 0 | ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_32, tvb, *offset, 5, uint32, "%s: %u", label, uint32); |
167 | 0 | if (value) |
168 | 0 | *value = wmem_strdup_printf(pinfo->pool, "%u", uint32); |
169 | 0 | *offset += 5; |
170 | 0 | break; |
171 | 0 | case 0xcf: |
172 | 0 | uint64 = tvb_get_ntoh64(tvb, *offset + 1); |
173 | 0 | ti = proto_tree_add_uint64_format(tree, hf_msgpack_uint_64, tvb, *offset, 9, uint64, "%s: %" PRIu64, label, uint64); |
174 | 0 | if (value) |
175 | 0 | *value = wmem_strdup_printf(pinfo->pool, "%" PRIu64, uint64); |
176 | 0 | *offset += 9; |
177 | 0 | break; |
178 | 0 | case 0xd0: |
179 | 0 | int8 = tvb_get_int8(tvb, *offset + 1); |
180 | 0 | ti = proto_tree_add_int_format(tree, hf_msgpack_int_8, tvb, *offset, 2, int8, "%s: %d", label, int8); |
181 | 0 | if (value) |
182 | 0 | *value = wmem_strdup_printf(pinfo->pool, "%d", int8); |
183 | 0 | *offset += 2; |
184 | 0 | break; |
185 | 0 | case 0xd1: |
186 | 0 | int16 = tvb_get_ntohs(tvb, *offset + 1); |
187 | 0 | ti = proto_tree_add_int_format(tree, hf_msgpack_int_16, tvb, *offset, 3, int16, "%s: %d", label, int16); |
188 | 0 | if (value) |
189 | 0 | *value = wmem_strdup_printf(pinfo->pool, "%d", int16); |
190 | 0 | *offset += 3; |
191 | 0 | break; |
192 | 0 | case 0xd2: |
193 | 0 | int32 = tvb_get_ntohl(tvb, *offset + 1); |
194 | 0 | ti = proto_tree_add_int_format(tree, hf_msgpack_int_32, tvb, *offset, 5, int32, "%s: %d", label, int32); |
195 | 0 | if (value) |
196 | 0 | *value = wmem_strdup_printf(pinfo->pool, "%d", int32); |
197 | 0 | *offset += 5; |
198 | 0 | break; |
199 | 0 | case 0xd3: |
200 | 0 | int64 = tvb_get_ntoh64(tvb, *offset + 1); |
201 | 0 | ti = proto_tree_add_int64_format(tree, hf_msgpack_int_64, tvb, *offset, 9, int64, "%s: %" PRId64, label, int64); |
202 | 0 | if (value) |
203 | 0 | *value = wmem_strdup_printf(pinfo->pool, "%" PRId64, int64); |
204 | 0 | *offset += 9; |
205 | 0 | break; |
206 | 0 | default: |
207 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
208 | 0 | break; |
209 | 0 | } |
210 | 0 | subtree = proto_item_add_subtree(ti, ett_msgpack_num); |
211 | 0 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, t_offset, 1, ENC_NA); |
212 | 0 | } |
213 | | |
214 | | // NOLINTNEXTLINE(misc-no-recursion) |
215 | | static void dissect_msgpack_map(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, uint8_t type, void* data, unsigned* offset, char** value) |
216 | 0 | { |
217 | 0 | proto_tree* subtree; |
218 | 0 | proto_tree* map_subtree; |
219 | 0 | proto_item* ti; |
220 | 0 | uint32_t len = 0; |
221 | 0 | uint8_t lensize = 0; |
222 | 0 | char* label; |
223 | 0 | unsigned i; |
224 | |
|
225 | 0 | if (type >> 4 == 0x8) { |
226 | 0 | len = type & 0x0F; |
227 | 0 | lensize = 0; |
228 | 0 | } |
229 | 0 | else if (type == 0xde) { |
230 | 0 | len = tvb_get_ntohs(tvb, *offset + 1); |
231 | 0 | lensize = 2; |
232 | 0 | } |
233 | 0 | else if (type == 0xdf) { |
234 | 0 | len = tvb_get_ntohl(tvb, *offset + 1); |
235 | 0 | lensize = 4; |
236 | 0 | } |
237 | 0 | else { |
238 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
239 | 0 | } |
240 | |
|
241 | 0 | label = wmem_strdup_printf(pinfo->pool, "%s: %u element%s", data ? (char*)data : "MsgPack Map", len, len > 1 ? "s" : ""); |
242 | |
|
243 | 0 | ti = proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1 + lensize, NULL, "%s", label); |
244 | 0 | subtree = proto_item_add_subtree(ti, ett_msgpack_map); |
245 | 0 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA); |
246 | 0 | *offset += lensize + 1; |
247 | 0 | for (i = 0; i < len; i++) { |
248 | | // We recurse here, but we'll run out of packet before we run out of stack. |
249 | 0 | map_subtree = proto_tree_add_subtree(subtree, tvb, *offset, 0, ett_msgpack_map_elem, NULL, ""); |
250 | 0 | dissect_msgpack_object(tvb, pinfo, map_subtree, "Key", offset, value); |
251 | 0 | if (value) |
252 | 0 | proto_item_append_text(map_subtree, " %s:", *value); |
253 | 0 | dissect_msgpack_object(tvb, pinfo, map_subtree, "Value", offset, value); |
254 | 0 | if (value) |
255 | 0 | proto_item_append_text(map_subtree, " %s", *value); |
256 | 0 | } |
257 | |
|
258 | 0 | if (value) |
259 | 0 | *value = label; |
260 | 0 | } |
261 | | |
262 | | // NOLINTNEXTLINE(misc-no-recursion) |
263 | | static void dissect_msgpack_array(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, uint8_t type, void* data, unsigned* offset, char** value) |
264 | 0 | { |
265 | 0 | proto_tree* subtree; |
266 | 0 | proto_item* ti; |
267 | 0 | uint32_t len = 0; |
268 | 0 | uint8_t lensize = 0; |
269 | 0 | char* label; |
270 | 0 | unsigned i; |
271 | |
|
272 | 0 | if (type >> 4 == 0x9) { |
273 | 0 | len = type & 0x0F; |
274 | 0 | lensize = 0; |
275 | 0 | } |
276 | 0 | else if (type == 0xdc) { |
277 | 0 | len = tvb_get_ntohs(tvb, *offset + 1); |
278 | 0 | lensize = 2; |
279 | 0 | } |
280 | 0 | else if (type == 0xdd) { |
281 | 0 | len = tvb_get_ntohl(tvb, *offset + 1); |
282 | 0 | lensize = 4; |
283 | 0 | } |
284 | 0 | else { |
285 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
286 | 0 | } |
287 | |
|
288 | 0 | label = wmem_strdup_printf(pinfo->pool, "%s %u element%s", data ? (char*)data : "MsgPack Array", len, len > 1 ? "s" : ""); |
289 | |
|
290 | 0 | ti = proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1 + lensize, NULL, "%s", label); |
291 | 0 | subtree = proto_item_add_subtree(ti, ett_msgpack_array); |
292 | 0 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA); |
293 | 0 | *offset += lensize + 1; |
294 | 0 | for (i = 0; i < len; i++) { |
295 | | // We recurse here, but we'll run out of packet before we run out of stack. |
296 | 0 | dissect_msgpack_object(tvb, pinfo, subtree, data, offset, value); |
297 | 0 | } |
298 | |
|
299 | 0 | if (value) |
300 | 0 | *value = label; |
301 | 0 | } |
302 | | |
303 | | static void dissect_msgpack_string(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int type, void* data, unsigned* offset, char** value) |
304 | 0 | { |
305 | 0 | uint32_t len = 0; |
306 | 0 | uint8_t lensize = 0; |
307 | 0 | char* label; |
308 | 0 | proto_item* ti; |
309 | 0 | proto_tree* subtree; |
310 | 0 | char* lvalue; |
311 | |
|
312 | 0 | if (type >> 5 == 0x5) { |
313 | 0 | len = type & 0x1F; |
314 | 0 | lensize = 0; |
315 | 0 | } |
316 | 0 | else if (type == 0xd9) { |
317 | 0 | len = tvb_get_uint8(tvb, *offset + 1); |
318 | 0 | lensize = 1; |
319 | 0 | } |
320 | 0 | else if (type == 0xda) { |
321 | 0 | len = tvb_get_ntohs(tvb, *offset + 1); |
322 | 0 | lensize = 2; |
323 | 0 | } |
324 | 0 | else if (type == 0xdb) { |
325 | 0 | len = tvb_get_ntohl(tvb, *offset + 1); |
326 | 0 | lensize = 4; |
327 | 0 | } |
328 | 0 | else { |
329 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
330 | 0 | } |
331 | |
|
332 | 0 | lvalue = (char*)tvb_get_string_enc(pinfo->pool, tvb, *offset + 1 + lensize, len, ENC_UTF_8); |
333 | 0 | label = (data ? (char*)data : "MsgPack String"); |
334 | |
|
335 | 0 | ti = proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1 + lensize + len, lvalue, "%s: %s", label, lvalue); |
336 | 0 | subtree = proto_item_add_subtree(ti, ett_msgpack_string); |
337 | 0 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA); |
338 | |
|
339 | 0 | if (lensize == 0) { |
340 | 0 | proto_tree_add_uint(subtree, hf_msgpack_string_len, tvb, *offset, 1, len); |
341 | 0 | *offset += 1; |
342 | 0 | } |
343 | 0 | else { |
344 | 0 | *offset += 1; |
345 | 0 | proto_tree_add_item(subtree, hf_msgpack_string_len, tvb, *offset, lensize, ENC_BIG_ENDIAN); |
346 | 0 | *offset += lensize; |
347 | 0 | } |
348 | 0 | proto_tree_add_item(subtree, hf_msgpack_string, tvb, *offset, len, ENC_UTF_8); |
349 | 0 | *offset += len; |
350 | |
|
351 | 0 | if (value) |
352 | 0 | *value = lvalue; |
353 | 0 | } |
354 | | |
355 | | static void dissect_msgpack_bin(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int type, void* data, unsigned* offset, char** value) |
356 | 0 | { |
357 | 0 | uint32_t len = 0; |
358 | 0 | uint8_t lensize = 0; |
359 | 0 | char* label; |
360 | 0 | proto_item* ti; |
361 | 0 | proto_tree* subtree; |
362 | 0 | char* lvalue; |
363 | |
|
364 | 0 | switch (type) { |
365 | 0 | case 0xc4: |
366 | 0 | len = tvb_get_uint8(tvb, *offset + 1); |
367 | 0 | lensize = 1; |
368 | 0 | break; |
369 | 0 | case 0xc5: |
370 | 0 | len = tvb_get_ntohs(tvb, *offset + 1); |
371 | 0 | lensize = 2; |
372 | 0 | break; |
373 | 0 | case 0xc6: |
374 | 0 | len = tvb_get_ntohl(tvb, *offset + 1); |
375 | 0 | lensize = 4; |
376 | 0 | break; |
377 | 0 | default: |
378 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
379 | 0 | break; |
380 | 0 | } |
381 | | |
382 | 0 | lvalue = (char*)tvb_bytes_to_str(pinfo->pool, tvb, *offset + 1 + lensize, len); |
383 | 0 | label = (data ? (char*)data : "MsgPack Bytes"); |
384 | |
|
385 | 0 | ti = proto_tree_add_bytes_format(tree, hf_msgpack_bin, tvb, *offset, 1 + lensize + len, NULL, "%s: %s", label, lvalue); |
386 | 0 | subtree = proto_item_add_subtree(ti, ett_msgpack_bin); |
387 | 0 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA); |
388 | |
|
389 | 0 | *offset += 1; |
390 | 0 | proto_tree_add_item(subtree, hf_msgpack_bin_len, tvb, *offset, lensize, ENC_BIG_ENDIAN); |
391 | 0 | *offset += lensize; |
392 | |
|
393 | 0 | proto_tree_add_item(subtree, hf_msgpack_bin, tvb, *offset, len, ENC_NA); |
394 | 0 | *offset += len; |
395 | |
|
396 | 0 | if (value) |
397 | 0 | *value = lvalue; |
398 | 0 | } |
399 | | |
400 | | static void dissect_msgpack_float(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree, int type, void* data, unsigned* offset, char** value) |
401 | 0 | { |
402 | 0 | char* label; |
403 | 0 | char* lvalue; |
404 | 0 | proto_item* ti; |
405 | 0 | proto_tree* subtree; |
406 | 0 | int s_offset = *offset; |
407 | |
|
408 | 0 | *offset += 1; |
409 | |
|
410 | 0 | if (type == 0xca) { |
411 | 0 | label = (data ? (char*)data : "MsgPack Float"); |
412 | 0 | float f = tvb_get_ntohieee_float(tvb, *offset); |
413 | 0 | lvalue = wmem_strdup_printf(pinfo->pool, "%f", f); |
414 | 0 | ti = proto_tree_add_float_format(tree, hf_msgpack_float, tvb, *offset, 4, f, "%s: %f", label, f); |
415 | 0 | if (value) |
416 | 0 | *value = lvalue; |
417 | 0 | *offset += 4; |
418 | 0 | } |
419 | 0 | else if (type == 0xcb) { |
420 | 0 | label = (data ? (char*)data : "MsgPack Double"); |
421 | 0 | double d = tvb_get_ntohieee_double(tvb, *offset); |
422 | 0 | lvalue = wmem_strdup_printf(pinfo->pool, "%lf", d); |
423 | 0 | ti = proto_tree_add_double_format(tree, hf_msgpack_double, tvb, *offset, 8, d, "%s: %lf", label, d); |
424 | 0 | if (value) |
425 | 0 | *value = lvalue; |
426 | 0 | *offset += 8; |
427 | 0 | } |
428 | 0 | else { |
429 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
430 | 0 | } |
431 | 0 | subtree = proto_item_add_subtree(ti, ett_msgpack_num); |
432 | 0 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, s_offset, 1, ENC_NA); |
433 | 0 | } |
434 | | |
435 | | static void dissect_msgpack_ext(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree, int type, void* data, unsigned* offset, char** value) |
436 | 0 | { |
437 | 0 | char* label; |
438 | 0 | uint32_t len = 0; |
439 | 0 | uint8_t lensize = 0; |
440 | 0 | proto_tree* subtree; |
441 | 0 | unsigned offset_start = *offset; |
442 | |
|
443 | 0 | label = (data ? (char*)data : "Ext"); |
444 | |
|
445 | 0 | subtree = proto_tree_add_subtree(tree, tvb, *offset, 0, ett_msgpack_ext, NULL, label); |
446 | |
|
447 | 0 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA); |
448 | 0 | if (type >= 0xd4 && type <= 0xd8) { |
449 | 0 | len = 1 << (type - 0xd4); |
450 | 0 | proto_tree_add_uint(subtree, hf_msgpack_ext_len, tvb, *offset, 1, len); |
451 | 0 | } |
452 | 0 | else if (type == 0xc7) { |
453 | 0 | len = tvb_get_uint8(tvb, *offset + 2); |
454 | 0 | lensize = 1; |
455 | 0 | } |
456 | 0 | else if (type == 0xc8) { |
457 | 0 | len = tvb_get_ntohs(tvb, *offset + 2); |
458 | 0 | lensize = 2; |
459 | 0 | } |
460 | 0 | else if (type == 0xc9) { |
461 | 0 | len = tvb_get_ntohl(tvb, *offset + 2); |
462 | 0 | lensize = 4; |
463 | 0 | } |
464 | 0 | else { |
465 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
466 | 0 | } |
467 | 0 | *offset += 1; |
468 | |
|
469 | 0 | proto_tree_add_item(subtree, hf_msgpack_ext_type, tvb, *offset, 1, ENC_NA); |
470 | 0 | *offset += 1; |
471 | |
|
472 | 0 | if (lensize > 0) { |
473 | 0 | proto_tree_add_item(subtree, hf_msgpack_ext_len, tvb, *offset, lensize, ENC_BIG_ENDIAN); |
474 | 0 | *offset += lensize; |
475 | 0 | } |
476 | 0 | proto_tree_add_item(subtree, hf_msgpack_ext_bytes, tvb, *offset, len, ENC_NA); |
477 | 0 | if (value) { |
478 | 0 | *value = tvb_bytes_to_str(pinfo->pool, tvb, *offset, len); |
479 | 0 | } |
480 | 0 | *offset += len; |
481 | |
|
482 | 0 | proto_item_set_len(subtree, *offset - offset_start); |
483 | 0 | } |
484 | | |
485 | | // NOLINTNEXTLINE(misc-no-recursion) |
486 | | static void dissect_msgpack_object(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data, unsigned* offset, char** value) |
487 | 0 | { |
488 | 0 | uint8_t type; |
489 | 0 | int s_offset = *offset; |
490 | |
|
491 | 0 | type = tvb_get_uint8(tvb, *offset); |
492 | |
|
493 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", rval_to_str_const(type, msgpack_types, " Unknown Msg Type")); |
494 | | |
495 | | // Nil |
496 | 0 | if (type == 0xc0) { |
497 | 0 | proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1, "nil", "nil"); |
498 | 0 | if (value) |
499 | 0 | *value = "nil"; |
500 | 0 | *offset += 1; |
501 | 0 | return; |
502 | 0 | } |
503 | | |
504 | | // True/False |
505 | 0 | if (type == 0xc2 || type == 0xc3) { |
506 | 0 | proto_tree_add_boolean(tree, hf_msgpack_bool, tvb, *offset, 1, type - 0xc2); |
507 | 0 | if (value) |
508 | 0 | *value = (type - 0xc2) ? "True" : "False"; |
509 | 0 | *offset += 1; |
510 | 0 | return; |
511 | 0 | } |
512 | | |
513 | | // Integer |
514 | 0 | if (type >= 0xe0 || type <= 0x7f || (type >= 0xcc && type <= 0xd3)) { |
515 | 0 | dissect_msgpack_integer(tvb, pinfo, tree, type, data, offset, value); |
516 | 0 | return; |
517 | 0 | } |
518 | | |
519 | | // Float |
520 | 0 | if (type == 0xca || type == 0xcb) { |
521 | 0 | dissect_msgpack_float(tvb, pinfo, tree, type, data, offset, value); |
522 | 0 | return; |
523 | 0 | } |
524 | | |
525 | | // String |
526 | 0 | if (type >> 5 == 0x5 || type == 0xd9 || type == 0xda || type == 0xdb) { |
527 | 0 | dissect_msgpack_string(tvb, pinfo, tree, type, data, offset, value); |
528 | 0 | return; |
529 | 0 | } |
530 | | |
531 | | // Bin |
532 | 0 | if (type == 0xc4 || type == 0xc5 || type == 0xc6) { |
533 | 0 | dissect_msgpack_bin(tvb, pinfo, tree, type, data, offset, value); |
534 | 0 | return; |
535 | 0 | } |
536 | | |
537 | | // Array |
538 | 0 | if (type >> 4 == 0x9 || type == 0xdc || type == 0xdd) { |
539 | | // We recurse here, but we'll run out of packet before we run out of stack. |
540 | 0 | dissect_msgpack_array(tvb, pinfo, tree, type, data, offset, value); |
541 | 0 | return; |
542 | 0 | } |
543 | | |
544 | | // Map |
545 | 0 | if (type >> 4 == 0x8 || type == 0xde || type == 0xdf) { |
546 | | // We recurse here, but we'll run out of packet before we run out of stack. |
547 | 0 | dissect_msgpack_map(tvb, pinfo, tree, type, data, offset, value); |
548 | 0 | return; |
549 | 0 | } |
550 | | |
551 | | // Ext |
552 | 0 | if ((type >= 0xd4 && type <= 0xd8) || (type >= 0xc7 && type <= 0xc9)) { |
553 | 0 | dissect_msgpack_ext(tvb, pinfo, tree, type, data, offset, value); |
554 | 0 | return; |
555 | 0 | } |
556 | | |
557 | 0 | if (*offset - s_offset == 0) { |
558 | 0 | expert_add_info_format(pinfo, tree, &ei_msgpack_unsupported, "Type 0x%x is unsupported", type); |
559 | 0 | } |
560 | 0 | } |
561 | | |
562 | | static int dissect_msgpack(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data) |
563 | 0 | { |
564 | 0 | unsigned offset = 0; |
565 | |
|
566 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "MsgPack"); |
567 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
568 | |
|
569 | 0 | dissect_msgpack_object(tvb, pinfo, tree, data, &offset, NULL); |
570 | 0 | return offset; |
571 | 0 | } |
572 | | |
573 | | void proto_register_msgpack(void) |
574 | 14 | { |
575 | 14 | expert_module_t* expert_msgpack; |
576 | | |
577 | 14 | static hf_register_info hf[] = { |
578 | 14 | { &hf_msgpack_string, |
579 | 14 | { "String", "msgpack.string", FT_STRING, BASE_NONE, NULL, 0x00, NULL, HFILL } |
580 | 14 | }, |
581 | 14 | { &hf_msgpack_type, |
582 | 14 | { "Type", "msgpack.type", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(msgpack_types), 0x00, NULL, HFILL } |
583 | 14 | }, |
584 | 14 | { &hf_msgpack_string_len, |
585 | 14 | { "Length", "msgpack.string.len", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } |
586 | 14 | }, |
587 | 14 | { &hf_msgpack_bin, |
588 | 14 | { "Bytes", "msgpack.bin", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL } |
589 | 14 | }, |
590 | 14 | { &hf_msgpack_bin_len, |
591 | 14 | { "Length", "msgpack.bin.len", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } |
592 | 14 | }, |
593 | 14 | { &hf_msgpack_uint_fix, |
594 | 14 | { "Integer", "msgpack.integer.fixint", FT_UINT8, BASE_DEC, NULL, 0x7F, NULL, HFILL } |
595 | 14 | }, |
596 | 14 | { &hf_msgpack_uint_8, |
597 | 14 | { "Integer", "msgpack.integer.u8", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL } |
598 | 14 | }, |
599 | 14 | { &hf_msgpack_uint_16, |
600 | 14 | { "Integer", "msgpack.integer.u16", FT_UINT16, BASE_DEC, NULL, 0x00, NULL, HFILL } |
601 | 14 | }, |
602 | 14 | { &hf_msgpack_uint_32, |
603 | 14 | { "Integer", "msgpack.integer.u32", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } |
604 | 14 | }, |
605 | 14 | { &hf_msgpack_uint_64, |
606 | 14 | { "Integer", "msgpack.integer.u64", FT_UINT64, BASE_DEC, NULL, 0x00, NULL, HFILL } |
607 | 14 | }, |
608 | 14 | { &hf_msgpack_int_fix, |
609 | 14 | { "Integer", "msgpack.integer.fixint", FT_INT8, BASE_DEC, NULL, 0x1F, NULL, HFILL } |
610 | 14 | }, |
611 | 14 | { &hf_msgpack_int_8, |
612 | 14 | { "Integer", "msgpack.integer.8", FT_INT8, BASE_DEC, NULL, 0x00, NULL, HFILL } |
613 | 14 | }, |
614 | 14 | { &hf_msgpack_int_16, |
615 | 14 | { "Integer", "msgpack.integer.16", FT_INT16, BASE_DEC, NULL, 0x00, NULL, HFILL } |
616 | 14 | }, |
617 | 14 | { &hf_msgpack_int_32, |
618 | 14 | { "Integer", "msgpack.integer.32", FT_INT32, BASE_DEC, NULL, 0x00, NULL, HFILL } |
619 | 14 | }, |
620 | 14 | { &hf_msgpack_int_64, |
621 | 14 | { "Integer", "msgpack.integer.64", FT_INT64, BASE_DEC, NULL, 0x00, NULL, HFILL } |
622 | 14 | }, |
623 | 14 | { &hf_msgpack_bool, |
624 | 14 | { "Boolean", "msgpack.boolean", FT_BOOLEAN, BASE_NONE, NULL, 0x00, NULL, HFILL } |
625 | 14 | }, |
626 | 14 | { &hf_msgpack_float, |
627 | 14 | { "Float", "msgpack.float", FT_FLOAT, BASE_NONE, NULL, 0x00, NULL, HFILL } |
628 | 14 | }, |
629 | 14 | { &hf_msgpack_double, |
630 | 14 | { "Double", "msgpack.double", FT_DOUBLE, BASE_NONE, NULL, 0x00, NULL, HFILL } |
631 | 14 | }, |
632 | 14 | { &hf_msgpack_ext_type, |
633 | 14 | { "Ext type", "msgpack.ext.type", FT_INT8, BASE_DEC, NULL, 0x00, NULL, HFILL } |
634 | 14 | }, |
635 | 14 | { &hf_msgpack_ext_len, |
636 | 14 | { "Length", "msgpack.ext.len", FT_UINT32, BASE_DEC, NULL, 0x00, NULL, HFILL } |
637 | 14 | }, |
638 | 14 | { &hf_msgpack_ext_bytes, |
639 | 14 | { "Ext", "msgpack.ext", FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL } |
640 | 14 | } |
641 | 14 | }; |
642 | | |
643 | 14 | static int* ett[] = { |
644 | 14 | &ett_msgpack, |
645 | 14 | &ett_msgpack_num, |
646 | 14 | &ett_msgpack_string, |
647 | 14 | &ett_msgpack_bin, |
648 | 14 | &ett_msgpack_array, |
649 | 14 | &ett_msgpack_map, |
650 | 14 | &ett_msgpack_map_elem, |
651 | 14 | &ett_msgpack_ext |
652 | 14 | }; |
653 | | |
654 | 14 | static ei_register_info ei[] = { |
655 | 14 | { &ei_msgpack_unsupported, { "msgpack.unsupported", PI_UNDECODED, PI_WARN, "Unsupported type", EXPFILL }} |
656 | 14 | }; |
657 | | |
658 | 14 | proto_msgpack = proto_register_protocol("Message Pack", "MsgPack", "msgpack"); |
659 | 14 | msgpack_handle = register_dissector("msgpack", dissect_msgpack, proto_msgpack); |
660 | | |
661 | 14 | expert_msgpack = expert_register_protocol(proto_msgpack); |
662 | 14 | expert_register_field_array(expert_msgpack, ei, array_length(ei)); |
663 | | |
664 | 14 | proto_register_field_array(proto_msgpack, hf, array_length(hf)); |
665 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
666 | 14 | } |
667 | | |
668 | | void proto_reg_handoff_msgpack(void) |
669 | 14 | { |
670 | | // If this is ever streamed (transported over TCP) we need to add recursion checks |
671 | 14 | dissector_add_for_decode_as("udp.port", msgpack_handle); |
672 | 14 | } |
673 | | |
674 | | /* |
675 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
676 | | * |
677 | | * Local variables: |
678 | | * c-basic-offset: 8 |
679 | | * tab-width: 8 |
680 | | * indent-tabs-mode: t |
681 | | * End: |
682 | | * |
683 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
684 | | * :indentSize=8:tabSize=8:noTabs=false: |
685 | | */ |