static int dissect_btsmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { int offset = 0; proto_item *ti; proto_tree *st; guint8 opcode; btl2cap_data_t *l2cap_data; guint32 interface_id; guint32 adapter_id; l2cap_data = (btl2cap_data_t *) data; if (l2cap_data) { interface_id = l2cap_data->interface_id; adapter_id = l2cap_data->adapter_id; } else { interface_id = HCI_INTERFACE_DEFAULT; adapter_id = HCI_ADAPTER_DEFAULT; } ti = proto_tree_add_item(tree, proto_btsmp, tvb, 0, tvb_captured_length(tvb), ENC_NA); st = proto_item_add_subtree(ti, ett_btsmp); col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMP"); switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_set_str(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_set_str(pinfo->cinfo, COL_INFO, "Rcvd "); break; default: col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection "); break; } if (tvb_reported_length(tvb) < 1) return FALSE; proto_tree_add_item(st, hf_btsmp_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN); opcode = tvb_get_guint8(tvb, 0); offset++; col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, opcode_vals, "<unknown>")); switch (opcode) { case 0x01: /* Pairing Request */ case 0x02: /* Pairing Response */ { col_append_str(pinfo->cinfo, COL_INFO, ": "); proto_tree_add_item(st, hf_btsmp_io_capabilities, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; proto_tree_add_item(st, hf_btsmp_oob_data_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st); proto_tree_add_item(st, hf_btsmp_max_enc_key_size, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, TRUE); offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, FALSE); break; } case 0x03: /* Pairing Confirm */ proto_tree_add_item(st, hf_btsmp_cfm_value, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x04: /* Pairing Random */ proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x05: /* Pairing Failed */ proto_tree_add_item(st, hf_btsmp_reason, tvb, offset, 1, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(tvb_get_guint8(tvb, offset), reason_vals, "<unknown>")); offset++; break; case 0x06: /* Encryption Information */ proto_tree_add_item(st, hf_btsmp_long_term_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x07: /* Master Identification */ proto_tree_add_item(st, hf_btsmp_ediv, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 8, ENC_NA); offset += 8; break; case 0x08: /* Identity Information */ proto_tree_add_item(st, hf_btsmp_id_resolving_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x09: /* Identity Address Information */ proto_tree_add_item(st, hf_address_type, tvb, offset, 1, ENC_NA); offset += 1; offset = dissect_bd_addr(hf_bd_addr, pinfo, st, tvb, offset, FALSE, interface_id, adapter_id, NULL); break; case 0x0a: /* Signing Information */ proto_tree_add_item(st, hf_btsmp_signature_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x0b: /* Security Request */ col_append_str(pinfo->cinfo, COL_INFO, ": "); offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st); break; default: break; } return offset; }
static void dissect_btsmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; proto_item *ti; proto_tree *st; guint8 opcode; col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMP"); switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_add_str(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_add_str(pinfo->cinfo, COL_INFO, "Rcvd "); break; default: col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ", pinfo->p2p_dir); break; } if (tvb_length_remaining(tvb, 0) < 1) return; ti = proto_tree_add_item(tree, proto_btsmp, tvb, 0, -1, ENC_NA); st = proto_item_add_subtree(ti, ett_btsmp); proto_tree_add_item(st, hf_btsmp_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN); opcode = tvb_get_guint8(tvb, 0); offset++; col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_const(opcode, opcode_vals, "<unknown>")); switch (opcode) { case 0x01: /* Pairing Request */ case 0x02: /* Pairing Response */ { col_append_fstr(pinfo->cinfo, COL_INFO, ": "); proto_tree_add_item(st, hf_btsmp_io_capabilities, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; proto_tree_add_item(st, hf_btsmp_oob_data_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st); proto_tree_add_item(st, hf_btsmp_max_enc_key_size, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, TRUE); offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, FALSE); break; } case 0x03: /* Pairing Confirm */ proto_tree_add_item(st, hf_btsmp_cfm_value, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x04: /* Pairing Random */ proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x05: /* Pairing Failed */ proto_tree_add_item(st, hf_btsmp_reason, tvb, offset, 1, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(tvb_get_guint8(tvb, offset), reason_vals, "<unknown>")); offset++; break; case 0x06: /* Encryption Information */ proto_tree_add_item(st, hf_btsmp_long_term_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x07: /* Master Identification */ proto_tree_add_item(st, hf_btsmp_ediv, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 8, ENC_NA); offset += 8; break; case 0x08: /* Identity Information */ proto_tree_add_item(st, hf_btsmp_id_resolving_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x0a: /* Signing Informationn */ proto_tree_add_item(st, hf_btsmp_signature_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x0b: /* Security Request */ col_append_fstr(pinfo->cinfo, COL_INFO, ": "); offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st); break; default: break; } }
static int dissect_btsmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { int offset = 0; proto_item *ti; proto_tree *st; guint8 opcode; guint32 interface_id; guint32 adapter_id; gint previous_proto; interface_id = HCI_INTERFACE_DEFAULT; adapter_id = HCI_ADAPTER_DEFAULT; previous_proto = (GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers))))); if (data && previous_proto == proto_btl2cap) { btl2cap_data_t *l2cap_data; l2cap_data = (btl2cap_data_t *) data; if (l2cap_data) { interface_id = l2cap_data->interface_id; adapter_id = l2cap_data->adapter_id; } } ti = proto_tree_add_item(tree, proto_btsmp, tvb, 0, tvb_captured_length(tvb), ENC_NA); st = proto_item_add_subtree(ti, ett_btsmp); col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMP"); switch (pinfo->p2p_dir) { case P2P_DIR_SENT: col_set_str(pinfo->cinfo, COL_INFO, "Sent "); break; case P2P_DIR_RECV: col_set_str(pinfo->cinfo, COL_INFO, "Rcvd "); break; default: col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection "); break; } if (tvb_reported_length(tvb) < 1) return FALSE; proto_tree_add_item(st, hf_btsmp_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN); opcode = tvb_get_guint8(tvb, 0); offset++; col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, opcode_vals, "<unknown>")); switch (opcode) { case 0x01: /* Pairing Request */ case 0x02: /* Pairing Response */ { col_append_str(pinfo->cinfo, COL_INFO, ": "); proto_tree_add_item(st, hf_btsmp_io_capabilities, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; proto_tree_add_item(st, hf_btsmp_oob_data_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st); proto_tree_add_item(st, hf_btsmp_max_enc_key_size, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset++; offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, TRUE); offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, FALSE); break; } case 0x03: /* Pairing Confirm */ proto_tree_add_item(st, hf_btsmp_cfm_value, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x04: /* Pairing Random */ proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x05: /* Pairing Failed */ proto_tree_add_item(st, hf_btsmp_reason, tvb, offset, 1, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(tvb_get_guint8(tvb, offset), reason_vals, "<unknown>")); offset++; break; case 0x06: /* Encryption Information */ proto_tree_add_item(st, hf_btsmp_long_term_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x07: /* Master Identification */ proto_tree_add_item(st, hf_btsmp_ediv, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 8, ENC_NA); offset += 8; break; case 0x08: /* Identity Information */ proto_tree_add_item(st, hf_btsmp_id_resolving_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x09: /* Identity Address Information */ proto_tree_add_item(st, hf_address_type, tvb, offset, 1, ENC_NA); offset += 1; offset = dissect_bd_addr(hf_bd_addr, pinfo, st, tvb, offset, FALSE, interface_id, adapter_id, NULL); break; case 0x0A: /* Signing Information */ proto_tree_add_item(st, hf_btsmp_signature_key, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x0B: /* Security Request */ col_append_str(pinfo->cinfo, COL_INFO, ": "); offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st); break; case 0x0C: /* Pairing Public Key */ { proto_item *sub_item; sub_item = proto_tree_add_item(st, hf_btsmp_public_key_x, tvb, offset, 32, ENC_NA); if (tvb_memeql(tvb, offset, debug_public_key_x, 32) == 0) proto_item_append_text(sub_item, " (Debug Key)"); offset += 32; sub_item = proto_tree_add_item(st, hf_btsmp_public_key_y, tvb, offset, 32, ENC_NA); if (tvb_memeql(tvb, offset, debug_public_key_y, 32) == 0) proto_item_append_text(sub_item, " (Debug Key)"); offset += 32; break;} case 0x0D: /* Pairing DHKey Check" */ proto_tree_add_item(st, hf_btsmp_dhkey_check, tvb, offset, 16, ENC_NA); offset += 16; break; case 0x0E: /* Pairing Keypress Notification */ proto_tree_add_item(st, hf_btsmp_notification_type, tvb, offset, 1, ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(tvb_get_guint8(tvb, offset), notification_type_vals, "<unknown>")); offset += 1; break; default: break; } return offset; }