Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-yami.c
bloba9418da09b341d22cd4409e741c2e486cc5a0e6d
1 /* packet-yami.c
2 * Routines for YAMI dissection
3 * Copyright 2010, Pawel Korbut
4 * Copyright 2012, Jakub Zawadzki <darkjames-ws@darkjames.pl>
6 * Protocol documentation available at http://www.inspirel.com/yami4/book/B-2.html
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * SPDX-License-Identifier: GPL-2.0-or-later
14 #include "config.h"
16 #include <epan/packet.h>
17 #include <epan/prefs.h>
18 #include <epan/to_str.h>
19 #include <wsutil/ws_roundup.h>
20 #include "packet-tcp.h"
22 void proto_reg_handoff_yami(void);
23 void proto_register_yami(void);
25 static bool yami_desegment = true;
27 static dissector_handle_t yami_handle;
29 #define YAMI_TYPE_BOOLEAN 1
30 #define YAMI_TYPE_INTEGER 2
31 #define YAMI_TYPE_LONGLONG 3
32 #define YAMI_TYPE_DOUBLE 4
33 #define YAMI_TYPE_STRING 5
34 #define YAMI_TYPE_BINARY 6
35 #define YAMI_TYPE_BOOLEAN_ARRAY 7
36 #define YAMI_TYPE_INTEGER_ARRAY 8
37 #define YAMI_TYPE_LONGLONG_ARRAY 9
38 #define YAMI_TYPE_DOUBLE_ARRAY 10
39 #define YAMI_TYPE_STRING_ARRAY 11
40 #define YAMI_TYPE_BINARY_ARRAY 12
41 #define YAMI_TYPE_NESTED 13
43 static const value_string yami_param_type_vals[] = {
44 { YAMI_TYPE_BOOLEAN, "boolean" },
45 { YAMI_TYPE_INTEGER, "integer" },
46 { YAMI_TYPE_LONGLONG, "long long" },
47 { YAMI_TYPE_DOUBLE, "double" },
48 { YAMI_TYPE_STRING, "string" },
49 { YAMI_TYPE_BINARY, "binary" },
50 { YAMI_TYPE_BOOLEAN_ARRAY, "boolean array" },
51 { YAMI_TYPE_INTEGER_ARRAY, "integer array" },
52 { YAMI_TYPE_LONGLONG_ARRAY, "long long array" },
53 { YAMI_TYPE_DOUBLE_ARRAY, "double array" },
54 { YAMI_TYPE_STRING_ARRAY, "string array" },
55 { YAMI_TYPE_BINARY_ARRAY, "binary array" },
56 { YAMI_TYPE_NESTED, "nested parameters" },
57 { 0, NULL }
60 static int proto_yami;
62 static int hf_yami_frame_number;
63 static int hf_yami_frame_payload_size;
64 static int hf_yami_items_count;
65 static int hf_yami_message_data;
66 static int hf_yami_message_hdr;
67 static int hf_yami_message_header_size;
68 static int hf_yami_message_id;
69 static int hf_yami_param;
70 static int hf_yami_param_name;
71 static int hf_yami_param_type;
72 static int hf_yami_param_value_bin;
73 static int hf_yami_param_value_bool;
74 static int hf_yami_param_value_double;
75 static int hf_yami_param_value_int;
76 static int hf_yami_param_value_long;
77 static int hf_yami_param_value_str;
78 static int hf_yami_params_count;
80 static int ett_yami;
81 static int ett_yami_msg_hdr;
82 static int ett_yami_msg_data;
83 static int ett_yami_param;
85 static int
86 // NOLINTNEXTLINE(misc-no-recursion)
87 dissect_yami_parameter(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, proto_item *par_ti)
89 const int orig_offset = offset;
91 proto_tree *yami_param;
92 proto_item *ti;
94 char *name;
95 int name_offset;
96 uint32_t name_len;
98 uint32_t type;
100 ti = proto_tree_add_item(tree, hf_yami_param, tvb, offset, 0, ENC_NA);
101 yami_param = proto_item_add_subtree(ti, ett_yami_param);
103 name_offset = offset;
104 name_len = tvb_get_letohl(tvb, offset);
105 offset += 4;
107 name = tvb_get_string_enc(pinfo->pool, tvb, offset, name_len, ENC_ASCII | ENC_NA);
108 proto_item_append_text(ti, ": %s", name);
109 proto_item_append_text(par_ti, "%s, ", name);
110 offset += WS_ROUNDUP_4(name_len);
111 proto_tree_add_string(yami_param, hf_yami_param_name, tvb, name_offset, offset - name_offset, name);
113 type = tvb_get_letohl(tvb, offset);
114 proto_tree_add_item(yami_param, hf_yami_param_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
115 offset += 4;
117 switch (type) {
118 case YAMI_TYPE_BOOLEAN:
120 uint32_t val = tvb_get_letohl(tvb, offset);
121 proto_item_append_text(ti, ", Type: boolean, Value: %s", val ? "True" : "False");
122 proto_tree_add_item(yami_param, hf_yami_param_value_bool, tvb, offset, 4, ENC_LITTLE_ENDIAN);
123 offset += 4;
124 break;
127 case YAMI_TYPE_INTEGER:
129 int32_t val = tvb_get_letohl(tvb, offset);
130 proto_item_append_text(ti, ", Type: integer, Value: %d", val);
131 proto_tree_add_item(yami_param, hf_yami_param_value_int, tvb, offset, 4, ENC_LITTLE_ENDIAN);
132 offset += 4;
133 break;
136 case YAMI_TYPE_LONGLONG:
138 int64_t val = tvb_get_letoh64(tvb, offset);
139 proto_item_append_text(ti, ", Type: long, Value: %" PRId64, val);
140 proto_tree_add_item(yami_param, hf_yami_param_value_long, tvb, offset, 8, ENC_LITTLE_ENDIAN);
141 offset += 8;
142 break;
145 case YAMI_TYPE_DOUBLE:
147 double val = tvb_get_letohieee_double(tvb, offset);
148 proto_item_append_text(ti, ", Type: double, Value: %g", val);
149 proto_tree_add_item(yami_param, hf_yami_param_value_double, tvb, offset, 8, ENC_LITTLE_ENDIAN);
150 offset += 8;
151 break;
154 case YAMI_TYPE_STRING:
156 const int val_offset = offset;
157 uint32_t val_len;
158 char *val;
160 val_len = tvb_get_letohl(tvb, offset);
161 offset += 4;
163 val = tvb_get_string_enc(pinfo->pool, tvb, offset, val_len, ENC_ASCII | ENC_NA);
165 proto_item_append_text(ti, ", Type: string, Value: \"%s\"", val);
166 offset += WS_ROUNDUP_4(val_len);
167 proto_tree_add_string(yami_param, hf_yami_param_value_str, tvb, val_offset, offset - val_offset, val);
168 break;
171 case YAMI_TYPE_BINARY:
173 const int val_offset = offset;
174 uint32_t val_len;
175 const uint8_t *val;
176 char *repr;
178 val_len = tvb_get_letohl(tvb, offset);
179 offset += 4;
181 val = tvb_get_ptr(tvb, offset, val_len);
182 repr = bytes_to_str(pinfo->pool, val, val_len);
184 proto_item_append_text(ti, ", Type: binary, Value: %s", repr);
185 offset += WS_ROUNDUP_4(val_len);
186 proto_tree_add_bytes_format_value(yami_param, hf_yami_param_value_bin, tvb, val_offset, offset - val_offset, val, "%s", repr);
187 break;
190 case YAMI_TYPE_BOOLEAN_ARRAY:
192 uint32_t count;
193 unsigned i;
194 int j;
196 count = tvb_get_letohl(tvb, offset);
197 proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
198 offset += 4;
200 proto_item_append_text(ti, ", Type: boolean[], %u items: {", count);
202 for (i = 0; i < count/32; i++) {
203 uint32_t val = tvb_get_letohl(tvb, offset);
205 for (j = 0; j < 32; j++) {
206 int r = !!(val & (1U << j));
208 proto_item_append_text(ti, "%s, ", r ? "T" : "F");
209 proto_tree_add_boolean(yami_param, hf_yami_param_value_bool, tvb, offset+(j/8), 1, r);
211 offset += 4;
214 if (count % 32) {
215 uint32_t val = tvb_get_letohl(tvb, offset);
216 int tmp = count % 32;
218 for (j = 0; j < tmp; j++) {
219 int r = !!(val & (1 << j));
221 proto_item_append_text(ti, "%s, ", r ? "T" : "F");
222 proto_tree_add_boolean(yami_param, hf_yami_param_value_bool, tvb, offset+(j/8), 1, r);
224 offset += 4;
227 proto_item_append_text(ti, "}");
228 break;
231 case YAMI_TYPE_INTEGER_ARRAY:
233 uint32_t count;
234 unsigned i;
236 count = tvb_get_letohl(tvb, offset);
237 proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
238 offset += 4;
240 proto_item_append_text(ti, ", Type: integer[], %u items: {", count);
241 for (i = 0; i < count; i++) {
242 int32_t val = tvb_get_letohl(tvb, offset);
244 proto_item_append_text(ti, "%d, ", val);
245 proto_tree_add_item(yami_param, hf_yami_param_value_int, tvb, offset, 4, ENC_LITTLE_ENDIAN);
246 offset += 4;
248 proto_item_append_text(ti, "}");
249 break;
252 case YAMI_TYPE_LONGLONG_ARRAY:
254 uint32_t count;
255 unsigned i;
257 count = tvb_get_letohl(tvb, offset);
258 proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
259 offset += 4;
261 proto_item_append_text(ti, ", Type: long long[], %u items: {", count);
263 for (i = 0; i < count; i++) {
264 int64_t val = tvb_get_letoh64(tvb, offset);
266 proto_item_append_text(ti, "%" PRId64 ", ", val);
267 proto_tree_add_item(yami_param, hf_yami_param_value_long, tvb, offset, 8, ENC_LITTLE_ENDIAN);
268 offset += 8;
270 proto_item_append_text(ti, "}");
271 break;
274 case YAMI_TYPE_DOUBLE_ARRAY:
276 uint32_t count;
277 unsigned i;
279 count = tvb_get_letohl(tvb, offset);
280 proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
281 offset += 4;
283 proto_item_append_text(ti, ", Type: double[], %u items: {", count);
285 for (i = 0; i < count; i++) {
286 double val = tvb_get_letohieee_double(tvb, offset);
288 proto_item_append_text(ti, "%g, ", val);
289 proto_tree_add_item(yami_param, hf_yami_param_value_double, tvb, offset, 8, ENC_LITTLE_ENDIAN);
290 offset += 8;
292 proto_item_append_text(ti, "}");
293 break;
296 case YAMI_TYPE_STRING_ARRAY:
298 uint32_t count;
299 unsigned i;
301 count = tvb_get_letohl(tvb, offset);
302 proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
303 offset += 4;
305 proto_item_append_text(ti, ", Type: string[], %u items: {", count);
307 for (i = 0; i < count; i++) {
308 const int val_offset = offset;
309 uint32_t val_len;
310 char *val;
312 val_len = tvb_get_letohl(tvb, offset);
313 offset += 4;
315 val = tvb_get_string_enc(pinfo->pool, tvb, offset, val_len, ENC_ASCII | ENC_NA);
317 proto_item_append_text(ti, "\"%s\", ", val);
318 proto_tree_add_string(yami_param, hf_yami_param_value_str, tvb, val_offset, offset - val_offset, val);
319 offset += WS_ROUNDUP_4(val_len);
321 proto_item_append_text(ti, "}");
322 break;
325 case YAMI_TYPE_BINARY_ARRAY:
327 uint32_t count;
328 unsigned i;
330 count = tvb_get_letohl(tvb, offset);
331 proto_tree_add_item(yami_param, hf_yami_items_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
332 offset += 4;
334 proto_item_append_text(ti, ", Type: binary[], %u items: {", count);
336 for (i = 0; i < count; i++) {
337 const int val_offset = offset;
338 uint32_t val_len;
339 const uint8_t *val;
340 char *repr;
342 val_len = tvb_get_letohl(tvb, offset);
343 offset += 4;
345 val = tvb_get_ptr(tvb, offset, val_len);
346 repr = bytes_to_str(pinfo->pool, val, val_len);
348 proto_item_append_text(ti, "%s, ", repr);
349 offset += WS_ROUNDUP_4(val_len);
350 proto_tree_add_bytes_format_value(yami_param, hf_yami_param_value_bin, tvb, val_offset, offset - val_offset, val, "%s", repr);
352 proto_item_append_text(ti, "}");
353 break;
356 case YAMI_TYPE_NESTED:
358 uint32_t count;
359 unsigned i;
361 count = tvb_get_letohl(tvb, offset);
362 proto_tree_add_item(yami_param, hf_yami_params_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
363 offset += 4;
365 proto_item_append_text(ti, ", Type: nested, %u parameters: ", count);
367 for (i = 0; i < count; i++) {
368 increment_dissection_depth(pinfo);
369 offset = dissect_yami_parameter(tvb, pinfo, yami_param, offset, ti);
370 decrement_dissection_depth(pinfo);
371 /* smth went wrong */
372 if (offset == -1)
373 return -1;
375 break;
378 default:
379 proto_item_append_text(ti, ", Type: unknown (%d)!", type);
380 return -1;
383 proto_item_set_len(ti, offset - orig_offset);
384 return offset;
387 static int
388 dissect_yami_data(tvbuff_t *tvb, packet_info *pinfo, bool data, proto_tree *tree, int offset)
390 const int orig_offset = offset;
392 proto_tree *yami_data_tree;
393 proto_item *ti;
395 uint32_t count;
396 unsigned i;
398 ti = proto_tree_add_item(tree, (data) ? hf_yami_message_data : hf_yami_message_hdr, tvb, offset, 0, ENC_NA);
399 yami_data_tree = proto_item_add_subtree(ti, (data) ? ett_yami_msg_data : ett_yami_msg_hdr);
401 count = tvb_get_letohl(tvb, offset);
402 proto_tree_add_item(yami_data_tree, hf_yami_params_count, tvb, offset, 4, ENC_LITTLE_ENDIAN);
403 offset += 4;
405 proto_item_append_text(ti, ", %u parameters: ", count);
407 for (i = 0; i < count; i++) {
408 offset = dissect_yami_parameter(tvb, pinfo, yami_data_tree, offset, ti);
409 /* smth went wrong */
410 if (offset == -1)
411 return -1;
414 proto_item_set_len(ti, offset - orig_offset);
416 return offset;
419 static int
420 dissect_yami_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
422 proto_tree *yami_tree;
423 proto_item *ti;
425 int frame_number;
426 int message_header_size;
427 int frame_payload_size;
428 int frame_size;
429 int offset;
431 col_set_str(pinfo->cinfo, COL_PROTOCOL, "YAMI");
432 col_clear(pinfo->cinfo, COL_INFO);
434 ti = proto_tree_add_item(tree, proto_yami, tvb, 0, -1, ENC_NA);
435 yami_tree = proto_item_add_subtree(ti, ett_yami);
437 offset = 0;
439 proto_tree_add_item(yami_tree, hf_yami_message_id, tvb, offset, 4, ENC_LITTLE_ENDIAN);
440 offset += 4;
442 frame_number = tvb_get_letohl(tvb, offset);
443 ti = proto_tree_add_item(yami_tree, hf_yami_frame_number, tvb, offset, 4, ENC_LITTLE_ENDIAN);
444 if(frame_number < 0)
445 proto_item_append_text(ti, "%s", " (last frame)");
446 offset += 4;
448 message_header_size = tvb_get_letohl(tvb, offset);
449 proto_tree_add_item(yami_tree, hf_yami_message_header_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
450 if (message_header_size < 4) {
451 /* XXX, expert info */
453 offset += 4;
455 frame_payload_size = tvb_get_letohl(tvb, offset);
456 ti = proto_tree_add_item(yami_tree, hf_yami_frame_payload_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
457 frame_size = frame_payload_size + 16;
458 proto_item_append_text(ti, ", (YAMI Frame Size: %d)", frame_size);
459 offset += 4;
461 if (frame_number == 1 || frame_number == -1) {
462 if (message_header_size <= frame_payload_size) {
463 const int orig_offset = offset;
465 offset = dissect_yami_data(tvb, pinfo, false, yami_tree, offset);
466 if (offset != orig_offset + message_header_size) {
467 /* XXX, expert info */
468 offset = orig_offset + message_header_size;
471 dissect_yami_data(tvb, pinfo, true, yami_tree, offset);
475 return tvb_captured_length(tvb);
478 #define FRAME_HEADER_LEN 16
480 static unsigned
481 get_yami_message_len(packet_info *pinfo _U_, tvbuff_t *tvb,
482 int offset, void *data _U_)
484 uint32_t len = tvb_get_letohl(tvb, offset + 12);
486 return len + FRAME_HEADER_LEN;
489 static int
490 dissect_yami(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
492 tcp_dissect_pdus(tvb, pinfo, tree, yami_desegment, FRAME_HEADER_LEN, get_yami_message_len, dissect_yami_pdu, data);
493 return tvb_captured_length(tvb);
496 void
497 proto_register_yami(void)
499 static hf_register_info hf[] = {
500 { &hf_yami_message_id,
501 { "Message ID", "yami.message_id",
502 FT_INT32, BASE_DEC, NULL, 0x00,
503 NULL, HFILL }
505 { &hf_yami_frame_number,
506 { "Frame Number", "yami.frame_number",
507 FT_INT32, BASE_DEC, NULL, 0x00,
508 NULL, HFILL }
510 { &hf_yami_message_header_size,
511 { "Message Header Size", "yami.message_header_size",
512 FT_INT32, BASE_DEC, NULL, 0x00,
513 NULL, HFILL }
515 { &hf_yami_frame_payload_size,
516 { "Frame Payload Size", "yami.frame_payload_size",
517 FT_INT32, BASE_DEC, NULL, 0x00,
518 NULL, HFILL }
520 { &hf_yami_message_hdr,
521 { "Header message", "yami.msg_hdr",
522 FT_NONE, BASE_NONE, NULL, 0x00,
523 NULL, HFILL }
525 { &hf_yami_message_data,
526 { "Data message", "yami.msg_data",
527 FT_NONE, BASE_NONE, NULL, 0x00,
528 NULL, HFILL }
530 { &hf_yami_param,
531 { "Parameter", "yami.param",
532 FT_NONE, BASE_NONE, NULL, 0x00,
533 NULL, HFILL }
535 { &hf_yami_param_name,
536 { "Name", "yami.param.name",
537 FT_STRING, BASE_NONE, NULL, 0x00,
538 "Parameter name", HFILL }
540 { &hf_yami_param_type,
541 { "Type", "yami.param.type",
542 FT_INT32, BASE_DEC, VALS(yami_param_type_vals), 0x00,
543 "Parameter type", HFILL }
545 { &hf_yami_param_value_bool,
546 { "Value", "yami.param.value_bool",
547 FT_BOOLEAN, BASE_NONE, NULL, 0x00,
548 "Parameter value (bool)", HFILL }
550 { &hf_yami_param_value_int,
551 { "Value", "yami.param.value_int",
552 FT_INT32, BASE_DEC, NULL, 0x00,
553 "Parameter value (int)", HFILL }
555 { &hf_yami_param_value_long,
556 { "Value", "yami.param.value_long",
557 FT_INT64, BASE_DEC, NULL, 0x00,
558 "Parameter value (long)", HFILL }
560 { &hf_yami_param_value_double,
561 { "Value", "yami.param.value_double",
562 FT_DOUBLE, BASE_NONE, NULL, 0x00,
563 "Parameter value (double)", HFILL }
565 { &hf_yami_param_value_str,
566 { "Value", "yami.param.value_str",
567 FT_STRING, BASE_NONE, NULL, 0x00,
568 "Parameter value (string)", HFILL }
570 { &hf_yami_param_value_bin,
571 { "Value", "yami.param.value_bin",
572 FT_BYTES, BASE_NONE, NULL, 0x00,
573 "Parameter value (binary)", HFILL }
575 { &hf_yami_params_count,
576 { "Parameters count", "yami.params_count",
577 FT_UINT32, BASE_DEC, NULL, 0x00,
578 NULL, HFILL }
580 { &hf_yami_items_count,
581 { "Items count", "yami.items_count",
582 FT_UINT32, BASE_DEC, NULL, 0x00,
583 NULL, HFILL }
587 static int *ett[] = {
588 &ett_yami,
589 &ett_yami_msg_hdr,
590 &ett_yami_msg_data,
591 &ett_yami_param
594 module_t *yami_module;
596 proto_yami = proto_register_protocol("YAMI Protocol", "YAMI", "yami");
598 proto_register_field_array(proto_yami, hf, array_length(hf));
599 proto_register_subtree_array(ett, array_length(ett));
601 yami_module = prefs_register_protocol(proto_yami, NULL);
602 prefs_register_bool_preference(yami_module, "desegment",
603 "Reassemble YAMI messages spanning multiple TCP segments",
604 "Whether the YAMI dissector should reassemble messages spanning multiple TCP segments."
605 "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
606 &yami_desegment);
608 yami_handle = register_dissector("yami", dissect_yami, proto_yami);
611 void
612 proto_reg_handoff_yami(void)
614 dissector_add_for_decode_as_with_preference("tcp.port", yami_handle);
615 dissector_add_for_decode_as_with_preference("udp.port", yami_handle);
619 * Editor modelines - https://www.wireshark.org/tools/modelines.html
621 * Local variables:
622 * c-basic-offset: 8
623 * tab-width: 8
624 * indent-tabs-mode: t
625 * End:
627 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
628 * :indentSize=8:tabSize=8:noTabs=false: