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
18 #include <epan/packet.h>
19 #include <epan/expert.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" },
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" },
63 { 0x0E, "GET_BOOTLOADER_INFO" },
64 { 0x0F, "BOOTLOADER_JUMP" },
65 { 0x10, "GET_RGB_COUNT" },
66 { 0x11, "GET_RGB_VALUES" },
68 { 0x13, "SET_RGB_INSTANT" },
69 { 0x14, "GET_LED_COUNT" },
70 { 0x15, "GET_LED_VALUE" },
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" },
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" },
174 static const true_false_string notify_connect_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
;
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
);
240 dissect_asphodel_tcp_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
243 proto_tree
*asphodel_tree
;
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
);
253 proto_item_set_text(ti
, "Asphodel No Op");
254 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, ", ", "No op");
259 proto_tree_add_item_ret_uint(asphodel_tree
, hf_asphodel_type
, tvb
, 2, 1, ENC_NA
, &type
);
264 case ASPHODEL_TCP_MSG_TYPE_DEVICE_CMD
:
265 proto_item_set_text(ti
, "Asphodel Command");
267 case ASPHODEL_TCP_MSG_TYPE_REMOTE_CMD
:
268 proto_item_set_text(ti
, "Asphodel Remote Command");
270 case ASPHODEL_TCP_MSG_TYPE_DEVICE_STREAM
:
271 proto_item_set_text(ti
, "Asphodel Stream Data");
273 case ASPHODEL_TCP_MSG_TYPE_REMOTE_STREAM
:
274 proto_item_set_text(ti
, "Asphodel Remote Stream Data");
276 case ASPHODEL_TCP_MSG_TYPE_REMOTE_NOTIFY
:
277 proto_item_set_text(ti
, "Asphodel Notify");
280 // keep the default "Asphodel" item text
286 case ASPHODEL_TCP_MSG_TYPE_DEVICE_CMD
:
287 case ASPHODEL_TCP_MSG_TYPE_REMOTE_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
)
300 proto_tree_add_item(asphodel_tree
, hf_asphodel_err_code
, tvb
, 5, 1, ENC_NA
);
303 proto_tree_add_item(asphodel_tree
, hf_asphodel_params
, tvb
, 6, -1, ENC_NA
);
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
);
317 // normal command response
320 proto_tree_add_item(asphodel_tree
, hf_asphodel_params
, tvb
, 5, -1, ENC_NA
);
327 expert_add_info(pinfo
, ti
, &ei_asphodel_bad_length
);
330 case ASPHODEL_TCP_MSG_TYPE_DEVICE_STREAM
:
331 case ASPHODEL_TCP_MSG_TYPE_REMOTE_STREAM
:
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);
340 expert_add_info(pinfo
, ti
, &ei_asphodel_bad_length
);
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
);
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
);
370 expert_add_info(pinfo
, ti
, &ei_asphodel_bad_length
);
371 col_append_sep_fstr(pinfo
->cinfo
, COL_INFO
, ", ", "Notify");
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
);
382 return tvb_captured_length(tvb
);
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;
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
);
402 dissect_asphodel_response(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
405 proto_tree
*asphodel_tree
;
406 proto_tree
*protocol_type_tree
;
407 conversation_t
*conversation
;
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)
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
);
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
);
463 proto_tree_add_item(asphodel_tree
, hf_asphodel_board_rev
, tvb
, offset
, 1, ENC_NA
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
516 dissect_asphodel_inquiry(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
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");
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
);
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
);
553 dissect_asphodel_heur_udp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
555 if (tvb_captured_length(tvb
) < 11)
560 if (tvb_memeql(tvb
, 2, (const uint8_t*)"Asphodel", 9) != 0)
565 dissect_asphodel_inquiry(tvb
, pinfo
, tree
, data
);
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,
581 { &hf_asphodel_identifier
,
582 { "Identifier", "asphodel.identifier",
583 FT_STRING
, BASE_NONE
, NULL
, 0x0,
586 { &hf_asphodel_tcp_version
,
587 { "TCP Version", "asphodel.tcp_version",
588 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
591 { &hf_asphodel_connected
,
592 { "Connected", "asphodel.connected",
593 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
596 { &hf_asphodel_max_incoming_param_length
,
597 { "Max Incoming Param Length", "asphodel.max_incoming_param_length",
598 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
601 { &hf_asphodel_max_outgoing_param_length
,
602 { "Max Outgoing Param Length", "asphodel.max_outgoing_param_length",
603 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
606 { &hf_asphodel_stream_packet_length
,
607 { "Stream Packet Length", "asphodel.stream_packet_length",
608 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
611 { &hf_asphodel_protocol_type
,
612 { "Protocol Type", "asphodel.protocol_type",
613 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
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
,
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
,
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
,
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
,
636 { &hf_asphodel_serial_number
,
637 { "Serial Number", "asphodel.serial_number",
638 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
641 { &hf_asphodel_board_rev
,
642 { "Board Rev", "asphodel.board_rev",
643 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
646 { &hf_asphodel_board_type
,
647 { "Board Type", "asphodel.board_type",
648 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
651 { &hf_asphodel_build_info
,
652 { "Build Info", "asphodel.build_info",
653 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
656 { &hf_asphodel_build_date
,
657 { "Build Date", "asphodel.build_date",
658 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
661 { &hf_asphodel_user_tag1
,
662 { "User Tag 1", "asphodel.user_tag1",
663 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
666 { &hf_asphodel_user_tag2
,
667 { "User Tag 2", "asphodel.user_tag2",
668 FT_STRINGZ
, BASE_NONE
, NULL
, 0x0,
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,
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,
681 { &hf_asphodel_remote_stream_packet_length
,
682 { "Remote Stream Packet Length", "asphodel.remote_stream_packet_length",
683 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
686 { &hf_asphodel_length
,
687 { "Length", "asphodel.length",
688 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
692 { "Type", "asphodel.type",
693 FT_UINT8
, BASE_HEX
, VALS(asphodel_type_vals
), 0x0,
697 { "Sequence", "asphodel.seq",
698 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
702 { "Command", "asphodel.cmd",
703 FT_UINT8
, BASE_HEX
, VALS(asphodel_cmd_vals
), 0x0,
706 { &hf_asphodel_err_code
,
707 { "Error Code", "asphodel.err_code",
708 FT_UINT8
, BASE_HEX
, VALS(asphodel_err_vals
), 0x0,
711 { &hf_asphodel_params
,
712 { "Command Parameter Data", "asphodel.params",
713 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
716 { &hf_asphodel_stream_data
,
717 { "Stream Data", "asphodel.stream_data",
718 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
721 { &hf_asphodel_notify
,
722 { "Notify", "asphodel.notify",
723 FT_BOOLEAN
, BASE_NONE
, TFS(¬ify_connect_disconnect
), 0x0,
726 { &hf_asphodel_notify_serial
,
727 { "Notify Serial Number", "asphodel.notify_serial",
728 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
733 static int *ett
[] = {
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
));
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
789 * indent-tabs-mode: nil
792 * vi: set shiftwidth=4 tabstop=8 expandtab:
793 * :indentSize=4:tabSize=8:noTabs=true: