TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags
[wireshark-sm.git] / epan / dissectors / packet-asphodel.c
blob7accaec89cc4fc30a22ee65626df837a11121708
1 /* packet-asphodel.c
2 * Routines for Asphodel dissection
3 * Copyright 2018, Greg Schwendimann <gregs@suprocktech.com>
4 * Copyright 2020, Jeffrey Nichols <jsnichols@suprocktech.com>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: BSD-2-Clause
14 * Asphodel: https://bitbucket.org/suprocktech/asphodel
17 #include <config.h>
18 #include <epan/packet.h>
19 #include <epan/expert.h>
20 #include <epan/tfs.h>
22 #include "packet-tcp.h"
24 void proto_reg_handoff_asphodel(void);
25 void proto_register_asphodel(void);
27 // useful #defines copied from asphodel_protocol.h and asphodel_tcp.c
28 #define ASPHODEL_PROTOCOL_TYPE_RF_POWER 0x01
29 #define ASPHODEL_PROTOCOL_TYPE_RADIO 0x02
30 #define ASPHODEL_PROTOCOL_TYPE_REMOTE 0x04
31 #define ASPHODEL_PROTOCOL_TYPE_BOOTLOADER 0x08
32 #define ASPHODEL_TCP_MSG_TYPE_DEVICE_CMD 0x00
33 #define ASPHODEL_TCP_MSG_TYPE_DEVICE_STREAM 0x01
34 #define ASPHODEL_TCP_MSG_TYPE_REMOTE_CMD 0x02
35 #define ASPHODEL_TCP_MSG_TYPE_REMOTE_STREAM 0x03
36 #define ASPHODEL_TCP_MSG_TYPE_REMOTE_NOTIFY 0x06
37 #define ASPHODEL_CMD_REPLY_ERROR 0xFF
39 static const value_string asphodel_type_vals[] = {
40 { ASPHODEL_TCP_MSG_TYPE_DEVICE_CMD, "DEVICE_CMD" },
41 { ASPHODEL_TCP_MSG_TYPE_DEVICE_STREAM, "DEVICE_STREAM" },
42 { ASPHODEL_TCP_MSG_TYPE_REMOTE_CMD, "REMOTE_CMD" },
43 { ASPHODEL_TCP_MSG_TYPE_REMOTE_STREAM, "REMOTE_STREAM" },
44 { ASPHODEL_TCP_MSG_TYPE_REMOTE_NOTIFY, "REMOTE_NOTIFY" },
45 { 0, NULL }
48 static const value_string asphodel_cmd_vals[] = {
49 { 0x00, "GET_PROTOCOL_VERSION" },
50 { 0x01, "GET_BOARD_INFO" },
51 { 0x02, "GET_USER_TAG_LOCATIONS" },
52 { 0x03, "GET_BUILD_INFO" },
53 { 0x04, "GET_BUILD_DATE" },
54 { 0x05, "GET_CHIP_FAMILY" },
55 { 0x06, "GET_CHIP_MODEL" },
56 { 0x07, "GET_CHIP_ID" },
57 { 0x08, "GET_NVM_SIZE" },
58 { 0x09, "ERASE_NVM" },
59 { 0x0A, "WRITE_NVM" },
60 { 0x0B, "READ_NVM" },
61 { 0x0C, "FLUSH" },
62 { 0x0D, "RESET" },
63 { 0x0E, "GET_BOOTLOADER_INFO" },
64 { 0x0F, "BOOTLOADER_JUMP" },
65 { 0x10, "GET_RGB_COUNT" },
66 { 0x11, "GET_RGB_VALUES" },
67 { 0x12, "SET_RGB" },
68 { 0x13, "SET_RGB_INSTANT" },
69 { 0x14, "GET_LED_COUNT" },
70 { 0x15, "GET_LED_VALUE" },
71 { 0x16, "SET_LED" },
72 { 0x17, "SET_LED_INSTANT" },
73 { 0x20, "GET_STREAM_COUNT_AND_ID" },
74 { 0x21, "GET_STREAM_CHANNELS" },
75 { 0x22, "GET_STREAM_FORMAT" },
76 { 0x23, "ENABLE_STREAM" },
77 { 0x24, "WARM_UP_STREAM" },
78 { 0x25, "GET_STREAM_STATUS" },
79 { 0x26, "GET_STREAM_RATE_INFO" },
80 { 0x30, "GET_CHANNEL_COUNT" },
81 { 0x31, "GET_CHANNEL_NAME" },
82 { 0x32, "GET_CHANNEL_INFO" },
83 { 0x33, "GET_CHANNEL_COEFFICIENTS" },
84 { 0x34, "GET_CHANNEL_CHUNK" },
85 { 0x35, "CHANNEL_SPECIFIC" },
86 { 0x36, "GET_CHANNEL_CALIBRATION" },
87 { 0x40, "GET_SUPPLY_COUNT" },
88 { 0x41, "GET_SUPPLY_NAME" },
89 { 0x42, "GET_SUPPLY_INFO" },
90 { 0x43, "CHECK_SUPPLY" },
91 { 0x50, "GET_CTRL_VAR_COUNT" },
92 { 0x51, "GET_CTRL_VAR_NAME" },
93 { 0x52, "GET_CTRL_VAR_INFO" },
94 { 0x53, "GET_CTRL_VAR" },
95 { 0x54, "SET_CTRL_VAR" },
96 { 0x60, "GET_SETTING_COUNT" },
97 { 0x61, "GET_SETTING_NAME" },
98 { 0x62, "GET_SETTING_INFO" },
99 { 0x63, "GET_SETTING_DEFAULT" },
100 { 0x64, "GET_CUSTOM_ENUM_COUNTS" },
101 { 0x65, "GET_CUSTOM_ENUM_VALUE_NAME" },
102 { 0x66, "GET_SETTING_CATEGORY_COUNT" },
103 { 0x67, "GET_SETTING_CATEGORY_NAME" },
104 { 0x68, "GET_SETTING_CATEGORY_SETTINGS" },
105 { 0x70, "SET_DEVICE_MODE" },
106 { 0x71, "GET_DEVICE_MODE" },
107 { 0x80, "ENABLE_RF_POWER" },
108 { 0x81, "GET_RF_POWER_STATUS" },
109 { 0x82, "GET_RF_POWER_CTRL_VARS" },
110 { 0x83, "RESET_RF_POWER_TIMEOUT" },
111 { 0x90, "STOP_RADIO" },
112 { 0x91, "START_RADIO_SCAN" },
113 { 0x92, "GET_RADIO_SCAN_RESULTS" },
114 { 0x93, "CONNECT_RADIO" },
115 { 0x94, "GET_RADIO_STATUS" },
116 { 0x95, "GET_RADIO_CTRL_VARS" },
117 { 0x96, "GET_RADIO_DEFAULT_SERIAL" },
118 { 0x97, "START_RADIO_SCAN_BOOT" },
119 { 0x98, "CONNECT_RADIO_BOOT" },
120 { 0x99, "GET_RADIO_EXTRA_SCAN_RESULTS" },
121 { 0x9A, "STOP_REMOTE" },
122 { 0x9B, "RESTART_REMOTE" },
123 { 0x9C, "GET_REMOTE_STATUS" },
124 { 0x9D, "RESTART_REMOTE_APP" },
125 { 0x9E, "RESTART_REMOTE_BOOT" },
126 { 0x9F, "GET_RADIO_SCAN_POWER" },
127 { 0xA0, "BOOTLOADER_START_PROGRAM" },
128 { 0xA1, "GET_BOOTLOADER_PAGE_INFO" },
129 { 0xA2, "GET_BOOTLOADER_BLOCK_SIZES" },
130 { 0xA3, "START_BOOTLOADER_PAGE" },
131 { 0xA4, "WRITE_BOOTLOADER_CODE_BLOCK" },
132 { 0xA5, "FINISH_BOOTLOADER_PAGE" },
133 { 0xA6, "VERIFY_BOOTLOADER_PAGE" },
134 { 0xE0, "GET_GPIO_PORT_COUNT" },
135 { 0xE1, "GET_GPIO_PORT_NAME" },
136 { 0xE2, "GET_GPIO_PORT_INFO" },
137 { 0xE3, "GET_GPIO_PORT_VALUES" },
138 { 0xE4, "SET_GPIO_PORT_MODES" },
139 { 0xE5, "DISABLE_GPIO_PORT_OVERRIDES" },
140 { 0xE6, "GET_BUS_COUNTS" },
141 { 0xE7, "SET_SPI_CS_MODE" },
142 { 0xE8, "DO_SPI_TRANSFER" },
143 { 0xE9, "DO_I2C_WRITE" },
144 { 0xEA, "DO_I2C_READ" },
145 { 0xEB, "DO_I2C_WRITE_READ" },
146 { 0xEC, "DO_RADIO_FIXED_TEST" },
147 { 0xED, "DO_RADIO_SWEEP_TEST" },
148 { 0xF0, "GET_INFO_REGION_COUNT" },
149 { 0xF1, "GET_INFO_REGION_NAME" },
150 { 0xF2, "GET_INFO_REGION" },
151 { 0xF3, "GET_STACK_INFO" },
152 { 0xFC, "ECHO_RAW" },
153 { 0xFD, "ECHO_TRANSACTION" },
154 { 0xFE, "ECHO_PARAMS" },
155 { 0xFF, "REPLY_ERROR" },
156 { 0, NULL }
159 static const value_string asphodel_err_vals[] = {
160 { 0x01, "ERROR_CODE_UNSPECIFIED" },
161 { 0x02, "ERROR_CODE_MALFORMED_COMMAND" },
162 { 0x03, "ERROR_CODE_UNIMPLEMENTED_COMMAND" },
163 { 0x04, "ERROR_CODE_BAD_CMD_LENGTH" },
164 { 0x05, "ERROR_CODE_BAD_ADDRESS" },
165 { 0x06, "ERROR_CODE_BAD_INDEX" },
166 { 0x07, "ERROR_CODE_INVALID_DATA" },
167 { 0x08, "ERROR_CODE_UNSUPPORTED" },
168 { 0x09, "ERROR_CODE_BAD_STATE" },
169 { 0x0A, "ERROR_CODE_I2C_ERROR" },
170 { 0x0B, "ERROR_CODE_INCOMPLETE" },
171 { 0, NULL }
174 static const true_false_string notify_connect_disconnect = {
175 "Connect",
176 "Disconnect"
179 static int proto_asphodel;
181 // asphodel inquiry fields
182 static int hf_asphodel_version;
183 static int hf_asphodel_identifier;
185 // asphodel response fields
186 static int hf_asphodel_tcp_version;
187 static int hf_asphodel_connected;
188 static int hf_asphodel_max_incoming_param_length;
189 static int hf_asphodel_max_outgoing_param_length;
190 static int hf_asphodel_stream_packet_length;
191 static int hf_asphodel_protocol_type;
192 static int hf_asphodel_protocol_type_rf_power;
193 static int hf_asphodel_protocol_type_radio;
194 static int hf_asphodel_protocol_type_remote;
195 static int hf_asphodel_protocol_type_bootloader;
196 static int hf_asphodel_serial_number;
197 static int hf_asphodel_board_rev;
198 static int hf_asphodel_board_type;
199 static int hf_asphodel_build_info;
200 static int hf_asphodel_build_date;
201 static int hf_asphodel_user_tag1;
202 static int hf_asphodel_user_tag2;
203 static int hf_asphodel_remote_max_incoming_param_length;
204 static int hf_asphodel_remote_max_outgoing_param_length;
205 static int hf_asphodel_remote_stream_packet_length;
207 // asphodel tcp fields
208 static int hf_asphodel_length;
209 static int hf_asphodel_type;
210 static int hf_asphodel_seq;
211 static int hf_asphodel_cmd;
212 static int hf_asphodel_err_code;
213 static int hf_asphodel_params;
214 static int hf_asphodel_stream_data;
215 static int hf_asphodel_notify;
216 static int hf_asphodel_notify_serial;
218 static int ett_asphodel;
219 static int ett_asphodel_protocol_type;
221 static expert_field ei_asphodel_bad_param_length;
222 static expert_field ei_asphodel_bad_length;
223 static expert_field ei_asphodel_cmd_error;
224 static expert_field ei_asphodel_unknown_type;
226 static dissector_handle_t asphodel_inquiry_handle;
227 static dissector_handle_t asphodel_response_handle;
228 static dissector_handle_t asphodel_tcp_handle;
230 static void
231 asphodel_fmt_version(char *result, uint32_t version)
233 uint8_t major = version >> 8;
234 uint8_t minor = (version >> 4) & 0x0F;
235 uint8_t subminor = version & 0x0F;
236 snprintf(result, ITEM_LABEL_LENGTH, "%d.%d.%d", major, minor, subminor);
239 static int
240 dissect_asphodel_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
242 proto_item *ti;
243 proto_tree *asphodel_tree;
244 uint32_t length;
246 ti = proto_tree_add_item(tree, proto_asphodel, tvb, 0, -1, ENC_NA);
247 asphodel_tree = proto_item_add_subtree(ti, ett_asphodel);
249 proto_tree_add_item_ret_uint(asphodel_tree, hf_asphodel_length, tvb, 0, 2, ENC_BIG_ENDIAN, &length);
251 if (length == 0)
253 proto_item_set_text(ti, "Asphodel No Op");
254 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "No op");
256 else
258 uint32_t type;
259 proto_tree_add_item_ret_uint(asphodel_tree, hf_asphodel_type, tvb, 2, 1, ENC_NA, &type);
261 // handle the text
262 switch (type)
264 case ASPHODEL_TCP_MSG_TYPE_DEVICE_CMD:
265 proto_item_set_text(ti, "Asphodel Command");
266 break;
267 case ASPHODEL_TCP_MSG_TYPE_REMOTE_CMD:
268 proto_item_set_text(ti, "Asphodel Remote Command");
269 break;
270 case ASPHODEL_TCP_MSG_TYPE_DEVICE_STREAM:
271 proto_item_set_text(ti, "Asphodel Stream Data");
272 break;
273 case ASPHODEL_TCP_MSG_TYPE_REMOTE_STREAM:
274 proto_item_set_text(ti, "Asphodel Remote Stream Data");
275 break;
276 case ASPHODEL_TCP_MSG_TYPE_REMOTE_NOTIFY:
277 proto_item_set_text(ti, "Asphodel Notify");
278 break;
279 default:
280 // keep the default "Asphodel" item text
281 break;
284 switch (type)
286 case ASPHODEL_TCP_MSG_TYPE_DEVICE_CMD:
287 case ASPHODEL_TCP_MSG_TYPE_REMOTE_CMD:
288 if (length >= 3)
290 uint32_t cmd;
291 proto_tree_add_item(asphodel_tree, hf_asphodel_seq, tvb, 3, 1, ENC_NA);
292 proto_tree_add_item_ret_uint(asphodel_tree, hf_asphodel_cmd, tvb, 4, 1, ENC_NA, &cmd);
294 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s", val_to_str(cmd, asphodel_cmd_vals, "Unknown type (0x%02x)"));
296 if (cmd == ASPHODEL_CMD_REPLY_ERROR)
298 if (length >= 4)
300 proto_tree_add_item(asphodel_tree, hf_asphodel_err_code, tvb, 5, 1, ENC_NA);
301 if (length >= 5)
303 proto_tree_add_item(asphodel_tree, hf_asphodel_params, tvb, 6, -1, ENC_NA);
306 else
308 // not long enough
309 expert_add_info(pinfo, ti, &ei_asphodel_bad_length);
312 // add a note that it's an error response
313 expert_add_info(pinfo, ti, &ei_asphodel_cmd_error);
315 else
317 // normal command response
318 if (length >= 4)
320 proto_tree_add_item(asphodel_tree, hf_asphodel_params, tvb, 5, -1, ENC_NA);
324 else
326 // not long enough
327 expert_add_info(pinfo, ti, &ei_asphodel_bad_length);
329 break;
330 case ASPHODEL_TCP_MSG_TYPE_DEVICE_STREAM:
331 case ASPHODEL_TCP_MSG_TYPE_REMOTE_STREAM:
332 if (length > 1)
334 proto_tree_add_item(asphodel_tree, hf_asphodel_stream_data, tvb, 3, -1, ENC_NA);
335 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "Stream(%d)", length - 1);
337 else
339 // not long enough
340 expert_add_info(pinfo, ti, &ei_asphodel_bad_length);
342 break;
343 case ASPHODEL_TCP_MSG_TYPE_REMOTE_NOTIFY:
344 if (length == 1) // disconnect
346 ti = proto_tree_add_boolean(asphodel_tree, hf_asphodel_notify, tvb, 2, 1, 0);
347 proto_item_set_generated(ti);
348 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "Notify Disconnect");
350 else if (length == 6) // connect
352 proto_tree *protocol_type_tree;
354 ti = proto_tree_add_boolean(asphodel_tree, hf_asphodel_notify, tvb, 2, 1, 1);
355 proto_item_set_generated(ti);
356 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "Notify Connect");
358 proto_tree_add_item(asphodel_tree, hf_asphodel_notify_serial, tvb, 3, 4, ENC_BIG_ENDIAN);
360 // protocol type
361 ti = proto_tree_add_item(asphodel_tree, hf_asphodel_protocol_type, tvb, 7, 1, ENC_NA);
362 protocol_type_tree = proto_item_add_subtree(ti, ett_asphodel_protocol_type);
363 proto_tree_add_item(protocol_type_tree, hf_asphodel_protocol_type_rf_power, tvb, 7, 1, ENC_NA);
364 proto_tree_add_item(protocol_type_tree, hf_asphodel_protocol_type_radio, tvb, 7, 1, ENC_NA);
365 proto_tree_add_item(protocol_type_tree, hf_asphodel_protocol_type_remote, tvb, 7, 1, ENC_NA);
366 proto_tree_add_item(protocol_type_tree, hf_asphodel_protocol_type_bootloader, tvb, 7, 1, ENC_NA);
368 else
370 expert_add_info(pinfo, ti, &ei_asphodel_bad_length);
371 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "Notify");
373 break;
374 default:
375 // unknown message type
376 expert_add_info(pinfo, ti, &ei_asphodel_unknown_type);
377 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "Unknown(%02x)", type);
378 break;
382 return tvb_captured_length(tvb);
385 static unsigned
386 get_asphodel_tcp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
388 return ((unsigned)tvb_get_ntohs(tvb, offset)) + 2;
391 static int
392 dissect_asphodel_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
394 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Asphodel");
395 col_clear(pinfo->cinfo, COL_INFO);
397 tcp_dissect_pdus(tvb, pinfo, tree, true, 2, get_asphodel_tcp_pdu_len, dissect_asphodel_tcp_pdu, data);
398 return tvb_reported_length(tvb);
401 static int
402 dissect_asphodel_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
404 proto_item *ti;
405 proto_tree *asphodel_tree;
406 proto_tree *protocol_type_tree;
407 conversation_t *conversation;
408 unsigned offset;
409 unsigned len;
410 unsigned protocol_type;
411 uint16_t incoming_cmd_buffer_size;
412 uint16_t outgoing_cmd_buffer_size;
413 uint16_t remote_incoming_cmd_buffer_size;
414 uint16_t remote_outgoing_cmd_buffer_size;
415 uint8_t *serial_number;
417 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Asphodel");
419 ti = proto_tree_add_item(tree, proto_asphodel, tvb, 0, -1, ENC_NA);
420 asphodel_tree = proto_item_add_subtree(ti, ett_asphodel);
421 proto_item_set_text(ti, "Asphodel Response");
423 if (tvb_captured_length(tvb) < 16)
425 // too short
426 return 0;
429 proto_tree_add_item(asphodel_tree, hf_asphodel_tcp_version, tvb, 0, 1, ENC_NA);
430 proto_tree_add_item(asphodel_tree, hf_asphodel_connected, tvb, 1, 1, ENC_NA);
432 incoming_cmd_buffer_size = tvb_get_ntohs(tvb, 2);
433 ti = proto_tree_add_uint(asphodel_tree, hf_asphodel_max_incoming_param_length, tvb, 2, 2, incoming_cmd_buffer_size - 2);
434 if (incoming_cmd_buffer_size <= 2)
436 expert_add_info(pinfo, ti, &ei_asphodel_bad_param_length);
439 outgoing_cmd_buffer_size = tvb_get_ntohs(tvb, 4);
440 ti = proto_tree_add_uint(asphodel_tree, hf_asphodel_max_outgoing_param_length, tvb, 4, 2, outgoing_cmd_buffer_size - 2);
441 if (outgoing_cmd_buffer_size <= 2)
443 expert_add_info(pinfo, ti, &ei_asphodel_bad_param_length);
446 proto_tree_add_item(asphodel_tree, hf_asphodel_stream_packet_length, tvb, 6, 2, ENC_BIG_ENDIAN);
448 ti = proto_tree_add_item_ret_uint(asphodel_tree, hf_asphodel_protocol_type, tvb, 8, 1, ENC_NA, &protocol_type);
449 protocol_type_tree = proto_item_add_subtree(ti, ett_asphodel_protocol_type);
450 proto_tree_add_item(protocol_type_tree, hf_asphodel_protocol_type_rf_power, tvb, 8, 1, ENC_NA);
451 proto_tree_add_item(protocol_type_tree, hf_asphodel_protocol_type_radio, tvb, 8, 1, ENC_NA);
452 proto_tree_add_item(protocol_type_tree, hf_asphodel_protocol_type_remote, tvb, 8, 1, ENC_NA);
453 proto_tree_add_item(protocol_type_tree, hf_asphodel_protocol_type_bootloader, tvb, 8, 1, ENC_NA);
455 offset = 9;
457 len = tvb_strsize(tvb, offset);
458 proto_tree_add_item(asphodel_tree, hf_asphodel_serial_number, tvb, offset, len, ENC_UTF_8 | ENC_NA);
459 serial_number = tvb_get_string_enc(pinfo->pool, tvb, offset, len, ENC_UTF_8);
460 col_add_fstr(pinfo->cinfo, COL_INFO, "Asphodel Response (%s)", serial_number);
461 offset += len;
463 proto_tree_add_item(asphodel_tree, hf_asphodel_board_rev, tvb, offset, 1, ENC_NA);
464 offset += 1;
466 len = tvb_strsize(tvb, offset);
467 proto_tree_add_item(asphodel_tree, hf_asphodel_board_type, tvb, offset, len, ENC_UTF_8 | ENC_NA);
468 offset += len;
470 len = tvb_strsize(tvb, offset);
471 proto_tree_add_item(asphodel_tree, hf_asphodel_build_info, tvb, offset, len, ENC_UTF_8 | ENC_NA);
472 offset += len;
474 len = tvb_strsize(tvb, offset);
475 proto_tree_add_item(asphodel_tree, hf_asphodel_build_date, tvb, offset, len, ENC_UTF_8 | ENC_NA);
476 offset += len;
478 len = tvb_strsize(tvb, offset);
479 proto_tree_add_item(asphodel_tree, hf_asphodel_user_tag1, tvb, offset, len, ENC_UTF_8 | ENC_NA);
480 offset += len;
482 len = tvb_strsize(tvb, offset);
483 proto_tree_add_item(asphodel_tree, hf_asphodel_user_tag2, tvb, offset, len, ENC_UTF_8 | ENC_NA);
484 offset += len;
486 if (protocol_type & ASPHODEL_PROTOCOL_TYPE_RADIO)
488 remote_incoming_cmd_buffer_size = tvb_get_ntohs(tvb, 2);
489 ti = proto_tree_add_uint(asphodel_tree, hf_asphodel_remote_max_incoming_param_length, tvb, offset, 2, remote_incoming_cmd_buffer_size - 2);
490 if (remote_incoming_cmd_buffer_size <= 2)
492 expert_add_info(pinfo, ti, &ei_asphodel_bad_param_length);
495 remote_outgoing_cmd_buffer_size = tvb_get_ntohs(tvb, 4);
496 ti = proto_tree_add_uint(asphodel_tree, hf_asphodel_remote_max_outgoing_param_length, tvb, offset + 2, 2, remote_outgoing_cmd_buffer_size - 2);
497 if (remote_outgoing_cmd_buffer_size <= 2)
499 expert_add_info(pinfo, ti, &ei_asphodel_bad_param_length);
502 proto_tree_add_item(asphodel_tree, hf_asphodel_remote_stream_packet_length, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
505 conversation = find_conversation(pinfo->num, &pinfo->src, 0, CONVERSATION_UDP, pinfo->srcport, 0, NO_ADDR_B | NO_PORT_B);
506 if (!conversation)
508 conversation = conversation_new(pinfo->num, &pinfo->src, 0, CONVERSATION_TCP, pinfo->srcport, 0, NO_ADDR2 | NO_PORT2);
509 conversation_set_dissector(conversation, asphodel_tcp_handle);
512 return tvb_reported_length(tvb);
515 static int
516 dissect_asphodel_inquiry(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
518 proto_item *ti;
519 proto_tree *asphodel_tree;
520 conversation_t *conversation;
522 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Asphodel");
523 col_set_str(pinfo->cinfo, COL_INFO, "Asphodel Inquiry");
525 if (tree != NULL)
527 ti = proto_tree_add_item(tree, proto_asphodel, tvb, 0, -1, ENC_NA);
528 asphodel_tree = proto_item_add_subtree(ti, ett_asphodel);
529 proto_item_set_text(ti, "Asphodel Inquiry");
531 if (tvb_captured_length(tvb) >= 2)
533 proto_tree_add_item(asphodel_tree, hf_asphodel_version, tvb, 0, 2, ENC_BIG_ENDIAN);
535 if (tvb_captured_length(tvb) > 2)
537 proto_tree_add_item(asphodel_tree, hf_asphodel_identifier, tvb, 2, -1, ENC_UTF_8 | ENC_NA);
542 conversation = find_conversation(pinfo->num, &pinfo->src, 0, CONVERSATION_UDP, pinfo->srcport, 0, NO_ADDR_B | NO_PORT_B);
543 if (!conversation)
545 conversation = conversation_new(pinfo->num, &pinfo->src, 0, CONVERSATION_UDP, pinfo->srcport, 0, NO_ADDR2 | NO_PORT2);
546 conversation_set_dissector(conversation, asphodel_response_handle);
549 return tvb_reported_length(tvb);
552 static bool
553 dissect_asphodel_heur_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
555 if (tvb_captured_length(tvb) < 11)
557 return false;
560 if (tvb_memeql(tvb, 2, (const uint8_t*)"Asphodel", 9) != 0)
562 return false;
565 dissect_asphodel_inquiry(tvb, pinfo, tree, data);
567 return true;
570 void
571 proto_register_asphodel(void)
573 expert_module_t *expert_asphodel;
575 static hf_register_info hf[] = {
576 { &hf_asphodel_version,
577 { "Version", "asphodel.version",
578 FT_UINT16, BASE_CUSTOM, CF_FUNC(asphodel_fmt_version), 0x0,
579 NULL, HFILL }
581 { &hf_asphodel_identifier,
582 { "Identifier", "asphodel.identifier",
583 FT_STRING, BASE_NONE, NULL, 0x0,
584 NULL, HFILL }
586 { &hf_asphodel_tcp_version,
587 { "TCP Version", "asphodel.tcp_version",
588 FT_UINT8, BASE_DEC, NULL, 0x0,
589 NULL, HFILL }
591 { &hf_asphodel_connected,
592 { "Connected", "asphodel.connected",
593 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
594 NULL, HFILL }
596 { &hf_asphodel_max_incoming_param_length,
597 { "Max Incoming Param Length", "asphodel.max_incoming_param_length",
598 FT_UINT16, BASE_DEC, NULL, 0x0,
599 NULL, HFILL }
601 { &hf_asphodel_max_outgoing_param_length,
602 { "Max Outgoing Param Length", "asphodel.max_outgoing_param_length",
603 FT_UINT16, BASE_DEC, NULL, 0x0,
604 NULL, HFILL }
606 { &hf_asphodel_stream_packet_length,
607 { "Stream Packet Length", "asphodel.stream_packet_length",
608 FT_UINT16, BASE_DEC, NULL, 0x0,
609 NULL, HFILL }
611 { &hf_asphodel_protocol_type,
612 { "Protocol Type", "asphodel.protocol_type",
613 FT_UINT8, BASE_HEX, NULL, 0x0,
614 NULL, HFILL }
616 { &hf_asphodel_protocol_type_rf_power,
617 { "RF Power", "asphodel.protocol_type.rf_power",
618 FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), ASPHODEL_PROTOCOL_TYPE_RF_POWER,
619 NULL, HFILL }
621 { &hf_asphodel_protocol_type_radio,
622 { "Radio", "asphodel.protocol_type.radio",
623 FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), ASPHODEL_PROTOCOL_TYPE_RADIO,
624 NULL, HFILL }
626 { &hf_asphodel_protocol_type_remote,
627 { "Remote", "asphodel.protocol_type.remote",
628 FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), ASPHODEL_PROTOCOL_TYPE_REMOTE,
629 NULL, HFILL }
631 { &hf_asphodel_protocol_type_bootloader,
632 { "Bootloader", "asphodel.protocol_type.bootloader",
633 FT_BOOLEAN, 8, TFS(&tfs_supported_not_supported), ASPHODEL_PROTOCOL_TYPE_BOOTLOADER,
634 NULL, HFILL }
636 { &hf_asphodel_serial_number,
637 { "Serial Number", "asphodel.serial_number",
638 FT_STRINGZ, BASE_NONE, NULL, 0x0,
639 NULL, HFILL }
641 { &hf_asphodel_board_rev,
642 { "Board Rev", "asphodel.board_rev",
643 FT_UINT8, BASE_DEC, NULL, 0x0,
644 NULL, HFILL }
646 { &hf_asphodel_board_type,
647 { "Board Type", "asphodel.board_type",
648 FT_STRINGZ, BASE_NONE, NULL, 0x0,
649 NULL, HFILL }
651 { &hf_asphodel_build_info,
652 { "Build Info", "asphodel.build_info",
653 FT_STRINGZ, BASE_NONE, NULL, 0x0,
654 NULL, HFILL }
656 { &hf_asphodel_build_date,
657 { "Build Date", "asphodel.build_date",
658 FT_STRINGZ, BASE_NONE, NULL, 0x0,
659 NULL, HFILL }
661 { &hf_asphodel_user_tag1,
662 { "User Tag 1", "asphodel.user_tag1",
663 FT_STRINGZ, BASE_NONE, NULL, 0x0,
664 NULL, HFILL }
666 { &hf_asphodel_user_tag2,
667 { "User Tag 2", "asphodel.user_tag2",
668 FT_STRINGZ, BASE_NONE, NULL, 0x0,
669 NULL, HFILL }
671 { &hf_asphodel_remote_max_incoming_param_length,
672 { "Remote Max Incoming Param Length", "asphodel.remote_max_incoming_param_length",
673 FT_UINT16, BASE_DEC, NULL, 0x0,
674 NULL, HFILL }
676 { &hf_asphodel_remote_max_outgoing_param_length,
677 { "Remote Max Outgoing Param Length", "asphodel.remote_max_outgoing_param_length",
678 FT_UINT16, BASE_DEC, NULL, 0x0,
679 NULL, HFILL }
681 { &hf_asphodel_remote_stream_packet_length,
682 { "Remote Stream Packet Length", "asphodel.remote_stream_packet_length",
683 FT_UINT16, BASE_DEC, NULL, 0x0,
684 NULL, HFILL }
686 { &hf_asphodel_length,
687 { "Length", "asphodel.length",
688 FT_UINT16, BASE_DEC, NULL, 0x0,
689 NULL, HFILL }
691 { &hf_asphodel_type,
692 { "Type", "asphodel.type",
693 FT_UINT8, BASE_HEX, VALS(asphodel_type_vals), 0x0,
694 NULL, HFILL }
696 { &hf_asphodel_seq,
697 { "Sequence", "asphodel.seq",
698 FT_UINT8, BASE_DEC, NULL, 0x0,
699 NULL, HFILL }
701 { &hf_asphodel_cmd,
702 { "Command", "asphodel.cmd",
703 FT_UINT8, BASE_HEX, VALS(asphodel_cmd_vals), 0x0,
704 NULL, HFILL }
706 { &hf_asphodel_err_code,
707 { "Error Code", "asphodel.err_code",
708 FT_UINT8, BASE_HEX, VALS(asphodel_err_vals), 0x0,
709 NULL, HFILL }
711 { &hf_asphodel_params,
712 { "Command Parameter Data", "asphodel.params",
713 FT_BYTES, BASE_NONE, NULL, 0x0,
714 NULL, HFILL }
716 { &hf_asphodel_stream_data,
717 { "Stream Data", "asphodel.stream_data",
718 FT_BYTES, BASE_NONE, NULL, 0x0,
719 NULL, HFILL }
721 { &hf_asphodel_notify,
722 { "Notify", "asphodel.notify",
723 FT_BOOLEAN, BASE_NONE, TFS(&notify_connect_disconnect), 0x0,
724 NULL, HFILL }
726 { &hf_asphodel_notify_serial,
727 { "Notify Serial Number", "asphodel.notify_serial",
728 FT_UINT32, BASE_DEC, NULL, 0x0,
729 NULL, HFILL }
733 static int *ett[] = {
734 &ett_asphodel,
735 &ett_asphodel_protocol_type,
738 static ei_register_info ei[] = {
739 { &ei_asphodel_bad_param_length,
740 { "asphodel.bad_param_length", PI_PROTOCOL, PI_WARN,
741 "Bad parameter length", EXPFILL }
743 { &ei_asphodel_bad_length,
744 { "asphodel.bad_cmd_length", PI_PROTOCOL, PI_WARN,
745 "Bad length", EXPFILL }
747 { &ei_asphodel_cmd_error,
748 { "asphodel.cmd_error", PI_RESPONSE_CODE, PI_NOTE,
749 "Command error response", EXPFILL }
751 { &ei_asphodel_unknown_type,
752 { "asphodel.unknown_type", PI_PROTOCOL, PI_WARN,
753 "Unknown message type", EXPFILL }
757 /* Register the protocol name and description */
758 proto_asphodel = proto_register_protocol("Asphodel", "Asphodel", "asphodel");
760 /* Register the dissectors */
761 asphodel_inquiry_handle = register_dissector("asphodel_inquiry", dissect_asphodel_inquiry, proto_asphodel);
762 asphodel_response_handle = register_dissector("asphodel_response", dissect_asphodel_response, proto_asphodel);
763 asphodel_tcp_handle = register_dissector("asphodel_tcp", dissect_asphodel_tcp, proto_asphodel);
765 /* Required function calls to register the header fields and subtrees */
766 proto_register_field_array(proto_asphodel, hf, array_length(hf));
767 proto_register_subtree_array(ett, array_length(ett));
769 /* Required function calls to register expert items */
770 expert_asphodel = expert_register_protocol(proto_asphodel);
771 expert_register_field_array(expert_asphodel, ei, array_length(ei));
774 void
775 proto_reg_handoff_asphodel(void)
777 heur_dissector_add("udp", dissect_asphodel_heur_udp, "Asphodel over UDP",
778 "asphodel_inquiry", proto_asphodel, HEURISTIC_ENABLE);
779 dissector_add_for_decode_as("udp.port", asphodel_response_handle);
780 dissector_add_for_decode_as("tcp.port", asphodel_tcp_handle);
784 * Editor modelines - https://www.wireshark.org/tools/modelines.html
786 * Local variables:
787 * c-basic-offset: 4
788 * tab-width: 8
789 * indent-tabs-mode: nil
790 * End:
792 * vi: set shiftwidth=4 tabstop=8 expandtab:
793 * :indentSize=4:tabSize=8:noTabs=true: