コード例 #1
0
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;
}
コード例 #2
0
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;
}
コード例 #3
0
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;
}
コード例 #4
0
ファイル: packet-ltp.c プロジェクト: HeartFlying/wireshark
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;
}
コード例 #5
0
ファイル: packet-xtp.c プロジェクト: pvons/wireshark
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;
}
コード例 #6
0
/* 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;
}
コード例 #7
0
    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;
    }
コード例 #8
0
ファイル: packet-ltp.c プロジェクト: HeartFlying/wireshark
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;
}
コード例 #9
0
ファイル: packet-wtls.c プロジェクト: P1sec/LTE_monitor_c2xx
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;
}
コード例 #10
0
    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;
            }
        }
    }
コード例 #11
0
ファイル: packet-xtp.c プロジェクト: pvons/wireshark
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);
}
コード例 #12
0
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;
}
コード例 #13
0
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);

}
コード例 #14
0
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);
}
コード例 #15
0
/* 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;
    }
}
コード例 #16
0
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, &ltp_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;
}
コード例 #17
0
ファイル: packet-xtp.c プロジェクト: pvons/wireshark
	/* 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;
}
コード例 #18
0
/* 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);
}
コード例 #19
0
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;
}
コード例 #20
0
/* 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);
}
コード例 #21
0
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);
}
コード例 #22
0
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;
}
コード例 #23
0
/* 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);
                }
            }
        }
    }
コード例 #24
0
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);
}
コード例 #25
0
ファイル: packet-ldss.c プロジェクト: glocklueng/wireshark
/* 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);
}