diff options
author | Michael Mann <mmann78@netscape.net> | 2013-11-06 20:57:23 +0000 |
---|---|---|
committer | Michael Mann <mmann78@netscape.net> | 2013-11-06 20:57:23 +0000 |
commit | 912b59120050d9f8b82dd7b51550cf06bd95a56a (patch) | |
tree | 0ab167bc1f9718074a4469279fe68c6a2e0a06ba /epan/dissectors/packet-rfid-pn532.c | |
parent | 99e20da08ec0b236de99d89f9a63e5f866740ebe (diff) |
NFC: PN532: Dissect InListPassiveTarget Response and Diagnose request and response. Bug 9333 (https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=9333)
From Michal Labedzki
From me: adjust datatype to guint8 on a few local variables to quiet the Microsoft compiler.
svn path=/trunk/; revision=53116
Diffstat (limited to 'epan/dissectors/packet-rfid-pn532.c')
-rw-r--r-- | epan/dissectors/packet-rfid-pn532.c | 557 |
1 files changed, 399 insertions, 158 deletions
diff --git a/epan/dissectors/packet-rfid-pn532.c b/epan/dissectors/packet-rfid-pn532.c index 0aa267dcfd..7e8dd389b9 100644 --- a/epan/dissectors/packet-rfid-pn532.c +++ b/epan/dissectors/packet-rfid-pn532.c @@ -35,6 +35,9 @@ #include <epan/packet.h> #include <epan/prefs.h> #include <epan/expert.h> +#include <epan/wmem/wmem.h> + +#include "packet-usb.h" static int proto_pn532 = -1; @@ -57,15 +60,7 @@ static int hf_pn532_fw_support_rfu = -1; static int hf_pn532_fw_support_iso_018092 = -1; static int hf_pn532_fw_support_iso_iec_14443_type_b = -1; static int hf_pn532_fw_support_iso_iec_14443_type_a = -1; -static int hf_pn532_14443a_sak = -1; -static int hf_pn532_14443a_atqa = -1; static int hf_pn532_14443a_uid = -1; -static int hf_pn532_14443a_ats_length = -1; -static int hf_pn532_14443a_uid_length = -1; -static int hf_pn532_14443a_ats = -1; -static int hf_pn532_14443b_pupi = -1; -static int hf_pn532_14443b_app_data = -1; -static int hf_pn532_14443b_proto_info = -1; static int hf_pn532_sam_mode = -1; static int hf_pn532_sam_timeout = -1; static int hf_pn532_sam_irq = -1; @@ -197,10 +192,38 @@ static int hf_pn532_optional_parameters = -1; static int hf_pn532_test_number = -1; static int hf_pn532_parameters = -1; static int hf_pn532_parameters_length = -1; +static int hf_pn532_sens_res = -1; +static int hf_pn532_sel_res = -1; +static int hf_pn532_nfc_id_length = -1; +static int hf_pn532_nfc_id_1 = -1; +static int hf_pn532_ats_length = -1; +static int hf_pn532_ats = -1; +static int hf_pn532_pol_res_length = -1; +static int hf_pn532_response_code = -1; +static int hf_pn532_nfc_id_2t = -1; +static int hf_pn532_pad = -1; +static int hf_pn532_syst_code = -1; +static int hf_pn532_atqb_response = -1; +static int hf_pn532_attrib_res_length = -1; +static int hf_pn532_attrib_res = -1; +static int hf_pn532_jewel_id = -1; +static int hf_pn532_response_for = -1; +static int hf_pn532_diagnose_baudrate = -1; +static int hf_pn532_reply_delay = -1; +static int hf_pn532_ciu_tx_mode = -1; +static int hf_pn532_ciu_rx_mode = -1; +static int hf_pn532_diagnose_result = -1; +static int hf_pn532_diagnose_number_of_fails = -1; +static int hf_pn532_andet_bot = -1; +static int hf_pn532_andet_up = -1; +static int hf_pn532_andet_ith = -1; +static int hf_pn532_andet_en = -1; static expert_field ei_unknown_data = EI_INIT; static expert_field ei_unexpected_data = EI_INIT; +static wmem_tree_t *command_info = NULL; + void proto_register_pn532(void); void proto_reg_handoff_pn532(void); @@ -286,6 +309,20 @@ enum { SUB_MAX }; +typedef struct command_data_t { + guint32 bus_id; + guint32 device_address; + guint32 endpoint; + + gint16 command; + guint32 command_frame_number; + guint32 response_frame_number; + union { + guint8 test_number; + guint8 baudrate; + } data; +} command_data_t; + static dissector_handle_t sub_handles[SUB_MAX]; static gint sub_selected = SUB_DATA; @@ -521,16 +558,6 @@ static const value_string pn532_baudrate_vals[] = { {0x00, NULL} }; -static void sam_timeout_base(gchar* buf, guint32 value) { - if (value == 0x00) { - g_snprintf(buf, ITEM_LABEL_LENGTH, "No timeout control"); - } else if (0x01 <= value && value <= 0x13) { - g_snprintf(buf, ITEM_LABEL_LENGTH, "%u ms", value * 50); - } else { - g_snprintf(buf, ITEM_LABEL_LENGTH, "%u.%03u s", value * 50 / 1000, value * 50 % 1000); - } -} - static const value_string pn532_type_vals[] = { {0x00, "Mifare, ISO/IEC14443-3 Type A, ISO/IEC14443-3 Type B, ISO/IEC18092 passive 106 kbps"}, {0x01, "ISO/IEC18092 Active Mode"}, @@ -556,6 +583,26 @@ static const value_string pn532_test_number_vals[] = { {0x00, NULL} }; +static const value_string pn532_diagnose_baudrate_vals[] = { + {0x01, "212 kbps"}, + {0x02, "424 kbps"}, + {0x00, NULL} +}; + +static void sam_timeout_base(gchar* buf, guint32 value) { + if (value == 0x00) { + g_snprintf(buf, ITEM_LABEL_LENGTH, "No timeout control"); + } else if (0x01 <= value && value <= 0x13) { + g_snprintf(buf, ITEM_LABEL_LENGTH, "%u ms", value * 50); + } else { + g_snprintf(buf, ITEM_LABEL_LENGTH, "%u.%03u s", value * 50 / 1000, value * 50 % 1000); + } +} + +static void replay_delay_base(gchar* buf, guint32 value) { + g_snprintf(buf, ITEM_LABEL_LENGTH, "%u.%03u s", value * 500 / 1000, value * 500 % 1000); +} + static gint dissect_status(proto_tree *tree, tvbuff_t *tvb, gint offset) { @@ -566,8 +613,8 @@ dissect_status(proto_tree *tree, tvbuff_t *tvb, gint offset) return offset + 1; } -static void -dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +static gint +dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *item; proto_tree *pn532_tree; @@ -575,15 +622,26 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) proto_tree *sub_tree; proto_item *next_item; proto_tree *next_tree; - guint8 cmd; + gint16 cmd = -1; guint8 config; guint8 baudrate; + guint8 test_number; guint8 length; guint8 value; guint8 type; guint8 item_value; tvbuff_t *next_tvb; gint offset = 0; + command_data_t *command_data = NULL; + usb_data_t *usb_data; + wmem_tree_key_t key[5]; + guint32 bus_id; + guint32 device_address; + guint32 endpoint; + guint32 k_bus_id; + guint32 k_device_address; + guint32 k_endpoint; + guint32 k_frame_number; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PN532"); @@ -599,29 +657,176 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) col_set_str(pinfo->cinfo, COL_INFO, val_to_str_ext_const(cmd, &pn532_commands_ext, "Unknown command")); + usb_data = (usb_data_t *) data; + DISSECTOR_ASSERT(usb_data); + + bus_id = usb_data->bus_id; + device_address = usb_data->device_address; + endpoint = usb_data->endpoint; + + k_bus_id = bus_id; + k_device_address = device_address; + k_endpoint = endpoint; + k_frame_number = pinfo->fd->num; + + key[0].length = 1; + key[0].key = &k_bus_id; + key[1].length = 1; + key[1].key = &k_device_address; + key[2].length = 1; + key[2].key = &k_endpoint; + key[3].length = 1; + key[3].key = &k_frame_number; + key[4].length = 0; + key[4].key = NULL; + + if (!pinfo->fd->flags.visited && cmd > 0 && !(cmd & 0x01)) { + command_data = wmem_new(wmem_file_scope(), command_data_t); + command_data->bus_id = bus_id; + command_data->device_address = device_address; + command_data->endpoint = endpoint; + + command_data->command = cmd; + command_data->command_frame_number = pinfo->fd->num; + command_data->response_frame_number = 0; + + wmem_tree_insert32_array(command_info, key, command_data); + + k_bus_id = bus_id; + k_device_address = device_address; + k_endpoint = endpoint; + k_frame_number = pinfo->fd->num; + + key[0].length = 1; + key[0].key = &k_bus_id; + key[1].length = 1; + key[1].key = &k_device_address; + key[2].length = 1; + key[2].key = &k_endpoint; + key[3].length = 1; + key[3].key = &k_frame_number; + key[4].length = 0; + key[4].key = NULL; + } + + if (cmd > 0 && cmd & 0x01) { + wmem_tree_t *wmem_tree; + + key[3].length = 0; + key[3].key = NULL; + + wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key); + if (wmem_tree) { + command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, pinfo->fd->num); + + if (command_data && (command_data->response_frame_number == 0 || + command_data->response_frame_number == pinfo->fd->num)) { + + if (!pinfo->fd->flags.visited && command_data->response_frame_number == 0) { + command_data->response_frame_number = pinfo->fd->num; + } + + } + } + + if (command_data) { + sub_item = proto_tree_add_uint(pn532_tree, hf_pn532_response_for, tvb, offset, tvb_length_remaining(tvb, offset), command_data->command_frame_number); + PROTO_ITEM_SET_GENERATED(sub_item); + } + } + switch (cmd) { case DIAGNOSE_REQ: - proto_tree_add_item(pn532_tree, hf_pn532_test_number, tvb, offset, 1, ENC_NA); + proto_tree_add_item(pn532_tree, hf_pn532_test_number, tvb, offset, 1, ENC_NA); + test_number = tvb_get_guint8(tvb, offset); offset += 1; - proto_tree_add_item(pn532_tree, hf_pn532_parameters_length, tvb, offset, 1, ENC_NA); + if (command_data) + command_data->data.test_number = test_number; + + proto_tree_add_item(pn532_tree, hf_pn532_parameters_length, tvb, offset, 1, ENC_NA); + length = tvb_get_guint8(tvb, offset); offset += 1; -/* TODO: "parameters" can be decoded using "test_number" value */ - proto_tree_add_item(pn532_tree, hf_pn532_parameters, tvb, offset, tvb_length_remaining(tvb, offset), ENC_NA); - offset += tvb_length_remaining(tvb, offset); + switch (test_number) { + case 0x00: + proto_tree_add_item(pn532_tree, hf_pn532_data_in, tvb, offset, length, ENC_NA); + offset += length; + break; + case 0x04: + proto_tree_add_item(pn532_tree, hf_pn532_diagnose_baudrate, tvb, offset, 1, ENC_NA); + offset += 1; + break; + case 0x05: + proto_tree_add_item(pn532_tree, hf_pn532_reply_delay, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(pn532_tree, hf_pn532_ciu_tx_mode, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(pn532_tree, hf_pn532_ciu_rx_mode, tvb, offset, 1, ENC_NA); + offset += 1; + break; + case 0x07: + proto_tree_add_item(pn532_tree, hf_pn532_andet_bot, tvb, offset, 1, ENC_NA); + proto_tree_add_item(pn532_tree, hf_pn532_andet_up, tvb, offset, 1, ENC_NA); + proto_tree_add_item(pn532_tree, hf_pn532_andet_ith, tvb, offset, 1, ENC_NA); + proto_tree_add_item(pn532_tree, hf_pn532_andet_en, tvb, offset, 1, ENC_NA); + offset += 1; + break; + case 0x01: + case 0x02: + case 0x06: + /* No parameters */ + break; + + default: + proto_tree_add_item(pn532_tree, hf_pn532_parameters, tvb, offset, tvb_length_remaining(tvb, offset), ENC_NA); + offset += tvb_length_remaining(tvb, offset); + } break; case DIAGNOSE_RSP: -/* TODO: There is no info for which TestNumber payload is here; but this - can be done be storing additional data from DIAGNOSE_REQ in wmem_tree */ + if (command_data && command_data->command == DIAGNOSE_REQ) + test_number = command_data->data.test_number; + else + test_number = -1; /* Force unknown test_numer */ + if (tvb_length_remaining(tvb, offset) >= 1) { - proto_tree_add_item(pn532_tree, hf_pn532_parameters_length, tvb, offset, 1, ENC_NA); + proto_tree_add_item(pn532_tree, hf_pn532_parameters_length, tvb, offset, 1, ENC_NA); offset += 1; - proto_tree_add_item(pn532_tree, hf_pn532_parameters, tvb, offset, tvb_length_remaining(tvb, offset), ENC_NA); - offset += tvb_length_remaining(tvb, offset); + switch (test_number) { + case 0x00: + proto_tree_add_item(pn532_tree, hf_pn532_test_number, tvb, offset, 1, ENC_NA); + offset += 1; + + proto_tree_add_item(pn532_tree, hf_pn532_parameters_length, tvb, offset, 1, ENC_NA); + length = tvb_length_remaining(tvb, offset); + offset += 1; + + proto_tree_add_item(pn532_tree, hf_pn532_data_out, tvb, offset, length, ENC_NA); + offset += length; + break; + case 0x01: + case 0x02: + case 0x06: + case 0x07: + proto_tree_add_item(pn532_tree, hf_pn532_diagnose_result, tvb, offset, 1, ENC_NA); + offset += 1; + break; + case 0x04: + proto_tree_add_item(pn532_tree, hf_pn532_diagnose_number_of_fails, tvb, offset, 1, ENC_NA); + offset += 1; + break; + case 0x05: + /* Not possible; test 0x05 runs infinitely */ + break; + default: + proto_tree_add_item(pn532_tree, hf_pn532_parameters, tvb, offset, tvb_length_remaining(tvb, offset), ENC_NA); + offset += tvb_length_remaining(tvb, offset); + } } break; @@ -630,16 +835,16 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) break; case GET_FIRMWARE_VERSION_RSP: - proto_tree_add_item(pn532_tree, hf_pn532_ic_version, tvb, offset, 1, ENC_NA); + proto_tree_add_item(pn532_tree, hf_pn532_ic_version, tvb, offset, 1, ENC_NA); offset += 1; - proto_tree_add_item(pn532_tree, hf_pn532_fw_version, tvb, offset, 1, ENC_NA); + proto_tree_add_item(pn532_tree, hf_pn532_fw_version, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(pn532_tree, hf_pn532_fw_revision, tvb, offset, 1, ENC_NA); offset += 1; - sub_item = proto_tree_add_item(pn532_tree, hf_pn532_fw_support, tvb, offset, 1, ENC_NA); + sub_item = proto_tree_add_item(pn532_tree, hf_pn532_fw_support, tvb, offset, 1, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_pn532_fw_support); proto_tree_add_item(sub_tree, hf_pn532_fw_support_rfu, tvb, offset, 1, ENC_NA); proto_tree_add_item(sub_tree, hf_pn532_fw_support_iso_018092, tvb, offset, 1, ENC_NA); @@ -664,7 +869,7 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) offset += 1; for (item_value = 1; item_value <= value; item_value += 1) { - sub_item = proto_tree_add_item(pn532_tree, hf_pn532_target, tvb, offset, 4, ENC_NA); + sub_item = proto_tree_add_item(pn532_tree, hf_pn532_target, tvb, offset, 4, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_pn532_target); proto_item_append_text(sub_item, " %u/%u", item_value, value); @@ -751,7 +956,7 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) break; case SET_PARAMETERS_REQ: - sub_item = proto_tree_add_item(pn532_tree, hf_pn532_flags, tvb, offset, 1, ENC_NA); + sub_item = proto_tree_add_item(pn532_tree, hf_pn532_flags, tvb, offset, 1, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_pn532_flags); proto_tree_add_item(sub_tree, hf_pn532_flags_rfu_7, tvb, offset, 1, ENC_BIG_ENDIAN); @@ -787,7 +992,7 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) break; case POWER_DOWN_REQ: - sub_item = proto_tree_add_item(pn532_tree, hf_pn532_wakeup_enable, tvb, offset, 1, ENC_NA); + sub_item = proto_tree_add_item(pn532_tree, hf_pn532_wakeup_enable, tvb, offset, 1, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_pn532_wakeup_enable); proto_tree_add_item(sub_tree, hf_pn532_wakeup_enable_i2c, tvb, offset, 1, ENC_BIG_ENDIAN); @@ -894,7 +1099,7 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) offset += 1; break; case 0x0D: - sub_item = proto_tree_add_item(pn532_tree, hf_pn532_config_212_kbps, tvb, offset, 3, ENC_NA); + sub_item = proto_tree_add_item(pn532_tree, hf_pn532_config_212_kbps, tvb, offset, 3, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_pn532_config_212_kbps); proto_tree_add_item(sub_tree, hf_pn532_config_ciu_rx_threshold, tvb, offset, 1, ENC_BIG_ENDIAN); @@ -906,7 +1111,7 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) proto_tree_add_item(sub_tree, hf_pn532_config_ciu_mif_nfc, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; - sub_item = proto_tree_add_item(pn532_tree, hf_pn532_config_424_kbps, tvb, offset, 3, ENC_NA); + sub_item = proto_tree_add_item(pn532_tree, hf_pn532_config_424_kbps, tvb, offset, 3, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_pn532_config_424_kbps); proto_tree_add_item(sub_tree, hf_pn532_config_ciu_rx_threshold, tvb, offset, 1, ENC_BIG_ENDIAN); @@ -918,7 +1123,7 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) proto_tree_add_item(sub_tree, hf_pn532_config_ciu_mif_nfc, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; - sub_item = proto_tree_add_item(pn532_tree, hf_pn532_config_848_kbps, tvb, offset, 3, ENC_NA); + sub_item = proto_tree_add_item(pn532_tree, hf_pn532_config_848_kbps, tvb, offset, 3, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_pn532_config_848_kbps); proto_tree_add_item(sub_tree, hf_pn532_config_ciu_rx_threshold, tvb, offset, 1, ENC_BIG_ENDIAN); @@ -1027,6 +1232,9 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) baudrate = tvb_get_guint8(tvb, offset); offset += 1; + if (command_data) + command_data->data.baudrate = baudrate; + switch(baudrate) { case ISO_IEC_14443A_106: while (tvb_length_remaining(tvb, offset) >= 4) { @@ -1061,118 +1269,92 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) value = tvb_get_guint8(tvb, offset); offset += 1; -/* TODO: implement in accordance with the specification, - need storing additional information ("baudrate" from request) in wmem_tree */ - for (item_value = 1; item_value <= value; item_value += 1) { - sub_item = proto_tree_add_item(pn532_tree, hf_pn532_target, tvb, offset, 0, ENC_NA); - /*sub_tree = proto_item_add_subtree(sub_item, ett_pn532_target);*/ - proto_item_append_text(sub_item, " %u/%u", item_value, value); - - - - /* Probably an ISO/IEC 14443-B tag */ - if (tvb_reported_length(tvb) == 18) { + if (command_data && command_data->command == IN_LIST_PASSIVE_TARGET_REQ) + baudrate = command_data->data.baudrate; + else + baudrate = -1; /* Force unknown baudrate... */ - /* Add the PUPI */ - proto_tree_add_item(pn532_tree, hf_pn532_14443b_pupi, tvb, 5, 4, ENC_BIG_ENDIAN); + sub_item = proto_tree_add_uint(pn532_tree, hf_pn532_BrTy, tvb, offset, tvb_length_remaining(tvb, offset), baudrate); + PROTO_ITEM_SET_GENERATED(sub_item); - /* Add the Application Data */ - proto_tree_add_item(pn532_tree, hf_pn532_14443b_app_data, tvb, 9, 4, ENC_BIG_ENDIAN); - - /* Add the Protocol Info */ - proto_tree_add_item(pn532_tree, hf_pn532_14443b_proto_info, tvb, 13, 3, ENC_BIG_ENDIAN); - } - - /* InnoVision Jewel/Topaz (ISO 14443-A/proprietary) */ - if (tvb_reported_length(tvb) == 10) { - - /* Add the ATQA/SENS_RES (0x0C00)*/ - proto_tree_add_item(pn532_tree, hf_pn532_14443a_atqa, tvb, 4, 2, ENC_BIG_ENDIAN); - - /* Add the UID (4 bytes) */ - proto_tree_add_item(pn532_tree, hf_pn532_14443a_uid, tvb, 6, 4, ENC_BIG_ENDIAN); - } - - /* Probably one of: - * a MiFare DESFire card (21 bytes), - * an MF UltraLight tag (15 bytes) - * an MF Classic card with a 4 byte UID (12 bytes) */ + for (item_value = 1; item_value <= value; item_value += 1) { + sub_item = proto_tree_add_item(pn532_tree, hf_pn532_target, tvb, offset, tvb_length_remaining(tvb, offset), ENC_NA); + sub_tree = proto_item_add_subtree(sub_item, ett_pn532_target); + proto_item_append_text(sub_item, " %u/%u", item_value, value); - if ((tvb_reported_length(tvb) == 21) || (tvb_reported_length(tvb) == 15) || (tvb_reported_length(tvb) == 12)) { + proto_tree_add_item(sub_tree, hf_pn532_Tg, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; - /* Add the ATQA/SENS_RES */ - proto_tree_add_item(pn532_tree, hf_pn532_14443a_atqa, tvb, 4, 2, ENC_BIG_ENDIAN); + switch (baudrate) { + case ISO_IEC_14443A_106: + proto_tree_add_item(sub_tree, hf_pn532_sens_res, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; - /* Add the SAK/SEL_RES value */ - proto_tree_add_item(pn532_tree, hf_pn532_14443a_sak, tvb, 6, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_pn532_sel_res, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; - /* Add the UID length */ - proto_tree_add_item(pn532_tree, hf_pn532_14443a_uid_length, tvb, 7, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_pn532_nfc_id_length, tvb, offset, 1, ENC_BIG_ENDIAN); + length = tvb_get_guint8(tvb, offset); + offset += 1; - /* Add the UID */ - if (tvb_reported_length(tvb) != 12) { - proto_tree_add_item(pn532_tree, hf_pn532_14443a_uid, tvb, 8, 7, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_pn532_nfc_id_1, tvb, offset, length, ENC_NA); + offset += length; - /* Probably MiFare DESFire, or some other 14443-A card with an ATS value/7 byte UID */ - if (tvb_reported_length(tvb) == 21) { + if (tvb_length_remaining(tvb, offset)) { + proto_tree_add_item(sub_tree, hf_pn532_ats_length, tvb, offset, 1, ENC_BIG_ENDIAN); + length = tvb_get_guint8(tvb, offset); + offset += 1; - /* Add the ATS value */ - proto_tree_add_item(pn532_tree, hf_pn532_14443a_ats, tvb, 16, 5, ENC_BIG_ENDIAN); - } - } - /* Probably MiFare Classic with a 4 byte UID */ - else { - proto_tree_add_item(pn532_tree, hf_pn532_14443a_uid, tvb, 8, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_pn532_ats, tvb, offset, length - 1, ENC_NA); + offset += length - 1; } + break; + case FELICA_212: + case FELICA_424: + proto_tree_add_item(sub_tree, hf_pn532_pol_res_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; - } - - /* Probably an EMV/ISO 14443-A (VISA - 28 bytes payload/MC - 31 bytes payload) - card with a 4 byte UID - - MTCOS-based contactless passports also have a 4 byte (randomised) UID (26 bytes payload) - */ - - if (tvb_reported_length(tvb) == 26 || tvb_reported_length(tvb) == 28 || tvb_reported_length(tvb) == 31) { - - /* Check to see if there's a plausible ATQA value (0x0004 for my MC/VISA cards, and 0x0008 for MTCOS) */ - - if (tvb_get_ntohs(tvb, 4) == 0x0004 || tvb_get_ntohs(tvb, 4) == 0x08) { - - /* Add the ATQA/SENS_RES */ - proto_tree_add_item(pn532_tree, hf_pn532_14443a_atqa, tvb, 4, 2, ENC_BIG_ENDIAN); - - /* Add the SAK/SEL_RES value */ - proto_tree_add_item(pn532_tree, hf_pn532_14443a_sak, tvb, 6, 1, ENC_BIG_ENDIAN); - - /* Add the UID length */ - proto_tree_add_item(pn532_tree, hf_pn532_14443a_uid_length, tvb, 7, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_pn532_response_code, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; - /* Add the UID */ - proto_tree_add_item(pn532_tree, hf_pn532_14443a_uid, tvb, 8, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_pn532_nfc_id_2t, tvb, offset, 8, ENC_NA); + offset += 8; - /* Dissect the ATS length for certainty... */ - proto_tree_add_item(pn532_tree, hf_pn532_14443a_ats_length, tvb, 12, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_pn532_pad, tvb, offset, 8, ENC_NA); + offset += 8; - /* Pass the ATS value to the Data dissector, since it's too long to handle normally - Don't care about the "status word" at the end, right now */ - next_tvb = tvb_new_subset_remaining(tvb, 13); - call_dissector(sub_handles[SUB_DATA], next_tvb, pinfo, tree); + if (tvb_length_remaining(tvb, offset) >= 2) { + proto_tree_add_item(sub_tree, hf_pn532_syst_code, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + } else if (tvb_length_remaining(tvb, offset) == 1) { + proto_tree_add_expert(pn532_tree, pinfo, &ei_unexpected_data, tvb, offset, 1); + offset += 1; } - } + break; + case ISO_IEC_14443B_106: + proto_tree_add_item(sub_tree, hf_pn532_atqb_response, tvb, offset, 12, ENC_NA); + offset += 12; - /* See if we've got a FeliCa payload with a System Code */ - if (tvb_reported_length(tvb) == 24) { + proto_tree_add_item(sub_tree, hf_pn532_attrib_res_length, tvb, offset, 1, ENC_BIG_ENDIAN); + length = tvb_get_guint8(tvb, offset); + offset += 1; - /* For FeliCa, this is at position 4. This doesn't exist for other payload types. */ - proto_tree_add_item(pn532_tree, hf_pn532_payload_length, tvb, 4, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_pn532_attrib_res, tvb, offset, length, ENC_NA); + offset += length; + break; + case JEWEL_14443A_106: + proto_tree_add_item(sub_tree, hf_pn532_sens_res, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; - /* Use the length value (20?) at position 4, and skip the Status Word (9000) at the end */ - next_tvb = tvb_new_subset(tvb, 5, tvb_get_guint8(tvb, 4) - 1, 19); - call_dissector(sub_handles[SUB_FELICA], next_tvb, pinfo, tree); + proto_tree_add_item(sub_tree, hf_pn532_jewel_id, tvb, offset, 4, ENC_NA); + offset += 4; + break; + default: + proto_tree_add_expert(pn532_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_length_remaining(tvb, offset)); + offset += tvb_length_remaining(tvb, offset); } - } + } break; case IN_ATR_REQ: @@ -1368,7 +1550,7 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) offset += 1; for (item_value = 1; item_value <= value; item_value += 1) { - sub_item = proto_tree_add_item(pn532_tree, hf_pn532_target, tvb, offset, 4, ENC_NA); + sub_item = proto_tree_add_item(pn532_tree, hf_pn532_target, tvb, offset, 4, ENC_NA); sub_tree = proto_item_add_subtree(sub_item, ett_pn532_target); proto_item_append_text(sub_item, " %u/%u", item_value, value); @@ -1561,7 +1743,10 @@ dissect_pn532(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) if (tvb_length_remaining(tvb, offset) > 0) { proto_tree_add_expert(pn532_tree, pinfo, &ei_unexpected_data, tvb, offset, tvb_length_remaining(tvb, offset)); + offset += tvb_length_remaining(tvb, offset); } + + return offset; } void proto_register_pn532(void) @@ -1628,33 +1813,9 @@ void proto_register_pn532(void) {&hf_pn532_fw_support_iso_iec_14443_type_a, {"ISO/IEC 14443 Type A", "pn532.fw.support.iso_iec_14443_type_a", FT_BOOLEAN, 8, NULL, 0x01, NULL, HFILL}}, - {&hf_pn532_14443a_sak, - {"ISO/IEC 14443-A SAK", "pn532.iso.14443a.sak", FT_UINT8, BASE_HEX, - NULL, 0x0, NULL, HFILL}}, - {&hf_pn532_14443a_atqa, - {"ISO/IEC 14443-A ATQA", "pn532.iso.14443a.atqa", FT_UINT16, BASE_HEX, - NULL, 0x0, NULL, HFILL}}, {&hf_pn532_14443a_uid, {"ISO/IEC 14443-A UID", "pn532.iso.14443a.uid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}}, - {&hf_pn532_14443a_uid_length, - {"ISO/IEC 14443-A UID Length", "pn532.iso.14443a.uid.length", FT_INT8, BASE_DEC, - NULL, 0x0, NULL, HFILL}}, - {&hf_pn532_14443a_ats_length, - {"ISO/IEC 14443-A ATS Length", "pn532.iso.14443a.ats.length", FT_INT8, BASE_DEC, - NULL, 0x0, NULL, HFILL}}, - {&hf_pn532_14443a_ats, - {"ISO/IEC 14443-A ATS", "pn532.iso.14443a.ats", FT_UINT64, BASE_HEX, - NULL, 0x0, NULL, HFILL}}, - {&hf_pn532_14443b_pupi, - {"ISO/IEC 14443-B PUPI", "pn532.iso.14443b.pupi", FT_UINT64, BASE_HEX, - NULL, 0x0, NULL, HFILL}}, - {&hf_pn532_14443b_app_data, - {"ISO/IEC 14443-B Application Data", "pn532.iso.14443b.app.data", FT_UINT64, BASE_HEX, - NULL, 0x0, NULL, HFILL}}, - {&hf_pn532_14443b_proto_info, - {"ISO/IEC 14443-B Protocol Info", "pn532.iso.14443b.protocol.info", FT_UINT64, BASE_HEX, - NULL, 0x0, NULL, HFILL}}, {&hf_pn532_sam_mode, {"SAM Mode", "pn532.sam.mode", FT_UINT8, BASE_HEX, VALS(pn532_sam_modes), 0x0, NULL, HFILL}}, @@ -2048,6 +2209,84 @@ void proto_register_pn532(void) {&hf_pn532_parameters_length, {"Parameters Length", "pn532.diagnose_parameters.length", FT_UINT8, BASE_DEC, NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_sens_res, + {"SENS RES", "pn532.sens_res", FT_UINT16, BASE_HEX, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_sel_res, + {"SEL RES", "pn532.sel_res", FT_UINT8, BASE_HEX, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_nfc_id_length, + {"NFC ID Length", "pn532.nfc_id_length", FT_UINT8, BASE_DEC, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_nfc_id_1, + {"NFC ID 1", "pn532.nfc_id_1", FT_BYTES, BASE_NONE, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_ats_length, + {"ATS Length", "pn532.ats_length", FT_UINT8, BASE_DEC, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_ats, + {"ATS", "pn532.ats", FT_BYTES, BASE_NONE, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_pol_res_length, + {"POL RES Length", "pn532.pol_res_length", FT_UINT8, BASE_DEC, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_response_code, + {"Response Code", "pn532.response_code", FT_UINT8, BASE_HEX, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_nfc_id_2t, + {"NFC ID 2t", "pn532.nfc_id_2t", FT_BYTES, BASE_NONE, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_pad, + {"Pad", "pn532.pad", FT_BYTES, BASE_NONE, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_syst_code, + {"Syst Code", "pn532.syst_code", FT_UINT16, BASE_HEX, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_atqb_response, + {"ATQB Response", "pn532.atqb_response", FT_BYTES, BASE_NONE, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_attrib_res_length, + {"Attrib RES Length", "pn532.attrib_res_length", FT_UINT8, BASE_DEC, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_attrib_res, + {"Attrib RES", "pn532.attrib_res", FT_BYTES, BASE_NONE, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_jewel_id, + {"Jewel ID", "pn532.jewel_id", FT_BYTES, BASE_NONE, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_response_for, + { "Response for", "pn532.response_for", FT_FRAMENUM, BASE_NONE, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_diagnose_baudrate, + {"Diagnose Baudrate", "pn532.diagnose_baudrate", FT_UINT8, BASE_HEX, + VALS(pn532_diagnose_baudrate_vals), 0x00, NULL, HFILL}}, + {&hf_pn532_reply_delay, + {"Reply Delay", "pn532.sam.reply_delay", FT_UINT8, BASE_CUSTOM, + replay_delay_base, 0x0, NULL, HFILL}}, + {&hf_pn532_ciu_tx_mode, + {"CIU Tx Mode", "pn532.ciu_tx_mode", FT_UINT8, BASE_HEX, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_ciu_rx_mode, + {"CIU Rx Mode", "pn532.ciu_rx_mode", FT_UINT8, BASE_HEX, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_diagnose_number_of_fails, + {"Number of Fails", "pn532.number_of_fails", FT_UINT8, BASE_DEC, + NULL, 0x00, NULL, HFILL}}, + {&hf_pn532_diagnose_result, + {"Result", "pn532.result", FT_BOOLEAN, BASE_NONE, + &tfs_ok_error, 0x00, NULL, HFILL}}, + {&hf_pn532_andet_bot, + {"Andet Bot", "pn532.andet.bot", FT_BOOLEAN, 8, + NULL, 0x80, NULL, HFILL}}, + {&hf_pn532_andet_up, + {"Andet Up", "pn532.andet.up", FT_BOOLEAN, 8, + NULL, 0x40, NULL, HFILL}}, + {&hf_pn532_andet_ith, + {"Andet Ith", "pn532.andet.ith", FT_BOOLEAN, 8, + NULL, 0x3E, NULL, HFILL}}, + {&hf_pn532_andet_en, + {"Andet En", "pn532.andet.en", FT_BOOLEAN, 8, + NULL, 0x01, NULL, HFILL}} }; static ei_register_info ei[] = { @@ -2077,6 +2316,8 @@ void proto_register_pn532(void) { NULL, NULL, 0 } }; + command_info = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); + proto_pn532 = proto_register_protocol("NXP PN532", "PN532", "pn532"); proto_register_field_array(proto_pn532, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); @@ -2093,7 +2334,7 @@ void proto_register_pn532(void) pn532_dissector_table = register_dissector_table("pn532.payload", "PN532 Payload", FT_UINT8, BASE_DEC); - register_dissector("pn532", dissect_pn532, proto_pn532); + new_register_dissector("pn532", dissect_pn532, proto_pn532); } /* Handler registration */ |