File: | builds/wireshark/wireshark/epan/dissectors/packet-msgpack.c |
Warning: | line 207, column 12 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | 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((void*)0)} | |||
105 | }; | |||
106 | ||||
107 | static void dissect_msgpack_object(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data, int* offset, char** value); | |||
108 | ||||
109 | static void dissect_msgpack_integer(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree, uint8_t type, void* data, int* offset, char** value) | |||
110 | { | |||
111 | uint8_t uint8; | |||
112 | uint16_t uint16; | |||
113 | uint32_t uint32; | |||
114 | uint64_t uint64; | |||
115 | int8_t int8; | |||
116 | int16_t int16; | |||
117 | int32_t int32; | |||
118 | int64_t int64; | |||
119 | char* label; | |||
120 | proto_tree* subtree; | |||
121 | proto_item* ti; | |||
122 | int t_offset = *offset; | |||
123 | ||||
124 | label = (data ? (char*)data : "MsgPack Integer"); | |||
125 | ||||
126 | if (type >> 7 == 0) { | |||
127 | ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_fix, tvb, *offset, 1, type, "%s: %u", label, type); | |||
128 | subtree = proto_item_add_subtree(ti, ett_msgpack_num); | |||
129 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA0x00000000); | |||
130 | ||||
131 | if (value) | |||
132 | *value = wmem_strdup_printf(pinfo->pool, "%u", type); | |||
133 | *offset += 1; | |||
134 | return; | |||
135 | } | |||
136 | ||||
137 | if (type >> 5 == 7) { | |||
138 | int8_t stype = (int8_t)type; | |||
139 | ti = proto_tree_add_int_format(tree, hf_msgpack_int_fix, tvb, *offset, 1, stype, "%s: %d", label, stype); | |||
140 | subtree = proto_item_add_subtree(ti, ett_msgpack_num); | |||
141 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA0x00000000); | |||
142 | ||||
143 | if (value) | |||
144 | *value = wmem_strdup_printf(pinfo->pool, "%d", stype); | |||
145 | *offset += 1; | |||
146 | return; | |||
147 | } | |||
148 | ||||
149 | switch (type) { | |||
150 | case 0xcc: | |||
151 | uint8 = tvb_get_uint8(tvb, *offset + 1); | |||
152 | ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_8, tvb, *offset, 2, uint8, "%s: %u", label, uint8); | |||
153 | if (value) | |||
154 | *value = wmem_strdup_printf(pinfo->pool, "%u", uint8); | |||
155 | *offset += 2; | |||
156 | break; | |||
157 | case 0xcd: | |||
158 | uint16 = tvb_get_ntohs(tvb, *offset + 1); | |||
159 | ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_16, tvb, *offset, 3, uint16, "%s: %u", label, uint16); | |||
160 | if (value) | |||
161 | *value = wmem_strdup_printf(pinfo->pool, "%u", uint16); | |||
162 | *offset += 3; | |||
163 | break; | |||
164 | case 0xce: | |||
165 | uint32 = tvb_get_ntohl(tvb, *offset + 1); | |||
166 | ti = proto_tree_add_uint_format(tree, hf_msgpack_uint_32, tvb, *offset, 5, uint32, "%s: %u", label, uint32); | |||
167 | if (value) | |||
168 | *value = wmem_strdup_printf(pinfo->pool, "%u", uint32); | |||
169 | *offset += 5; | |||
170 | break; | |||
171 | case 0xcf: | |||
172 | uint64 = tvb_get_ntoh64(tvb, *offset + 1); | |||
173 | ti = proto_tree_add_uint64_format(tree, hf_msgpack_uint_64, tvb, *offset, 9, uint64, "%s: %" PRIu64"l" "u", label, uint64); | |||
174 | if (value) | |||
175 | *value = wmem_strdup_printf(pinfo->pool, "%" PRIu64"l" "u", uint64); | |||
176 | *offset += 9; | |||
177 | break; | |||
178 | case 0xd0: | |||
179 | int8 = tvb_get_int8(tvb, *offset + 1); | |||
180 | ti = proto_tree_add_int_format(tree, hf_msgpack_int_8, tvb, *offset, 2, int8, "%s: %d", label, int8); | |||
181 | if (value) | |||
182 | *value = wmem_strdup_printf(pinfo->pool, "%d", int8); | |||
183 | *offset += 2; | |||
184 | break; | |||
185 | case 0xd1: | |||
186 | int16 = tvb_get_ntohs(tvb, *offset + 1); | |||
187 | ti = proto_tree_add_int_format(tree, hf_msgpack_int_16, tvb, *offset, 3, int16, "%s: %d", label, int16); | |||
188 | if (value) | |||
189 | *value = wmem_strdup_printf(pinfo->pool, "%d", int16); | |||
190 | *offset += 3; | |||
191 | break; | |||
192 | case 0xd2: | |||
193 | int32 = tvb_get_ntohl(tvb, *offset + 1); | |||
194 | ti = proto_tree_add_int_format(tree, hf_msgpack_int_32, tvb, *offset, 5, int32, "%s: %d", label, int32); | |||
195 | if (value) | |||
196 | *value = wmem_strdup_printf(pinfo->pool, "%d", int32); | |||
197 | *offset += 5; | |||
198 | break; | |||
199 | case 0xd3: | |||
200 | int64 = tvb_get_ntoh64(tvb, *offset + 1); | |||
201 | ti = proto_tree_add_int64_format(tree, hf_msgpack_int_64, tvb, *offset, 9, int64, "%s: %" PRId64"l" "d", label, int64); | |||
202 | if (value) | |||
203 | *value = wmem_strdup_printf(pinfo->pool, "%" PRId64"l" "d", int64); | |||
204 | *offset += 9; | |||
205 | break; | |||
206 | } | |||
207 | subtree = proto_item_add_subtree(ti, ett_msgpack_num); | |||
| ||||
208 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, t_offset, 1, ENC_NA0x00000000); | |||
209 | } | |||
210 | ||||
211 | // NOLINTNEXTLINE(misc-no-recursion) | |||
212 | static void dissect_msgpack_map(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, uint8_t type, void* data, int* offset, char** value) | |||
213 | { | |||
214 | proto_tree* subtree; | |||
215 | proto_tree* map_subtree; | |||
216 | proto_item* ti; | |||
217 | uint32_t len = 0; | |||
218 | uint8_t lensize = 0; | |||
219 | char* label; | |||
220 | unsigned i; | |||
221 | ||||
222 | if (type >> 4 == 0x8) { | |||
223 | len = type & 0x0F; | |||
224 | lensize = 0; | |||
225 | } | |||
226 | else if (type == 0xde) { | |||
227 | len = tvb_get_ntohs(tvb, *offset + 1); | |||
228 | lensize = 2; | |||
229 | } | |||
230 | else if (type == 0xdf) { | |||
231 | len = tvb_get_ntohl(tvb, *offset + 1); | |||
232 | lensize = 4; | |||
233 | } | |||
234 | ||||
235 | label = wmem_strdup_printf(pinfo->pool, "%s: %u element%s", data ? (char*)data : "MsgPack Map", len, len > 1 ? "s" : ""); | |||
236 | ||||
237 | ti = proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1 + lensize, NULL((void*)0), "%s", label); | |||
238 | subtree = proto_item_add_subtree(ti, ett_msgpack_map); | |||
239 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA0x00000000); | |||
240 | *offset += lensize + 1; | |||
241 | for (i = 0; i < len; i++) { | |||
242 | // We recurse here, but we'll run out of packet before we run out of stack. | |||
243 | map_subtree = proto_tree_add_subtree(subtree, tvb, *offset, 0, ett_msgpack_map_elem, NULL((void*)0), ""); | |||
244 | dissect_msgpack_object(tvb, pinfo, map_subtree, "Key", offset, value); | |||
245 | if (value) | |||
246 | proto_item_append_text(map_subtree, " %s:", *value); | |||
247 | dissect_msgpack_object(tvb, pinfo, map_subtree, "Value", offset, value); | |||
248 | if (value) | |||
249 | proto_item_append_text(map_subtree, " %s", *value); | |||
250 | } | |||
251 | ||||
252 | if (value) | |||
253 | *value = label; | |||
254 | } | |||
255 | ||||
256 | // NOLINTNEXTLINE(misc-no-recursion) | |||
257 | static void dissect_msgpack_array(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, uint8_t type, void* data, int* offset, char** value) | |||
258 | { | |||
259 | proto_tree* subtree; | |||
260 | proto_item* ti; | |||
261 | uint32_t len = 0; | |||
262 | uint8_t lensize = 0; | |||
263 | char* label; | |||
264 | unsigned i; | |||
265 | ||||
266 | if (type >> 4 == 0x9) { | |||
267 | len = type & 0x0F; | |||
268 | lensize = 0; | |||
269 | } | |||
270 | else if (type == 0xdc) { | |||
271 | len = tvb_get_ntohs(tvb, *offset + 1); | |||
272 | lensize = 2; | |||
273 | } | |||
274 | else if (type == 0xdd) { | |||
275 | len = tvb_get_ntohl(tvb, *offset + 1); | |||
276 | lensize = 4; | |||
277 | } | |||
278 | ||||
279 | label = wmem_strdup_printf(pinfo->pool, "%s %u element%s", data ? (char*)data : "MsgPack Array", len, len > 1 ? "s" : ""); | |||
280 | ||||
281 | ti = proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1 + lensize, NULL((void*)0), "%s", label); | |||
282 | subtree = proto_item_add_subtree(ti, ett_msgpack_array); | |||
283 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA0x00000000); | |||
284 | *offset += lensize + 1; | |||
285 | for (i = 0; i < len; i++) { | |||
286 | // We recurse here, but we'll run out of packet before we run out of stack. | |||
287 | dissect_msgpack_object(tvb, pinfo, subtree, data, offset, value); | |||
288 | } | |||
289 | ||||
290 | if (value) | |||
291 | *value = label; | |||
292 | } | |||
293 | ||||
294 | static void dissect_msgpack_string(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int type, void* data, int* offset, char** value) | |||
295 | { | |||
296 | uint32_t len = 0; | |||
297 | uint8_t lensize = 0; | |||
298 | char* label; | |||
299 | proto_item* ti; | |||
300 | proto_tree* subtree; | |||
301 | char* lvalue; | |||
302 | ||||
303 | if (type >> 5 == 0x5) { | |||
304 | len = type & 0x1F; | |||
305 | lensize = 0; | |||
306 | } | |||
307 | else if (type == 0xd9) { | |||
308 | len = tvb_get_uint8(tvb, *offset + 1); | |||
309 | lensize = 1; | |||
310 | } | |||
311 | else if (type == 0xda) { | |||
312 | len = tvb_get_ntohs(tvb, *offset + 1); | |||
313 | lensize = 2; | |||
314 | } | |||
315 | else if (type == 0xdb) { | |||
316 | len = tvb_get_ntohl(tvb, *offset + 1); | |||
317 | lensize = 4; | |||
318 | } | |||
319 | ||||
320 | lvalue = (char*)tvb_get_string_enc(pinfo->pool, tvb, *offset + 1 + lensize, len, ENC_UTF_80x00000002); | |||
321 | label = (data ? (char*)data : "MsgPack String"); | |||
322 | ||||
323 | ti = proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1 + lensize + len, lvalue, "%s: %s", label, lvalue); | |||
324 | subtree = proto_item_add_subtree(ti, ett_msgpack_string); | |||
325 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA0x00000000); | |||
326 | ||||
327 | if (lensize == 0) { | |||
328 | proto_tree_add_uint(subtree, hf_msgpack_string_len, tvb, *offset, 1, len); | |||
329 | *offset += 1; | |||
330 | } | |||
331 | else { | |||
332 | *offset += 1; | |||
333 | proto_tree_add_item(subtree, hf_msgpack_string_len, tvb, *offset, lensize, ENC_BIG_ENDIAN0x00000000); | |||
334 | *offset += lensize; | |||
335 | } | |||
336 | proto_tree_add_item(subtree, hf_msgpack_string, tvb, *offset, len, ENC_UTF_80x00000002); | |||
337 | *offset += len; | |||
338 | ||||
339 | if (value) | |||
340 | *value = lvalue; | |||
341 | } | |||
342 | ||||
343 | static void dissect_msgpack_bin(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, int type, void* data, int* offset, char** value) | |||
344 | { | |||
345 | uint32_t len = 0; | |||
346 | uint8_t lensize = 0; | |||
347 | char* label; | |||
348 | proto_item* ti; | |||
349 | proto_tree* subtree; | |||
350 | char* lvalue; | |||
351 | ||||
352 | switch (type) { | |||
353 | case 0xc4: | |||
354 | len = tvb_get_uint8(tvb, *offset + 1); | |||
355 | lensize = 1; | |||
356 | break; | |||
357 | case 0xc5: | |||
358 | len = tvb_get_ntohs(tvb, *offset + 1); | |||
359 | lensize = 2; | |||
360 | break; | |||
361 | case 0xc6: | |||
362 | len = tvb_get_ntohl(tvb, *offset + 1); | |||
363 | lensize = 4; | |||
364 | break; | |||
365 | } | |||
366 | ||||
367 | lvalue = (char*)tvb_bytes_to_str(pinfo->pool, tvb, *offset + 1 + lensize, len); | |||
368 | label = (data ? (char*)data : "MsgPack Bytes"); | |||
369 | ||||
370 | ti = proto_tree_add_bytes_format(tree, hf_msgpack_bin, tvb, *offset, 1 + lensize + len, lvalue, "%s: %s", label, lvalue); | |||
371 | subtree = proto_item_add_subtree(ti, ett_msgpack_bin); | |||
372 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA0x00000000); | |||
373 | ||||
374 | *offset += 1; | |||
375 | proto_tree_add_item(subtree, hf_msgpack_bin_len, tvb, *offset, lensize, ENC_BIG_ENDIAN0x00000000); | |||
376 | *offset += lensize; | |||
377 | ||||
378 | proto_tree_add_item(subtree, hf_msgpack_bin, tvb, *offset, len, ENC_NA0x00000000); | |||
379 | *offset += len; | |||
380 | ||||
381 | if (value) | |||
382 | *value = lvalue; | |||
383 | } | |||
384 | ||||
385 | static void dissect_msgpack_float(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree, int type, void* data, int* offset, char** value) | |||
386 | { | |||
387 | char* label; | |||
388 | char* lvalue; | |||
389 | proto_item* ti; | |||
390 | proto_tree* subtree; | |||
391 | int s_offset = *offset; | |||
392 | ||||
393 | *offset += 1; | |||
394 | ||||
395 | if (type == 0xca) { | |||
396 | label = (data ? (char*)data : "MsgPack Float"); | |||
397 | float f = tvb_get_ntohieee_float(tvb, *offset); | |||
398 | lvalue = wmem_strdup_printf(pinfo->pool, "%f", f); | |||
399 | ti = proto_tree_add_float_format(tree, hf_msgpack_float, tvb, *offset, 4, f, "%s: %f", label, f); | |||
400 | if (value) | |||
401 | *value = lvalue; | |||
402 | *offset += 4; | |||
403 | } else { | |||
404 | label = (data ? (char*)data : "MsgPack Double"); | |||
405 | double d = tvb_get_ntohieee_double(tvb, *offset); | |||
406 | lvalue = wmem_strdup_printf(pinfo->pool, "%lf", d); | |||
407 | ti = proto_tree_add_double_format(tree, hf_msgpack_double, tvb, *offset, 8, d, "%s: %lf", label, d); | |||
408 | if (value) | |||
409 | *value = lvalue; | |||
410 | *offset += 8; | |||
411 | } | |||
412 | subtree = proto_item_add_subtree(ti, ett_msgpack_num); | |||
413 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, s_offset, 1, ENC_NA0x00000000); | |||
414 | } | |||
415 | ||||
416 | static void dissect_msgpack_ext(tvbuff_t* tvb, packet_info *pinfo, proto_tree* tree, int type, void* data, int* offset, char** value) | |||
417 | { | |||
418 | char* label; | |||
419 | uint32_t len = 0; | |||
420 | uint8_t lensize = 0; | |||
421 | proto_tree* subtree; | |||
422 | unsigned offset_start = *offset; | |||
423 | ||||
424 | label = (data ? (char*)data : "Ext"); | |||
425 | ||||
426 | subtree = proto_tree_add_subtree(tree, tvb, *offset, 0, ett_msgpack_ext, NULL((void*)0), label); | |||
427 | ||||
428 | proto_tree_add_item(subtree, hf_msgpack_type, tvb, *offset, 1, ENC_NA0x00000000); | |||
429 | if (type >= 0xd4 && type <= 0xd8) { | |||
430 | len = 1 << (type - 0xd4); | |||
431 | proto_tree_add_uint(subtree, hf_msgpack_ext_len, tvb, *offset, 1, len); | |||
432 | } | |||
433 | else if (type == 0xc7) { | |||
434 | len = tvb_get_uint8(tvb, *offset + 2); | |||
435 | lensize = 1; | |||
436 | } | |||
437 | else if (type == 0xc8) { | |||
438 | len = tvb_get_ntohs(tvb, *offset + 2); | |||
439 | lensize = 2; | |||
440 | } | |||
441 | else if (type == 0xc9) { | |||
442 | len = tvb_get_ntohl(tvb, *offset + 2); | |||
443 | lensize = 4; | |||
444 | } | |||
445 | *offset += 1; | |||
446 | ||||
447 | proto_tree_add_item(subtree, hf_msgpack_ext_type, tvb, *offset, 1, ENC_NA0x00000000); | |||
448 | *offset += 1; | |||
449 | ||||
450 | if (lensize > 0) { | |||
451 | proto_tree_add_item(subtree, hf_msgpack_ext_len, tvb, *offset, lensize, ENC_BIG_ENDIAN0x00000000); | |||
452 | *offset += lensize; | |||
453 | } | |||
454 | proto_tree_add_item(subtree, hf_msgpack_ext_bytes, tvb, *offset, len, ENC_NA0x00000000); | |||
455 | if (value) { | |||
456 | *value = tvb_bytes_to_str(pinfo->pool, tvb, *offset, len); | |||
457 | } | |||
458 | *offset += len; | |||
459 | ||||
460 | proto_item_set_len(subtree, *offset - offset_start); | |||
461 | } | |||
462 | ||||
463 | // NOLINTNEXTLINE(misc-no-recursion) | |||
464 | static void dissect_msgpack_object(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data, int* offset, char** value) | |||
465 | { | |||
466 | uint8_t type; | |||
467 | int s_offset = *offset; | |||
468 | ||||
469 | type = tvb_get_uint8(tvb, *offset); | |||
470 | ||||
471 | // Nil | |||
472 | if (type == 0xc0) { | |||
473 | proto_tree_add_string_format(tree, hf_msgpack_string, tvb, *offset, 1, "nil", "nil"); | |||
474 | if (value) | |||
475 | *value = "nil"; | |||
476 | *offset += 1; | |||
477 | return; | |||
478 | } | |||
479 | ||||
480 | // True/False | |||
481 | if (type == 0xc2 || type == 0xc3) { | |||
482 | proto_tree_add_boolean(tree, hf_msgpack_bool, tvb, *offset, 1, type - 0xc2); | |||
483 | if (value) | |||
484 | *value = (type - 0xc2) ? "True" : "False"; | |||
485 | *offset += 1; | |||
486 | return; | |||
487 | } | |||
488 | ||||
489 | // Integer | |||
490 | if (type >= 0xe0 || type <= 0x7f || (type >= 0xcc && type <= 0xd3)) { | |||
491 | dissect_msgpack_integer(tvb, pinfo, tree, type, data, offset, value); | |||
492 | return; | |||
493 | } | |||
494 | ||||
495 | // Float | |||
496 | if (type == 0xca || type == 0xcb) { | |||
497 | dissect_msgpack_float(tvb, pinfo, tree, type, data, offset, value); | |||
498 | return; | |||
499 | } | |||
500 | ||||
501 | // String | |||
502 | if (type >> 5 == 0x5 || type == 0xd9 || type == 0xda || type == 0xdb) { | |||
503 | dissect_msgpack_string(tvb, pinfo, tree, type, data, offset, value); | |||
504 | return; | |||
505 | } | |||
506 | ||||
507 | // Bin | |||
508 | if (type == 0xc4 || type == 0xc5 || type == 0xc6) { | |||
509 | dissect_msgpack_bin(tvb, pinfo, tree, type, data, offset, value); | |||
510 | return; | |||
511 | } | |||
512 | ||||
513 | // Array | |||
514 | if (type >> 4 == 0x9 || type == 0xdc || type == 0xdd) { | |||
515 | // We recurse here, but we'll run out of packet before we run out of stack. | |||
516 | dissect_msgpack_array(tvb, pinfo, tree, type, data, offset, value); | |||
517 | return; | |||
518 | } | |||
519 | ||||
520 | // Map | |||
521 | if (type >> 4 == 0x8 || type == 0xde || type == 0xdf) { | |||
522 | // We recurse here, but we'll run out of packet before we run out of stack. | |||
523 | dissect_msgpack_map(tvb, pinfo, tree, type, data, offset, value); | |||
524 | return; | |||
525 | } | |||
526 | ||||
527 | // Ext | |||
528 | if ((type >= 0xd4 && type <= 0xd8) || (type >= 0xc7 && type <= 0xc9)) { | |||
529 | dissect_msgpack_ext(tvb, pinfo, tree, type, data, offset, value); | |||
530 | return; | |||
531 | } | |||
532 | ||||
533 | if (*offset - s_offset == 0) { | |||
534 | expert_add_info_format(pinfo, tree, &ei_msgpack_unsupported, "Type 0x%x is unsupported", type); | |||
535 | } | |||
536 | } | |||
537 | ||||
538 | static int dissect_msgpack(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data) | |||
539 | { | |||
540 | int offset = 0; | |||
541 | dissect_msgpack_object(tvb, pinfo, tree, data, &offset, NULL((void*)0)); | |||
| ||||
542 | return offset; | |||
543 | } | |||
544 | ||||
545 | void proto_register_msgpack(void) | |||
546 | { | |||
547 | expert_module_t* expert_msgpack; | |||
548 | ||||
549 | static hf_register_info hf[] = { | |||
550 | { &hf_msgpack_string, | |||
551 | { "String", "msgpack.string", FT_STRING, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
552 | }, | |||
553 | { &hf_msgpack_type, | |||
554 | { "Type", "msgpack.type", FT_UINT8, BASE_HEX|BASE_RANGE_STRING0x00000100, RVALS(msgpack_types)((0 ? (const struct _range_string*)0 : ((msgpack_types)))), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
555 | }, | |||
556 | { &hf_msgpack_string_len, | |||
557 | { "Length", "msgpack.string.len", FT_UINT32, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
558 | }, | |||
559 | { &hf_msgpack_bin, | |||
560 | { "Bytes", "msgpack.bin", FT_BYTES, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
561 | }, | |||
562 | { &hf_msgpack_bin_len, | |||
563 | { "Length", "msgpack.bin.len", FT_UINT32, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
564 | }, | |||
565 | { &hf_msgpack_uint_fix, | |||
566 | { "Integer", "msgpack.integer.fixint", FT_UINT8, BASE_DEC, NULL((void*)0), 0x7F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
567 | }, | |||
568 | { &hf_msgpack_uint_8, | |||
569 | { "Integer", "msgpack.integer.u8", FT_UINT8, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
570 | }, | |||
571 | { &hf_msgpack_uint_16, | |||
572 | { "Integer", "msgpack.integer.u16", FT_UINT16, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
573 | }, | |||
574 | { &hf_msgpack_uint_32, | |||
575 | { "Integer", "msgpack.integer.u32", FT_UINT32, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
576 | }, | |||
577 | { &hf_msgpack_uint_64, | |||
578 | { "Integer", "msgpack.integer.u64", FT_UINT64, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
579 | }, | |||
580 | { &hf_msgpack_int_fix, | |||
581 | { "Integer", "msgpack.integer.fixint", FT_INT8, BASE_DEC, NULL((void*)0), 0x1F, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
582 | }, | |||
583 | { &hf_msgpack_int_8, | |||
584 | { "Integer", "msgpack.integer.8", FT_INT8, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
585 | }, | |||
586 | { &hf_msgpack_int_16, | |||
587 | { "Integer", "msgpack.integer.16", FT_INT16, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
588 | }, | |||
589 | { &hf_msgpack_int_32, | |||
590 | { "Integer", "msgpack.integer.32", FT_INT32, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
591 | }, | |||
592 | { &hf_msgpack_int_64, | |||
593 | { "Integer", "msgpack.integer.64", FT_INT64, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
594 | }, | |||
595 | { &hf_msgpack_bool, | |||
596 | { "Boolean", "msgpack.boolean", FT_BOOLEAN, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
597 | }, | |||
598 | { &hf_msgpack_float, | |||
599 | { "Float", "msgpack.float", FT_FLOAT, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
600 | }, | |||
601 | { &hf_msgpack_double, | |||
602 | { "Double", "msgpack.double", FT_DOUBLE, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
603 | }, | |||
604 | { &hf_msgpack_ext_type, | |||
605 | { "Ext type", "msgpack.ext.type", FT_INT8, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
606 | }, | |||
607 | { &hf_msgpack_ext_len, | |||
608 | { "Length", "msgpack.ext.len", FT_UINT32, BASE_DEC, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
609 | }, | |||
610 | { &hf_msgpack_ext_bytes, | |||
611 | { "Ext", "msgpack.ext", FT_BYTES, BASE_NONE, NULL((void*)0), 0x00, NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) } | |||
612 | } | |||
613 | }; | |||
614 | ||||
615 | static int* ett[] = { | |||
616 | &ett_msgpack, | |||
617 | &ett_msgpack_num, | |||
618 | &ett_msgpack_string, | |||
619 | &ett_msgpack_bin, | |||
620 | &ett_msgpack_array, | |||
621 | &ett_msgpack_map, | |||
622 | &ett_msgpack_map_elem, | |||
623 | &ett_msgpack_ext | |||
624 | }; | |||
625 | ||||
626 | static ei_register_info ei[] = { | |||
627 | { &ei_msgpack_unsupported, { "msgpack.unsupported", PI_UNDECODED0x05000000, PI_WARN0x00600000, "Unsupported type", EXPFILL0, ((void*)0), 0, {0, {((void*)0), ((void*)0), FT_NONE, BASE_NONE , ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE, -1, ((void *)0)}} }} | |||
628 | }; | |||
629 | ||||
630 | proto_msgpack = proto_register_protocol("Message Pack", "MsgPack", "msgpack"); | |||
631 | msgpack_handle = register_dissector("msgpack", dissect_msgpack, proto_msgpack); | |||
632 | ||||
633 | expert_msgpack = expert_register_protocol(proto_msgpack); | |||
634 | expert_register_field_array(expert_msgpack, ei, array_length(ei)(sizeof (ei) / sizeof (ei)[0])); | |||
635 | ||||
636 | proto_register_field_array(proto_msgpack, hf, array_length(hf)(sizeof (hf) / sizeof (hf)[0])); | |||
637 | proto_register_subtree_array(ett, array_length(ett)(sizeof (ett) / sizeof (ett)[0])); | |||
638 | } | |||
639 | ||||
640 | void proto_reg_handoff_msgpack(void) | |||
641 | { | |||
642 | // If this is ever streamed (transported over TCP) we need to add recursion checks | |||
643 | dissector_add_for_decode_as("udp.port", msgpack_handle); | |||
644 | } | |||
645 | ||||
646 | /* | |||
647 | * Editor modelines - https://www.wireshark.org/tools/modelines.html | |||
648 | * | |||
649 | * Local variables: | |||
650 | * c-basic-offset: 8 | |||
651 | * tab-width: 8 | |||
652 | * indent-tabs-mode: t | |||
653 | * End: | |||
654 | * | |||
655 | * vi: set shiftwidth=8 tabstop=8 noexpandtab: | |||
656 | * :indentSize=8:tabSize=8:noTabs=false: | |||
657 | */ |