static void dissect_xtp_cntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset) { guint32 len = tvb_length_remaining(tvb, offset); guint32 start = offset; proto_item *top_ti; proto_tree *xtp_subtree; struct xtp_cntl cntl[1]; top_ti = proto_tree_add_text(tree, tvb, offset, len, "Common Control Segment"); xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_cntl); if (len != XTP_CNTL_PKT_LEN) { proto_item_append_text(top_ti, ", bogus length(%u, must be %u)", len, XTP_CNTL_PKT_LEN); return; } /** parse **/ /* rseq(8) */ cntl->rseq = tvb_get_ntohl(tvb, offset); cntl->rseq <<= 32; cntl->rseq += tvb_get_ntohl(tvb, offset+4); offset += 8; /* alloc(8) */ cntl->alloc = tvb_get_ntohl(tvb, offset); cntl->alloc <<= 32; cntl->alloc += tvb_get_ntohl(tvb, offset+4); offset += 8; /* echo(4) */ cntl->echo = tvb_get_ntohl(tvb, offset); /** add summary **/ if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, " Recv-Seq=%" G_GINT64_MODIFIER "u", cntl->rseq); col_append_fstr(pinfo->cinfo, COL_INFO, " Alloc=%" G_GINT64_MODIFIER "u", cntl->alloc); } proto_item_append_text(top_ti, ", Recv-Seq: %" G_GINT64_MODIFIER "u", cntl->rseq); /** display **/ offset = start; /* rseq(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_cntl_rseq, tvb, offset, 8, cntl->rseq); offset += 8; /* alloc(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_cntl_alloc, tvb, offset, 8, cntl->alloc); offset += 4; /* echo(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_cntl_echo, tvb, offset, 4, cntl->echo); return; }
static int dissect_report_ack_segment(proto_tree *ltp_tree, tvbuff_t *tvb,int frame_offset){ guint64 rpt_sno; int rpt_sno_size; int segment_offset = 0; proto_item *ltp_rpt_ack_item; proto_tree *ltp_rpt_ack_tree; /* Extracing receipt serial number info */ rpt_sno = evaluate_sdnv_64(tvb,frame_offset, &rpt_sno_size); segment_offset += rpt_sno_size; if((unsigned)(frame_offset + segment_offset) > tvb_length(tvb)){ return 0; } /* Creating tree for the report ack segment */ ltp_rpt_ack_item = proto_tree_add_text(ltp_tree, tvb,frame_offset, segment_offset, "Report Ack Segment"); ltp_rpt_ack_tree = proto_item_add_subtree(ltp_rpt_ack_item, ett_rpt_ack_segm); proto_tree_add_uint64(ltp_rpt_ack_tree, hf_ltp_rpt_ack_sno, tvb, frame_offset,rpt_sno_size, rpt_sno); return segment_offset; }
bool dissect_protobuf_field(const FieldDescriptor* field, const Message* message, tvbuff_t *tvb, guint* offset, proto_tree *leaf) { int len = WireFormat::FieldByteSize( field, *message ); map<string, Handles*>::iterator it = g_mapHandles.find( field->full_name() ); if( it == g_mapHandles.end() ) { return false; // bug } Handles* handles = it->second; const Reflection *reflection = message->GetReflection(); const EnumValueDescriptor* enumDesc = NULL; switch( field->cpp_type() ) { case FieldDescriptor::CPPTYPE_UINT32: proto_tree_add_uint( leaf, handles->p_id, tvb, *offset, len, reflection->GetUInt32( *message, field ) ); break; case FieldDescriptor::CPPTYPE_INT32: proto_tree_add_int( leaf, handles->p_id, tvb, *offset, len, reflection->GetInt32( *message, field ) ); break; case FieldDescriptor::CPPTYPE_FLOAT: proto_tree_add_float( leaf, handles->p_id, tvb, *offset, len, reflection->GetFloat( *message, field ) ); break; case FieldDescriptor::CPPTYPE_UINT64: proto_tree_add_uint64( leaf, handles->p_id, tvb, *offset, len, reflection->GetUInt64( *message, field ) ); break; case FieldDescriptor::CPPTYPE_INT64: proto_tree_add_int64( leaf, handles->p_id, tvb, *offset, len, reflection->GetInt64( *message, field ) ); break; case FieldDescriptor::CPPTYPE_DOUBLE: proto_tree_add_double( leaf, handles->p_id, tvb, *offset, len, reflection->GetDouble( *message, field ) ); break; case FieldDescriptor::CPPTYPE_BOOL: proto_tree_add_boolean( leaf, handles->p_id, tvb, *offset, len, reflection->GetBool( *message, field ) ); break; case FieldDescriptor::CPPTYPE_ENUM: enumDesc = reflection->GetEnum( *message, field ); proto_tree_add_int_format_value( leaf, handles->p_id, tvb, *offset, len, enumDesc->number(), "%d ( %s )", enumDesc->number(), enumDesc->name().c_str() ); break; case FieldDescriptor::CPPTYPE_STRING: proto_tree_add_string( leaf, handles->p_id, tvb, *offset, len, reflection->GetString( *message, field ).c_str() ); break; default: proto_tree_add_item( leaf, handles->p_id, tvb, *offset, len, true ); }; *offset += len; return true; }
static int dissect_report_ack_segment(proto_tree *ltp_tree, tvbuff_t *tvb,int frame_offset){ gint64 rpt_sno; int rpt_sno_size; int segment_offset = 0; proto_tree *ltp_rpt_ack_tree; /* Extracing receipt serial number info */ rpt_sno = evaluate_sdnv_64(tvb,frame_offset, &rpt_sno_size); /* XXX - verify that this does not overflow */ segment_offset += rpt_sno_size; if((unsigned)(frame_offset + segment_offset) > tvb_captured_length(tvb)){ return 0; } /* Creating tree for the report ack segment */ ltp_rpt_ack_tree = proto_tree_add_subtree(ltp_tree, tvb,frame_offset, segment_offset, ett_rpt_ack_segm, NULL, "Report Ack Segment"); proto_tree_add_uint64(ltp_rpt_ack_tree, hf_ltp_rpt_ack_sno, tvb, frame_offset,rpt_sno_size, (guint64)rpt_sno); return segment_offset; }
static void dissect_xtp_data(tvbuff_t *tvb, proto_tree *tree, guint32 offset, gboolean have_btag) { guint32 len = tvb_length_remaining(tvb, offset); proto_item *ti; proto_tree *xtp_subtree; guint64 btag; ti = proto_tree_add_text(tree, tvb, offset, len, "Data Segment"); xtp_subtree = proto_item_add_subtree(ti, ett_xtp_data); if (have_btag) { btag = tvb_get_ntohl(tvb, offset); btag <<= 32; btag += tvb_get_ntohl(tvb, offset+4); proto_tree_add_uint64(xtp_subtree, hf_xtp_btag, tvb, offset, 8, btag); offset += 8; len -= 8; } proto_tree_add_text(xtp_subtree, tvb, offset, len, "Data (%u byte%s)", len, plurality(len, "", "s")); return; }
/* Code to dissect a message block */ guint dissect_moldudp64_msgblk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint64 sequence) { proto_item *ti; proto_tree *blk_tree; guint16 msglen, real_msglen, whole_len; guint remaining; if (tvb_length_remaining(tvb, offset) < MOLDUDP64_MSGLEN_LEN) return 0; msglen = tvb_get_ntohs(tvb, offset); remaining = tvb_reported_length(tvb) - offset - MOLDUDP64_MSGLEN_LEN; if (remaining < (offset + MOLDUDP64_MSGLEN_LEN)) real_msglen = 0; else if (msglen <= remaining) real_msglen = msglen; else real_msglen = remaining; /* msglen and real_msglen only count the data section, and don't * include the two bytes for the length field itself. */ whole_len = real_msglen + MOLDUDP64_MSGLEN_LEN; ti = proto_tree_add_item(tree, hf_moldudp64_msgblk, tvb, offset, whole_len, ENC_NA); blk_tree = proto_item_add_subtree(ti, ett_moldudp64_msgblk); ti = proto_tree_add_uint64(blk_tree, hf_moldudp64_msgseq, tvb, offset, 0, sequence); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_item(blk_tree, hf_moldudp64_msglen, tvb, offset, MOLDUDP64_MSGLEN_LEN, ENC_BIG_ENDIAN); if (msglen != real_msglen) expert_add_info_format_text(pinfo, ti, &ei_moldudp64_msglen_invalid, "Invalid Message Length (claimed %u, found %u)", msglen, real_msglen); offset += MOLDUDP64_MSGLEN_LEN; proto_tree_add_item(blk_tree, hf_moldudp64_msgdata, tvb, offset, real_msglen, ENC_NA); return whole_len; }
void DDS_Dissector::dissect_transport_header (proto_tree* ltree, const DCPS::TransportHeader& header, gint& offset) { gint len; offset += sizeof(header.protocol_) - 2; // skip preamble // hf_version len = sizeof(header.protocol_) - offset; const guint8 *data_ptr = reinterpret_cast<const guint8*>(header.protocol_ + offset); proto_tree_add_bytes_format_value (ltree, hf_version, tvb_, offset, len, data_ptr, "%d.%d", header.protocol_[4], header.protocol_[5]); offset += len; // hf_flags len = sizeof(ACE_CDR::Octet); proto_tree_add_bitmask(ltree, tvb_, offset, hf_flags, ett_trans_flags, flags_fields, FALSE); offset += len; offset += sizeof(header.reserved_); // skip reserved // hf_length len = sizeof(header.length_); proto_tree_add_uint_format_value(ltree, hf_length, tvb_, offset, len, header.length_, "%d octets", header.length_); offset += len; // hf_sequence size_t size = 0, padding = 0; gen_find_size(header.sequence_, size, padding); len = static_cast<gint>(size); proto_tree_add_uint64(ltree, hf_sequence, tvb_, offset, len, gint64(header.sequence_.getValue())); offset += len; // hf_source len = sizeof(header.source_); proto_tree_add_uint(ltree, hf_source, tvb_, offset, len, guint32(header.source_)); offset += len; }
static int add_sdnv64_to_tree(proto_tree *tree, tvbuff_t *tvb, packet_info* pinfo, int offset, int hf_sdnv, guint64 *value, proto_item** item_ret) { int sdnv_status; int sdnv_length; guint64 sdnv_value; proto_item* ti; sdnv_status = evaluate_sdnv64(tvb, offset, &sdnv_length, &sdnv_value); ti = proto_tree_add_uint64(tree, hf_sdnv, tvb, offset, sdnv_length, sdnv_value); *value = sdnv_value; if (NULL != *item_ret) *item_ret = ti; if (!sdnv_status) { expert_add_info(pinfo, ti, &ei_ltp_sdnv_length); } return sdnv_length; }
static int add_session_id(proto_tree *tree, int hf, int hf_str, tvbuff_t *tvb, int offset) { guint count; guint i; guint64 session_id; header_field_info *hfinfo; count = tvb_get_guint8(tvb, offset); if (count == 0) proto_tree_add_string (tree, hf_str, tvb, offset, count+1, "NULL"); else if (count <= 8) { session_id = 0; for (i = 0; i < count; i++) session_id = (session_id << 8) | tvb_get_guint8(tvb, offset + i); proto_tree_add_uint64 (tree, hf, tvb, offset, count+1, session_id); } else { hfinfo = proto_registrar_get_nth(hf); proto_tree_add_text (tree, tvb, offset, count+1, "%s: %s", hfinfo->name, tvb_bytes_to_str(tvb, offset+1, count)); } return offset+1+count; }
void DDS_Dissector::dissect_sample_header (proto_tree* ltree, const DCPS::DataSampleHeader& sample, gint& offset) { gint len; // hf_sample_id len = sizeof(sample.message_id_); proto_tree_add_item(ltree, hf_sample_id, tvb_, offset, len, FALSE); offset += len; // hf_sample_sub_id len = sizeof(sample.submessage_id_); if (sample.submessage_id_ != SUBMESSAGE_NONE) { proto_tree_add_item(ltree, hf_sample_sub_id, tvb_, offset, len, FALSE); } offset += len; // hf_sample_flags len = sizeof(ACE_CDR::Octet); proto_tree_add_bitmask(ltree, tvb_, offset, hf_sample_flags, ett_sample_flags, sample_flags_fields, FALSE); offset += len; // hf_sample_flags2 len = sizeof(ACE_CDR::Octet); proto_tree_add_bitmask(ltree, tvb_, offset, hf_sample_flags2, ett_sample_flags2, sample_flags2_fields, FALSE); offset += len; // hf_sample_length len = sizeof(sample.message_length_); proto_tree_add_uint_format_value(ltree, hf_sample_length, tvb_, offset, len, sample.message_length_, "%d octets", sample.message_length_); offset += len; // hf_sample_sequence size_t size = 0, padding = 0; gen_find_size(sample.sequence_, size, padding); len = static_cast<gint>(size); if (sample.message_id_ == SAMPLE_DATA) { proto_tree_add_uint64(ltree, hf_sample_sequence, tvb_, offset, len, gint64(sample.sequence_.getValue())); } offset += len; // hf_sample_timestamp len = sizeof(sample.source_timestamp_sec_) + sizeof(sample.source_timestamp_nanosec_); if (sample.message_id_ != TRANSPORT_CONTROL) { nstime_t ns = { sample.source_timestamp_sec_, int(sample.source_timestamp_nanosec_) }; proto_tree_add_time(ltree, hf_sample_timestamp, tvb_, offset, len, &ns); } offset += len; // hf_sample_lifespan if (sample.lifespan_duration_) { len = sizeof(sample.lifespan_duration_sec_) + sizeof(sample.lifespan_duration_nanosec_); if (sample.message_id_ != TRANSPORT_CONTROL) { nstime_t ns = { sample.lifespan_duration_sec_, int(sample.lifespan_duration_nanosec_) }; proto_tree_add_time(ltree, hf_sample_lifespan, tvb_, offset, len, &ns); } offset += len; } // hf_sample_publication size = 0; gen_find_size(sample.publication_id_, size, padding); len = static_cast<gint>(size); const guint8 *data_ptr = reinterpret_cast<const guint8*>(&sample.publication_id_); if (sample.message_id_ != TRANSPORT_CONTROL) { GuidConverter converter (sample.publication_id_); proto_tree_add_bytes_format_value (ltree, hf_sample_publication, tvb_, offset, len, data_ptr, "%s", std::string(converter).c_str()); } offset += len; // hf_sample_publisher if (sample.group_coherent_) { size = 0; gen_find_size(sample.publisher_id_, size, padding); len = static_cast<gint>(size); data_ptr = reinterpret_cast<const guint8*>(&sample.publisher_id_); if (sample.message_id_ != DCPS::TRANSPORT_CONTROL) { DCPS::GuidConverter converter(sample.publisher_id_); proto_tree_add_bytes_format_value (ltree, hf_sample_publisher, tvb_, offset, len, data_ptr, "%s", std::string(converter).c_str() ); } offset += len; } // hf_sample_content_filt if (sample.content_filter_) { size = 0; gen_find_size(sample.content_filter_entries_, size, padding); gint total_len = static_cast<gint>(size); len = sizeof(CORBA::ULong); if (sample.message_id_ != DCPS::TRANSPORT_CONTROL) { proto_item *item = proto_tree_add_uint_format_value (ltree, hf_sample_content_filt, tvb_, offset, len, sample.content_filter_entries_.length(), "%d entries", sample.content_filter_entries_.length()); offset += len; proto_tree *subtree = proto_item_add_subtree (item, ett_filters); for (CORBA::ULong i = 0; i < sample.content_filter_entries_.length(); i++) { const GUID_t &filter = sample.content_filter_entries_[i]; DCPS::GuidConverter converter(filter); std::stringstream strm; strm << "filter [" << i << "] = " << converter << std::ends; size = 0; gen_find_size(filter, size, padding); len = static_cast<gint>(size); proto_tree_add_text (subtree, tvb_, offset, len, "%s", strm.str().c_str()); offset += len; } } else { offset += total_len; } } }
static int dissect_xtp_traffic_cntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset) { guint32 len = tvb_length_remaining(tvb, offset); guint32 start = offset; proto_item *top_ti; proto_tree *xtp_subtree; struct xtp_traffic_cntl tcntl[1]; top_ti = proto_tree_add_text(tree, tvb, offset, len, "Traffic Control Segment"); xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_tcntl); if (len < XTP_TRAFFIC_CNTL_LEN) { proto_item_append_text(top_ti, ", bogus length(%u, must be at least %u)", len, XTP_TRAFFIC_CNTL_LEN); return 0; } /** parse **/ /* rseq(8) */ tcntl->rseq = tvb_get_ntohl(tvb, offset); tcntl->rseq <<= 32; tcntl->rseq += tvb_get_ntohl(tvb, offset+4); offset += 8; /* alloc(8) */ tcntl->alloc = tvb_get_ntohl(tvb, offset); tcntl->alloc <<= 32; tcntl->alloc += tvb_get_ntohl(tvb, offset+4); offset += 8; /* echo(4) */ tcntl->echo = tvb_get_ntohl(tvb, offset); offset += 4; /* rsvd(4) */ tcntl->rsvd = tvb_get_ntohl(tvb, offset); offset += 4; /* xkey(8) */ tcntl->xkey = tvb_get_ntohl(tvb, offset); tcntl->xkey <<= 32; tcntl->xkey += tvb_get_ntohl(tvb, offset+4); /** add summary **/ col_append_fstr(pinfo->cinfo, COL_INFO, " Recv-Seq=%" G_GINT64_MODIFIER "u", tcntl->rseq); col_append_fstr(pinfo->cinfo, COL_INFO, " Alloc=%" G_GINT64_MODIFIER "u", tcntl->alloc); proto_item_append_text(top_ti, ", Recv-Seq: %" G_GINT64_MODIFIER "u", tcntl->rseq); /** display **/ offset = start; /* rseq(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_rseq, tvb, offset, 8, tcntl->rseq); offset += 8; /* alloc(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_alloc, tvb, offset, 8, tcntl->alloc); offset += 4; /* echo(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_tcntl_echo, tvb, offset, 4, tcntl->echo); offset += 4; /* rsvd(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_tcntl_rsvd, tvb, offset, 4, tcntl->rsvd); offset += 4; /* xkey(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_tcntl_xkey, tvb, offset, 8, tcntl->xkey); offset += 8; return (offset - start); }
bool dissect_protobuf_repeated_field(const FieldDescriptor* field, const Message* message, tvbuff_t *tvb, guint* offset, proto_tree *leaf, int iRepeatedIndex) { int len = 0; string scratch; if( !field->options().packed() ) { len += WireFormat::TagSize( field->number(), field->type() ); } map<string, Handles*>::iterator it = g_mapHandles.find( field->full_name() ); if( it == g_mapHandles.end() ) { return false; // bug } Handles* handles = it->second; const Reflection *reflection = message->GetReflection(); const EnumValueDescriptor* enumDesc = NULL; switch( field->cpp_type() ) { case FieldDescriptor::CPPTYPE_UINT32: if( field->type() == FieldDescriptor::TYPE_FIXED32 ) { len += WireFormatLite::kFixed32Size; } else { len += WireFormatLite::UInt32Size( reflection->GetRepeatedUInt32( *message, field, iRepeatedIndex ) ); } proto_tree_add_uint( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedUInt32( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_INT32: if( field->type() == FieldDescriptor::TYPE_SFIXED32 ) { len += WireFormatLite::kSFixed32Size; } else if( field->type() == FieldDescriptor::TYPE_SINT32 ) { len += WireFormatLite::SInt32Size( reflection->GetRepeatedInt32( *message, field, iRepeatedIndex ) ); } else { len += WireFormatLite::Int32Size( reflection->GetRepeatedInt32( *message, field, iRepeatedIndex ) ); } proto_tree_add_int( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedInt32( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_FLOAT: len += WireFormatLite::kFloatSize; proto_tree_add_float( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedFloat( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_UINT64: if( field->type() == FieldDescriptor::TYPE_FIXED64 ) { len += WireFormatLite::kFixed64Size; } else { len += WireFormatLite::UInt64Size( reflection->GetRepeatedUInt64( *message, field, iRepeatedIndex ) ); } proto_tree_add_uint64( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedUInt64( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_INT64: if( field->type() == FieldDescriptor::TYPE_SFIXED64 ) { len += WireFormatLite::kSFixed64Size; } else if( field->type() == FieldDescriptor::TYPE_SINT64 ) { len += WireFormatLite::SInt64Size( reflection->GetRepeatedInt64( *message, field, iRepeatedIndex ) ); } else { len += WireFormatLite::Int64Size( reflection->GetRepeatedInt64( *message, field, iRepeatedIndex ) ); } proto_tree_add_int64( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedInt64( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_DOUBLE: len += WireFormatLite::kDoubleSize; proto_tree_add_double( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedDouble( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_BOOL: len += WireFormatLite::kBoolSize; proto_tree_add_boolean( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedBool( *message, field, iRepeatedIndex ) ); break; case FieldDescriptor::CPPTYPE_ENUM: enumDesc = reflection->GetRepeatedEnum( *message, field, iRepeatedIndex ); len += WireFormatLite::EnumSize( enumDesc->number() ); proto_tree_add_int_format_value( leaf, handles->p_id, tvb, *offset, len, enumDesc->number(), "%d ( %s )", enumDesc->number(), enumDesc->name().c_str() ); break; case FieldDescriptor::CPPTYPE_STRING: len += WireFormatLite::StringSize( reflection->GetRepeatedStringReference( *message, field, iRepeatedIndex, &scratch ) ); proto_tree_add_string( leaf, handles->p_id, tvb, *offset, len, reflection->GetRepeatedString( *message, field, iRepeatedIndex ).c_str() ); break; default: proto_tree_add_item( leaf, handles->p_id, tvb, *offset, len, true ); }; *offset += len; return true; }
static void dissect_ata_pdu(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean response, guint32 tag) { proto_item *tmp_item; guint8 aflags; guint64 lba; ata_info_t *ata_info=NULL; conversation_t *conversation; /* only create a conversation for ATA commands */ conversation = find_or_create_conversation(pinfo); if( !(pinfo->fd->flags.visited) ){ if(!response){ ata_info_t *tmp_ata_info; /* first time we see this request so add a struct for request/response matching */ ata_info=se_new(ata_info_t); ata_info->tag=tag; ata_info->conversation=conversation; ata_info->request_frame=pinfo->fd->num; ata_info->response_frame=0; ata_info->cmd=tvb_get_guint8(tvb, offset+3); ata_info->req_time=pinfo->fd->abs_ts; tmp_ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_unmatched, ata_info); if(tmp_ata_info){ g_hash_table_remove(ata_cmd_unmatched, tmp_ata_info); } g_hash_table_insert(ata_cmd_unmatched, ata_info, ata_info); } else { ata_info_t tmp_ata_info; /* first time we see this response so see if we can match it with a request */ tmp_ata_info.tag=tag; tmp_ata_info.conversation=conversation; ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_unmatched, &tmp_ata_info); /* woo hoo we could, so no need to store this in unmatched any more, move both request and response to the matched table */ if(ata_info){ ata_info->response_frame=pinfo->fd->num; g_hash_table_remove(ata_cmd_unmatched, ata_info); g_hash_table_insert(ata_cmd_matched, GUINT_TO_POINTER(ata_info->request_frame), ata_info); g_hash_table_insert(ata_cmd_matched, GUINT_TO_POINTER(ata_info->response_frame), ata_info); } } } else { ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_matched, GUINT_TO_POINTER(pinfo->fd->num)); } if(ata_info){ if(response){ if(ata_info->request_frame){ nstime_t delta_ts; tmp_item=proto_tree_add_uint(tree, hf_aoe_response_to, tvb, 0, 0, ata_info->request_frame); PROTO_ITEM_SET_GENERATED(tmp_item); nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &ata_info->req_time); tmp_item=proto_tree_add_time(tree, hf_aoe_time, tvb, offset, 0, &delta_ts); PROTO_ITEM_SET_GENERATED(tmp_item); } } else { if(ata_info->response_frame){ tmp_item=proto_tree_add_uint(tree, hf_aoe_response_in, tvb, 0, 0, ata_info->response_frame); PROTO_ITEM_SET_GENERATED(tmp_item); } } } /* aflags */ aflags=tvb_get_guint8(tvb, offset); proto_tree_add_item(tree, hf_aoe_aflags_e, tvb, offset, 1, ENC_BIG_ENDIAN); if(aflags&AOE_AFLAGS_E){ proto_tree_add_item(tree, hf_aoe_aflags_d, tvb, offset, 1, ENC_BIG_ENDIAN); } if(aflags&AOE_AFLAGS_W){ proto_tree_add_item(tree, hf_aoe_aflags_a, tvb, offset, 1, ENC_BIG_ENDIAN); } proto_tree_add_item(tree, hf_aoe_aflags_w, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* err/feature */ proto_tree_add_item(tree, hf_aoe_err_feature, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* sector count */ proto_tree_add_item(tree, hf_aoe_sector_count, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; /* ata command/status */ if(!response){ proto_tree_add_item(tree, hf_aoe_acmd, tvb, offset, 1, ENC_BIG_ENDIAN); col_append_fstr(pinfo->cinfo, COL_INFO, " ATA:%s", val_to_str(tvb_get_guint8(tvb, offset), ata_cmd_vals, " Unknown ATA<0x%02x>")); } else { proto_tree_add_item(tree, hf_aoe_astatus, tvb, offset, 1, ENC_BIG_ENDIAN); if(ata_info != NULL && ata_info->request_frame){ /* we dont know what command it was unless we saw the request_frame */ tmp_item=proto_tree_add_uint(tree, hf_aoe_acmd, tvb, 0, 0, ata_info->cmd); PROTO_ITEM_SET_GENERATED(tmp_item); col_append_fstr(pinfo->cinfo, COL_INFO, " ATA:%s", val_to_str(ata_info->cmd, ata_cmd_vals, " Unknown ATA<0x%02x>")); } } offset++; /*lba probably complete wrong */ lba=tvb_get_letohs(tvb, offset+4); lba=(lba<<32)|tvb_get_letohl(tvb, offset); offset+=8; proto_tree_add_uint64(tree, hf_aoe_lba, tvb, offset-8, 6, lba); }
static void dissect_radiotap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *radiotap_tree = NULL; proto_tree *pt, *present_tree = NULL; proto_tree *ft; proto_item *ti = NULL, *hidden_item; int align_offset, offset; tvbuff_t *next_tvb; guint32 version; guint length, length_remaining; guint32 rate, freq, flags; gint8 dbm; guint8 db, rflags; guint32 present, next_present; int bit; /* backward compat with bit 14 == fcs in header */ proto_item *hdr_fcs_ti = NULL; int hdr_fcs_offset = 0; guint32 sent_fcs = 0; guint32 calc_fcs; struct _radiotap_info *radiotap_info; static struct _radiotap_info rtp_info_arr[1]; radiotap_info = &rtp_info_arr[0]; col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN"); col_clear(pinfo->cinfo, COL_INFO); offset = 0; version = tvb_get_guint8(tvb, offset); length = tvb_get_letohs(tvb, offset+2); present = tvb_get_letohl(tvb, offset+4); radiotap_info->radiotap_length = length; col_add_fstr(pinfo->cinfo, COL_INFO, "Radiotap Capture v%u, Length %u", version, length); /* Dissect the packet */ if (tree) { ti = proto_tree_add_protocol_format(tree, proto_radiotap, tvb, 0, length, "Radiotap Header v%u, Length %u", version, length); radiotap_tree = proto_item_add_subtree(ti, ett_radiotap); proto_tree_add_uint(radiotap_tree, hf_radiotap_version, tvb, offset, 1, version); proto_tree_add_item(radiotap_tree, hf_radiotap_pad, tvb, offset + 1, 1, FALSE); ti = proto_tree_add_uint(radiotap_tree, hf_radiotap_length, tvb, offset + 2, 2, length); } length_remaining = length; /* * FIXME: This only works if there is exactly 1 it_present * field in the header */ if (length_remaining < RADIOTAP_MIN_HEADER_LEN) { /* * Radiotap header is shorter than the fixed-length portion * plus one "present" bitset. */ if (tree) proto_item_append_text(ti, " (bogus - minimum length is 8)"); return; } /* Subtree for the "present flags" bitfield. */ if (tree) { pt = proto_tree_add_uint(radiotap_tree, hf_radiotap_present, tvb, offset + 4, 4, present); present_tree = proto_item_add_subtree(pt, ett_radiotap_present); proto_tree_add_item(present_tree, hf_radiotap_present_tsft, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_flags, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_rate, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_channel, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_fhss, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_dbm_antsignal, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_dbm_antnoise, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_lock_quality, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_tx_attenuation, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_db_tx_attenuation, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_dbm_tx_attenuation, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_antenna, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_db_antsignal, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_db_antnoise, tvb, offset + 4, 4, TRUE); if (radiotap_bit14_fcs) { proto_tree_add_item(present_tree, hf_radiotap_present_hdrfcs, tvb, offset + 4, 4, TRUE); } else { proto_tree_add_item(present_tree, hf_radiotap_present_rxflags, tvb, offset + 4, 4, TRUE); } proto_tree_add_item(present_tree, hf_radiotap_present_xchannel, tvb, offset + 4, 4, TRUE); proto_tree_add_item(present_tree, hf_radiotap_present_ext, tvb, offset + 4, 4, TRUE); } offset += RADIOTAP_MIN_HEADER_LEN; length_remaining -= RADIOTAP_MIN_HEADER_LEN; rflags = 0; for (; present; present = next_present) { /* clear the least significant bit that is set */ next_present = present & (present - 1); /* extract the least significant bit that is set */ bit = BITNO_32(present ^ next_present); switch (bit) { case IEEE80211_RADIOTAP_TSFT: align_offset = ALIGN_OFFSET(offset, 8); offset += align_offset; length_remaining -= align_offset; if (length_remaining < 8) break; radiotap_info->tsft=tvb_get_letoh64(tvb, offset); if (tree) { proto_tree_add_uint64(radiotap_tree, hf_radiotap_mactime, tvb, offset, 8,radiotap_info->tsft ); } offset+=8; length_remaining-=8; break; case IEEE80211_RADIOTAP_FLAGS: { proto_tree *flags_tree; if (length_remaining < 1) break; rflags = tvb_get_guint8(tvb, offset); if (tree) { ft = proto_tree_add_item(radiotap_tree, hf_radiotap_flags, tvb, offset, 1, FALSE); flags_tree = proto_item_add_subtree(ft, ett_radiotap_flags); proto_tree_add_item(flags_tree, hf_radiotap_flags_cfp, tvb, offset, 1, FALSE); proto_tree_add_item(flags_tree, hf_radiotap_flags_preamble, tvb, offset, 1, FALSE); proto_tree_add_item(flags_tree, hf_radiotap_flags_wep, tvb, offset, 1, FALSE); proto_tree_add_item(flags_tree, hf_radiotap_flags_frag, tvb, offset, 1, FALSE); proto_tree_add_item(flags_tree, hf_radiotap_flags_fcs, tvb, offset, 1, FALSE); proto_tree_add_item(flags_tree, hf_radiotap_flags_datapad, tvb, offset, 1, FALSE); proto_tree_add_item(flags_tree, hf_radiotap_flags_badfcs, tvb, offset, 1, FALSE); proto_tree_add_item(flags_tree, hf_radiotap_flags_shortgi, tvb, offset, 1, FALSE); } offset++; length_remaining--; break; } case IEEE80211_RADIOTAP_RATE: if (length_remaining < 1) break; rate = tvb_get_guint8(tvb, offset); if (rate & 0x80) { /* XXX adjust by CW and short GI like other sniffers? */ rate = ieee80211_htrates[rate & 0xf]; } col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%d.%d", rate / 2, rate & 1 ? 5 : 0); if (tree) { proto_tree_add_float_format(radiotap_tree, hf_radiotap_datarate, tvb, offset, 1, (float)rate / 2, "Data Rate: %.1f Mb/s", (float)rate / 2); } offset++; length_remaining--; radiotap_info->rate = rate; break; case IEEE80211_RADIOTAP_CHANNEL: { proto_item *it; proto_tree *flags_tree; gchar *chan_str; align_offset = ALIGN_OFFSET(offset, 2); offset += align_offset; length_remaining -= align_offset; if (length_remaining < 2) break; if (tree) { freq = tvb_get_letohs(tvb, offset); flags = tvb_get_letohs(tvb, offset+2); chan_str = ieee80211_mhz_to_str(freq); col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%s", chan_str); proto_tree_add_uint_format(radiotap_tree, hf_radiotap_channel_frequency, tvb, offset, 2, freq, "Channel frequency: %s", chan_str); g_free(chan_str); /* We're already 2-byte aligned. */ it = proto_tree_add_uint(radiotap_tree, hf_radiotap_channel_flags, tvb, offset+2, 2, flags); flags_tree = proto_item_add_subtree(it, ett_radiotap_channel_flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_turbo, tvb, offset+2, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_cck, tvb, offset+2, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_ofdm, tvb, offset+2, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_2ghz, tvb, offset+2, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_5ghz, tvb, offset+3, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_passive, tvb, offset+3, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_dynamic, tvb, offset+3, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_gfsk, tvb, offset+3, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_gsm, tvb, offset+3, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_sturbo, tvb, offset+3, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_half, tvb, offset+3, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_channel_flags_quarter, tvb, offset+3, 1, flags); radiotap_info->freq=freq; radiotap_info->flags=flags; } offset+=4 /* Channel + flags */; length_remaining-=4; break; } case IEEE80211_RADIOTAP_FHSS: align_offset = ALIGN_OFFSET(offset, 2); offset += align_offset; length_remaining -= align_offset; if (length_remaining < 2) break; proto_tree_add_item(radiotap_tree, hf_radiotap_fhss_hopset, tvb, offset, 1, FALSE); proto_tree_add_item(radiotap_tree, hf_radiotap_fhss_pattern, tvb, offset, 1, FALSE); offset+=2; length_remaining-=2; break; case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: if (length_remaining < 1) break; dbm = (gint8) tvb_get_guint8(tvb, offset); col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", dbm); if (tree) { proto_tree_add_int_format(radiotap_tree, hf_radiotap_dbm_antsignal, tvb, offset, 1, dbm, "SSI Signal: %d dBm", dbm); } offset++; length_remaining--; radiotap_info->dbm_antsignal=dbm; break; case IEEE80211_RADIOTAP_DBM_ANTNOISE: if (length_remaining < 1) break; dbm = (gint8) tvb_get_guint8(tvb, offset); if (tree) { proto_tree_add_int_format(radiotap_tree, hf_radiotap_dbm_antnoise, tvb, offset, 1, dbm, "SSI Noise: %d dBm", dbm); } offset++; length_remaining--; radiotap_info->dbm_antnoise=dbm; break; case IEEE80211_RADIOTAP_LOCK_QUALITY: align_offset = ALIGN_OFFSET(offset, 2); offset += align_offset; length_remaining -= align_offset; if (length_remaining < 2) break; if (tree) { proto_tree_add_uint(radiotap_tree, hf_radiotap_quality, tvb, offset, 2, tvb_get_letohs(tvb, offset)); } offset+=2; length_remaining-=2; break; case IEEE80211_RADIOTAP_TX_ATTENUATION: align_offset = ALIGN_OFFSET(offset, 2); offset += align_offset; length_remaining -= align_offset; if (length_remaining < 2) break; proto_tree_add_item(radiotap_tree, hf_radiotap_tx_attenuation, tvb, offset, 2, FALSE); offset+=2; length_remaining-=2; break; case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: align_offset = ALIGN_OFFSET(offset, 2); offset += align_offset; length_remaining -= align_offset; if (length_remaining < 2) break; proto_tree_add_item(radiotap_tree, hf_radiotap_db_tx_attenuation, tvb, offset, 2, FALSE); offset+=2; length_remaining-=2; break; case IEEE80211_RADIOTAP_DBM_TX_POWER: if (length_remaining < 1) break; if (tree) { proto_tree_add_int(radiotap_tree, hf_radiotap_txpower, tvb, offset, 1, tvb_get_guint8(tvb, offset)); } offset++; length_remaining--; break; case IEEE80211_RADIOTAP_ANTENNA: if (length_remaining < 1) break; if (tree) { proto_tree_add_uint(radiotap_tree, hf_radiotap_antenna, tvb, offset, 1, tvb_get_guint8(tvb, offset)); } offset++; length_remaining--; break; case IEEE80211_RADIOTAP_DB_ANTSIGNAL: if (length_remaining < 1) break; db = tvb_get_guint8(tvb, offset); col_add_fstr(pinfo->cinfo, COL_RSSI, "%u dB", db); if (tree) { proto_tree_add_uint_format(radiotap_tree, hf_radiotap_db_antsignal, tvb, offset, 1, db, "SSI Signal: %u dB", db); } offset++; length_remaining--; break; case IEEE80211_RADIOTAP_DB_ANTNOISE: if (length_remaining < 1) break; db = tvb_get_guint8(tvb, offset); if (tree) { proto_tree_add_uint_format(radiotap_tree, hf_radiotap_db_antnoise, tvb, offset, 1, db, "SSI Noise: %u dB", db); } offset++; length_remaining--; break; case IEEE80211_RADIOTAP_RX_FLAGS: { proto_tree *flags_tree; if (radiotap_bit14_fcs) { align_offset = ALIGN_OFFSET(offset, 4); offset += align_offset; length_remaining -= align_offset; if (length_remaining < 4) break; if (tree) { sent_fcs = tvb_get_ntohl(tvb, offset); hdr_fcs_ti = proto_tree_add_uint(radiotap_tree, hf_radiotap_fcs, tvb, offset, 4, sent_fcs); hdr_fcs_offset = offset; } offset+=4; length_remaining-=4; } else { proto_item *it; align_offset = ALIGN_OFFSET(offset, 2); offset += align_offset; length_remaining -= align_offset; if (length_remaining < 2) break; if (tree) { flags = tvb_get_letohs(tvb, offset); it = proto_tree_add_uint(radiotap_tree, hf_radiotap_rxflags, tvb, offset, 2, flags); flags_tree = proto_item_add_subtree(it, ett_radiotap_rxflags); proto_tree_add_boolean(flags_tree, hf_radiotap_rxflags_badplcp, tvb, offset, 1, flags); } offset+=2; length_remaining-=2; } break; } case IEEE80211_RADIOTAP_XCHANNEL: { proto_item *it; proto_tree *flags_tree; align_offset = ALIGN_OFFSET(offset, 4); offset += align_offset; length_remaining -= align_offset; if (length_remaining < 8) break; if (tree) { int channel; guint8 maxpower; flags = tvb_get_letohl(tvb, offset); freq = tvb_get_letohs(tvb, offset+4); channel = tvb_get_guint8(tvb, offset+6); maxpower = tvb_get_guint8(tvb, offset+7); proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel, tvb, offset+6, 1, (guint32) channel); proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel_frequency, tvb, offset+4, 2, freq); it = proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel_flags, tvb, offset+0, 4, flags); flags_tree = proto_item_add_subtree(it, ett_radiotap_xchannel_flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_turbo, tvb, offset+0, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_cck, tvb, offset+0, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ofdm, tvb, offset+0, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_2ghz, tvb, offset+0, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_5ghz, tvb, offset+1, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_passive, tvb, offset+1, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_dynamic, tvb, offset+1, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_gfsk, tvb, offset+1, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_gsm, tvb, offset+1, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_sturbo, tvb, offset+1, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_half, tvb, offset+1, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_quarter, tvb, offset+1, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ht20, tvb, offset+2, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ht40u, tvb, offset+2, 1, flags); proto_tree_add_boolean(flags_tree, hf_radiotap_xchannel_flags_ht40d, tvb, offset+2, 1, flags); #if 0 proto_tree_add_uint(radiotap_tree, hf_radiotap_xchannel_maxpower, tvb, offset+7, 1, maxpower); #endif } offset+=8 /* flags + freq + ieee + maxregpower */; length_remaining-=8; break; } default: /* * This indicates a field whose size we do not * know, so we cannot proceed. */ next_present = 0; continue; } } /* This handles the case of an FCS exiting at the end of the frame. */ if (rflags & IEEE80211_RADIOTAP_F_FCS) pinfo->pseudo_header->ieee_802_11.fcs_len = 4; else pinfo->pseudo_header->ieee_802_11.fcs_len = 0; /* Grab the rest of the frame. */ next_tvb = tvb_new_subset_remaining(tvb, length); /* If we had an in-header FCS, check it. * This can only happen if the backward-compat configuration option * is chosen by the user. */ if (hdr_fcs_ti) { /* It would be very strange for the header to have an FCS for the * frame *and* the frame to have the FCS at the end, but it's possible, so * take that into account by using the FCS length recorded in pinfo. */ /* Watch out for [erroneously] short frames */ if (tvb_length(next_tvb) > (unsigned int) pinfo->pseudo_header->ieee_802_11.fcs_len) { calc_fcs = crc32_802_tvb(next_tvb, tvb_length(next_tvb) - pinfo->pseudo_header->ieee_802_11.fcs_len); /* By virtue of hdr_fcs_ti being set, we know that 'tree' is set, * so there's no need to check it here. */ if (calc_fcs == sent_fcs) { proto_item_append_text(hdr_fcs_ti, " [correct]"); } else { proto_item_append_text(hdr_fcs_ti, " [incorrect, should be 0x%08x]", calc_fcs); hidden_item = proto_tree_add_boolean(radiotap_tree, hf_radiotap_fcs_bad, tvb, hdr_fcs_offset, 4, TRUE); PROTO_ITEM_SET_HIDDEN(hidden_item); } } else { proto_item_append_text(hdr_fcs_ti, " [cannot verify - not enough data]"); } } /* dissect the 802.11 header next */ call_dissector((rflags & IEEE80211_RADIOTAP_F_DATAPAD) ? ieee80211_datapad_handle : ieee80211_handle, next_tvb, pinfo, tree); tap_queue_packet(radiotap_tap, pinfo, radiotap_info); }
/* Decode an EXT_FTI extension and fill FEC array */ void fec_decode_ext_fti(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint8 encoding_id) { guint64 transfer_length; fec_packet_data_t *fec_data; guint8 instance_id = 0; proto_item *ti; if (encoding_id == 6){ /* Raptor Q uses 40-bit transfer length */ transfer_length = tvb_get_ntoh40(tvb, offset+2); } else { /* Decode 48-bit length field */ transfer_length = tvb_get_ntoh48(tvb, offset+2); } if (encoding_id >= 128) { instance_id = (guint8) tvb_get_ntohs(tvb, offset+8); /* Decode FEC Instance ID */ fec_data = wmem_new0(wmem_file_scope(), fec_packet_data_t); fec_data->instance_id = instance_id; p_add_proto_data(wmem_file_scope(), pinfo, proto_rmt_fec, 0, fec_data); } if (encoding_id == 6){ /* Raptor Q uses 40-bit transfer length */ proto_tree_add_uint64(tree, hf_fti_transfer_length, tvb, offset+2, 5, transfer_length); } else { proto_tree_add_uint64(tree, hf_fti_transfer_length, tvb, offset+2, 6, transfer_length); ti = proto_tree_add_item(tree, hf_instance_id, tvb, offset+8, 2, ENC_BIG_ENDIAN); if ((encoding_id < 128) && (encoding_id != 0)) { expert_add_info(pinfo, ti, &ei_fec_encoding_id); } } switch (encoding_id) { case 1: proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_num_blocks, tvb, offset+12, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_num_subblocks, tvb, offset+14, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_alignment, tvb, offset+15, 1, ENC_BIG_ENDIAN); break; case 6: proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+8, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_num_blocks, tvb, offset+10, 1, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_num_subblocks, tvb, offset+11, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_alignment, tvb, offset+13, 1, ENC_BIG_ENDIAN); break; case 0: case 2: case 128: case 130: proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_max_source_block_length, tvb, offset+12, 4, ENC_BIG_ENDIAN); break; case 129: proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_max_source_block_length, tvb, offset+12, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_max_number_encoding_symbols, tvb, offset+14, 2, ENC_BIG_ENDIAN); break; case 132: proto_tree_add_item(tree, hf_fti_encoding_symbol_length, tvb, offset+10, 2, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_max_source_block_length, tvb, offset+12, 4, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_fti_max_number_encoding_symbols, tvb, offset+16, 4, ENC_BIG_ENDIAN); break; } }
static int dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int frame_offset,int ltp_type, guint64 session_num){ guint64 client_id; guint64 offset; guint64 length; guint64 chkp_sno = 0; guint64 rpt_sno = 0; int segment_offset = 0; int client_id_size; int offset_size; int length_size; int chkp_sno_size; int rpt_sno_size; int data_offset = 0; int data_length; int bundle_size = 0; int dissected_data_size = 0; int data_count = 1; proto_item *ltp_data_item; proto_item *ltp_data_data_item; proto_tree *ltp_data_tree; proto_tree *ltp_data_data_tree; tvbuff_t *datatvb; fragment_data *frag_msg = NULL; gboolean more_frags = TRUE; tvbuff_t *new_tvb = NULL; /* Extract the info for the data segment */ client_id = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&client_id_size); segment_offset+= client_id_size; if((unsigned)(frame_offset + segment_offset) >= tvb_length(tvb)){ /* This would mean the data segment is incomplete */ return 0; } offset = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&offset_size); segment_offset+= offset_size; if((unsigned)(frame_offset + segment_offset) >= tvb_length(tvb)){ /* This would mean the data segment is incomplete */ return 0; } length = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&length_size); segment_offset+= length_size; if((unsigned)(frame_offset + segment_offset) >= tvb_length(tvb)){ /* This would mean the data segment is incomplete */ return 0; } if(ltp_type != 0 ) { chkp_sno = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&chkp_sno_size); segment_offset+= chkp_sno_size; if((unsigned)(frame_offset + segment_offset) >= tvb_length(tvb)){ /* This would mean the data segment is incomplete */ return 0; } rpt_sno = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&rpt_sno_size); segment_offset+= rpt_sno_size; if((unsigned)(frame_offset + segment_offset) >= tvb_length(tvb)){ /* This would mean the data segment is incomplete */ return 0; } } /* Adding size of the data */ if ((segment_offset + (int)length < segment_offset) || (segment_offset + (int)length < (int)length)) { /* Addition result has wrapped */ return 0; } segment_offset+= (int)length; if ((segment_offset + frame_offset < segment_offset) || (segment_offset + frame_offset < frame_offset)) { /* Addition result has wrapped */ return 0; } if((unsigned)(frame_offset + segment_offset) > tvb_length(tvb)){ /* This would mean the data segment is incomplete */ return 0; } /* Create a subtree for data segment and add the other fields under it */ ltp_data_item = proto_tree_add_text(ltp_tree, tvb,frame_offset, segment_offset, "Data Segment"); ltp_data_tree = proto_item_add_subtree(ltp_data_item, ett_data_segm); proto_tree_add_uint64(ltp_data_tree,hf_ltp_data_clid, tvb, frame_offset,client_id_size,client_id); frame_offset += client_id_size; proto_tree_add_uint64(ltp_data_tree, hf_ltp_data_offset, tvb, frame_offset,offset_size, offset); frame_offset += offset_size; proto_tree_add_uint64(ltp_data_tree,hf_ltp_data_length, tvb, frame_offset,length_size,length); frame_offset += length_size; if(ltp_type != 0 ) { proto_tree_add_uint64(ltp_data_tree, hf_ltp_data_chkp, tvb, frame_offset,chkp_sno_size, chkp_sno); frame_offset += chkp_sno_size; proto_tree_add_uint64(ltp_data_tree, hf_ltp_data_rpt, tvb, frame_offset,rpt_sno_size, rpt_sno); frame_offset += rpt_sno_size; more_frags = FALSE; frag_msg = fragment_add_check(tvb, frame_offset, pinfo, (guint32)session_num, ltp_fragment_table, ltp_reassembled_table, (guint32)offset, (guint32)length, more_frags); } else { more_frags = TRUE; frag_msg = fragment_add_check(tvb, frame_offset, pinfo, (guint32)session_num, ltp_fragment_table, ltp_reassembled_table, (guint32)offset, (guint32)length, more_frags); } if(frag_msg) { /* Checking if the segment is completely reassembled */ if(!(frag_msg->flags & FD_PARTIAL_REASSEMBLY)) { /* if the segment has not been fragmented, then no reassembly is needed */ if(!more_frags && offset == 0) { new_tvb = tvb_new_subset(tvb,frame_offset,tvb_length(tvb)-frame_offset,-1); } else { new_tvb = process_reassembled_data(tvb, frame_offset, pinfo, "Reassembled LTP Segment", frag_msg, <p_frag_items,NULL, ltp_data_tree); } } } if(new_tvb) { data_length = tvb_length(new_tvb); while(dissected_data_size < data_length) { ltp_data_data_item = proto_tree_add_text(ltp_data_tree, tvb,frame_offset, 0, "Data[%d]",data_count); ltp_data_data_tree = proto_item_add_subtree(ltp_data_data_item, ett_data_data_segm); datatvb = tvb_new_subset(new_tvb, data_offset, (int)data_length - dissected_data_size, tvb_length(new_tvb)); bundle_size = dissect_complete_bundle(datatvb, pinfo, ltp_data_data_tree); if(bundle_size == 0) { /*Couldn't parse bundle*/ col_set_str(pinfo->cinfo, COL_INFO, "Dissection Failed"); return 0; /*Give up*/ } data_offset += bundle_size; dissected_data_size += bundle_size; data_count++; } } else { if(frag_msg && more_frags) { col_append_fstr(pinfo->cinfo, COL_INFO, "[Reassembled in %d] ",frag_msg->reassembled_in); } else { col_append_str(pinfo->cinfo, COL_INFO, "[Unfinished LTP Segment] "); } } return segment_offset; }
/* echo(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_cntl_echo, tvb, offset, 4, cntl->echo); return; } static void dissect_xtp_first(tvbuff_t *tvb, proto_tree *tree, guint32 offset) { if (!dissect_xtp_aseg(tvb, tree, offset)) return; offset += XTP_IP_ADDR_SEG_LEN; dissect_xtp_tspec(tvb, tree, offset); return; } #define XTP_MAX_NSPANS 10000 /* Arbitrary. (Documentation link is dead.) */ static void dissect_xtp_ecntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset) { guint32 len = tvb_length_remaining(tvb, offset); guint32 start = offset; proto_item *top_ti; proto_tree *xtp_subtree; struct xtp_ecntl ecntl[1]; guint spans_len; guint i; top_ti = proto_tree_add_text(tree, tvb, offset, len, "Error Control Segment"); xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_ecntl); if (len < MIN_XTP_ECNTL_PKT_LEN) { proto_item_append_text(top_ti, ", bogus length (%u, must be at least %u)", len, MIN_XTP_ECNTL_PKT_LEN); return; } /** parse **/ /* rseq(8) */ ecntl->rseq = tvb_get_ntohl(tvb, offset); ecntl->rseq <<= 32; ecntl->rseq += tvb_get_ntohl(tvb, offset+4); offset += 8; /* alloc(8) */ ecntl->alloc = tvb_get_ntohl(tvb, offset); ecntl->alloc <<= 32; ecntl->alloc += tvb_get_ntohl(tvb, offset+4); offset += 8; /* echo(4) */ ecntl->echo = tvb_get_ntohl(tvb, offset); offset += 4; /* nspan(4) */ ecntl->nspan = tvb_get_ntohl(tvb, offset); offset += 4; len = len + XTP_HEADER_LEN - offset; spans_len = 16 * ecntl->nspan; if (len != spans_len) { expert_add_info_format(pinfo, top_ti, &ei_xtp_spans_bad, "Number of spans (%u) incorrect. Should be %u.", ecntl->nspan, len); THROW(ReportedBoundsError); } if (ecntl->nspan > XTP_MAX_NSPANS) { expert_add_info_format(pinfo, top_ti, &ei_xtp_spans_bad, "Too many spans: %u", ecntl->nspan); THROW(ReportedBoundsError); } /** add summary **/ col_append_fstr(pinfo->cinfo, COL_INFO, " Recv-Seq=%" G_GINT64_MODIFIER "u", ecntl->rseq); col_append_fstr(pinfo->cinfo, COL_INFO, " Alloc=%" G_GINT64_MODIFIER "u", ecntl->alloc); proto_item_append_text(top_ti, ", Recv-Seq: %" G_GINT64_MODIFIER "u", ecntl->rseq); /** display **/ offset = start; /* rseq(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_rseq, tvb, offset, 8, ecntl->rseq); offset += 8; /* alloc(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_alloc, tvb, offset, 8, ecntl->alloc); offset += 8; /* echo(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_echo, tvb, offset, 4, ecntl->echo); offset += 4; /* nspan(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_nspan, tvb, offset, 4, ecntl->nspan); offset += 4; /* spans(16n) */ for (i = 0; i < ecntl->nspan; i++) { proto_tree_add_item(xtp_subtree, hf_xtp_ecntl_span_left, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; proto_tree_add_item(xtp_subtree, hf_xtp_ecntl_span_right, tvb, offset, 8, ENC_LITTLE_ENDIAN); offset += 8; } return; }
/* main dissector */ static int dissect_xtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { guint32 offset, len; proto_item *ti; proto_tree *xtp_tree, *xtp_cmd_tree, *xtp_subtree; struct xtphdr xtph[1]; int error = 0; gchar *options = "<None>"; const char *fstr[] = { "<None>", "NOCHECK", "EDGE", "NOERR", "MULTI", "RES", "SORT", "NOFLOW", "FASTNAK", "SREQ", "DREQ", "RCLOSE", "WCLOSE", "EOM", "END", "BTAG" }; gint fpos = 0, returned_length; guint i, bpos; guint cmd_options; vec_t cksum_vec[1]; guint16 computed_cksum; gboolean have_btag; if ((len = tvb_length(tvb)) < XTP_HEADER_LEN) return 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "XTP"); col_clear(pinfo->cinfo, COL_INFO); /** parse header **/ offset = 0; /* key(8) */ xtph->key = tvb_get_ntohl(tvb, offset); xtph->key <<= 32; xtph->key += tvb_get_ntohl(tvb, offset+4); offset += 8; /* cmd(4) */ xtph->cmd = tvb_get_ntohl(tvb, offset); xtph->cmd_options = xtph->cmd >> 8; xtph->cmd_ptype = xtph->cmd & 0xff; xtph->cmd_ptype_ver = (xtph->cmd_ptype & 0xe0) >> 5; xtph->cmd_ptype_pformat = xtph->cmd_ptype & 0x1f; offset += 4; /* dlen(4) */ xtph->dlen = tvb_get_ntohl(tvb, offset); offset += 4; /* check(2) */ xtph->check = tvb_get_ntohs(tvb, offset); offset += 2; /* sort(2) */ xtph->sort = tvb_get_ntohs(tvb, offset); offset += 2; /* sync(4) */ xtph->sync = tvb_get_ntohl(tvb, offset); offset += 4; /* seq(8) */ xtph->seq = tvb_get_ntohl(tvb, offset); xtph->seq <<= 32; xtph->seq += tvb_get_ntohl(tvb, offset+4); #define MAX_OPTIONS_LEN 128 options=ep_alloc(MAX_OPTIONS_LEN); options[0]=0; cmd_options = xtph->cmd_options >> 8; for (i = 0; i < 16; i++) { bpos = 1 << (15 - i); if (cmd_options & bpos) { returned_length = g_snprintf(&options[fpos], MAX_OPTIONS_LEN-fpos, "%s%s", fpos?", ":"", fstr[i]); fpos += MIN(returned_length, MAX_OPTIONS_LEN-fpos); } } if (check_col(pinfo->cinfo, COL_INFO)) { col_add_str(pinfo->cinfo, COL_INFO, val_to_str(xtph->cmd_ptype_pformat, pformat_vals, "Unknown pformat (%u)")); col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", options); col_append_fstr(pinfo->cinfo, COL_INFO, " Seq=%" G_GINT64_MODIFIER "u", xtph->seq); col_append_fstr(pinfo->cinfo, COL_INFO, " Len=%u", xtph->dlen); } if (tree) { ti = proto_tree_add_item(tree, proto_xtp, tvb, 0, -1, FALSE); /** add summary **/ proto_item_append_text(ti, ", Key: 0x%016" G_GINT64_MODIFIER "X", xtph->key); proto_item_append_text(ti, ", Seq: %" G_GINT64_MODIFIER "u", xtph->seq); proto_item_append_text(ti, ", Len: %u", xtph->dlen); xtp_tree = proto_item_add_subtree(ti, ett_xtp); /* key(8) */ offset = 0; ti = proto_tree_add_uint64(xtp_tree, hf_xtp_key, tvb, offset, 8, xtph->key); xtp_subtree = proto_item_add_subtree(ti, ett_xtp_key); offset += 8; /* cmd(4) */ ti = proto_tree_add_uint(xtp_tree, hf_xtp_cmd, tvb, offset, 4, xtph->cmd); xtp_cmd_tree = proto_item_add_subtree(ti, ett_xtp_cmd); ti = proto_tree_add_uint(xtp_cmd_tree, hf_xtp_cmd_options, tvb, offset, 3, xtph->cmd_options); /** add summary **/ proto_item_append_text(ti, " [%s]", options); xtp_subtree = proto_item_add_subtree(ti, ett_xtp_cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_nocheck, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_edge, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_noerr, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_multi, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_res, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_sort, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_noflow, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_fastnak, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_sreq, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_dreq, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_rclose, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_wclose, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_eom, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_end, tvb, offset, 3, xtph->cmd_options); proto_tree_add_boolean(xtp_subtree, hf_xtp_cmd_options_btag, tvb, offset, 3, xtph->cmd_options); offset += 3; ti = proto_tree_add_uint(xtp_cmd_tree, hf_xtp_cmd_ptype, tvb, offset, 1, xtph->cmd_ptype); xtp_subtree = proto_item_add_subtree(ti, ett_xtp_cmd_ptype); proto_tree_add_uint(xtp_subtree, hf_xtp_cmd_ptype_ver, tvb, offset, 1, xtph->cmd_ptype_ver); if (xtph->cmd_ptype_ver != XTP_VERSION_4) { proto_item_append_text(ti, ", Unknown XTP version (%03X)", xtph->cmd_ptype_ver); error = 1; } proto_tree_add_uint(xtp_subtree, hf_xtp_cmd_ptype_pformat, tvb, offset, 1, xtph->cmd_ptype_pformat); offset++; /* dlen(4) */ ti = proto_tree_add_uint(xtp_tree, hf_xtp_dlen, tvb, offset, 4, xtph->dlen); if (xtph->dlen != len - XTP_HEADER_LEN) { proto_item_append_text(ti, ", bogus length (%u, must be %u)", xtph->dlen, len - XTP_HEADER_LEN); error = 1; } offset += 4; /* check(2) */ if (!pinfo->fragmented) { guint32 check_len = XTP_HEADER_LEN; if (!(xtph->cmd_options & XTP_CMD_OPTIONS_NOCHECK)) check_len += xtph->dlen; cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, check_len); cksum_vec[0].len = check_len; computed_cksum = in_cksum(cksum_vec, 1); if (computed_cksum == 0) { proto_tree_add_text(xtp_tree, tvb, offset, 2, "Checksum: 0x%04x [correct]", xtph->check); } else { proto_tree_add_text(xtp_tree, tvb, offset, 2, "Checksum: 0x%04x [incorrect, should be 0x%04x]", xtph->check, in_cksum_shouldbe(xtph->check, computed_cksum)); } } else { proto_tree_add_text(xtp_tree, tvb, offset, 2, "Checksum: 0x%04x", xtph->check); } offset += 2; /* sort(2) */ proto_tree_add_uint(xtp_tree, hf_xtp_sort, tvb, offset, 2, xtph->sort); offset += 2; /* sync(4) */ proto_tree_add_uint(xtp_tree, hf_xtp_sync, tvb, offset, 4, xtph->sync); offset += 4; /* seq(8) */ proto_tree_add_uint64(xtp_tree, hf_xtp_seq, tvb, offset, 8, xtph->seq); offset += 8; if (!error) { switch (xtph->cmd_ptype_pformat) { case XTP_DATA_PKT: have_btag = !!(xtph->cmd_options & XTP_CMD_OPTIONS_BTAG); dissect_xtp_data(tvb, xtp_tree, offset, have_btag); break; case XTP_CNTL_PKT: dissect_xtp_cntl(tvb, pinfo, xtp_tree, offset); break; case XTP_FIRST_PKT: dissect_xtp_first(tvb, xtp_tree, offset); break; case XTP_ECNTL_PKT: dissect_xtp_ecntl(tvb, pinfo, xtp_tree, offset); break; case XTP_TCNTL_PKT: dissect_xtp_tcntl(tvb, pinfo, xtp_tree, offset); break; case XTP_JOIN_PKT: /* obsolete */ break; case XTP_JCNTL_PKT: dissect_xtp_jcntl(tvb, pinfo, xtp_tree, offset); break; case XTP_DIAG_PKT: dissect_xtp_diag(tvb, xtp_tree, offset); break; default: /* error */ break; } } } return tvb_length(tvb); }
static void dissect_xtp_ecntl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset) { guint32 len = tvb_length_remaining(tvb, offset); guint32 start = offset; proto_item *top_ti, *ti; proto_tree *xtp_subtree; struct xtp_ecntl ecntl[1]; guint64 *spans, *p; guint32 spans_len; guint i; top_ti = proto_tree_add_text(tree, tvb, offset, len, "Error Control Segment"); xtp_subtree = proto_item_add_subtree(top_ti, ett_xtp_ecntl); if (len < MIN_XTP_ECNTL_PKT_LEN) { proto_item_append_text(top_ti, ", bogus length (%u, must be at least %u)", len, MIN_XTP_ECNTL_PKT_LEN); return; } /** parse **/ /* rseq(8) */ ecntl->rseq = tvb_get_ntohl(tvb, offset); ecntl->rseq <<= 32; ecntl->rseq += tvb_get_ntohl(tvb, offset+4); offset += 8; /* alloc(8) */ ecntl->alloc = tvb_get_ntohl(tvb, offset); ecntl->alloc <<= 32; ecntl->alloc += tvb_get_ntohl(tvb, offset+4); offset += 8; /* echo(4) */ ecntl->echo = tvb_get_ntohl(tvb, offset); offset += 4; /* nspan(4) */ ecntl->nspan = tvb_get_ntohl(tvb, offset); offset += 4; len = len + XTP_HEADER_LEN - offset; spans_len = 16 * ecntl->nspan; if (len != spans_len) { proto_item_append_text(top_ti, ", bogus spans field length (%u, must be %u)", len, spans_len); return; } /* spans(16n) */ spans = ep_alloc0(spans_len); p = spans; for (i = 0; i < ecntl->nspan*2; i++) { guint64 span = tvb_get_ntohl(tvb, offset); span <<= 32; span += tvb_get_ntohl(tvb, offset+4); *p++ = span; offset += 8; } /** add summary **/ if (check_col(pinfo->cinfo, COL_INFO)) { col_append_fstr(pinfo->cinfo, COL_INFO, " Recv-Seq=%" G_GINT64_MODIFIER "u", ecntl->rseq); col_append_fstr(pinfo->cinfo, COL_INFO, " Alloc=%" G_GINT64_MODIFIER "u", ecntl->alloc); } proto_item_append_text(top_ti, ", Recv-Seq: %" G_GINT64_MODIFIER "u", ecntl->rseq); /** display **/ offset = start; /* rseq(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_rseq, tvb, offset, 8, ecntl->rseq); offset += 8; /* alloc(8) */ proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_alloc, tvb, offset, 8, ecntl->alloc); offset += 8; /* echo(4) */ proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_echo, tvb, offset, 4, ecntl->echo); offset += 4; /* nspan(4) */ ti = proto_tree_add_uint(xtp_subtree, hf_xtp_ecntl_nspan, tvb, offset, 4, ecntl->nspan); offset += 4; /* spans(16n) */ p = spans; for (i = 0; i < ecntl->nspan; i++) { proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_span_left, tvb, offset, 8, *p); p++; offset += 8; proto_tree_add_uint64(xtp_subtree, hf_xtp_ecntl_span_right, tvb, offset, 8, *p); p++; offset += 8; } return; }
/* Decode an EXT_FTI extension and fill FEC array */ void fec_decode_ext_fti(struct _ext *e, tvbuff_t *tvb, proto_tree *tree, gint ett, struct _fec_ptr f) { proto_item* ti = NULL; proto_tree *ext_tree; if (tree) ti = proto_tree_add_none_format(tree, f.hf->fti_header, tvb, e->offset, e->length, "EXT_FTI, FEC Object Transmission Information (%u)", e->het); if (f.fec->encoding_id_present) { ext_tree = proto_item_add_subtree(ti, ett); rmt_ext_decode_default_header(e, tvb, ext_tree); /* Decode 48-bit length field */ f.fec->transfer_length = tvb_get_ntoh64(tvb, e->offset) & G_GINT64_CONSTANT(0xFFFFFFFFFFFFU); if (f.fec->encoding_id >= 128) { /* Decode FEC Instance ID */ f.fec->instance_id_present = TRUE; f.fec->instance_id = (guint8) tvb_get_ntohs(tvb, e->offset+8); } if (tree) proto_tree_add_uint64(ext_tree, f.hf->fti_transfer_length, tvb, e->offset+2, 6, f.fec->transfer_length); switch (f.fec->encoding_id) { case 0: case 2: case 128: case 130: f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10); f.fec->max_source_block_length = tvb_get_ntohl(tvb, e->offset+12); if (tree) { proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length); proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 4, f.fec->max_source_block_length); } break; case 129: f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10); f.fec->max_source_block_length = tvb_get_ntohs(tvb, e->offset+12); f.fec->max_number_encoding_symbols = tvb_get_ntohs(tvb, e->offset+14); if (tree) { proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length); proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 2, f.fec->max_source_block_length); proto_tree_add_uint(ext_tree, f.hf->fti_max_number_encoding_symbols, tvb, e->offset+14, 2, f.fec->max_number_encoding_symbols); } break; case 132: f.fec->encoding_symbol_length = tvb_get_ntohs(tvb, e->offset+10); f.fec->max_source_block_length = tvb_get_ntohl(tvb, e->offset+12); f.fec->max_number_encoding_symbols = tvb_get_ntohl(tvb, e->offset+16); if (tree) { proto_tree_add_uint(ext_tree, f.hf->fti_encoding_symbol_length, tvb, e->offset+10, 2, f.fec->encoding_symbol_length); proto_tree_add_uint(ext_tree, f.hf->fti_max_source_block_length, tvb, e->offset+12, 4, f.fec->max_source_block_length); proto_tree_add_uint(ext_tree, f.hf->fti_max_number_encoding_symbols, tvb, e->offset+16, 4, f.fec->max_number_encoding_symbols); } break; } } else if (tree) rmt_ext_decode_default_subtree(e, tvb, ti, ett); }
static int dissect_dtpt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *dtpt_tree = NULL; proto_item *dtpt_item = NULL; guint8 version; guint8 message_type; guint32 flags; guint32 payload_size; version = tvb_get_guint8(tvb, 0); if (version != 1) return 0; message_type = tvb_get_guint8(tvb, 1); switch (message_type) { case LookupBeginRequest: case LookupBeginResponse: case LookupNextRequest: case LookupNextResponse: case LookupEndRequest: if (tvb_reported_length(tvb) != 20) return 0; break; case ConnectRequest: case ConnectResponseOK: case ConnectResponseERR: if (tvb_reported_length(tvb) != 36) return 0; break; default: return 0; } col_set_str(pinfo->cinfo, COL_PROTOCOL, "DTPT"); if (check_col(pinfo->cinfo, COL_INFO)) col_add_str(pinfo->cinfo, COL_INFO, val_to_str(message_type, names_message_type, "Unknown (%d)")); if (message_type == LookupBeginRequest) { conversation_t *c; c = find_or_create_conversation(pinfo); conversation_set_dissector(c, dtpt_conversation_handle); } if (tree) { dtpt_item = proto_tree_add_item(tree, proto_dtpt, tvb, 0, -1, ENC_NA); if (dtpt_item) dtpt_tree = proto_item_add_subtree(dtpt_item, ett_dtpt); } if (dtpt_tree) { proto_tree_add_uint(dtpt_tree, hf_dtpt_version, tvb, 0, 1, version); proto_tree_add_uint(dtpt_tree, hf_dtpt_message_type, tvb, 1, 1, message_type); switch (message_type) { case LookupBeginRequest: { proto_item* flags_item = NULL; proto_tree* flags_tree = NULL; flags = tvb_get_letohl(tvb, 12); flags_item = proto_tree_add_uint(dtpt_tree, hf_dtpt_flags, tvb, 12, 4, flags); if (flags_item) { flags_tree = proto_item_add_subtree(flags_item, ett_dtpt_flags); } if (flags_tree) { proto_tree_add_boolean(flags_tree, hf_dtpt_flags_res_service, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_flushprevious, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_flushcache, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_query_string, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_aliases, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_blob, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_addr, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_comment, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_version, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_type, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_return_name, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_nearest, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_nocontainers, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_containers, tvb, 12, 4, flags); proto_tree_add_boolean(flags_tree, hf_dtpt_flags_deep, tvb, 12, 4, flags); } payload_size = tvb_get_letohl(tvb, 16); proto_tree_add_uint(dtpt_tree, hf_dtpt_payload_size, tvb, 16, 4, payload_size); } break; case LookupBeginResponse: { proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle, tvb, 4, 8, tvb_get_letoh64(tvb, 4)); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 12, 4, tvb_get_letohl(tvb, 12)); } break; case LookupNextRequest: { proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle, tvb, 4, 8, tvb_get_letoh64(tvb, 4)); proto_tree_add_uint(dtpt_tree, hf_dtpt_buffer_size, tvb, 16, 4, tvb_get_letohl(tvb, 16)); } break; case LookupNextResponse: { proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 12, 4, tvb_get_letohl(tvb, 12)); proto_tree_add_uint(dtpt_tree, hf_dtpt_data_size, tvb, 16, 4, tvb_get_letohl(tvb, 16)); } break; case LookupEndRequest: { proto_tree_add_uint64(dtpt_tree, hf_dtpt_handle, tvb, 4, 8, tvb_get_letoh64(tvb, 4)); } break; case ConnectRequest: { dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 32, 4, tvb_get_letohl(tvb, 32)); } break; case ConnectResponseOK: { dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 32, 4, tvb_get_letohl(tvb, 32)); } break; case ConnectResponseERR: { dissect_dtpt_sockaddr(tvb, 2, dtpt_tree, hf_dtpt_connect_addr, SOCKADDR_CONNECT); proto_tree_add_uint(dtpt_tree, hf_dtpt_error, tvb, 32, 4, tvb_get_letohl(tvb, 32)); } break; } } return tvb_length(tvb); }
static int dissect_report_segment(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ltp_tree, int frame_offset) { guint64 rpt_sno; guint64 chkp_sno; guint64 upper_bound; guint64 lower_bound; int rcpt_clm_cnt; guint64 offset; guint64 length; int rpt_sno_size; int chkp_sno_size; int upper_bound_size; int lower_bound_size; int rcpt_clm_cnt_size; int offset_size; int length_size; int segment_offset = 0; int i; proto_item *ltp_rpt_item; proto_item *ltp_rpt_clm_item; proto_tree *ltp_rpt_tree; proto_tree *ltp_rpt_clm_tree; /* Create the subtree for report segment under the main LTP tree and all the report segment fields under it */ ltp_rpt_item = proto_tree_add_text(ltp_tree, tvb, frame_offset, -1, "Report Segment"); ltp_rpt_tree = proto_item_add_subtree(ltp_rpt_item, ett_rpt_segm); /* Extract the report segment info */ rpt_sno = evaluate_sdnv_64(tvb, frame_offset, &rpt_sno_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_sno, tvb, frame_offset + segment_offset, rpt_sno_size, rpt_sno); segment_offset += rpt_sno_size; chkp_sno = evaluate_sdnv_64(tvb, frame_offset + segment_offset, &chkp_sno_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_chkp, tvb, frame_offset + segment_offset, chkp_sno_size, chkp_sno); segment_offset += chkp_sno_size; upper_bound = evaluate_sdnv(tvb, frame_offset + segment_offset, &upper_bound_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_ub, tvb, frame_offset + segment_offset, upper_bound_size, upper_bound); segment_offset += upper_bound_size; lower_bound = evaluate_sdnv(tvb, frame_offset + segment_offset, &lower_bound_size); proto_tree_add_uint64(ltp_rpt_tree, hf_ltp_rpt_lb, tvb, frame_offset + segment_offset, lower_bound_size, lower_bound); segment_offset += lower_bound_size; rcpt_clm_cnt = evaluate_sdnv(tvb, frame_offset + segment_offset, &rcpt_clm_cnt_size); if (rcpt_clm_cnt < 0){ proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset); expert_add_info_format(pinfo, ltp_tree, PI_UNDECODED, PI_ERROR, "Negative reception claim count: %d", rcpt_clm_cnt); return 0; } /* Each reception claim is at least 2 bytes, so if the count is larger than the * max number of claims we can possibly squeeze into the remaining tvbuff, then * the packet is malformed. */ if (rcpt_clm_cnt > tvb_length_remaining(tvb, frame_offset + segment_offset) / 2) { proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset); expert_add_info_format(pinfo, ltp_tree, PI_MALFORMED, PI_ERROR, "Reception claim count impossibly large: %d > %d", rcpt_clm_cnt, tvb_length_remaining(tvb, frame_offset + segment_offset) / 2); return 0; } proto_tree_add_uint(ltp_rpt_tree, hf_ltp_rpt_clm_cnt, tvb, frame_offset + segment_offset, rcpt_clm_cnt_size, rcpt_clm_cnt); segment_offset += rcpt_clm_cnt_size; ltp_rpt_clm_item = proto_tree_add_text(ltp_rpt_tree, tvb, frame_offset + segment_offset, -1, "Reception claims"); ltp_rpt_clm_tree = proto_item_add_subtree(ltp_rpt_clm_item, ett_rpt_clm); /* There can be multiple reception claims in the same report segment */ for(i = 0; i<rcpt_clm_cnt; i++){ offset = evaluate_sdnv(tvb,frame_offset + segment_offset, &offset_size); proto_tree_add_uint64_format(ltp_rpt_clm_tree, hf_ltp_rpt_clm_off, tvb, frame_offset + segment_offset, offset_size, offset, "Offset[%d] : %"G_GINT64_MODIFIER"d", i, offset); segment_offset += offset_size; length = evaluate_sdnv(tvb,frame_offset + segment_offset, &length_size); proto_tree_add_uint64_format(ltp_rpt_clm_tree, hf_ltp_rpt_clm_len, tvb, frame_offset + segment_offset, length_size, length, "Length[%d] : %"G_GINT64_MODIFIER"d",i, length); segment_offset += length_size; } proto_item_set_end(ltp_rpt_clm_item, tvb, frame_offset + segment_offset); proto_item_set_end(ltp_rpt_item, tvb, frame_offset + segment_offset); return segment_offset; }
/* The dissector itself */ static void dissect_chdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { // Here are all the variables proto_item *item; proto_item *stream_item; proto_tree *chdr_tree; proto_item *header_item; proto_tree *header_tree; proto_tree *stream_tree; proto_item *response_item; proto_tree *response_tree; proto_item *cmd_item; proto_tree *cmd_tree; gint len; gint flag_offset; guint8 *bytes; guint8 hdr_bits = 0; guint8 pkt_type = 0; gboolean flag_has_time = 0; gboolean flag_is_data = 0; gboolean flag_is_fc = 0; gboolean flag_is_cmd = 0; gboolean flag_is_resp = 0; gboolean flag_is_eob = 0; gboolean flag_is_error = 0; unsigned long long timestamp; gboolean is_network; gint endianness; gint id_pos_usb[4] = {7, 6, 5, 4}; gint id_pos_net[4] = {4, 5, 6, 7}; gint id_pos[4] = {7, 6, 5, 4}; if(pinfo->match_uint == CHDR_PORT){ is_network = TRUE; flag_offset = 0; endianness = ENC_BIG_ENDIAN; memcpy(id_pos, id_pos_net, 4 * sizeof(gint)); } else{ // Parsing a USB capture is_network = FALSE; flag_offset = 3; endianness = ENC_LITTLE_ENDIAN; memcpy(id_pos, id_pos_usb, 4 * sizeof(gint)); } len = tvb_reported_length(tvb); col_append_str(pinfo->cinfo, COL_PROTOCOL, "/CHDR"); /* This throws a warning: */ /*col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "CHDR", tvb_format_text_wsp(tvb, 0, len));*/ col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "CHDR"); if (tree){ int chdr_size = -1; if (len >= 4){ chdr_size = 8; bytes = tvb_get_string(wmem_packet_scope(), tvb, 0, 4); hdr_bits = (bytes[flag_offset] & 0xF0) >> 4; pkt_type = hdr_bits >> 2; flag_is_data = (pkt_type == 0); flag_is_fc = (pkt_type == 1); flag_is_cmd = (pkt_type == 2); flag_is_resp = (pkt_type == 3); flag_is_eob = flag_is_data && (hdr_bits & 0x1); flag_is_error = flag_is_resp && (hdr_bits & 0x1); flag_has_time = hdr_bits & 0x2; if (flag_has_time) chdr_size += 8; // 64-bit timestamp } /* Start with a top-level item to add everything else to */ item = proto_tree_add_item(tree, proto_chdr, tvb, 0, min(len, chdr_size), ENC_NA); if (len >= 4) { chdr_tree = proto_item_add_subtree(item, ett_chdr); /* Header info. First, a top-level header tree item: */ header_item = proto_tree_add_item(chdr_tree, hf_chdr_hdr, tvb, flag_offset, 1, endianness); header_tree = proto_item_add_subtree(header_item, ett_chdr_header); proto_item_append_text(header_item, ", Packet type: %s", val_to_str(hdr_bits & 0xD, CHDR_PACKET_TYPES, "Unknown (0x%x)") ); /* Let us query hdr.type */ proto_tree_add_string( header_tree, hf_chdr_type, tvb, flag_offset, 1, val_to_str(hdr_bits & 0xD, CHDR_PACKET_TYPES_SHORT, "invalid") ); /* And other flags */ proto_tree_add_boolean(header_tree, hf_chdr_has_time, tvb, flag_offset, 1, flag_has_time); if (flag_is_data) { proto_tree_add_boolean(header_tree, hf_chdr_eob, tvb, flag_offset, 1, flag_is_eob); } if (flag_is_resp) { proto_tree_add_boolean(header_tree, hf_chdr_error, tvb, flag_offset, 1, flag_is_error); } /* These lines add sequence, packet_size and stream ID */ proto_tree_add_item(chdr_tree, hf_chdr_sequence, tvb, (is_network ? 0:2), 2, endianness); proto_tree_add_item(chdr_tree, hf_chdr_packet_size, tvb, (is_network ? 2:0), 2, endianness); if (len >= 8){ /* stream id can be broken down to 4 sections. these are collapsed in a subtree */ stream_item = proto_tree_add_item(chdr_tree, hf_chdr_stream_id, tvb, 4, 4, endianness); stream_tree = proto_item_add_subtree(stream_item, ett_chdr_id); proto_tree_add_item(stream_tree, hf_chdr_src_dev, tvb, id_pos[0], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_src_ep, tvb, id_pos[1], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_dst_dev, tvb, id_pos[2], 1, ENC_NA); proto_tree_add_item(stream_tree, hf_chdr_dst_ep, tvb, id_pos[3], 1, ENC_NA); /* Block ports (only add them if address points to a device) */ bytes = tvb_get_string(wmem_packet_scope(), tvb, 0, 8); if (bytes[id_pos[0]] != 0) { proto_tree_add_item(stream_tree, hf_chdr_src_blockport, tvb, id_pos[1], 1, ENC_NA); } if (bytes[id_pos[2]] != 0) { proto_tree_add_item(stream_tree, hf_chdr_dst_blockport, tvb, id_pos[3], 1, ENC_NA); } /* Append SID in sid_t hex format */ proto_item_append_text(stream_item, " (%02X:%02X>%02X:%02X)", bytes[id_pos[0]], bytes[id_pos[1]], bytes[id_pos[2]], bytes[id_pos[3]] ); /* if has_time flag is present interpret timestamp */ if ((flag_has_time) && (len >= 16)){ if (is_network) item = proto_tree_add_item(chdr_tree, hf_chdr_timestamp, tvb, 8, 8, endianness); else{ bytes = (guint8*) tvb_get_string(wmem_packet_scope(), tvb, 8, sizeof(unsigned long long)); timestamp = get_timestamp(bytes, sizeof(unsigned long long)); proto_tree_add_uint64(chdr_tree, hf_chdr_timestamp, tvb, 8, 8, timestamp); } } int remaining_bytes = (len - chdr_size); int show_raw_payload = (remaining_bytes > 0); if (flag_is_cmd && remaining_bytes == 8) { cmd_item = proto_tree_add_item(chdr_tree, hf_chdr_cmd, tvb, chdr_size, 8, endianness); cmd_tree = proto_item_add_subtree(cmd_item, ett_chdr_cmd); proto_tree_add_item(cmd_tree, hf_chdr_cmd_address, tvb, chdr_size, 4, endianness); proto_tree_add_item(cmd_tree, hf_chdr_cmd_value, tvb, chdr_size + 4, 4, endianness); } else if (flag_is_resp) { response_item = proto_tree_add_item(chdr_tree, hf_chdr_ext_response, tvb, chdr_size, 8, endianness); response_tree = proto_item_add_subtree(response_item, ett_chdr_response); proto_tree_add_item(response_tree, hf_chdr_ext_status_code, tvb, chdr_size, 4, endianness); /* This will show the 12-bits of sequence ID in the last 2 bytes */ proto_tree_add_item(response_tree, hf_chdr_ext_seq_num, tvb, (chdr_size + 4 + (is_network ? 2 : 0)), 2, endianness); } else if (show_raw_payload) { proto_tree_add_item(chdr_tree, hf_chdr_payload, tvb, chdr_size, -1, ENC_NA); } } } }
static int dissect_ltp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_item *ti = NULL; proto_tree *ltp_tree = NULL; int frame_offset; int header_offset; int segment_offset = 0; int hdr_extn_offset = 0; int trl_extn_offset = 0; guint8 ltp_hdr; gint ltp_type; guint8 ltp_extn_cnt; gint hdr_extn_cnt; gint trl_extn_cnt; guint64 engine_id; guint64 session_num; int engine_id_size; int session_num_size; proto_item *ltp_header_item = NULL; proto_item *ltp_session_item = NULL; proto_tree *ltp_header_tree = NULL; proto_tree *ltp_session_tree = NULL; /* Check that there's enough data */ if(tvb_length(tvb) < LTP_MIN_DATA_BUFFER){ return 0; } frame_offset = 0; header_offset = 0; col_set_str(pinfo->cinfo, COL_PROTOCOL, "LTP Segment"); /* Extract all the header info from the packet */ ltp_hdr = tvb_get_guint8(tvb, frame_offset); header_offset++; engine_id = evaluate_sdnv_64(tvb,frame_offset + header_offset,&engine_id_size); header_offset += engine_id_size; if((unsigned)header_offset >= tvb_length(tvb)){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } session_num = evaluate_sdnv_64(tvb,frame_offset + header_offset,&session_num_size); header_offset += session_num_size; if((unsigned)header_offset >= tvb_length(tvb)){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } ti = proto_tree_add_item(tree, proto_ltp, tvb, 0, -1, ENC_NA); ltp_tree = proto_item_add_subtree(ti, ett_ltp); /* Adding Header Subtree */ ltp_header_item = proto_tree_add_text(ltp_tree, tvb, frame_offset, header_offset+1, "LTP Header"); ltp_header_tree = proto_item_add_subtree(ltp_header_item, ett_ltp_hdr); proto_tree_add_uint(ltp_header_tree,hf_ltp_version,tvb,frame_offset,1,hi_nibble(ltp_hdr)); ltp_type = lo_nibble(ltp_hdr); proto_tree_add_uint_format_value(ltp_header_tree,hf_ltp_type,tvb,frame_offset,1,ltp_type,"%x (%s)", ltp_type,val_to_str(ltp_type,ltp_type_codes,"Invalid")); frame_offset++; /* Adding the session id subtree */ ltp_session_item = proto_tree_add_item(ltp_header_item,hf_ltp_session_id,tvb,frame_offset, engine_id_size + session_num_size,ENC_NA); ltp_session_tree = proto_item_add_subtree(ltp_session_item,ett_hdr_session); proto_tree_add_uint64(ltp_session_tree,hf_ltp_session_orig,tvb,frame_offset,engine_id_size,engine_id); frame_offset+=engine_id_size; proto_tree_add_uint64(ltp_session_tree,hf_ltp_session_no, tvb, frame_offset,session_num_size,session_num); frame_offset+=session_num_size; /* Adding Extension count to the header tree */ ltp_extn_cnt = tvb_get_guint8(tvb,frame_offset); hdr_extn_cnt = hi_nibble(ltp_extn_cnt); trl_extn_cnt = lo_nibble(ltp_extn_cnt); proto_tree_add_uint(ltp_header_tree,hf_ltp_hdr_extn_cnt,tvb,frame_offset,1,hdr_extn_cnt); proto_tree_add_uint(ltp_header_tree,hf_ltp_trl_extn_cnt,tvb,frame_offset,1,trl_extn_cnt); frame_offset++; col_add_str(pinfo->cinfo, COL_INFO, val_to_str_const(ltp_type,ltp_type_col_info,"Protocol Error")); if((unsigned)frame_offset >= tvb_length(tvb)){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } /* Check if there are any header extensions */ if(hdr_extn_cnt > 0){ hdr_extn_offset = dissect_header_extn(ltp_tree, tvb, frame_offset,hdr_extn_cnt); if(hdr_extn_offset == 0){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } frame_offset += hdr_extn_offset; } if((unsigned)frame_offset >= tvb_length(tvb)){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } /* Call sub routines to handle the segment content*/ if((ltp_type >= 0) && (ltp_type < 8)){ segment_offset = dissect_data_segment(ltp_tree,tvb,pinfo,frame_offset,ltp_type,session_num); if(segment_offset == 0){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } } else if(ltp_type == 8){ segment_offset = dissect_report_segment(tvb, pinfo, ltp_tree,frame_offset); if(segment_offset == 0){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } } else if(ltp_type == 9){ segment_offset = dissect_report_ack_segment(ltp_tree,tvb,frame_offset); if(segment_offset == 0){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } } else if(ltp_type == 12 || ltp_type == 14){ segment_offset = dissect_cancel_segment(ltp_tree,tvb,frame_offset); if(segment_offset == 0){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } } frame_offset += segment_offset; /* Check to see if there are any trailer extensions */ if(trl_extn_cnt > 0){ if((unsigned)frame_offset >= tvb_length(tvb)){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } trl_extn_offset = dissect_trailer_extn(ltp_tree, tvb, frame_offset,trl_extn_cnt); if(trl_extn_offset == 0){ col_set_str(pinfo->cinfo, COL_INFO, "Protocol Error"); return 0; } } /* Return the amount of data this dissector was able to dissect */ return tvb_length(tvb); }
/* Transfers happen in response to broadcasts, they are always TCP and are * used to send the file to the port mentioned in the broadcast. There are * 2 types of transfers: Pushes, which are direct responses to searches, * in which the peer that has the file connects to the peer that doesn't and * sends it, then disconnects. The other type of transfer is a pull, where * the peer that doesn't have the file connects to the peer that does and * requests it be sent. * * Pulls have a file request which identifies the desired file, * while pushes simply send the file. In practice this works because every * file the implementation sends searches for is on a different TCP port * on the searcher's machine. */ static int dissect_ldss_transfer (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { conversation_t *transfer_conv; ldss_transfer_info_t *transfer_info; struct tcpinfo *transfer_tcpinfo; proto_tree *ti, *line_tree = NULL, *ldss_tree = NULL; nstime_t broadcast_response_time; /* Reject the packet if data is NULL */ if (data == NULL) return 0; transfer_tcpinfo = (struct tcpinfo *)data; col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDSS"); /* Look for the transfer conversation; this was created during * earlier broadcast dissection (see prepare_ldss_transfer_conv) */ transfer_conv = find_conversation (pinfo->num, &pinfo->src, &pinfo->dst, PT_TCP, pinfo->srcport, pinfo->destport, 0); transfer_info = (ldss_transfer_info_t *)conversation_get_proto_data(transfer_conv, proto_ldss); /* For a pull, the first packet in the TCP connection is the file request. * First packet is identified by relative seq/ack numbers of 1. * File request only appears on a pull (triggered by an offer - see above * about broadcasts) */ if (transfer_tcpinfo->seq == 1 && transfer_tcpinfo->lastackseq == 1 && transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND) { /* LDSS pull transfers look a lot like HTTP. * Sample request: * md5:01234567890123... * Size: 2550 * Start: 0 * Compression: 0 * (remote end sends the file identified by the digest) */ guint offset = 0; gboolean already_dissected = TRUE; col_set_str(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Requesting file - pull)"); if (highest_num_seen == 0 || highest_num_seen < pinfo->num) { already_dissected = FALSE; transfer_info->req = wmem_new0(wmem_file_scope(), ldss_file_request_t); transfer_info->req->file = wmem_new0(wmem_file_scope(), ldss_file_t); highest_num_seen = pinfo->num; } if (tree) { ti = proto_tree_add_item(tree, proto_ldss, tvb, 0, tvb_reported_length(tvb), ENC_NA); ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer); } /* Populate digest data into the file struct in the request */ transfer_info->file = transfer_info->req->file; /* Grab each line from the packet, there should be 4 but lets * not walk off the end looking for more. */ while (tvb_offset_exists(tvb, offset)) { gint next_offset; const guint8 *line; int linelen; gboolean is_digest_line; guint digest_type_len; linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); /* Include new-line in line */ line = (guint8 *)tvb_memdup(NULL, tvb, offset, linelen+1); /* XXX - memory leak? */ line_tree = proto_tree_add_subtree(ldss_tree, tvb, offset, linelen, ett_ldss_transfer_req, NULL, tvb_format_text(tvb, offset, next_offset-offset)); /* Reduce code duplication processing digest lines. * There are too many locals to pass to a function - the signature * looked pretty ugly when I tried! */ is_digest_line = FALSE; if (strncmp(line,"md5:",4)==0) { is_digest_line = TRUE; digest_type_len = 4; transfer_info->file->digest_type = DIGEST_TYPE_MD5; } else if (strncmp(line, "sha1:", 5)==0) { is_digest_line = TRUE; digest_type_len = 5; transfer_info->file->digest_type = DIGEST_TYPE_SHA1; } else if (strncmp(line, "sha256:", 7)==0) { is_digest_line = TRUE; digest_type_len = 7; transfer_info->file->digest_type = DIGEST_TYPE_SHA256; } else if (strncmp(line, "unknown:", 8)==0) { is_digest_line = TRUE; digest_type_len = 8; transfer_info->file->digest_type = DIGEST_TYPE_UNKNOWN; } else if (strncmp(line, "Size: ", 6)==0) { /* Sample size line: * Size: 2550\n */ transfer_info->req->size = g_ascii_strtoull(line+6, NULL, 10); if (tree) { ti = proto_tree_add_uint64(line_tree, hf_ldss_size, tvb, offset+6, linelen-6, transfer_info->req->size); PROTO_ITEM_SET_GENERATED(ti); } } else if (strncmp(line, "Start: ", 7)==0) { /* Sample offset line: * Start: 0\n */ transfer_info->req->offset = g_ascii_strtoull(line+7, NULL, 10); if (tree) { ti = proto_tree_add_uint64(line_tree, hf_ldss_offset, tvb, offset+7, linelen-7, transfer_info->req->offset); PROTO_ITEM_SET_GENERATED(ti); } } else if (strncmp(line, "Compression: ", 13)==0) { /* Sample compression line: * Compression: 0\n */ transfer_info->req->compression = (gint8)strtol(line+13, NULL, 10); /* XXX - bad cast */ if (tree) { ti = proto_tree_add_uint(line_tree, hf_ldss_compression, tvb, offset+13, linelen-13, transfer_info->req->compression); PROTO_ITEM_SET_GENERATED(ti); } } else { proto_tree_add_expert(line_tree, pinfo, &ei_ldss_unrecognized_line, tvb, offset, linelen); } if (is_digest_line) { /* Sample digest-type/digest line: * md5:0123456789ABCDEF\n */ if (!already_dissected) { GByteArray *digest_bytes; digest_bytes = g_byte_array_new(); hex_str_to_bytes( tvb_get_ptr(tvb, offset+digest_type_len, linelen-digest_type_len), digest_bytes, FALSE); if(digest_bytes->len >= DIGEST_LEN) digest_bytes->len = (DIGEST_LEN-1); /* Ensure the digest is zero-padded */ transfer_info->file->digest = (guint8 *)wmem_alloc0(wmem_file_scope(), DIGEST_LEN); memcpy(transfer_info->file->digest, digest_bytes->data, digest_bytes->len); g_byte_array_free(digest_bytes, TRUE); } if (tree) { proto_item *tii = NULL; tii = proto_tree_add_uint(line_tree, hf_ldss_digest_type, tvb, offset, digest_type_len, transfer_info->file->digest_type); PROTO_ITEM_SET_GENERATED(tii); tii = proto_tree_add_bytes(line_tree, hf_ldss_digest, tvb, offset+digest_type_len, MIN(linelen-digest_type_len, DIGEST_LEN), transfer_info->file->digest); PROTO_ITEM_SET_GENERATED(tii); } } offset = next_offset; } /* Link forwards to the response for this pull. */ if (tree && transfer_info->resp_num != 0) { ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_in, tvb, 0, 0, transfer_info->resp_num); PROTO_ITEM_SET_GENERATED(ti); } transfer_info->req->num = pinfo->num; transfer_info->req->ts = pinfo->abs_ts; } /* Remaining packets are the file response */ else { guint64 size; guint64 offset; guint8 compression; /* size, digest, compression come from the file request for a pull but * they come from the broadcast for a push. Pushes don't bother * with a file request - they just send the data. We have to get file * info from the offer broadcast which triggered this transfer. * If we cannot find the file request, default to the broadcast. */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL) { transfer_info->file = transfer_info->req->file; size = transfer_info->req->size; offset = transfer_info->req->offset; compression = transfer_info->req->compression; } else { transfer_info->file = transfer_info->broadcast->file; size = transfer_info->broadcast->size; offset = transfer_info->broadcast->offset; compression = transfer_info->broadcast->compression; } /* Remaining data in this TCP connection is all file data. * Always desegment if the size is 0 (ie. unknown) */ if (pinfo->can_desegment) { if (size == 0 || tvb_captured_length(tvb) < size) { pinfo->desegment_offset = 0; pinfo->desegment_len = DESEGMENT_UNTIL_FIN; return 0; } } /* OK. Now we have the whole file that was transferred. */ transfer_info->resp_num = pinfo->num; transfer_info->resp_ts = pinfo->abs_ts; col_add_fstr(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Sending file - %s)", transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND ? "pull" : "push"); if (tree) { ti = proto_tree_add_item(tree, proto_ldss, tvb, 0, tvb_reported_length(tvb), ENC_NA); ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer); proto_tree_add_bytes_format(ldss_tree, hf_ldss_file_data, tvb, 0, tvb_captured_length(tvb), NULL, compression == COMPRESSION_GZIP ? "Gzip compressed data: %d bytes" : "File data: %d bytes", tvb_captured_length(tvb)); #ifdef HAVE_ZLIB /* Be nice and uncompress the file data. */ if (compression == COMPRESSION_GZIP) { tvbuff_t *uncomp_tvb; uncomp_tvb = tvb_child_uncompress(tvb, tvb, 0, tvb_captured_length(tvb)); if (uncomp_tvb != NULL) { /* XXX: Maybe not a good idea to add a data_source for what may very well be a large buffer since then the full uncompressed buffer will be shown in a tab in the hex bytes pane ? However, if we don't, bytes in an unrelated tab will be highlighted. */ add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Data"); proto_tree_add_bytes_format_value(ldss_tree, hf_ldss_file_data, uncomp_tvb, 0, tvb_captured_length(uncomp_tvb), NULL, "Uncompressed data: %d bytes", tvb_captured_length(uncomp_tvb)); } } #endif ti = proto_tree_add_uint(ldss_tree, hf_ldss_digest_type, tvb, 0, 0, transfer_info->file->digest_type); PROTO_ITEM_SET_GENERATED(ti); if (transfer_info->file->digest != NULL) { /* This is ugly. You can't add bytes of nonzero length and have * filtering work correctly unless you give a valid location in * the packet. This hack pretends the first 32 bytes of the packet * are the digest, which they aren't: they're actually the first 32 * bytes of the file that was sent. */ ti = proto_tree_add_bytes(ldss_tree, hf_ldss_digest, tvb, 0, DIGEST_LEN, transfer_info->file->digest); } PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint64(ldss_tree, hf_ldss_size, tvb, 0, 0, size); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint64(ldss_tree, hf_ldss_offset, tvb, 0, 0, offset); PROTO_ITEM_SET_GENERATED(ti); ti = proto_tree_add_uint(ldss_tree, hf_ldss_compression, tvb, 0, 0, compression); PROTO_ITEM_SET_GENERATED(ti); /* Link to the request for a pull. */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL && transfer_info->req->num != 0) { ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_to, tvb, 0, 0, transfer_info->req->num); PROTO_ITEM_SET_GENERATED(ti); } } } /* Print the pull response time */ if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND && transfer_info->req != NULL && transfer_info->resp_num != 0) { nstime_t pull_response_time; nstime_delta(&pull_response_time, &transfer_info->resp_ts, &transfer_info->req->ts); ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_response_time, tvb, 0, 0, &pull_response_time); PROTO_ITEM_SET_GENERATED(ti); } /* Link the transfer back to the initiating broadcast. Response time is * calculated as the time from broadcast to completed transfer. */ ti = proto_tree_add_uint(ldss_tree, hf_ldss_initiated_by, tvb, 0, 0, transfer_info->broadcast->num); PROTO_ITEM_SET_GENERATED(ti); if (transfer_info->resp_num != 0) { nstime_delta(&broadcast_response_time, &transfer_info->resp_ts, &transfer_info->broadcast->ts); ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_completed_in, tvb, 0, 0, &broadcast_response_time); PROTO_ITEM_SET_GENERATED(ti); } /* This conv got its addr2/port2 set by the TCP dissector because a TCP * connection was established. Make a new one to handle future connections * to the addr/port mentioned in the broadcast, because that socket is * still open. */ if (transfer_tcpinfo->seq == 1 && transfer_tcpinfo->lastackseq == 1) { prepare_ldss_transfer_conv(transfer_info->broadcast); } return tvb_captured_length(tvb); }