lbttcp_transport_t * lbttcp_transport_add(const address * source_address, guint16 source_port, guint32 session_id, guint32 frame) { lbttcp_transport_t * entry = NULL; conversation_t * conv = NULL; lbttcp_transport_conv_data_t * conv_data = NULL; conv = find_conversation(frame, source_address, &lbttcp_null_address, PT_TCP, source_port, 0, 0); if (conv == NULL) { conv = conversation_new(frame, source_address, &lbttcp_null_address, PT_TCP, source_port, 0, 0); } conv_data = (lbttcp_transport_conv_data_t *) conversation_get_proto_data(conv, proto_lbttcp); if (conv_data == NULL) { conv_data = wmem_new(wmem_file_scope(), lbttcp_transport_conv_data_t); conv_data->frame_tree = wmem_tree_new(wmem_file_scope()); conv_data->session_tree = wmem_tree_new(wmem_file_scope()); conversation_add_proto_data(conv, proto_lbttcp, (void *) conv_data); } entry = (lbttcp_transport_t *) wmem_tree_lookup32(conv_data->session_tree, session_id); if (entry != NULL) { return (entry); } entry = lbttcp_transport_create(source_address, source_port, session_id); wmem_tree_insert32(conv_data->session_tree, session_id, (void *) entry); wmem_tree_insert32(conv_data->frame_tree, frame, (void *) entry); return (entry); }
/*----------------------------------------------------------------------------*/ lbm_transport_frame_t * lbm_transport_frame_add(wmem_tree_t * list, guint8 type, guint32 frame, guint32 sqn, gboolean retransmission) { lbm_transport_frame_t * frame_entry = NULL; /* Locate the frame. */ frame_entry = (lbm_transport_frame_t *) wmem_tree_lookup32(list, frame); if (frame_entry != NULL) { return (frame_entry); } frame_entry = wmem_new(wmem_file_scope(), lbm_transport_frame_t); frame_entry->frame = frame; frame_entry->type = type; frame_entry->sqn = sqn; frame_entry->previous_frame = 0; frame_entry->previous_type_frame = 0; frame_entry->next_frame = 0; frame_entry->next_type_frame = 0; frame_entry->retransmission = retransmission; frame_entry->sqn_gap = 0; frame_entry->ooo_gap = 0; frame_entry->duplicate = FALSE; wmem_tree_insert32(list, frame, (void *) frame_entry); return (frame_entry); }
static oid_info_t* add_oid(const char* name, oid_kind_t kind, const oid_value_type_t* type, oid_key_t* key, guint oid_len, guint32 *subids) { guint i = 0; oid_info_t* c = &oid_root; prepopulate_oids(); oid_len--; do { oid_info_t* n = (oid_info_t *)wmem_tree_lookup32(c->children,subids[i]); if(n) { if (i == oid_len) { if (n->name) { if (!g_str_equal(n->name,name)) { D(2,("Renaming Oid from: %s -> %s, this means the same oid is registered more than once",n->name,name)); } wmem_free(wmem_epan_scope(), n->name); } n->name = wmem_strdup(wmem_epan_scope(), name); if (! n->value_type) { n->value_type = type; } return n; } } else { n = wmem_new(wmem_epan_scope(), oid_info_t); n->subid = subids[i]; n->kind = kind; n->children = wmem_tree_new(wmem_epan_scope()); n->value_hfid = -2; n->key = key; n->parent = c; n->bits = NULL; wmem_tree_insert32(c->children,n->subid,n); if (i == oid_len) { n->name = wmem_strdup(wmem_epan_scope(), name); n->value_type = type; n->kind = kind; return n; } else { n->name = NULL; n->value_type = NULL; n->kind = OID_KIND_UNKNOWN; } } c = n; } while(++i); g_assert_not_reached(); return NULL; }
static ipmi_frame_data_t * get_frame_data(ipmi_packet_data_t * data, guint32 frame_num) { ipmi_frame_data_t * frame = (ipmi_frame_data_t *) wmem_tree_lookup32(data->frame_tree, frame_num); if (frame == NULL) { frame = wmem_new0(wmem_file_scope(), ipmi_frame_data_t); wmem_tree_insert32(data->frame_tree, frame_num, frame); } return frame; }
/* Try to find the NBAP C-RNC Context and, if found, pair it with a given U-RNTI */ static void rrc_try_map_urnti_to_crncc(guint32 u_rnti, asn1_ctx_t *actx) { guint32 scrambling_code, crnc_context; /* Getting the user's Uplink Scrambling Code*/ scrambling_code = private_data_get_scrambling_code(actx); if (u_rnti != 0 && scrambling_code != 0) { /* Looking for the C-RNC Context mapped to this Scrambling Code */ crnc_context = GPOINTER_TO_UINT(wmem_tree_lookup32(nbap_scrambling_code_crncc_map,scrambling_code)); if (crnc_context != 0) { /* Mapping the U-RNTI to the C-RNC context*/ wmem_tree_insert32(nbap_crncc_urnti_map,crnc_context,GUINT_TO_POINTER(u_rnti)); } } }
lbttcp_transport_t * lbttcp_transport_find(const address * source_address, guint16 source_port, guint32 session_id, guint32 frame) { lbttcp_transport_t * entry = NULL; conversation_t * conv = NULL; lbttcp_transport_conv_data_t * conv_data = NULL; conv = find_conversation(frame, source_address, &lbttcp_null_address, PT_TCP, source_port, 0, 0); if (conv != NULL) { conv_data = (lbttcp_transport_conv_data_t *) conversation_get_proto_data(conv, proto_lbttcp); if (conv_data != NULL) { entry = (lbttcp_transport_t *) wmem_tree_lookup32(conv_data->session_tree, session_id); } } return (entry); }
static int dissect_ret_unlink(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, usbip_conv_info_t *usbip_info, guint32 seqnum) { usbip_transaction_t *victim; col_set_str(pinfo->cinfo, COL_INFO, "URB Unlink Response"); victim = (usbip_transaction_t *) wmem_tree_lookup32(usbip_info->pdus, seqnum); if (victim) { proto_item *ti; victim->ret_frame = pinfo->num; ti = proto_tree_add_uint(tree, hf_usbip_vic_frame, NULL, 0, 0, victim->cmd_frame); PROTO_ITEM_SET_GENERATED(ti); } proto_tree_add_item(tree, hf_usbip_status, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; return offset; }
static lbttcp_client_transport_t * lbttcp_client_transport_find(lbttcp_transport_t * transport, const address * receiver_address, guint16 receiver_port, guint32 frame) { lbttcp_client_transport_t * entry = NULL; conversation_t * client_conv = NULL; if (transport == NULL) { return (NULL); } client_conv = find_conversation(frame, &(transport->source_address), receiver_address, PT_TCP, transport->source_port, receiver_port, 0); if (client_conv != NULL) { wmem_tree_t * session_tree = NULL; session_tree = (wmem_tree_t *) conversation_get_proto_data(client_conv, proto_lbttcp); if (session_tree != NULL) { entry = (lbttcp_client_transport_t *) wmem_tree_lookup32(session_tree, transport->session_id); } } return (entry); }
lbm_transport_sqn_t * lbm_transport_sqn_add(wmem_tree_t * list, lbm_transport_frame_t * frame) { lbm_transport_sqn_t * sqn_entry = NULL; lbm_transport_sqn_frame_t * frame_entry = NULL; /* Locate the SQN. */ sqn_entry = (lbm_transport_sqn_t *) wmem_tree_lookup32(list, frame->sqn); if (sqn_entry == NULL) { sqn_entry = wmem_new(wmem_file_scope(), lbm_transport_sqn_t); sqn_entry->sqn = frame->sqn; sqn_entry->frame_count = 0; sqn_entry->frame = wmem_tree_new(wmem_file_scope()); wmem_tree_insert32(list, frame->sqn, (void *) sqn_entry); } /* Add this frame to the list of frames this SQN appears in. */ frame_entry = wmem_new(wmem_file_scope(), lbm_transport_sqn_frame_t); frame_entry->frame = frame->frame; frame_entry->retransmission = frame->retransmission; wmem_tree_insert32(sqn_entry->frame, frame->frame, (void *) frame_entry); sqn_entry->frame_count++; return (sqn_entry); }
static void dissect_fcp_cmnd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, proto_tree *tree, conversation_t *conversation, fc_hdr *fchdr, fcp_conv_data_t *fcp_conv_data) { int offset = 0; int add_len = 0; guint8 flags, rwflags, lun0; guint16 lun = 0xffff; tvbuff_t *cdb_tvb; int tvb_len, tvb_rlen; fcp_request_data_t *request_data = NULL; itl_nexus_t itl; fcp_proto_data_t *proto_data; /* Determine the length of the FCP part of the packet */ flags = tvb_get_guint8(tvb, offset+10); if (flags) { add_len = tvb_get_guint8(tvb, offset+11) & 0x7C; add_len = add_len >> 2; } lun0 = tvb_get_guint8(tvb, offset); /* Display single-level LUNs in decimal for clarity */ /* I'm taking a shortcut here by assuming that if the first byte of the * LUN field is 0, it is a single-level LUN. This is not true. For a * real single-level LUN, all 8 bytes except byte 1 must be 0. */ if (lun0) { proto_tree_add_item(tree, hf_fcp_multilun, tvb, offset, 8, ENC_NA); lun = tvb_get_guint8(tvb, offset) & 0x3f; lun <<= 8; lun |= tvb_get_guint8(tvb, offset+1); } else { proto_tree_add_item(tree, hf_fcp_singlelun, tvb, offset+1, 1, ENC_BIG_ENDIAN); lun = tvb_get_guint8(tvb, offset+1); } if (!pinfo->fd->flags.visited) { proto_data = wmem_new(wmem_file_scope(), fcp_proto_data_t); proto_data->lun = lun; p_add_proto_data(wmem_file_scope(), pinfo, proto_fcp, 0, proto_data); } request_data = (fcp_request_data_t*)wmem_tree_lookup32(fcp_conv_data->luns, lun); if (!request_data) { request_data = wmem_new(wmem_file_scope(), fcp_request_data_t); request_data->request_frame = pinfo->fd->num; request_data->response_frame = 0; request_data->request_time = pinfo->fd->abs_ts; request_data->itlq = wmem_new(wmem_file_scope(), itlq_nexus_t); request_data->itlq->first_exchange_frame=0; request_data->itlq->last_exchange_frame=0; request_data->itlq->lun=lun; request_data->itlq->scsi_opcode=0xffff; request_data->itlq->task_flags=0; request_data->itlq->data_length=0; request_data->itlq->bidir_data_length=0; request_data->itlq->fc_time=pinfo->fd->abs_ts; request_data->itlq->flags=0; request_data->itlq->alloc_len=0; request_data->itlq->extra_data=NULL; wmem_tree_insert32(fcp_conv_data->luns, lun, request_data); } /* populate the exchange struct */ if(!pinfo->fd->flags.visited){ if(fchdr->fctl&FC_FCTL_EXCHANGE_FIRST){ request_data->itlq->first_exchange_frame=pinfo->fd->num; request_data->itlq->fc_time = pinfo->fd->abs_ts; } if(fchdr->fctl&FC_FCTL_EXCHANGE_LAST){ request_data->itlq->last_exchange_frame=pinfo->fd->num; } } if (request_data->itlq) request_data->itlq->lun = lun; fchdr->lun = lun; proto_tree_add_item(tree, hf_fcp_crn, tvb, offset+8, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fcp_taskattr, tvb, offset+9, 1, ENC_BIG_ENDIAN); dissect_task_mgmt_flags(pinfo, tree, tvb, offset+10); proto_tree_add_item(tree, hf_fcp_addlcdblen, tvb, offset+11, 1, ENC_BIG_ENDIAN); rwflags = tvb_get_guint8(tvb, offset+11); if (request_data->itlq) { if (rwflags & 0x02) { request_data->itlq->task_flags |= SCSI_DATA_READ; } if (rwflags & 0x01) { request_data->itlq->task_flags |= SCSI_DATA_WRITE; } } proto_tree_add_item(tree, hf_fcp_rddata, tvb, offset+11, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fcp_wrdata, tvb, offset+11, 1, ENC_BIG_ENDIAN); tvb_len = tvb_length_remaining(tvb, offset+12); if (tvb_len > (16 + add_len)) tvb_len = 16 + add_len; tvb_rlen = tvb_reported_length_remaining(tvb, offset+12); if (tvb_rlen > (16 + add_len)) tvb_rlen = 16 + add_len; itl.cmdset = 0xff; itl.conversation = conversation; cdb_tvb = tvb_new_subset(tvb, offset+12, tvb_len, tvb_rlen); dissect_scsi_cdb(cdb_tvb, pinfo, parent_tree, SCSI_DEV_UNKNOWN, request_data->itlq, &itl); proto_tree_add_item(tree, hf_fcp_dl, tvb, offset+12+16+add_len, 4, ENC_BIG_ENDIAN); if (request_data->itlq) { request_data->itlq->data_length = tvb_get_ntohl(tvb, offset+12+16+add_len); } if ( ((rwflags & 0x03) == 0x03) && tvb_length_remaining(tvb, offset+12+16+add_len+4) >= 4) { proto_tree_add_item(tree, hf_fcp_bidir_dl, tvb, offset+12+16+add_len+4, 4, ENC_BIG_ENDIAN); if (request_data->itlq) { request_data->itlq->bidir_data_length = tvb_get_ntohl(tvb, offset+12+16+add_len+4); } } }
static gint dissect_hci_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *ttree = NULL; proto_tree *titem = NULL; proto_item *pitem = NULL; gint offset = 0; usb_conv_info_t *usb_conv_info = (usb_conv_info_t *)data; tvbuff_t *next_tvb = NULL; hci_data_t *hci_data; gint p2p_dir_save; guint32 session_id; fragment_head *reassembled; if (tvb_length_remaining(tvb, offset) <= 0) return 0; titem = proto_tree_add_item(tree, proto_hci_usb, tvb, offset, -1, ENC_NA); ttree = proto_item_add_subtree(titem, ett_hci_usb); col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_USB"); DISSECTOR_ASSERT(usb_conv_info); p2p_dir_save = pinfo->p2p_dir; pinfo->p2p_dir = usb_conv_info->direction; 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_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction"); break; } session_id = usb_conv_info->bus_id << 16 | usb_conv_info->device_address << 8 | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0 ) << 7 | usb_conv_info->endpoint; hci_data = (hci_data_t *) wmem_new(wmem_packet_scope(), hci_data_t); hci_data->interface_id = HCI_INTERFACE_USB; hci_data->adapter_id = usb_conv_info->bus_id << 8 | usb_conv_info->device_address; hci_data->chandle_to_bdaddr_table = chandle_to_bdaddr_table; hci_data->bdaddr_to_name_table = bdaddr_to_name_table; hci_data->localhost_bdaddr = localhost_bdaddr; hci_data->localhost_name = localhost_name; pinfo->ptype = PT_BLUETOOTH; next_tvb = tvb_new_subset_remaining(tvb, offset); if (!pinfo->fd->flags.visited && usb_conv_info->endpoint <= 0x02) { fragment_info_t *fragment_info; fragment_info = (fragment_info_t *) wmem_tree_lookup32(fragment_info_table, session_id); if (fragment_info == NULL) { fragment_info = (fragment_info_t *) wmem_new(wmem_file_scope(), fragment_info_t); fragment_info->fragment_id = 0; fragment_info->remaining_length = 0; wmem_tree_insert32(fragment_info_table, session_id, fragment_info); } if (fragment_info->fragment_id == 0) { switch(usb_conv_info->endpoint) { case 0: fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 2) + 3; break; case 1: fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 1) + 2; break; case 2: fragment_info->remaining_length = tvb_get_letohs(tvb, offset + 2) + 4; break; } } fragment_info->remaining_length -= tvb_ensure_length_remaining(tvb, offset); fragment_add_seq_check(&hci_usb_reassembly_table, tvb, offset, pinfo, session_id, NULL, fragment_info->fragment_id, tvb_length_remaining(tvb, offset), (fragment_info->remaining_length == 0) ? FALSE : TRUE); if (fragment_info->remaining_length > 0) fragment_info->fragment_id += 1; else fragment_info->fragment_id = 0; } reassembled = fragment_get_reassembled_id(&hci_usb_reassembly_table, pinfo, session_id); if (reassembled && pinfo->fd->num < reassembled->reassembled_in) { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_fragment, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); col_append_str(pinfo->cinfo, COL_INFO, " Fragment"); } else if (reassembled && pinfo->fd->num == reassembled->reassembled_in) { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_complete, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); if (reassembled->len > tvb_ensure_length_remaining(tvb, offset)) { next_tvb = process_reassembled_data(tvb, 0, pinfo, "Reassembled HCI_USB", reassembled, &hci_usb_msg_frag_items, NULL, ttree); } switch(usb_conv_info->endpoint) { case 0: call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, hci_data); break; case 1: call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, hci_data); break; case 2: call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, hci_data); break; } } else { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_unknown_fragment, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); } if (usb_conv_info->endpoint == 0x03) { call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, hci_data); } else if (usb_conv_info->endpoint > 0x03) { proto_tree_add_item(ttree, hf_bthci_usb_data, tvb, offset, -1, ENC_NA); } offset += tvb_length_remaining(tvb, offset); pinfo->p2p_dir = p2p_dir_save; return offset; }
static int usbip_dissect_urb(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree, proto_tree *orig, int offset, usbip_conv_info_t *usbip_info) { proto_item *ti = NULL; usbip_transaction_t *usbip_trans; guint32 command; guint32 devid; guint32 seqnum; guint32 dir; guint32 ep; struct usbip_header header; proto_tree_add_item_ret_uint(tree, hf_usbip_command, tvb, offset, 4, ENC_BIG_ENDIAN, &command); offset += 4; proto_tree_add_item_ret_uint(tree, hf_usbip_seqnum, tvb, offset, 4, ENC_BIG_ENDIAN, &seqnum); offset += 4; dir = tvb_get_ntohl(tvb, offset + 4); ep = tvb_get_ntohl(tvb, offset + 8); devid = tvb_get_ntohl(tvb, offset); if (!PINFO_FD_VISITED(pinfo)) { if (command == OP_CMD_SUBMIT || command == OP_CMD_UNLINK) { usbip_trans = wmem_new(wmem_file_scope(), usbip_transaction_t); usbip_trans->devid = devid; usbip_trans->dir = dir; usbip_trans->ep = ep; usbip_trans->seqnum = seqnum; usbip_trans->cmd_frame = pinfo->num; usbip_trans->ret_frame = 0; usbip_trans->unlink_seqnum = 0; wmem_tree_insert32(usbip_info->pdus, seqnum, (void *) usbip_trans); } else { usbip_trans = (usbip_transaction_t *) wmem_tree_lookup32(usbip_info->pdus, seqnum); if (usbip_trans) usbip_trans->ret_frame = pinfo->num; } } else { usbip_trans = (usbip_transaction_t *) wmem_tree_lookup32(usbip_info->pdus, seqnum); } if (!usbip_trans) { usbip_trans = wmem_new(wmem_packet_scope(), usbip_transaction_t); usbip_trans->cmd_frame = 0; usbip_trans->ret_frame = 0; usbip_trans->devid = 0; usbip_trans->unlink_seqnum = 0; usbip_trans->seqnum = seqnum; } /* only the OP_CMD_SUBMIT has a valid devid - in all other case we have to restore it from the transaction */ if (command == OP_RET_SUBMIT || command == OP_RET_UNLINK) { devid = usbip_trans->devid; ep = usbip_trans->ep; dir = usbip_trans->dir; } ti = proto_tree_add_uint(tree, hf_usbip_cmd_frame, NULL, 0, 0, usbip_trans->cmd_frame); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint(tree, hf_usbip_ret_frame, NULL, 0, 0, usbip_trans->ret_frame); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint(tree, hf_usbip_devid, NULL, 0, 0, devid); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint(tree, hf_usbip_direction, NULL, 0, 0, dir); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint(tree, hf_usbip_ep, NULL, 0, 0, ep); PROTO_ITEM_SET_GENERATED(ti); proto_tree_add_item(tree, hf_usbip_devid, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_usbip_direction, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tree, hf_usbip_ep, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; header.ep = ep; header.dir = dir; header.devid = devid & 0x00ff; header.busid = devid >> 16; switch (command) { case OP_CMD_SUBMIT: offset = dissect_cmd_submit(pinfo, tree, tvb, offset); dissect_usb_common(tvb, pinfo, orig, USB_HEADER_USBIP, &header); break; case OP_CMD_UNLINK: offset = dissect_cmd_unlink(pinfo, tree, tvb, offset, usbip_info, usbip_trans); break; case OP_RET_SUBMIT: { guint32 status; status = tvb_get_ntohl(tvb, offset); offset = dissect_ret_submit(pinfo, tree, tvb, offset); if (status == 0) dissect_usb_common(tvb, pinfo, orig, USB_HEADER_USBIP, &header); break; } case OP_RET_UNLINK: offset = dissect_ret_unlink(pinfo, tree, tvb, offset, usbip_info, usbip_trans->unlink_seqnum); break; default: proto_tree_add_item(tree, hf_usbip_urb_data, tvb, offset, -1, ENC_NA); offset = tvb_reported_length_remaining(tvb, offset); expert_add_info_format( pinfo, ti, &ei_usbip, "Dissector for USBIP Command" " (%x) code not implemented, Contact" " Wireshark developers if you want this supported", command); proto_item_append_text(ti, ": Undecoded"); break; } return offset; }
static void wmem_test_tree(void) { wmem_allocator_t *allocator, *extra_allocator; wmem_tree_t *tree; guint32 i; int seen_values = 0; int j; gchar *str_key; #define WMEM_TREE_MAX_KEY_COUNT 8 #define WMEM_TREE_MAX_KEY_LEN 4 int key_count; wmem_tree_key_t keys[WMEM_TREE_MAX_KEY_COUNT]; allocator = wmem_allocator_new(WMEM_ALLOCATOR_STRICT); extra_allocator = wmem_allocator_new(WMEM_ALLOCATOR_STRICT); tree = wmem_tree_new(allocator); g_assert(tree); g_assert(wmem_tree_is_empty(tree)); /* test basic 32-bit key operations */ for (i=0; i<CONTAINER_ITERS; i++) { g_assert(wmem_tree_lookup32(tree, i) == NULL); if (i > 0) { g_assert(wmem_tree_lookup32_le(tree, i) == GINT_TO_POINTER(i-1)); } wmem_tree_insert32(tree, i, GINT_TO_POINTER(i)); g_assert(wmem_tree_lookup32(tree, i) == GINT_TO_POINTER(i)); g_assert(!wmem_tree_is_empty(tree)); } wmem_free_all(allocator); tree = wmem_tree_new(allocator); for (i=0; i<CONTAINER_ITERS; i++) { guint32 rand_int = g_test_rand_int(); wmem_tree_insert32(tree, rand_int, GINT_TO_POINTER(i)); g_assert(wmem_tree_lookup32(tree, rand_int) == GINT_TO_POINTER(i)); } wmem_free_all(allocator); /* test auto-reset functionality */ tree = wmem_tree_new_autoreset(allocator, extra_allocator); for (i=0; i<CONTAINER_ITERS; i++) { g_assert(wmem_tree_lookup32(tree, i) == NULL); wmem_tree_insert32(tree, i, GINT_TO_POINTER(i)); g_assert(wmem_tree_lookup32(tree, i) == GINT_TO_POINTER(i)); } wmem_free_all(extra_allocator); for (i=0; i<CONTAINER_ITERS; i++) { g_assert(wmem_tree_lookup32(tree, i) == NULL); g_assert(wmem_tree_lookup32_le(tree, i) == NULL); } wmem_free_all(allocator); /* test array key functionality */ tree = wmem_tree_new(allocator); key_count = g_random_int_range(1, WMEM_TREE_MAX_KEY_COUNT); for (j=0; j<key_count; j++) { keys[j].length = g_random_int_range(1, WMEM_TREE_MAX_KEY_LEN); } keys[key_count].length = 0; for (i=0; i<CONTAINER_ITERS; i++) { for (j=0; j<key_count; j++) { keys[j].key = (guint32*)wmem_test_rand_string(allocator, (keys[j].length*4), (keys[j].length*4)+1); } wmem_tree_insert32_array(tree, keys, GINT_TO_POINTER(i)); g_assert(wmem_tree_lookup32_array(tree, keys) == GINT_TO_POINTER(i)); } wmem_free_all(allocator); tree = wmem_tree_new(allocator); keys[0].length = 1; keys[0].key = wmem_new(allocator, guint32); *(keys[0].key) = 0; keys[1].length = 0; for (i=0; i<CONTAINER_ITERS; i++) { wmem_tree_insert32_array(tree, keys, GINT_TO_POINTER(i)); *(keys[0].key) += 4; } *(keys[0].key) = 0; for (i=0; i<CONTAINER_ITERS; i++) { g_assert(wmem_tree_lookup32_array(tree, keys) == GINT_TO_POINTER(i)); for (j=0; j<3; j++) { (*(keys[0].key)) += 1; g_assert(wmem_tree_lookup32_array_le(tree, keys) == GINT_TO_POINTER(i)); } *(keys[0].key) += 1; } wmem_free_all(allocator); /* test string key functionality */ tree = wmem_tree_new(allocator); for (i=0; i<CONTAINER_ITERS; i++) { str_key = wmem_test_rand_string(allocator, 1, 64); wmem_tree_insert_string(tree, str_key, GINT_TO_POINTER(i), 0); g_assert(wmem_tree_lookup_string(tree, str_key, 0) == GINT_TO_POINTER(i)); } wmem_free_all(allocator); tree = wmem_tree_new(allocator); for (i=0; i<CONTAINER_ITERS; i++) { str_key = wmem_test_rand_string(allocator, 1, 64); wmem_tree_insert_string(tree, str_key, GINT_TO_POINTER(i), WMEM_TREE_STRING_NOCASE); g_assert(wmem_tree_lookup_string(tree, str_key, WMEM_TREE_STRING_NOCASE) == GINT_TO_POINTER(i)); } wmem_free_all(allocator); /* test for-each functionality */ tree = wmem_tree_new(allocator); expected_user_data = GINT_TO_POINTER(g_test_rand_int()); for (i=0; i<CONTAINER_ITERS; i++) { gint tmp; do { tmp = g_test_rand_int(); } while (wmem_tree_lookup32(tree, tmp)); value_seen[i] = FALSE; wmem_tree_insert32(tree, tmp, GINT_TO_POINTER(i)); } cb_called_count = 0; cb_continue_count = CONTAINER_ITERS; wmem_tree_foreach(tree, wmem_test_foreach_cb, expected_user_data); g_assert(cb_called_count == CONTAINER_ITERS); g_assert(cb_continue_count == 0); for (i=0; i<CONTAINER_ITERS; i++) { g_assert(value_seen[i]); value_seen[i] = FALSE; } cb_called_count = 0; cb_continue_count = 10; wmem_tree_foreach(tree, wmem_test_foreach_cb, expected_user_data); g_assert(cb_called_count == 10); g_assert(cb_continue_count == 0); for (i=0; i<CONTAINER_ITERS; i++) { if (value_seen[i]) { seen_values++; } } g_assert(seen_values == 10); wmem_destroy_allocator(extra_allocator); wmem_destroy_allocator(allocator); }
static int dissect_gssapi_work(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_verifier, gssapi_encrypt_info_t* encrypt_info) { proto_item *volatile item; proto_tree *volatile subtree; volatile int return_offset = 0; gssapi_conv_info_t *volatile gss_info; gssapi_oid_value *oidvalue; dissector_handle_t handle; conversation_t *conversation; tvbuff_t *oid_tvb; int len, start_offset, oid_start_offset; volatile int offset; gint8 appclass; gboolean pc, ind_field; gint32 tag; guint32 len1; const char *oid; fragment_head *fd_head=NULL; gssapi_frag_info_t *fi; tvbuff_t *volatile gss_tvb=NULL; asn1_ctx_t asn1_ctx; start_offset=0; offset=0; asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo); /* * We don't know whether the data is encrypted, so say it's * not, for now. The subdissector must set gssapi_data_encrypted * if it is. */ encrypt_info->gssapi_data_encrypted = FALSE; /* * We need a conversation for later */ conversation = find_or_create_conversation(pinfo); gss_info = (gssapi_conv_info_t *)conversation_get_proto_data(conversation, proto_gssapi); if (!gss_info) { gss_info = wmem_new(wmem_file_scope(), gssapi_conv_info_t); gss_info->oid=NULL; gss_info->do_reassembly=FALSE; gss_info->frags=wmem_tree_new(wmem_file_scope()); conversation_add_proto_data(conversation, proto_gssapi, gss_info); } item = proto_tree_add_item( tree, proto_gssapi, tvb, offset, -1, ENC_NA); subtree = proto_item_add_subtree(item, ett_gssapi); /* * Catch the ReportedBoundsError exception; the stuff we've been * handed doesn't necessarily run to the end of the packet, it's * an item inside a packet, so if it happens to be malformed (or * we, or a dissector we call, has a bug), so that an exception * is thrown, we want to report the error, but return and let * our caller dissect the rest of the packet. * * If it gets a BoundsError, we can stop, as there's nothing more * in the packet after our blob to see, so we just re-throw the * exception. */ TRY { gss_tvb=tvb; /* First of all, if it's the first time we see this packet * then check whether we are in the middle of reassembly or not */ if( (!pinfo->fd->flags.visited) && (gss_info->do_reassembly) && (gssapi_reassembly) ){ fi=(gssapi_frag_info_t *)wmem_tree_lookup32(gss_info->frags, gss_info->first_frame); if(!fi){ goto done; } wmem_tree_insert32(gss_info->frags, pinfo->num, fi); fd_head=fragment_add(&gssapi_reassembly_table, tvb, 0, pinfo, fi->first_frame, NULL, gss_info->frag_offset, tvb_captured_length(tvb), TRUE); gss_info->frag_offset+=tvb_captured_length(tvb); /* we need more fragments */ if(!fd_head){ goto done; } /* this blob is now fully reassembled */ gss_info->do_reassembly=FALSE; fi->reassembled_in=pinfo->num; gss_tvb=tvb_new_chain(tvb, fd_head->tvb_data); add_new_data_source(pinfo, gss_tvb, "Reassembled GSSAPI"); } /* We have seen this packet before. * Is this blob part of reassembly or a normal blob ? */ if( (pinfo->fd->flags.visited) && (gssapi_reassembly) ){ fi=(gssapi_frag_info_t *)wmem_tree_lookup32(gss_info->frags, pinfo->num); if(fi){ fd_head=fragment_get(&gssapi_reassembly_table, pinfo, fi->first_frame, NULL); if(fd_head && (fd_head->flags&FD_DEFRAGMENTED)){ if(pinfo->num==fi->reassembled_in){ proto_item *frag_tree_item; gss_tvb=tvb_new_chain(tvb, fd_head->tvb_data); add_new_data_source(pinfo, gss_tvb, "Reassembled GSSAPI"); show_fragment_tree(fd_head, &gssapi_frag_items, tree, pinfo, tvb, &frag_tree_item); } else { proto_item *it; it=proto_tree_add_uint(tree, hf_gssapi_reassembled_in, tvb, 0, 0, fi->reassembled_in); PROTO_ITEM_SET_GENERATED(it); goto done; } } } } /* Read header */ offset = get_ber_identifier(gss_tvb, offset, &appclass, &pc, &tag); offset = get_ber_length(gss_tvb, offset, &len1, &ind_field); if (!(appclass == BER_CLASS_APP && pc && tag == 0)) { /* It could be NTLMSSP, with no OID. This can happen for anything that microsoft calls 'Negotiate' or GSS-SPNEGO */ if ((tvb_captured_length_remaining(gss_tvb, start_offset)>7) && (tvb_strneql(gss_tvb, start_offset, "NTLMSSP", 7) == 0)) { return_offset = call_dissector(ntlmssp_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree); goto done; } /* Maybe it's new NTLMSSP payload */ if ((tvb_captured_length_remaining(gss_tvb, start_offset)>16) && ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) { return_offset = call_dissector(ntlmssp_payload_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree); encrypt_info->gssapi_data_encrypted = TRUE; goto done; } if ((tvb_captured_length_remaining(gss_tvb, start_offset)==16) && ((tvb_memeql(gss_tvb, start_offset, "\x01\x00\x00\x00", 4) == 0))) { if( is_verifier ) { return_offset = call_dissector(ntlmssp_verf_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree); } else if( encrypt_info->gssapi_encrypted_tvb ) { return_offset = call_dissector_with_data(ntlmssp_data_only_handle, tvb_new_subset_remaining(encrypt_info->gssapi_encrypted_tvb, 0), pinfo, subtree, &encrypt_info->gssapi_decrypted_tvb); encrypt_info->gssapi_data_encrypted = TRUE; } goto done; } /* Maybe it's new GSSKRB5 CFX Wrapping */ if ((tvb_captured_length_remaining(gss_tvb, start_offset)>2) && ((tvb_memeql(gss_tvb, start_offset, "\04\x04", 2) == 0) || (tvb_memeql(gss_tvb, start_offset, "\05\x04", 2) == 0))) { return_offset = call_dissector_with_data(spnego_krb5_wrap_handle, tvb_new_subset_remaining(gss_tvb, start_offset), pinfo, subtree, encrypt_info); goto done; } /* * If we do not recognise an Application class, * then we are probably dealing with an inner context * token or a wrap token, and we should retrieve the * gssapi_oid_value pointer from the per-frame data or, * if there is no per-frame data (as would be the case * the first time we dissect this frame), from the * conversation that exists or that we created from * pinfo (and then make it per-frame data). * We need to make it per-frame data as there can be * more than one GSS-API negotiation in a conversation. * * Note! We "cheat". Since we only need the pointer, * we store that as the data. (That's not really * "cheating" - the per-frame data and per-conversation * data code doesn't care what you supply as a data * pointer; it just treats it as an opaque pointer, it * doesn't dereference it or free what it points to.) */ oidvalue = (gssapi_oid_value *)p_get_proto_data(wmem_file_scope(), pinfo, proto_gssapi, 0); if (!oidvalue && !pinfo->fd->flags.visited) { /* No handle attached to this frame, but it's the first */ /* pass, so it'd be attached to the conversation. */ oidvalue = gss_info->oid; if (gss_info->oid) p_add_proto_data(wmem_file_scope(), pinfo, proto_gssapi, 0, gss_info->oid); } if (!oidvalue) { proto_tree_add_expert_format(subtree, pinfo, &ei_gssapi_unknown_header, gss_tvb, start_offset, 0, "Unknown header (class=%d, pc=%d, tag=%d)", appclass, pc, tag); return_offset = tvb_captured_length(gss_tvb); goto done; } else { tvbuff_t *oid_tvb_local; oid_tvb_local = tvb_new_subset_remaining(gss_tvb, start_offset); if (is_verifier) handle = oidvalue->wrap_handle; else handle = oidvalue->handle; len = call_dissector_with_data(handle, oid_tvb_local, pinfo, subtree, encrypt_info); if (len == 0) return_offset = tvb_captured_length(gss_tvb); else return_offset = start_offset + len; goto done; /* We are finished here */ } } /* Read oid */ oid_start_offset=offset; offset=dissect_ber_object_identifier_str(FALSE, &asn1_ctx, subtree, gss_tvb, offset, hf_gssapi_oid, &oid); oidvalue = gssapi_lookup_oid_str(oid); /* Check if we need reassembly of this blob. * Only try reassembly for OIDs we recognize * and when we have the entire tvb * * SMB will sometimes split one large GSSAPI blob * across multiple SMB/SessionSetup commands. * While we should look at the uid returned in the response * to the first SessionSetup and use that as a key * instead for simplicity we assume there will not be several * such authentication at once on a single tcp session */ if( (!pinfo->fd->flags.visited) && (oidvalue) && (tvb_captured_length(gss_tvb)==tvb_reported_length(gss_tvb)) && (len1>(guint32)tvb_captured_length_remaining(gss_tvb, oid_start_offset)) && (gssapi_reassembly) ){ fi=wmem_new(wmem_file_scope(), gssapi_frag_info_t); fi->first_frame=pinfo->num; fi->reassembled_in=0; wmem_tree_insert32(gss_info->frags, pinfo->num, fi); fragment_add(&gssapi_reassembly_table, gss_tvb, 0, pinfo, pinfo->num, NULL, 0, tvb_captured_length(gss_tvb), TRUE); fragment_set_tot_len(&gssapi_reassembly_table, pinfo, pinfo->num, NULL, len1+oid_start_offset); gss_info->do_reassembly=TRUE; gss_info->first_frame=pinfo->num; gss_info->frag_offset=tvb_captured_length(gss_tvb); goto done; } /* * Hand off to subdissector. */ if ((oidvalue == NULL) || !proto_is_protocol_enabled(oidvalue->proto)) { /* No dissector for this oid */ proto_tree_add_item(subtree, hf_gssapi_token_object, gss_tvb, oid_start_offset, -1, ENC_NA); return_offset = tvb_captured_length(gss_tvb); goto done; } /* Save a pointer to the data for the OID for the * GSSAPI protocol for this conversation. */ /* * Now add the proto data ... * but only if it is not already there. */ if(!gss_info->oid){ gss_info->oid=oidvalue; } if (is_verifier) { handle = oidvalue->wrap_handle; if (handle != NULL) { oid_tvb = tvb_new_subset_remaining(gss_tvb, offset); len = call_dissector_with_data(handle, oid_tvb, pinfo, subtree, encrypt_info); if (len == 0) return_offset = tvb_captured_length(gss_tvb); else return_offset = offset + len; } else { proto_tree_add_item(subtree, hf_gssapi_auth_verifier, gss_tvb, offset, -1, ENC_NA); return_offset = tvb_captured_length(gss_tvb); } } else { handle = oidvalue->handle; if (handle != NULL) { oid_tvb = tvb_new_subset_remaining(gss_tvb, offset); len = call_dissector_with_data(handle, oid_tvb, pinfo, subtree, encrypt_info); if (len == 0) return_offset = tvb_captured_length(gss_tvb); else return_offset = offset + len; } else { proto_tree_add_item(subtree, hf_gssapi_auth_credentials, gss_tvb, offset, -1, ENC_NA); return_offset = tvb_captured_length(gss_tvb); } } done: ; } CATCH_NONFATAL_ERRORS { /* * Somebody threw an exception that means that there * was a problem dissecting the payload; that means * that a dissector was found, so we don't need to * dissect the payload as data or update the protocol * or info columns. * * Just show the exception and then drive on to show * the trailer, after noting that a dissector was found * and restoring the protocol value that was in effect * before we called the subdissector. */ show_exception(gss_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); } ENDTRY; proto_item_set_len(item, return_offset); return return_offset; }
/* * Function for the PANA PDU dissector. */ static void dissect_pana_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *pana_tree = NULL; guint16 flags; guint16 msg_type; guint32 msg_length; guint32 avp_length; guint32 seq_num; conversation_t *conversation; pana_conv_info_t *pana_info; pana_transaction_t *pana_trans; int offset = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "PANA"); col_clear(pinfo->cinfo, COL_INFO); /* Get message length, type and flags */ msg_length = tvb_get_ntohs(tvb, 2); flags = tvb_get_ntohs(tvb, 4); msg_type = tvb_get_ntohs(tvb, 6); seq_num = tvb_get_ntohl(tvb, 12); avp_length = msg_length - 16; col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s-%s", val_to_str(msg_type, msg_type_names, "Unknown (%d)"), val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)")); /* Make the protocol tree */ if (tree) { proto_item *ti; ti = proto_tree_add_item(tree, proto_pana, tvb, 0, -1, ENC_NA); pana_tree = proto_item_add_subtree(ti, ett_pana); } /* * We need to track some state for this protocol on a per conversation * basis so we can do neat things like request/response tracking */ conversation = find_or_create_conversation(pinfo); /* * Do we already have a state structure for this conv */ pana_info = (pana_conv_info_t *)conversation_get_proto_data(conversation, proto_pana); if (!pana_info) { /* No. Attach that information to the conversation, and add * it to the list of information structures. */ pana_info = wmem_new(wmem_file_scope(), pana_conv_info_t); pana_info->pdus=wmem_tree_new(wmem_file_scope()); conversation_add_proto_data(conversation, proto_pana, pana_info); } if(!pinfo->fd->flags.visited){ if(flags&PANA_FLAG_R){ /* This is a request */ pana_trans=wmem_new(wmem_file_scope(), pana_transaction_t); pana_trans->req_frame=pinfo->fd->num; pana_trans->rep_frame=0; pana_trans->req_time=pinfo->fd->abs_ts; wmem_tree_insert32(pana_info->pdus, seq_num, (void *)pana_trans); } else { pana_trans=(pana_transaction_t *)wmem_tree_lookup32(pana_info->pdus, seq_num); if(pana_trans){ pana_trans->rep_frame=pinfo->fd->num; } } } else { pana_trans=(pana_transaction_t *)wmem_tree_lookup32(pana_info->pdus, seq_num); } if(!pana_trans){ /* create a "fake" pana_trans structure */ pana_trans=wmem_new(wmem_packet_scope(), pana_transaction_t); pana_trans->req_frame=0; pana_trans->rep_frame=0; pana_trans->req_time=pinfo->fd->abs_ts; } /* print state tracking in the tree */ if(flags&PANA_FLAG_R){ /* This is a request */ if(pana_trans->rep_frame){ proto_item *it; it=proto_tree_add_uint(pana_tree, hf_pana_response_in, tvb, 0, 0, pana_trans->rep_frame); PROTO_ITEM_SET_GENERATED(it); } } else { /* This is a reply */ if(pana_trans->req_frame){ proto_item *it; nstime_t ns; it=proto_tree_add_uint(pana_tree, hf_pana_response_to, tvb, 0, 0, pana_trans->req_frame); PROTO_ITEM_SET_GENERATED(it); nstime_delta(&ns, &pinfo->fd->abs_ts, &pana_trans->req_time); it=proto_tree_add_time(pana_tree, hf_pana_response_time, tvb, 0, 0, &ns); PROTO_ITEM_SET_GENERATED(it); } } /* Reserved field */ proto_tree_add_item(pana_tree, hf_pana_reserved_type, tvb, offset, 2, ENC_NA); offset += 2; /* Length */ proto_tree_add_item(pana_tree, hf_pana_length_type, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* Flags */ dissect_pana_flags(pana_tree, tvb, offset, flags); offset += 2; /* Message Type */ proto_tree_add_uint_format_value(pana_tree, hf_pana_msg_type, tvb, offset, 2, msg_type, "%s-%s (%d)", val_to_str(msg_type, msg_type_names, "Unknown (%d)"), val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"), msg_type); offset += 2; /* Session ID */ proto_tree_add_item(pana_tree, hf_pana_session_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* Sequence Number */ proto_tree_add_item(pana_tree, hf_pana_seqnumber, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; /* AVPs */ if(avp_length != 0){ tvbuff_t *avp_tvb; proto_tree *avp_tree; proto_item *avp_item; avp_tvb = tvb_new_subset(tvb, offset, avp_length, avp_length); avp_item = proto_tree_add_text(pana_tree, tvb, offset, avp_length, "Attribute Value Pairs"); avp_tree = proto_item_add_subtree(avp_item, ett_pana_avp); if (avp_tree != NULL) { dissect_avps(avp_tvb, pinfo, avp_tree); } } }
static gint dissect_hci_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *ttree = NULL; proto_tree *titem = NULL; proto_item *pitem = NULL; gint offset = 0; usb_conv_info_t *usb_conv_info; tvbuff_t *next_tvb = NULL; bluetooth_data_t *bluetooth_data; gint p2p_dir_save; guint32 session_id; fragment_head *reassembled; bluetooth_data = (bluetooth_data_t *) data; /* Reject the packet if data is NULL */ if (data == NULL) return 0; DISSECTOR_ASSERT(bluetooth_data->previous_protocol_data_type == BT_PD_USB_CONV_INFO); usb_conv_info = bluetooth_data->previous_protocol_data.usb_conv_info; titem = proto_tree_add_item(tree, proto_hci_usb, tvb, offset, -1, ENC_NA); ttree = proto_item_add_subtree(titem, ett_hci_usb); col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI_USB"); p2p_dir_save = pinfo->p2p_dir; pinfo->p2p_dir = (usb_conv_info->is_request) ? P2P_DIR_SENT : P2P_DIR_RECV; 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 (usb_conv_info->is_setup) { proto_tree_add_item(ttree, hf_bthci_usb_setup_request, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; proto_tree_add_item(ttree, hf_bthci_usb_setup_value, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(ttree, hf_bthci_usb_setup_adapter_id, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; proto_tree_add_item(ttree, hf_bthci_usb_setup_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; } session_id = usb_conv_info->bus_id << 16 | usb_conv_info->device_address << 8 | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0 ) << 7 | usb_conv_info->endpoint; bluetooth_data->adapter_id = usb_conv_info->bus_id << 8 | usb_conv_info->device_address; /* TODO: adapter disconnect on some USB action, for now do not support adapter disconnection */ bluetooth_data->adapter_disconnect_in_frame = &max_disconnect_in_frame; next_tvb = tvb_new_subset_remaining(tvb, offset); if (!pinfo->fd->flags.visited && usb_conv_info->endpoint <= 0x02 && tvb_captured_length(tvb) == tvb_reported_length(tvb)) { fragment_info_t *fragment_info; fragment_info = (fragment_info_t *) wmem_tree_lookup32(fragment_info_table, session_id); if (fragment_info == NULL) { fragment_info = (fragment_info_t *) wmem_new(wmem_file_scope(), fragment_info_t); fragment_info->fragment_id = 0; fragment_info->remaining_length = 0; wmem_tree_insert32(fragment_info_table, session_id, fragment_info); } if (fragment_info->fragment_id == 0) { switch(usb_conv_info->endpoint) { case 0: fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 2) + 3; break; case 1: fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 1) + 2; break; case 2: fragment_info->remaining_length = tvb_get_letohs(tvb, offset + 2) + 4; break; } } fragment_info->remaining_length -= tvb_reported_length_remaining(tvb, offset); fragment_add_seq_check(&hci_usb_reassembly_table, tvb, offset, pinfo, session_id, NULL, fragment_info->fragment_id, tvb_reported_length_remaining(tvb, offset), (fragment_info->remaining_length == 0) ? FALSE : TRUE); if (fragment_info->remaining_length > 0) fragment_info->fragment_id += 1; else fragment_info->fragment_id = 0; } reassembled = fragment_get_reassembled_id(&hci_usb_reassembly_table, pinfo, session_id); if (reassembled && pinfo->num < reassembled->reassembled_in) { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_fragment, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); col_append_str(pinfo->cinfo, COL_INFO, " Fragment"); } else if (reassembled && pinfo->num == reassembled->reassembled_in) { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_complete, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); if (reassembled->len > (guint) tvb_reported_length_remaining(tvb, offset)) { next_tvb = process_reassembled_data(tvb, 0, pinfo, "Reassembled HCI_USB", reassembled, &hci_usb_msg_frag_items, NULL, ttree); } switch(usb_conv_info->endpoint) { case 0: call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, bluetooth_data); break; case 1: call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, bluetooth_data); break; case 2: call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, bluetooth_data); break; } } else { pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_unknown_fragment, tvb, offset, -1, ENC_NA); PROTO_ITEM_SET_GENERATED(pitem); } if (usb_conv_info->endpoint == 0x03) { call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, bluetooth_data); } else if (usb_conv_info->endpoint > 0x03) { proto_tree_add_item(ttree, hf_bthci_usb_data, tvb, offset, -1, ENC_NA); } offset += tvb_reported_length_remaining(tvb, offset); pinfo->p2p_dir = p2p_dir_save; return offset; }