/* * get a Lilliputian unsigned integer from a tvb */ WSLUA_METHOD TvbRange_le_uint(lua_State* L) { /* Get a Little Endian unsigned integer from a TvbRange. The range must be 1, 2, 3 or 4 octets long. */ TvbRange tvbr = checkTvbRange(L,1); if (!(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } switch (tvbr->len) { case 1: /* XXX unsigned anyway */ lua_pushnumber(L,(lua_Number)tvb_get_guint8(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 2: lua_pushnumber(L,tvb_get_letohs(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 3: lua_pushnumber(L,tvb_get_letoh24(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 4: lua_pushnumber(L,tvb_get_letohl(tvbr->tvb->ws_tvb,tvbr->offset)); WSLUA_RETURN(1); /* The unsigned integer value */ default: luaL_error(L,"TvbRange:le_uint() does not handle %d byte integers",tvbr->len); return 0; } }
/* return a TLV value based on TLV length and TLV type (host/network order) */ static int juniper_ext_get_tlv_value(tvbuff_t *tvb, guint tlv_type, guint tlv_len, guint offset) { int tlv_value; if (tlv_type < 128) { /* TLVs < 128 are little-endian / host order encoded */ switch (tlv_len) { case 1: tlv_value = tvb_get_guint8(tvb, offset); break; case 2: tlv_value = tvb_get_letohs(tvb, offset); break; case 3: tlv_value = tvb_get_letoh24(tvb, offset); break; case 4: tlv_value = tvb_get_letohl(tvb, offset); break; default: tlv_value = -1; break; } } else { /* TLVs >= 128 are big-endian / network order encoded */ switch (tlv_len) { case 1: tlv_value = tvb_get_guint8(tvb, offset); break; case 2: tlv_value = tvb_get_ntohs(tvb, offset); break; case 3: tlv_value = tvb_get_ntoh24(tvb, offset); break; case 4: tlv_value = tvb_get_ntohl(tvb, offset); break; default: tlv_value = -1; break; } } return tlv_value; }
/* Common function for dissecting 3-byte (ANSI or China) PCs. */ void dissect_mtp3_3byte_pc(tvbuff_t *tvb, guint offset, proto_tree *tree, gint ett_pc, int hf_pc_string, int hf_pc_network, int hf_pc_cluster, int hf_pc_member, int hf_dpc, int hf_pc) { guint32 pc; proto_item *pc_item, *hidden_item; proto_tree *pc_tree; char pc_string[MAX_STRUCTURED_PC_LENGTH]; pc = tvb_get_letoh24(tvb, offset); mtp3_pc_to_str_buf(pc, pc_string, sizeof(pc_string)); pc_item = proto_tree_add_string(tree, hf_pc_string, tvb, offset, ANSI_PC_LENGTH, pc_string); /* Add alternate formats of the PC * NOTE: each of these formats is shown to the user, * so I think that using hidden fields in this case is OK. */ g_snprintf(pc_string, sizeof(pc_string), "%u", pc); proto_item_append_text(pc_item, " (%s)", pc_string); hidden_item = proto_tree_add_string(tree, hf_pc_string, tvb, offset, ANSI_PC_LENGTH, pc_string); PROTO_ITEM_SET_HIDDEN(hidden_item); g_snprintf(pc_string, sizeof(pc_string), "0x%x", pc); proto_item_append_text(pc_item, " (%s)", pc_string); hidden_item = proto_tree_add_string(tree, hf_pc_string, tvb, offset, ANSI_PC_LENGTH, pc_string); PROTO_ITEM_SET_HIDDEN(hidden_item); pc_tree = proto_item_add_subtree(pc_item, ett_pc); proto_tree_add_uint(pc_tree, hf_pc_network, tvb, offset + ANSI_NETWORK_OFFSET, ANSI_NCM_LENGTH, pc); proto_tree_add_uint(pc_tree, hf_pc_cluster, tvb, offset + ANSI_CLUSTER_OFFSET, ANSI_NCM_LENGTH, pc); proto_tree_add_uint(pc_tree, hf_pc_member, tvb, offset + ANSI_MEMBER_OFFSET, ANSI_NCM_LENGTH, pc); /* add full integer values of DPC as hidden for filtering purposes */ if (hf_dpc) { hidden_item = proto_tree_add_uint(pc_tree, hf_dpc, tvb, offset, ANSI_PC_LENGTH, pc); PROTO_ITEM_SET_HIDDEN(hidden_item); } if (hf_pc) { hidden_item = proto_tree_add_uint(pc_tree, hf_pc, tvb, offset, ANSI_PC_LENGTH, pc); PROTO_ITEM_SET_HIDDEN(hidden_item); } }
/* * get a Lilliputian unsigned 64 bit integer from a tvb */ WSLUA_METHOD TvbRange_le_uint64(lua_State* L) { /* Get a Little Endian unsigned 64 bit integer from a `TvbRange`, as a `UInt64` object. The range must be 1-8 octets long. */ TvbRange tvbr = checkTvbRange(L,1); if (!(tvbr && tvbr->tvb)) return 0; if (tvbr->tvb->expired) { luaL_error(L,"expired tvb"); return 0; } switch (tvbr->len) { case 1: pushUInt64(L,tvb_get_guint8(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 2: pushUInt64(L,tvb_get_letohs(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 3: pushUInt64(L,tvb_get_letoh24(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 4: pushUInt64(L,tvb_get_letohl(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 5: pushUInt64(L,tvb_get_letoh40(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 6: pushUInt64(L,tvb_get_letoh48(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 7: pushUInt64(L,tvb_get_letoh56(tvbr->tvb->ws_tvb,tvbr->offset)); return 1; case 8: pushUInt64(L,tvb_get_letoh64(tvbr->tvb->ws_tvb,tvbr->offset)); WSLUA_RETURN(1); /* The `UInt64` object. */ default: luaL_error(L,"TvbRange:le_uint64() does not handle %d byte integers",tvbr->len); return 0; } }
static void dissect_mtp3_routing_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree) { guint32 label, dpc, opc; proto_item *label_item, *label_dpc_item, *label_opc_item; proto_item *hidden_item; proto_tree *label_tree; proto_tree *pc_subtree; int hf_dpc_string; int hf_opc_string; switch (mtp3_standard) { case ITU_STANDARD: label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); label = tvb_get_letohl(tvb, ROUTING_LABEL_OFFSET); opc = (label & ITU_OPC_MASK) >> 14; dpc = label & ITU_DPC_MASK; hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc); PROTO_ITEM_SET_HIDDEN(hidden_item); label_dpc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_dpc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); if (mtp3_pc_structured()) proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc)); if(mtp3_addr_dpc->ni == 0) { pc_subtree = proto_item_add_subtree(label_dpc_item, ett_mtp3_label_dpc); analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc); } label_opc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_opc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); if (mtp3_pc_structured()) proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc)); if(mtp3_addr_opc->ni == 0) { pc_subtree = proto_item_add_subtree(label_opc_item, ett_mtp3_label_opc); analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc); } proto_tree_add_uint(label_tree, hf_mtp3_itu_sls, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label); break; case ANSI_STANDARD: case CHINESE_ITU_STANDARD: if (mtp3_standard == ANSI_STANDARD) { hf_dpc_string = hf_mtp3_ansi_dpc; hf_opc_string = hf_mtp3_ansi_opc; } else /* CHINESE_ITU_STANDARD */ { hf_dpc_string = hf_mtp3_chinese_dpc; hf_opc_string = hf_mtp3_chinese_opc; } /* Create the Routing Label Tree */ label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ANSI_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); /* create and fill the DPC tree */ dissect_mtp3_3byte_pc(tvb, ANSI_DPC_OFFSET, label_tree, ett_mtp3_label_dpc, hf_dpc_string, hf_mtp3_dpc_network, hf_mtp3_dpc_cluster, hf_mtp3_dpc_member, hf_mtp3_24bit_dpc, hf_mtp3_24bit_pc); /* Store dpc for mtp3_addr below */ dpc = tvb_get_letoh24(tvb, ANSI_DPC_OFFSET); /* create and fill the OPC tree */ dissect_mtp3_3byte_pc(tvb, ANSI_OPC_OFFSET, label_tree, ett_mtp3_label_opc, hf_opc_string, hf_mtp3_opc_network, hf_mtp3_opc_cluster, hf_mtp3_opc_member, hf_mtp3_24bit_opc, hf_mtp3_24bit_pc); /* Store opc for mtp3_addr below */ opc = tvb_get_letoh24(tvb, ANSI_OPC_OFFSET); /* SLS */ if (mtp3_standard == ANSI_STANDARD) { if (mtp3_use_ansi_5_bit_sls) proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); else proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); } else /* CHINESE_ITU_STANDARD */ { proto_tree_add_item(label_tree, hf_mtp3_chinese_itu_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA); } break; case JAPAN_STANDARD: label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, JAPAN_ROUTING_LABEL_LENGTH, "Routing label"); label_tree = proto_item_add_subtree(label_item, ett_mtp3_label); label_dpc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_dpc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); dpc = tvb_get_letohs(tvb, ROUTING_LABEL_OFFSET); if (mtp3_pc_structured()) { proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc)); } label_opc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_opc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); opc = tvb_get_letohs(tvb, JAPAN_OPC_OFFSET); if (mtp3_pc_structured()) { proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc)); } hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN); PROTO_ITEM_SET_HIDDEN(hidden_item); if (mtp3_use_japan_5_bit_sls) { proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); } else { proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA); } break; default: DISSECTOR_ASSERT_NOT_REACHED(); } mtp3_addr_opc->type = mtp3_standard; mtp3_addr_opc->pc = opc; SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc); mtp3_addr_dpc->type = mtp3_standard; mtp3_addr_dpc->pc = dpc; SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc); }
static gint dissect_usb_dfu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { proto_item *main_item; proto_tree *main_tree; proto_item *command_item; proto_item *sub_item; proto_tree *command_tree; gint offset = 0; gint p2p_dir_save; guint8 command; gint16 command_response = -1; command_data_t *command_data = NULL; wmem_tree_t *wmem_tree; wmem_tree_key_t key[5]; guint32 bus_id; guint32 device_address; guint32 k_bus_id; guint32 k_device_address; guint32 k_frame_number; gint32 block_number = -1; usb_conv_info_t *usb_conv_info = (usb_conv_info_t *)data; if (!usb_conv_info) return offset; bus_id = usb_conv_info->bus_id; device_address = usb_conv_info->device_address; k_bus_id = bus_id; k_device_address = device_address; 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; main_item = proto_tree_add_item(tree, proto_usb_dfu, tvb, offset, -1, ENC_NA); main_tree = proto_item_add_subtree(main_item, ett_usb_dfu); col_set_str(pinfo->cinfo, COL_PROTOCOL, "USB DFU"); 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_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction "); break; } if (usb_conv_info->is_setup) { guint16 interface; command_item = proto_tree_add_item(main_tree, hf_setup_command, tvb, offset, 1, ENC_NA); command = tvb_get_guint8(tvb, offset); if (!((usb_conv_info->setup_requesttype == 0x21 && (command == 0x00 || command == 0x01 || command == 0x04 || command == 0x06)) || (usb_conv_info->setup_requesttype == 0xa1 && (command == 0x02 || command == 0x03 || command == 0x05)))) expert_add_info(pinfo, command_item, &ei_invalid_command_for_request_type); offset += 1; col_append_fstr(pinfo->cinfo, COL_INFO, "Command: %s", val_to_str_ext_const(command, &command_vals_ext, "Unknown")); if (command == 0x00) { /* Detach */ proto_tree_add_item(main_tree, hf_setup_timeout, tvb, offset, 2, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, " Timeout=%u", tvb_get_letohs(tvb, offset)); } else if (command == 0x01 || command == 0x02) { /* Download || Upload */ proto_tree_add_item(main_tree, hf_setup_block_number, tvb, offset, 2, ENC_LITTLE_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, " Block Number=%u", tvb_get_letohs(tvb, offset)); block_number = tvb_get_letohs(tvb, offset); } else { proto_tree_add_item(main_tree, hf_setup_unused, tvb, offset, 2, ENC_LITTLE_ENDIAN); } offset += 2; proto_tree_add_item(main_tree, hf_setup_interface, tvb, offset, 2, ENC_LITTLE_ENDIAN); interface = tvb_get_letohs(tvb, offset); offset += 2; proto_tree_add_item(main_tree, hf_setup_length, tvb, offset, 2, ENC_LITTLE_ENDIAN); offset += 2; if (command == 0x01) { /* Download */ proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); offset = tvb_length(tvb); } if (tvb_length_remaining(tvb, offset) > 0) { proto_tree_add_expert(main_tree, pinfo, &ei_unexpected_data, tvb, offset, tvb_length_remaining(tvb, offset)); offset = tvb_length(tvb); } /* Save request info (command_data) */ if (!pinfo->fd->flags.visited && command != 21) { key[2].length = 1; key[2].key = &k_frame_number; key[3].length = 0; key[3].key = NULL; command_data = wmem_new(wmem_file_scope(), command_data_t); command_data->bus_id = bus_id; command_data->device_address = device_address; command_data->command = command; command_data->interface = interface; command_data->command_frame_number = pinfo->fd->num; command_data->block_number = block_number; wmem_tree_insert32_array(command_info, key, command_data); } pinfo->p2p_dir = p2p_dir_save; return offset; } /* Get request info (command_data) */ key[2].length = 0; key[2].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_response = command_data->command; block_number = command_data->block_number; } } if (!command_data) { col_append_str(pinfo->cinfo, COL_INFO, "Response: Unknown"); proto_tree_add_expert(main_tree, pinfo, &ei_unknown_data, tvb, offset, tvb_length_remaining(tvb, offset)); pinfo->p2p_dir = p2p_dir_save; return tvb_length(tvb); } col_append_fstr(pinfo->cinfo, COL_INFO, "Response: %s", val_to_str_ext_const(command_response, &command_vals_ext, "Unknown")); command_item = proto_tree_add_uint(main_tree, hf_response, tvb, offset, 0, command_response); command_tree = proto_item_add_subtree(command_item, ett_command); PROTO_ITEM_SET_GENERATED(command_item); if (command_data) { command_item = proto_tree_add_uint(main_tree, hf_setup_interface, tvb, offset, 0, command_data->interface); PROTO_ITEM_SET_GENERATED(command_item); command_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_frame_number); PROTO_ITEM_SET_GENERATED(command_item); } switch (command_response) { case 0x02: /* Upload */ if (block_number != -1) { sub_item = proto_tree_add_uint(main_tree, hf_setup_block_number, tvb, offset, 0, block_number); PROTO_ITEM_SET_GENERATED(sub_item); col_append_fstr(pinfo->cinfo, COL_INFO, " Block Number=%u", block_number); } proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA); offset = tvb_length(tvb); break; case 0x03: /* Get Status */ col_append_fstr(pinfo->cinfo, COL_INFO, " = Status: %s, PollTimeout: %u ms, State: %s", val_to_str_ext_const(tvb_get_guint8(tvb, offset), &status_vals_ext, "Unknown"), tvb_get_letoh24(tvb, offset + 1), val_to_str_ext_const(tvb_get_guint8(tvb, offset + 4), &state_vals_ext, "Unknown")); proto_tree_add_item(main_tree, hf_status, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(main_tree, hf_poll_timeout, tvb, offset, 3, ENC_LITTLE_ENDIAN); offset += 3; proto_tree_add_item(main_tree, hf_state, tvb, offset, 1, ENC_NA); offset += 1; proto_tree_add_item(main_tree, hf_iString, tvb, offset, 1, ENC_NA); offset += 1; break; case 0x05: /* Get State */ proto_tree_add_item(main_tree, hf_state, tvb, offset, 1, ENC_NA); col_append_fstr(pinfo->cinfo, COL_INFO, " = %s", val_to_str_ext_const(tvb_get_guint8(tvb, offset), &state_vals_ext, "Unknown")); offset += 1; break; case 0x00: /* Detach */ case 0x01: /* Download */ case 0x04: /* Clear Status */ case 0x06: /* Abort */ default: proto_tree_add_expert(command_tree, pinfo, &ei_unexpected_response, tvb, offset, 0); if (tvb_length_remaining(tvb, offset) > 0) { proto_tree_add_expert(main_tree, pinfo, &ei_unknown_data, tvb, offset, -1); offset = tvb_length(tvb); } } pinfo->p2p_dir = p2p_dir_save; return offset; }