static int dissect_extension(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset) { guint8 extension_flag; guint8 extension_type; guint16 extension_length; guint8 type; proto_tree_add_item(tree, hf_btbnep_extension_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_btbnep_extension_flag, tvb, offset, 1, ENC_BIG_ENDIAN); type = tvb_get_guint8(tvb, offset); extension_flag = type & 0x01; extension_type = type >> 1; offset += 1; proto_tree_add_item(tree, hf_btbnep_extension_length, tvb, offset, 1, ENC_BIG_ENDIAN); extension_length = tvb_get_ntohs(tvb, offset); offset += 2; if (extension_type == 0x00) { /* Extension Control */ offset = dissect_control(tvb, pinfo, tree, offset); } else { offset += extension_length; } if (extension_flag) offset = dissect_extension(tvb, pinfo, tree, offset); return offset; }
static void dissect_bthcrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *main_item; proto_tree *main_tree; btl2cap_data_t *l2cap_data; gint offset = 0; gboolean is_client_message; l2cap_data = (btl2cap_data_t *) pinfo->private_data; col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCRP"); col_clear(pinfo->cinfo, COL_INFO); 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; } main_item = proto_tree_add_item(tree, proto_bthcrp, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_bthcrp); /* TODO: Implement streams reconizing by SDP * Server provide SDP record for Control and Data PSM * Client provide SDP record for Notification PSM (optional) */ is_client_message = (is_client && pinfo->p2p_dir == P2P_DIR_SENT) || (!is_client && pinfo->p2p_dir == P2P_DIR_RECV); if (psm_control != 0 && l2cap_data->psm == psm_control) { offset = dissect_control(tvb, pinfo, main_tree, offset, is_client_message); } else if (psm_data_stream != 0 && l2cap_data->psm == psm_data_stream) { offset = dissect_data(tvb, pinfo, main_tree, offset); } else if (psm_notification != 0 && l2cap_data->psm == psm_notification) { offset = dissect_notification(tvb, pinfo, main_tree, offset, is_client_message); } else { col_append_fstr(pinfo->cinfo, COL_INFO, "HCRP stream (CID: 0x%04X)", l2cap_data->cid); } if (tvb_length_remaining(tvb, offset)) { proto_item *pitem; pitem = proto_tree_add_item(main_tree, hf_bthcrp_data, tvb, offset, -1, ENC_NA); expert_add_info_format(pinfo, pitem, PI_PROTOCOL, PI_WARN, "Unexpected data"); } }
/* * This dissector dissects the lwapp protocol itself. It assumes an * lwapp payload in the data, and doesn't care whether the data was * from a UDP packet, or a Layer 2 one. */ static void dissect_lwapp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { LWAPP_Header header; guint8 slotId; guint8 version; proto_tree *lwapp_tree; proto_tree *flags_tree; tvbuff_t *next_client; guint8 dest_mac[6]; guint8 have_destmac=0; /* Set up structures needed to add the protocol subtree and manage it */ proto_item *ti; gint offset=0; /* Make entries in Protocol column and Info column on summary display */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LWAPP"); col_set_str(pinfo->cinfo, COL_INFO, "LWAPP IP or Layer 2"); /* First, set up our dest mac, if we're a control packet with a * dest of port 12223 */ if (pinfo->destport == 12223 ) { tvb_memcpy(tvb, dest_mac, offset, 6); have_destmac = 1; /* Copy our header */ tvb_memcpy(tvb, (guint8*) &header, offset + 6, sizeof(header)); } else { /* Copy our header */ tvb_memcpy(tvb, (guint8*) &header, offset, sizeof(header)); } /* * Fix the length (network byte ordering), and set our version & * slot id */ header.length = g_ntohs(header.length); version = (header.flags & 0xc0) >> 6; slotId = (header.flags & 0x38) >> 3; if (check_col(pinfo->cinfo, COL_INFO)) { if ((header.flags & LWAPP_FLAGS_T) != 0) col_append_str(pinfo->cinfo, COL_INFO, " Control Packet"); else col_append_str(pinfo->cinfo, COL_INFO, " 802.11 Packet"); } /* In the interest of speed, if "tree" is NULL, don't do any work not necessary to generate protocol tree items. */ if (tree) { /* create display subtree for the protocol */ ti = proto_tree_add_item(tree, proto_lwapp, tvb, offset, -1, FALSE); lwapp_tree = proto_item_add_subtree(ti, ett_lwapp); if (have_destmac) { proto_tree_add_ether(lwapp_tree, hf_lwapp_control_mac, tvb, offset, 6, dest_mac); offset += 6; } proto_tree_add_uint(lwapp_tree, hf_lwapp_version, tvb, offset, 1, version); proto_tree_add_uint(lwapp_tree, hf_lwapp_slotid, tvb, offset, 1, slotId); flags_tree = proto_item_add_subtree(lwapp_tree, ett_lwapp_flags); proto_tree_add_boolean(flags_tree, hf_lwapp_flags_type, tvb, offset, 1, header.flags); proto_tree_add_boolean(flags_tree, hf_lwapp_flags_fragment, tvb, offset, 1, header.flags); proto_tree_add_boolean(flags_tree, hf_lwapp_flags_fragment_type, tvb, offset, 1, header.flags); offset++; proto_tree_add_uint(lwapp_tree, hf_lwapp_fragment_id, tvb, offset, 1, header.fragmentId); offset++; proto_tree_add_uint(lwapp_tree, hf_lwapp_length, tvb, offset, 2, header.length); offset += 2; proto_tree_add_uint(lwapp_tree, hf_lwapp_rssi, tvb, offset, 1, header.rssi); offset++; proto_tree_add_uint(lwapp_tree, hf_lwapp_snr, tvb, offset, 1, header.snr); offset++; } /* tree */ next_client = tvb_new_subset(tvb, (have_destmac?6:0) + sizeof(LWAPP_Header), -1, -1); if ((header.flags & LWAPP_FLAGS_T) == 0) { call_dissector(swap_frame_control ? wlan_bsfc_handle : wlan_handle, next_client, pinfo, tree); } else { dissect_control(next_client, pinfo, tree); } return; } /* dissect_lwapp*/
static gint dissect_bthcrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *main_item; proto_tree *main_tree; gint offset = 0; gint protocol = -1; gboolean is_client_message = FALSE; gint previous_proto; previous_proto = (GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers))))); if (previous_proto == proto_btl2cap) { btl2cap_data_t *l2cap_data; wmem_tree_key_t key[10]; guint32 interface_id; guint32 adapter_id; guint32 sdp_psm = SDP_PSM_DEFAULT; guint32 direction; guint32 bd_addr_oui; guint32 bd_addr_id; guint32 service_type; guint32 service_channel; guint32 frame_number; service_info_t *service_info; l2cap_data = (btl2cap_data_t *) data; interface_id = l2cap_data->interface_id; adapter_id = l2cap_data->adapter_id; direction = (l2cap_data->is_local_psm) ? P2P_DIR_SENT : P2P_DIR_RECV; if (direction == P2P_DIR_RECV) { bd_addr_oui = l2cap_data->remote_bd_addr_oui; bd_addr_id = l2cap_data->remote_bd_addr_id; } else { bd_addr_oui = 0; bd_addr_id = 0; } service_type = BTSDP_L2CAP_PROTOCOL_UUID; service_channel = l2cap_data->psm; frame_number = pinfo->fd->num; key[0].length = 1; key[0].key = &interface_id; key[1].length = 1; key[1].key = &adapter_id; key[2].length = 1; key[2].key = &sdp_psm; key[3].length = 1; key[3].key = &direction; key[4].length = 1; key[4].key = &bd_addr_oui; key[5].length = 1; key[5].key = &bd_addr_id; key[6].length = 1; key[6].key = &service_type; key[7].length = 1; key[7].key = &service_channel; key[8].length = 1; key[8].key = &frame_number; key[9].length = 0; key[9].key = NULL; service_info = btsdp_get_service_info(key); if (service_info && service_info->interface_id == interface_id && service_info->adapter_id == adapter_id && service_info->sdp_psm == SDP_PSM_DEFAULT && ((service_info->direction == P2P_DIR_RECV && service_info->bd_addr_oui == bd_addr_oui && service_info->bd_addr_id == bd_addr_id) || (service_info->direction != P2P_DIR_RECV && service_info->bd_addr_oui == 0 && service_info->bd_addr_id == 0)) && service_info->type == BTSDP_L2CAP_PROTOCOL_UUID && service_info->channel == l2cap_data->psm) { if ((service_info->protocol == BTSDP_HARDCOPY_CONTROL_CHANNEL_PROTOCOL_UUID || service_info->protocol == BTSDP_HARDCOPY_DATA_CHANNEL_PROTOCOL_UUID) && ((!l2cap_data->is_local_psm && pinfo->p2p_dir == P2P_DIR_SENT) || (l2cap_data->is_local_psm && pinfo->p2p_dir == P2P_DIR_RECV))) { is_client_message = TRUE; } else if (service_info->protocol == BTSDP_HARDCOPY_NOTIFICATION_PROTOCOL_UUID && ((l2cap_data->is_local_psm && pinfo->p2p_dir == P2P_DIR_SENT) || (!l2cap_data->is_local_psm && pinfo->p2p_dir == P2P_DIR_RECV))) { is_client_message = TRUE; } protocol = service_info->protocol; } if (psm_control != 0 && l2cap_data->psm == psm_control) { protocol = BTSDP_HARDCOPY_CONTROL_CHANNEL_PROTOCOL_UUID; } else if (psm_data_stream != 0 && l2cap_data->psm == psm_data_stream) { protocol = BTSDP_HARDCOPY_DATA_CHANNEL_PROTOCOL_UUID; } else if (psm_notification != 0 && l2cap_data->psm == psm_notification) { protocol = BTSDP_HARDCOPY_NOTIFICATION_PROTOCOL_UUID; } } main_item = proto_tree_add_item(tree, proto_bthcrp, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_bthcrp); col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCRP"); 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 (force_client != FORCE_CLIENT_DEFAULT) { is_client_message = (force_client == FORCE_CLIENT_YES && pinfo->p2p_dir == P2P_DIR_SENT) || (force_client != FORCE_CLIENT_YES && pinfo->p2p_dir == P2P_DIR_RECV); } if (protocol == BTSDP_HARDCOPY_CONTROL_CHANNEL_PROTOCOL_UUID) { offset = dissect_control(tvb, pinfo, main_tree, offset, is_client_message); } else if (protocol == BTSDP_HARDCOPY_DATA_CHANNEL_PROTOCOL_UUID) { offset = dissect_data(tvb, pinfo, main_tree, offset); } else if (protocol == BTSDP_HARDCOPY_NOTIFICATION_PROTOCOL_UUID) { offset = dissect_notification(tvb, pinfo, main_tree, offset, is_client_message); } else { col_append_fstr(pinfo->cinfo, COL_INFO, "HCRP stream"); } if (tvb_reported_length_remaining(tvb, offset)) { proto_item *pitem; pitem = proto_tree_add_item(main_tree, hf_bthcrp_data, tvb, offset, tvb_reported_length_remaining(tvb, offset), ENC_NA); expert_add_info(pinfo, pitem, &ei_bthcrp_unexpected_data); } return offset; }
static void dissect_btbnep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *pi; proto_tree *btbnep_tree; gint offset = 0; guint bnep_type; guint extension_flag; guint type = 0; proto_item *addr_item; proto_tree *addr_tree = NULL; const guint8 *src_addr; const guint8 *dst_addr; col_set_str(pinfo->cinfo, COL_PROTOCOL, "BNEP"); col_clear(pinfo->cinfo, COL_INFO); 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; } pi = proto_tree_add_item(tree, proto_btbnep, tvb, offset, -1, ENC_NA); btbnep_tree = proto_item_add_subtree(pi, ett_btbnep); proto_tree_add_item(btbnep_tree, hf_btbnep_extension_flag, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(btbnep_tree, hf_btbnep_bnep_type, tvb, offset, 1, ENC_BIG_ENDIAN); bnep_type = tvb_get_guint8(tvb, offset); extension_flag = bnep_type & 0x80; bnep_type = bnep_type & 0x7F; offset += 1; col_append_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_const(bnep_type, bnep_type_vals, "Unknown type")); if (extension_flag) col_append_fstr(pinfo->cinfo, COL_INFO, "+E"); if (bnep_type == BNEP_TYPE_GENERAL_ETHERNET || bnep_type == BNEP_TYPE_COMPRESSED_ETHERNET_DESTINATION_ONLY) { dst_addr = tvb_get_ptr(tvb, offset, 6); SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, dst_addr); SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, dst_addr); addr_item = proto_tree_add_ether(btbnep_tree, hf_btbnep_dst, tvb, offset, 6, dst_addr); if (addr_item) addr_tree = proto_item_add_subtree(addr_item, ett_addr); proto_tree_add_ether(addr_tree, hf_btbnep_addr, tvb, offset, 6, dst_addr); proto_tree_add_item(addr_tree, hf_btbnep_lg, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_btbnep_ig, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 6; } if (bnep_type == BNEP_TYPE_GENERAL_ETHERNET || bnep_type == BNEP_TYPE_COMPRESSED_ETHERNET_SOURCE_ONLY) { src_addr = tvb_get_ptr(tvb, offset, 6); SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, src_addr); SET_ADDRESS(&pinfo->src, AT_ETHER, 6, src_addr); addr_item = proto_tree_add_ether(btbnep_tree, hf_btbnep_src, tvb, offset, 6, src_addr); if (addr_item) { addr_tree = proto_item_add_subtree(addr_item, ett_addr); if (tvb_get_guint8(tvb, offset) & 0x01) { expert_add_info_format(pinfo, addr_item, PI_PROTOCOL, PI_WARN, "Source MAC must not be a group address: IEEE 802.3-2002, Section 3.2.3(b)"); } } proto_tree_add_ether(addr_tree, hf_btbnep_addr, tvb, offset, 6, src_addr); proto_tree_add_item(addr_tree, hf_btbnep_lg, tvb, offset, 3, ENC_BIG_ENDIAN); proto_tree_add_item(addr_tree, hf_btbnep_ig, tvb, offset, 3, ENC_BIG_ENDIAN); offset += 6; } if (bnep_type != BNEP_TYPE_CONTROL) { type = tvb_get_ntohs(tvb, offset); if (!top_dissect) { proto_tree_add_item(btbnep_tree, hf_btbnep_type, tvb, offset, 2, ENC_BIG_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, " - Type: %s", val_to_str_const(type, etype_vals, "unknown")); } offset += 2; } else { offset = dissect_control(tvb, pinfo, btbnep_tree, offset); } if (extension_flag) { offset = dissect_extension(tvb, pinfo, btbnep_tree, offset); } if (bnep_type != BNEP_TYPE_CONTROL) { /* dissect normal network */ if (top_dissect) { ethertype(type, tvb, offset, pinfo, tree, btbnep_tree, hf_btbnep_type, 0, 0); } else { tvbuff_t *next_tvb; next_tvb = tvb_new_subset_remaining(tvb, offset); call_dissector(data_handle, next_tvb, pinfo, tree); } } }