Example #1
0
static void uadecode(e_ua_direction  direction,
                     proto_tree     *tree,
                     packet_info    *pinfo,
                     tvbuff_t       *tvb,
                     gint            offset,
                     gint            opcode,
                     gint            length)
{
    switch (opcode & 0x7f) /* suppression of the CP bit */
    {
    case 0x15:
    case 0x16:
        {
            call_dissector(noe_handle,
                           tvb_new_subset(tvb, offset, length, length),
                           pinfo,
                           tree);
            break;
        }
    case 0x00:
    case 0x01:
    case 0x02:
    case 0x03:
    case 0x04:
    case 0x05:
    case 0x06:
    case 0x07:  /* Only UA NOE */
    case 0x08:  /* Only UA NOE */
    case 0x09:
    case 0x0A:
    case 0x0B:
    case 0x0C:
    case 0x0D:
    case 0x0E:
    case 0x0F:
    case 0x11:
    case 0x12:
    case 0x13:
    case 0x14:
    case 0x17:
    case 0x18:
    case 0x1F:  /* case 0x9F */
    case 0x20:
    case 0x21:
    case 0x22:
    case 0x23:
    case 0x24:  /* Only IP NOE */
    case 0x25:  /* Only IP NOE */
    case 0x26:
    case 0x27:
    case 0x28:
    case 0x29:
    case 0x2A:
    case 0x2B:  /* Only UA NOE */
    case 0x2C:
    case 0x2D:
    case 0x2E:
    case 0x30:
    case 0x31:
    case 0x32:  /* Only UA NOE */
    case 0x33:
    case 0x35:
    case 0x36:  /* IP Phone */
    case 0x38:
    case 0x39:
    case 0x3A:
    case 0x3B:
    case 0x3C:
    case 0x3D:
    case 0x3E:
    case 0x3F:
    case 0x40:
    case 0x41:
    case 0x42:
    case 0x43:
    case 0x44:
    case 0x45:
    case 0x46:
    case 0x47:
    case 0x48:
    case 0x49:
    case 0x4A:
    case 0x4B:
    case 0x4C:
    case 0x4D:
    case 0x4E:
    case 0x4F:
    case 0x50:  /* Only UA NOE */
        {
            call_dissector_with_data(ua3g_handle,
                       tvb_new_subset(tvb, offset, length, length),
                       pinfo,
                       tree, &direction);
            break;
        }
    default:
        {
            /* add text to the frame "INFO" column */
            col_append_str(pinfo->cinfo, COL_INFO, " - UA3G Message ERR: Opcode Unknown");

            proto_tree_add_text(tree,
                tvb,
                offset,
                length,
                "Opcode Unknown 0x%02x",
                tvb_get_guint8(tvb, (offset + 2)));
            break;
        }
    }
}
Example #2
0
static
void dissect_pw_cesopsn( tvbuff_t * tvb_original
						,packet_info * pinfo
						,proto_tree * tree
						,pwc_demux_type_t demux)
{
	const int encaps_size = 4; /*RTP header in encapsulation is not supported yet*/
	gint      packet_size;
	gint      payload_size;
	gint      padding_size;
	int properties;

	packet_size = tvb_reported_length_remaining(tvb_original, 0);

	/*
	 * FIXME
	 * "4" below should be replaced by something like "min_packet_size_this_dissector"
	 * Also call to dissect_try_cw_first_nibble() should be moved before this block
	 */
	if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */
	{
		proto_item  *item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		expert_add_info_format(pinfo, item, &ei_packet_size_too_small,
				       "PW packet size (%d) is too small to carry sensible information"
				       ,(int)packet_size);
		col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
		col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
		return;
	}

	switch (demux)
	{
	case PWC_DEMUX_MPLS:
		if (dissect_try_cw_first_nibble(tvb_original, pinfo, tree))
		{
			return;
		}
		break;
	case PWC_DEMUX_UDP:
		break;
	default:
		DISSECTOR_ASSERT_NOT_REACHED();
		return;
	}

	/* check how "good" is this packet */
	/* also decide payload length from packet size and CW */
	properties = PWC_PACKET_PROPERTIES_T_INITIALIZER;
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/))
	{
		properties |= PWC_CW_BAD_BITS03;
	}
	if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/))
	{
		properties |= PWC_CW_BAD_FRAG;
	}
	{
		/* RFC5086:
		 * [LEN (bits (10 to 15) MAY be used to carry the length of the CESoPSN
		 * packet (defined as the size of the CESoPSN header + the payload size)
		 * if it is less than 64 bytes, and MUST be set to zero otherwise.
		 * Note:  If fixed RTP header is used in the encapsulation, it is
		 * considered part of the CESoPSN header.]
		 *
		 * Note that this differs from RFC4385's definition of length:
		 * [ If the MPLS payload is less than 64 bytes, the length field
		 * MUST be set to the length of the PW payload...]
		 *
		 * We will use RFC5086's definition here.
		 */
		int  cw_len;
		gint payload_size_from_packet;

		cw_len = tvb_get_guint8(tvb_original, 1) & 0x3f;
		payload_size_from_packet = packet_size - encaps_size;
		if (cw_len != 0)
		{
			gint payload_size_from_cw;
			payload_size_from_cw = cw_len - encaps_size;
			/*
			 * Assumptions for error case,
			 * will be overwritten if no errors found:
			 */
			payload_size = payload_size_from_packet;
			padding_size = 0;

			if (payload_size_from_cw < 0)
			{
				properties |= PWC_CW_BAD_PAYLEN_LT_0;
			}
			else if (payload_size_from_cw > payload_size_from_packet)
			{
				properties |= PWC_CW_BAD_PAYLEN_GT_PACKET;
			}
			else if (payload_size_from_packet >= 64)
			{
				properties |= PWC_CW_BAD_LEN_MUST_BE_0;
			}
			else /* ok */
			{
				payload_size = payload_size_from_cw;
				padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
			}
		}
		else
		{
			payload_size = payload_size_from_packet;
			padding_size = 0;
		}
	}

	{
		guint8 cw_lm;
		cw_lm = tvb_get_guint8(tvb_original, 0) & 0x0b /*l+mod*/;
		if (NULL == try_val_to_str(cw_lm, vals_cw_lm))
		{
			properties |= PWC_CW_SUSPECT_LM;
		}

		{
			guint8 l_bit, m_bits;
			l_bit  = (cw_lm & 0x08) >> 3;
			m_bits = (cw_lm & 0x03) >> 0;
			if ((l_bit == 0 && m_bits == 0x0) /*CESoPSN data packet - normal situation*/
			    ||(l_bit == 0 && m_bits == 0x2) /*CESoPSN data packet - RDI on the AC*/ )
			{
				if ((payload_size == 0) || ((payload_size % 8) != 0))
				{
					properties |= PWC_PAY_SIZE_BAD;
				}
			}
			else if (l_bit == 1 && m_bits == 0x0) /*TDM data is invalid; payload MAY be omitted*/
			{
				/*allow any size of payload*/
			}
			else /*reserved combinations*/
			{
				/*allow any size of payload*/
			}
		}
	}

	/* fill up columns*/
	col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
	col_clear(pinfo->cinfo, COL_INFO);
	if (properties & PWC_ANYOF_CW_BAD)
	{
		col_set_str(pinfo->cinfo, COL_INFO, "CW:Bad, ");
	}
	else if (properties & PWC_ANYOF_CW_SUSPECT)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "CW:Suspect, ");
	}

	if (properties & PWC_PAY_SIZE_BAD)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "Payload size:Bad, ");
	}

	col_append_fstr(pinfo->cinfo, COL_INFO, "TDM octets:%d", (int)payload_size);

	if (padding_size != 0)
	{
		col_append_fstr(pinfo->cinfo, COL_INFO, ", Padding:%d", (int)padding_size);
	}

	{
		proto_item* item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		pwc_item_append_cw(item,tvb_get_ntohl(tvb_original, 0),TRUE);
		pwc_item_append_text_n_items(item,(int)payload_size,"octet");
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				proto_item* item2;
				tvb = tvb_new_subset_length(tvb_original, 0, PWC_SIZEOF_CW);
				item2 = proto_tree_add_item(tree2, hf_cw, tvb, 0, -1, ENC_NA);
				pwc_item_append_cw(item2,tvb_get_ntohl(tvb, 0),FALSE);
				{
					proto_tree* tree3;
					tree3 = proto_item_add_subtree(item, ett);
					{
						proto_item* item3;
						if (properties & PWC_CW_BAD_BITS03) /*display only if value is wrong*/
						{
							item3 = proto_tree_add_item(tree3, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN);
							expert_add_info(pinfo, item3, &ei_cw_bits03);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_lm,  tvb, 0, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_SUSPECT_LM)
						{
							expert_add_info(pinfo, item3, &ei_cw_lm);
						}

						proto_tree_add_item(tree3, hf_cw_r, tvb, 0, 1, ENC_BIG_ENDIAN);

						item3 = proto_tree_add_item(tree3, hf_cw_frg, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_FRAG)
						{
							expert_add_info(pinfo, item3, &ei_cw_frg);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_len, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_PAYLEN_LT_0)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: too small, must be > %d",
								(int)encaps_size);
						}
						if (properties & PWC_CW_BAD_PAYLEN_GT_PACKET)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: must be <= than PSN packet size (%d)",
								(int)packet_size);
						}
						if (properties & PWC_CW_BAD_LEN_MUST_BE_0)
						{
							expert_add_info_format(pinfo, item3, &ei_pref_cw_len,
								"Bad Length: must be 0 if CESoPSN packet size (%d) is > 64",
								(int)packet_size);
						}

						proto_tree_add_item(tree3, hf_cw_seq, tvb, 2, 2, ENC_BIG_ENDIAN);

					}
				}
			}
		}

		/* payload */
		if (payload_size == 0)
		{
			if (properties & PWC_PAY_SIZE_BAD)
			{
				expert_add_info_format(pinfo, item, &ei_payload_size_invalid_error,
					"CESoPSN payload: none found. Size of payload must be <> 0");
			}
			else
			{
				expert_add_info_format(pinfo, item, &ei_payload_size_invalid_undecoded,
					"CESoPSN payload: omitted to conserve bandwidth");
			}
		}
		else
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				proto_item* item2;
				tvbuff_t* tvb;
				tvb = tvb_new_subset_length(tvb_original, PWC_SIZEOF_CW, payload_size);
				item2 = proto_tree_add_item(tree2, hf_payload, tvb, 0, -1, ENC_NA);
				pwc_item_append_text_n_items(item2,(int)payload_size,"octet");
				if (properties & PWC_PAY_SIZE_BAD)
				{
					expert_add_info_format(pinfo, item2, &ei_payload_size_invalid_error,
						"CESoPSN packet payload size must be multiple of 8");
				}
				tree2 = proto_item_add_subtree(item2, ett);
				call_dissector(data_handle, tvb, pinfo, tree2);
				item2 = proto_tree_add_int(tree2, hf_payload_l, tvb, 0, 0
					,(int)payload_size); /* allow filtering */
				PROTO_ITEM_SET_HIDDEN(item2);
			}
		}

		/* padding */
		if (padding_size > 0)
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1);
				call_dissector(pw_padding_handle, tvb, pinfo, tree2);
			}
		}
	}
	return;
}
Example #3
0
static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
                             proto_tree *tree, proto_tree *tns_tree)
{
    proto_tree *data_tree = NULL, *ti;
    proto_item *hidden_item;
    int is_sns = 0;

    if ( tvb_bytes_exist(tvb, offset+2, 4) )
    {
        if ( tvb_get_guint8(tvb, offset+2) == 0xDE &&
                tvb_get_guint8(tvb, offset+3) == 0xAD &&
                tvb_get_guint8(tvb, offset+4) == 0xBE &&
                tvb_get_guint8(tvb, offset+5) == 0xEF )
        {
            is_sns = 1;
        }
    }

    if ( tree )
    {
        if ( is_sns )
        {
            ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
                                     "Secure Network Services");
        }
        else
        {
            ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
                                     "Data");
        }
        data_tree = proto_item_add_subtree(ti, ett_tns_data);

        hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_data, tvb, 0, 0,
                                             TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
    }

    if ( tree )
    {
        proto_tree *df_tree = NULL;

        ti = proto_tree_add_item(data_tree, hf_tns_data_flag, tvb, offset, 2, ENC_BIG_ENDIAN);

        df_tree = proto_item_add_subtree(ti, ett_tns_data_flag);
        proto_tree_add_item(df_tree, hf_tns_data_flag_send, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(df_tree, hf_tns_data_flag_rc, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(df_tree, hf_tns_data_flag_c, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(df_tree, hf_tns_data_flag_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(df_tree, hf_tns_data_flag_more, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(df_tree, hf_tns_data_flag_eof, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(df_tree, hf_tns_data_flag_dic, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(df_tree, hf_tns_data_flag_rts, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(df_tree, hf_tns_data_flag_sntt, tvb, offset, 2, ENC_BIG_ENDIAN);
    }
    offset += 2;

    if ( check_col(pinfo->cinfo, COL_INFO) )
    {
        if ( is_sns )
        {
            col_append_str(pinfo->cinfo, COL_INFO, ", SNS");
        }
        else
        {
            col_append_str(pinfo->cinfo, COL_INFO, ", Data");
        }
    }

    if ( data_tree )
    {
        call_dissector(data_handle,
                       tvb_new_subset_remaining(tvb, offset), pinfo, data_tree);
    }

    return;
}
Example #4
0
/*
 * Dissector that returns:
 *
 *	The amount of data in the protocol's PDU, if it was able to
 *	dissect all the data;
 *
 *	0, if the tvbuff doesn't contain a PDU for that protocol;
 *
 *	The negative of the amount of additional data needed, if
 *	we need more data (e.g., from subsequent TCP segments) to
 *	dissect the entire PDU.
 */
static int
dissect_ccn(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    guint tvb_size = 0;
    proto_tree *ccn_tree;
    proto_item *ti = NULL;
    const unsigned char *ccnb;
    struct ccn_skeleton_decoder skel_decoder;
    struct ccn_skeleton_decoder *sd;
    struct ccn_charbuf *c;
    int packet_type = 0;
    int packet_type_length = 0;
    /* a couple of basic checks to rule out packets that are definitely not ours */
    tvb_size = tvb_length(tvb);
    if (tvb_size < CCN_MIN_PACKET_SIZE || tvb_get_guint8(tvb, 0) == 0)
        return (0);
    
    sd = &skel_decoder;
    memset(sd, 0, sizeof(*sd));
    sd->state |= CCN_DSTATE_PAUSE;
    ccnb = ep_tvb_memdup(tvb, 0, tvb_size);
    ccn_skeleton_decode(sd, ccnb, tvb_size);
    if (sd->state < 0)
        return (0);
    if (CCN_GET_TT_FROM_DSTATE(sd->state) == CCN_DTAG) {
        packet_type = sd->numval;
        packet_type_length = sd->index;
    } else {
        return (0);
    }
    memset(sd, 0, sizeof(*sd));
    ccn_skeleton_decode(sd, ccnb, tvb_size);
    if (!CCN_FINAL_DSTATE(sd->state)) {
        pinfo->desegment_offset = 0;
        pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
        return (-1); /* what should this be? */
    }
    
    /* Make it visible that we're taking this packet */
    if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "CCN");
    }
    
    /* Clear out stuff in the info column */
    if (check_col(pinfo->cinfo, COL_INFO)) {
        col_clear(pinfo->cinfo, COL_INFO);
    }
    
    c = ccn_charbuf_create();
    ccn_uri_append(c, ccnb, tvb_size, 1);
    
    /* Add the packet type and CCN URI to the info column */
    if (check_col(pinfo->cinfo, COL_INFO)) {
        col_add_str(pinfo->cinfo, COL_INFO,
                    val_to_str(packet_type, VALS(ccn_dtag_dict.dict), "Unknown (0x%02x"));
        col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, ccn_charbuf_as_string(c));
    }
    
    if (tree == NULL) {
        ccn_charbuf_destroy(&c);
        return (sd->index);
    }
    
    ti = proto_tree_add_protocol_format(tree, proto_ccn, tvb, 0, -1,
                                        "Content-centric Networking Protocol, %s, %s",
                                        val_to_str(packet_type, VALS(ccn_dtag_dict.dict), "Unknown (0x%02x"),
                                        ccn_charbuf_as_string(c));
    ccn_tree = proto_item_add_subtree(ti, ett_ccn);
    ccn_charbuf_destroy(&c);
    ti = proto_tree_add_uint(ccn_tree, hf_ccn_type, tvb, 0, packet_type_length, packet_type);
    
    switch (packet_type) {
        case CCN_DTAG_ContentObject:
            if (0 > dissect_ccn_contentobject(ccnb, sd->index, tvb, pinfo, ccn_tree))
                return (0);
            break;
        case CCN_DTAG_Interest:
            if (0 > dissect_ccn_interest(ccnb, sd->index, tvb, pinfo, ccn_tree))
                return (0);
            break;
    }
    
    return (sd->index);
}
static void
dissect_dtp_tlv(packet_info *pinfo, tvbuff_t *tvb, int offset, int length,
		proto_tree *tree, proto_item *ti, proto_item *tlv_length_item, guint8 type)
{
	switch (type) {

	case DTP_TLV_DOMAIN:
		if (length <= 33) { /* VTP domain name is at most 32 bytes long and is null-terminated */
			proto_item_append_text(ti, ": %s", tvb_format_text(tvb, offset, length - 1));
			proto_tree_add_item(tree, hf_dtp_domain, tvb, offset, length, ENC_ASCII|ENC_NA);
		}
		else
			expert_add_info(pinfo, tlv_length_item, &ei_dtp_tlv_length_invalid);

		break;

	case DTP_TLV_TRSTATUS:
		if (length == 1) { /* Value field length must be 1 byte */
			proto_item * value_item = NULL;
			proto_tree * field_tree = NULL;
			guint8 trunk_status = tvb_get_guint8(tvb, offset);

			proto_item_append_text(ti,
				" (Operating/Administrative): %s/%s (0x%02x)",
				val_to_str_const(DTP_TOSVALUE(trunk_status), dtp_tos_vals, "Unknown operating status"),
				val_to_str_const(DTP_TASVALUE(trunk_status), dtp_tas_vals, "Unknown administrative status"),
				trunk_status);
			value_item = proto_tree_add_text(tree, tvb, offset, length, "Value: %s/%s (0x%02x)",
				val_to_str_const(DTP_TOSVALUE(trunk_status), dtp_tos_vals, "Unknown operating status"),
				val_to_str_const(DTP_TASVALUE(trunk_status), dtp_tas_vals, "Unknown administrative status"),
				trunk_status);
			field_tree = proto_item_add_subtree(value_item, ett_dtp_status);
			proto_tree_add_item(field_tree, hf_dtp_tos, tvb, offset, length, ENC_NA);
			proto_tree_add_item(field_tree, hf_dtp_tas, tvb, offset, length, ENC_NA);
			}
			else
				expert_add_info(pinfo, tlv_length_item, &ei_dtp_tlv_length_invalid);

		break;

	case DTP_TLV_TRTYPE:
		if (length == 1) { /* Value field length must be 1 byte */
			proto_item * value_item = NULL;
			proto_tree * field_tree = NULL;
			guint8 trunk_type = tvb_get_guint8(tvb, offset);
			proto_item_append_text(ti,
				" (Operating/Administrative): %s/%s (0x%02x)",
				val_to_str_const(DTP_TOTVALUE(trunk_type), dtp_tot_vals, "Unknown operating type"),
				val_to_str_const(DTP_TATVALUE(trunk_type), dtp_tat_vals, "Unknown administrative type"),
				trunk_type);
			value_item = proto_tree_add_text(tree, tvb, offset, length, "Value: %s/%s (0x%02x)",
				val_to_str_const(DTP_TOTVALUE(trunk_type), dtp_tot_vals, "Unknown operating type"),
				val_to_str_const(DTP_TATVALUE(trunk_type), dtp_tat_vals, "Unknown administrative type"),
				trunk_type);
			field_tree = proto_item_add_subtree(value_item, ett_dtp_type);
			proto_tree_add_item(field_tree, hf_dtp_tot, tvb, offset, length, ENC_NA);
			proto_tree_add_item(field_tree, hf_dtp_tat, tvb, offset, length, ENC_NA);
			}
			else
				expert_add_info(pinfo, tlv_length_item, &ei_dtp_tlv_length_invalid);

		break;

	case DTP_TLV_SENDERID:
		if (length == 6) { /* Value length must be 6 bytes for a MAC address */
			proto_item_append_text(ti, ": %s",
				tvb_ether_to_str(tvb, offset));	/* XXX - resolve? */
			proto_tree_add_item(tree, hf_dtp_senderid, tvb, offset, length, ENC_NA);
		}
		else
			expert_add_info(pinfo, tlv_length_item, &ei_dtp_tlv_length_invalid);

		break;

	default:
		proto_tree_add_text(tree, tvb, offset, length, "Data");
		break;
	}
}
Example #6
0
static void
dissect_macctrl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_item *ti, *opcode_item;
  proto_tree *macctrl_tree = NULL;
  proto_tree *pause_times_tree = NULL;
  guint16     opcode;
  guint16     pause_time;
  int i;

  col_set_str(pinfo->cinfo, COL_PROTOCOL, "MAC CTRL");
  col_clear(pinfo->cinfo, COL_INFO);

  opcode = tvb_get_ntohs(tvb, 0);

  ti = proto_tree_add_item(tree, proto_macctrl, tvb, 0, 46, ENC_NA);
  macctrl_tree = proto_item_add_subtree(ti, ett_macctrl);

  opcode_item = proto_tree_add_uint(macctrl_tree, hf_macctrl_opcode, tvb, 0, 2, opcode);
  proto_tree_add_item(macctrl_tree, hf_macctrl_timestamp, tvb, 2, 4, ENC_BIG_ENDIAN);
  col_add_str(pinfo->cinfo, COL_INFO, val_to_str(opcode, opcode_vals, "Unknown"));

  switch (opcode) {

    case MACCTRL_PAUSE:
      if (!addresses_equal(&pinfo->dst, &macctrl_dst_address)) {
        expert_add_info(pinfo, opcode_item, &ei_macctrl_dst_address);
      }

      pause_time = tvb_get_ntohs(tvb, 6);
      col_append_fstr(pinfo->cinfo, COL_INFO, ": pause_time: %u quanta",
                      pause_time);
      proto_tree_add_uint(macctrl_tree, hf_macctrl_pause_time, tvb, 6, 2,
                          pause_time);
      break;

    case MACCTRL_GATE:
      break;

    case MACCTRL_REPORT:
      break;

    case MACCTRL_REGISTER_REQ:
      /* Flags */
      proto_tree_add_item(macctrl_tree, hf_reg_flags, tvb,
                          6, 1, ENC_NA);

      /* Pending Grants */
      proto_tree_add_item(macctrl_tree, hf_reg_req_grants, tvb,
                          7, 1, ENC_NA);
      break;

    case MACCTRL_REGISTER:

      /* Assigned Port */
      proto_tree_add_item(macctrl_tree, hf_reg_port, tvb,
                          6, 2, ENC_BIG_ENDIAN);

      /* Flags */
      proto_tree_add_item(macctrl_tree, hf_reg_flags, tvb,
                          8, 1, ENC_NA);
      /* Synch Time */
      proto_tree_add_item(macctrl_tree, hf_reg_time, tvb,
                          9, 2, ENC_BIG_ENDIAN);

      /* Echoed Pending Grants */
      proto_tree_add_item(macctrl_tree, hf_reg_grants, tvb,
                          11, 1, ENC_NA);
      break;

    case MACCTRL_REGISTER_ACK:

      /* Flags */
      proto_tree_add_item(macctrl_tree, hf_reg_flags, tvb,
                          6, 1, ENC_NA);

      /* Echoed Assigned Port */
      proto_tree_add_item(macctrl_tree, hf_reg_ack_port, tvb,
                          7, 2, ENC_BIG_ENDIAN);

      /* Echoed Synch Time */
      proto_tree_add_item(macctrl_tree, hf_reg_ack_time, tvb,
                          9, 2, ENC_BIG_ENDIAN);
      break;

    case MACCTRL_CLASS_BASED_FLOW_CNTRL_PAUSE:
      if (!addresses_equal(&pinfo->dst, &macctrl_dst_address)) {
        expert_add_info(pinfo, opcode_item, &ei_macctrl_dst_address);
      }

      ti = proto_tree_add_bitmask(macctrl_tree, tvb, 2, hf_macctrl_cbfc_enbv,
                             ett_macctrl_cbfc_enbv, macctrl_cbfc_enbv_list, ENC_BIG_ENDIAN);
      if (tvb_get_guint8(tvb, 2) != 0) {
        expert_add_info(pinfo, ti, &ei_macctrl_cbfc_enbv);
      }

      pause_times_tree = proto_tree_add_subtree(macctrl_tree, tvb, 4, 8*2, ett_macctrl_cbfc_pause_times, NULL, "CBFC Class Pause Times");

      for (i=0; i<8; i++) {
        proto_tree_add_item(pause_times_tree, *macctrl_cbfc_pause_times_list[i], tvb, 4+i*2, 2, ENC_BIG_ENDIAN);
      }
      break;
    default:
      expert_add_info(pinfo, opcode_item, &ei_macctrl_opcode);
     break;
  }
}
Example #7
0
/* Code to actually dissect the packets */
static void
dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    char *szInfo;
    int			offCur		= 0;   /* current offset from start of WTP data */
    gint		returned_length, str_index = 0;

    unsigned char	b0;

    /* continuation flag */
    unsigned char  	fCon;			/* Continue flag	*/
    unsigned char  	fRID;			/* Re-transmission indicator*/
    unsigned char  	fTTR = '\0';		/* Transmission trailer	*/
    guint 		cbHeader   	= 0;	/* Fixed header length	*/
    guint 		vHeader   	= 0;	/* Variable header length*/
    int 		abortType  	= 0;

    /* Set up structures we'll need to add the protocol subtree and manage it */
    proto_item		*ti = NULL;
    proto_tree		*wtp_tree = NULL;

    char		pdut;
    char		clsTransaction = 3;
    int			numMissing = 0;		/* Number of missing packets in a negative ack */
    int			i;
    tvbuff_t		*wsp_tvb = NULL;
    guint8		psn = 0;		/* Packet sequence number*/
    guint16		TID = 0;		/* Transaction-Id	*/
    int			dataOffset;
    gint		dataLen;

#define SZINFO_SIZE 256
    szInfo=ep_alloc(SZINFO_SIZE);

    b0 = tvb_get_guint8 (tvb, offCur + 0);
    /* Discover Concatenated PDUs */
    if (b0 == 0) {
	guint	c_fieldlen = 0;		/* Length of length-field	*/
	guint	c_pdulen = 0;		/* Length of conc. PDU	*/

	if (tree) {
	    ti = proto_tree_add_item(tree, proto_wtp,
				    tvb, offCur, 1, ENC_NA);
	    wtp_tree = proto_item_add_subtree(ti, ett_wtp_sub_pdu_tree);
		proto_item_append_text(ti, ", PDU concatenation");
	}
	offCur = 1;
	i = 1;
	while (offCur < (int) tvb_reported_length(tvb)) {
	    tvbuff_t *wtp_tvb;
	    /* The length of an embedded WTP PDU is coded as either:
	     *	- a 7-bit value contained in one octet with highest bit == 0.
	     *	- a 15-bit value contained in two octets (little endian)
	     *	  if the 1st octet has its highest bit == 1.
	     * This means that this is NOT encoded as an uintvar-integer!!!
	     */
	    b0 = tvb_get_guint8(tvb, offCur + 0);
	    if (b0 & 0x80) {
		c_fieldlen = 2;
		c_pdulen = ((b0 & 0x7f) << 8) | tvb_get_guint8(tvb, offCur + 1);
	    } else {
		c_fieldlen = 1;
		c_pdulen = b0;
	    }
	    if (tree) {
		proto_tree_add_uint(wtp_tree, hf_wtp_header_sub_pdu_size,
				    tvb, offCur, c_fieldlen, c_pdulen);
	    }
	    if (i > 1) {
		col_append_str(pinfo->cinfo, COL_INFO, ", ");
	    }
	    /* Skip the length field for the WTP sub-tvb */
	    wtp_tvb = tvb_new_subset(tvb, offCur + c_fieldlen, c_pdulen, c_pdulen);
	    dissect_wtp_common(wtp_tvb, pinfo, wtp_tree);
	    offCur += c_fieldlen + c_pdulen;
	    i++;
	}
	if (tree) {
		proto_item_append_text(ti, ", PDU count: %u", i);
	}
	return;
    }
    /* No concatenation */
    fCon = b0 & 0x80;
    fRID = retransmission_indicator(b0);
    pdut = pdu_type(b0);

#ifdef DEBUG
	printf("WTP packet %u: tree = %p, pdu = %s (%u) length: %u\n",
			pinfo->fd->num, tree,
			val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x"),
			pdut, tvb_length(tvb));
#endif

    /* Develop the string to put in the Info column */
    returned_length =  g_snprintf(szInfo, SZINFO_SIZE, "WTP %s",
		    val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x"));
    str_index += MIN(returned_length, SZINFO_SIZE-str_index);

    switch (pdut) {
	case INVOKE:
	    fTTR = transmission_trailer(b0);
	    TID = tvb_get_ntohs(tvb, offCur + 1);
	    psn = 0;
	    clsTransaction = transaction_class(tvb_get_guint8(tvb, offCur + 3));
	    returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index,
		" Class %d", clsTransaction);
            str_index += MIN(returned_length, SZINFO_SIZE-str_index);
	    cbHeader = 4;
	    break;

	case SEGMENTED_INVOKE:
	case SEGMENTED_RESULT:
	    fTTR = transmission_trailer(b0);
	    TID = tvb_get_ntohs(tvb, offCur + 1);
	    psn = tvb_get_guint8(tvb, offCur + 3);
	    if (psn != 0) {
		returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index,
			" (%u)", psn);
                str_index += MIN(returned_length, SZINFO_SIZE-str_index);
	    }
	    cbHeader = 4;
	    break;

	case ABORT:
	    cbHeader = 4;
	    break;

	case RESULT:
	    fTTR = transmission_trailer(b0);
	    TID = tvb_get_ntohs(tvb, offCur + 1);
	    psn = 0;
	    cbHeader = 3;
	    break;

	case ACK:
	    cbHeader = 3;
	    break;

	case NEGATIVE_ACK:
	    /* Variable number of missing packets */
	    numMissing = tvb_get_guint8(tvb, offCur + 3);
	    cbHeader = numMissing + 4;
	    break;

	default:
	    break;
    };
    if (fRID) {
	returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index, " R" );
        str_index += MIN(returned_length, SZINFO_SIZE-str_index);
    };
    /* In the interest of speed, if "tree" is NULL, don't do any work not
       necessary to generate protocol tree items. */
    if (tree) {
#ifdef DEBUG
	fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader);
#endif
	/* NOTE - Length will be set when we process the TPI */
	ti = proto_tree_add_item(tree, proto_wtp, tvb, offCur, 0, ENC_NA);
#ifdef DEBUG
	fprintf(stderr, "dissect_wtp: (7) Returned from proto_tree_add_item\n");
#endif
	wtp_tree = proto_item_add_subtree(ti, ett_wtp);

/* Code to process the packet goes here */
#ifdef DEBUG
	fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader);
	fprintf(stderr, "dissect_wtp: offCur = %d\n", offCur);
#endif
	/* Add common items: only CON and PDU Type */
	proto_tree_add_item(
			wtp_tree,	 		/* tree */
			hf_wtp_header_flag_continue, 	/* id */
			tvb,
			offCur, 			/* start of highlight */
			1,				/* length of highlight*/
			b0				/* value */
	     );
	proto_tree_add_item(wtp_tree, hf_wtp_header_pdu_type, tvb, offCur, 1, ENC_LITTLE_ENDIAN);

	switch(pdut) {
	    case INVOKE:
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

		proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_version , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_TIDNew, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_UP, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_Reserved, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_TransactionClass, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_item_append_text(ti,
				", PDU: Invoke (%u)"
				", Transaction Class: %s (%u)",
				INVOKE,
				val_to_str(clsTransaction, vals_transaction_classes, "Undefined"),
				clsTransaction);
		break;

	    case RESULT:
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_item_append_text(ti, ", PDU: Result (%u)", RESULT);
		break;

	    case ACK:
		proto_tree_add_item(wtp_tree, hf_wtp_header_Ack_flag_TVETOK, tvb, offCur, 1, ENC_BIG_ENDIAN);

		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_item_append_text(ti, ", PDU: ACK (%u)", ACK);
		break;

	    case ABORT:
		abortType = tvb_get_guint8 (tvb, offCur) & 0x07;
		proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_type , tvb, offCur , 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

		if (abortType == PROVIDER)
		{
			guint8 reason = tvb_get_guint8(tvb, offCur + 3);
		    proto_tree_add_item( wtp_tree, hf_wtp_header_Abort_reason_provider , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN);
			proto_item_append_text(ti,
					", PDU: Abort (%u)"
					", Type: Provider (%u)"
					", Reason: %s (%u)",
					ABORT,
					PROVIDER,
					val_to_str(reason, vals_abort_reason_provider, "Undefined"),
					reason);
		}
		else if (abortType == USER)
		{
			guint8 reason = tvb_get_guint8(tvb, offCur + 3);
		    proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_reason_user , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN);
			proto_item_append_text(ti,
					", PDU: Abort (%u)"
					", Type: User (%u)"
					", Reason: %s (%u)",
					ABORT,
					PROVIDER,
					val_to_str_ext_const(reason, &vals_wsp_reason_codes_ext, "Undefined"),
					reason);
		}
		break;

	    case SEGMENTED_INVOKE:
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

		proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_item_append_text(ti,
				", PDU: Segmented Invoke (%u)"
				", Packet Sequence Number: %u",
				SEGMENTED_INVOKE, psn);
		break;

	    case SEGMENTED_RESULT:
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

		proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		proto_item_append_text(ti,
				", PDU: Segmented Result (%u)"
				", Packet Sequence Number: %u",
				SEGMENTED_RESULT, psn);
		break;

	    case NEGATIVE_ACK:
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

		proto_tree_add_item(wtp_tree, hf_wtp_header_missing_packets , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
		/* Iterate through missing packets */
		for (i = 0; i < numMissing; i++)
		{
		    proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number, tvb, offCur + 4 + i, 1, ENC_LITTLE_ENDIAN);
		}
		proto_item_append_text(ti,
				", PDU: Negative Ack (%u)"
				", Missing Packets: %u",
				NEGATIVE_ACK, numMissing);
		break;

	    default:
		break;
	};
	if (fRID) {
		proto_item_append_text(ti, ", Retransmission");
	}
    } else { /* tree is NULL */
#ifdef DEBUG
	fprintf(stderr, "dissect_wtp: (4) tree was %p\n", tree);
#endif
    }
	/* Process the variable part */
	if (fCon) {			/* Now, analyze variable part	*/
	    unsigned char	 tCon;
	    unsigned char	 tByte;
	    unsigned char	 tpiLen;
	    tvbuff_t		*tmp_tvb;

	    vHeader = 0;		/* Start scan all over	*/

	    do {
		tByte = tvb_get_guint8(tvb, offCur + cbHeader + vHeader);
		tCon = tByte & 0x80;
		if (tByte & 0x04)	/* Long TPI	*/
		    tpiLen = 2 + tvb_get_guint8(tvb,
					    offCur + cbHeader + vHeader + 1);
		else
		    tpiLen = 1 + (tByte & 0x03);
		if (tree)
		{
		tmp_tvb = tvb_new_subset(tvb, offCur + cbHeader + vHeader,
					tpiLen, tpiLen);
		wtp_handle_tpi(wtp_tree, tmp_tvb);
		}
		vHeader += tpiLen;
	    } while (tCon);
	} else {
		/* There is no variable part */
	}	/* End of variable part of header */

	/* Set the length of the WTP protocol part now we know the length of the
	 * fixed and variable WTP headers */
	if (tree)
	proto_item_set_len(ti, cbHeader + vHeader);

#ifdef DEBUG
    fprintf( stderr, "dissect_wtp: cbHeader = %d\n", cbHeader );
#endif

    /*
     * Any remaining data ought to be WSP data (if not WTP ACK, NACK
     * or ABORT pdu), so, if we have any remaining data, and it's
     * not an ACK, NACK, or ABORT PDU, hand it off (defragmented) to the
     * WSP dissector.
     * Note that the last packet of a fragmented WTP message needn't
     * contain any data, so we allow payloadless packets to be
     * reassembled.  (XXX - does the reassembly code handle this
     * for packets other than the last packet?)
     *
	 * Try calling a subdissector only if:
	 *	- The WTP payload is ressembled in this very packet,
	 *	- The WTP payload is not fragmented across packets.
	 */
    dataOffset = offCur + cbHeader + vHeader;
    dataLen = tvb_reported_length_remaining(tvb, dataOffset);
    if ((dataLen >= 0) &&
			! ((pdut==ACK) || (pdut==NEGATIVE_ACK) || (pdut==ABORT)))
    {
		/* Try to reassemble if needed, and hand over to WSP
		 * A fragmented WTP packet is either:
		 *	- An INVOKE with fTTR (transmission trailer) not set,
		 *	- a SEGMENTED_INVOKE,
		 *	- A RESULT with fTTR (transmission trailer) not set,
		 *	- a SEGMENTED_RESULT.
		 */
		if ( ( (pdut == SEGMENTED_INVOKE) || (pdut == SEGMENTED_RESULT)
				|| ( ((pdut == INVOKE) || (pdut == RESULT)) && (!fTTR) )
			) && tvb_bytes_exist(tvb, dataOffset, dataLen) )
		{
			/* Try reassembling fragments */
			fragment_data *fd_wtp = NULL;
			guint32 reassembled_in = 0;
			gboolean save_fragmented = pinfo->fragmented;

			pinfo->fragmented = TRUE;
			fd_wtp = fragment_add_seq(tvb, dataOffset, pinfo, TID,
					wtp_fragment_table, psn, dataLen, !fTTR);
			/* XXX - fragment_add_seq() yields NULL unless Wireshark knows
			 * that the packet is part of a reassembled whole. This means
			 * that fd_wtp will be NULL as long as Wireshark did not encounter
			 * (and process) the packet containing the last fragment.
			 * This implies that Wireshark needs two passes over the data for
			 * correct reassembly. At the first pass, a capture containing
			 * three fragments plus a retransmssion of the last fragment
			 * will progressively show:
			 *
			 *		Packet 1: (Unreassembled fragment 1)
			 *		Packet 2: (Unreassembled fragment 2)
			 *		Packet 3: (Reassembled WTP)
			 *		Packet 4: (WTP payload reassembled in packet 3)
			 *
			 * However at subsequent evaluation (e.g., by applying a display
			 * filter) the packet summary will show:
			 *
			 *		Packet 1: (WTP payload reassembled in packet 3)
			 *		Packet 2: (WTP payload reassembled in packet 3)
			 *		Packet 3: (Reassembled WTP)
			 *		Packet 4: (WTP payload reassembled in packet 3)
			 *
			 * This is important to know, and also affects read filters!
			 */
			wsp_tvb = process_reassembled_data(tvb, dataOffset, pinfo,
					"Reassembled WTP", fd_wtp, &wtp_frag_items,
					NULL, wtp_tree);
#ifdef DEBUG
			printf("WTP: Packet %u %s -> %d: wsp_tvb = %p, fd_wtp = %p, frame = %u\n",
					pinfo->fd->num,
					fd_wtp ? "Reassembled" : "Not reassembled",
					fd_wtp ? fd_wtp->reassembled_in : -1,
					wsp_tvb,
					fd_wtp
					);
#endif
			if (fd_wtp) {
				/* Reassembled */
				reassembled_in = fd_wtp->reassembled_in;
				if (pinfo->fd->num == reassembled_in) {
					/* Reassembled in this very packet:
					 * We can safely hand the tvb to the WSP dissector */
					call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
				} else {
					/* Not reassembled in this packet */
					if (check_col(pinfo->cinfo, COL_INFO)) {
						col_append_fstr(pinfo->cinfo, COL_INFO,
								"%s (WTP payload reassembled in packet %u)",
								szInfo, fd_wtp->reassembled_in);
					}
					if (tree) {
						proto_tree_add_text(wtp_tree, tvb, dataOffset, -1,
								"Payload");
					}
				}
			} else {
				/* Not reassembled yet, or not reassembled at all */
				if (check_col(pinfo->cinfo, COL_INFO)) {
					col_append_fstr(pinfo->cinfo, COL_INFO,
								"%s (Unreassembled fragment %u)",
								szInfo, psn);
				}
				if (tree) {
					proto_tree_add_text(wtp_tree, tvb, dataOffset, -1,
							"Payload");
				}
			}
			/* Now reset fragmentation information in pinfo */
			pinfo->fragmented = save_fragmented;
		}
		else if ( ((pdut == INVOKE) || (pdut == RESULT)) && (fTTR) )
		{
			/* Non-fragmented payload */
			wsp_tvb = tvb_new_subset_remaining(tvb, dataOffset);
			/* We can safely hand the tvb to the WSP dissector */
			call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
		}
		else
		{
			/* Nothing to hand to subdissector */
			if (check_col(pinfo->cinfo, COL_INFO))
				col_append_str(pinfo->cinfo, COL_INFO, szInfo);
		}
	}
	else
	{
		/* Nothing to hand to subdissector */
		if (check_col(pinfo->cinfo, COL_INFO))
			col_append_str(pinfo->cinfo, COL_INFO, szInfo);
	}
}
Example #8
0
/* Code to actually dissect the packets */
static void
dissect_gvrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item   *ti;
    proto_tree   *gvrp_tree;
    guint16       protocol_id;
    guint8        octet;
    int           msg_index, attr_index, offset = 0, length = tvb_reported_length(tvb);

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "GVRP");

    col_set_str(pinfo->cinfo, COL_INFO, "GVRP");

    if (tree)
    {
	ti = proto_tree_add_item(tree, proto_gvrp, tvb, 0, length, FALSE);

	gvrp_tree = proto_item_add_subtree(ti, ett_gvrp);

	/* Read in GARP protocol ID */
	protocol_id = tvb_get_ntohs(tvb, GARP_PROTOCOL_ID);

	proto_tree_add_uint_format(gvrp_tree, hf_gvrp_proto_id, tvb,
				   GARP_PROTOCOL_ID, sizeof(guint16),
				   protocol_id,
				   "Protocol Identifier: 0x%04x (%s)",
				   protocol_id,
				   protocol_id == GARP_DEFAULT_PROTOCOL_ID ?
				     "GARP VLAN Registration Protocol" :
				     "Unknown Protocol");

	/* Currently only one protocol ID is supported */
	if (protocol_id != GARP_DEFAULT_PROTOCOL_ID)
	{
	    proto_tree_add_text(gvrp_tree, tvb, GARP_PROTOCOL_ID, sizeof(guint16),
 "   (Warning: this version of Wireshark only knows about protocol id = 1)");
	    call_dissector(data_handle,
	        tvb_new_subset(tvb, GARP_PROTOCOL_ID + sizeof(guint16), -1, -1),
	        pinfo, tree);
	    return;
	}

	offset += sizeof(guint16);
	length -= sizeof(guint16);

	msg_index = 0;

	/* Begin to parse GARP messages */
	while (length)
	{
	    proto_item   *msg_item;
	    int           msg_start = offset;

	    /* Read in attribute type. */
	    octet = tvb_get_guint8(tvb, offset);

	    /* Check for end of mark */
	    if (octet == GARP_END_OF_MARK)
	    {
		/* End of GARP PDU */
		if (msg_index)
		{
		    proto_tree_add_text(gvrp_tree, tvb, offset, sizeof(guint8),
					"End of mark");
		    break;
		}
		else
		{
		    call_dissector(data_handle,
		        tvb_new_subset_remaining(tvb, offset), pinfo, tree);
		    return;
		}
	    }

	    offset += sizeof(guint8);
	    length -= sizeof(guint8);

	    msg_item = proto_tree_add_text(gvrp_tree, tvb, msg_start, -1,
					   "Message %d", msg_index + 1);

	    proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_type, tvb,
				msg_start, sizeof(guint8), octet);

	    /* GVRP only supports one attribute type. */
	    if (octet != GVRP_ATTRIBUTE_TYPE)
	    {
		call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset),
		    pinfo, tree);
		return;
	    }

	    attr_index = 0;

	    while (length)
	    {
		int          attr_start = offset;
		proto_item   *attr_item;

		/* Read in attribute length. */
		octet = tvb_get_guint8(tvb, offset);

		/* Check for end of mark */
		if (octet == GARP_END_OF_MARK)
		{
		    /* If at least one message has been already read,
		     * check for another end of mark.
		     */
		    if (attr_index)
		    {
			proto_tree_add_text(gvrp_tree, tvb, offset,
					    sizeof(guint8), "  End of mark");

			offset += sizeof(guint8);
			length -= sizeof(guint8);

			proto_item_set_len(msg_item, offset - msg_start);
			break;
		    }
		    else
		    {
			call_dissector(data_handle,
			    tvb_new_subset_remaining(tvb, offset), pinfo, tree);
			return;
		    }
		}
		else
		{
		    guint8   event;

		    offset += sizeof(guint8);
		    length -= sizeof(guint8);

		    attr_item = proto_tree_add_text(gvrp_tree, tvb,
			 attr_start, -1, "  Attribute %d", attr_index + 1);

		    proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_length,
			 tvb, attr_start, sizeof(guint8), octet);

		    /* Read in attribute event */
		    event = tvb_get_guint8(tvb, offset);

		    proto_tree_add_uint(gvrp_tree, hf_gvrp_attribute_event,
			 tvb, offset, sizeof(guint8), event);

		    offset += sizeof(guint8);
		    length -= sizeof(guint8);

		    switch (event) {

		    case GVRP_EVENT_LEAVEALL:
			if (octet != GVRP_LENGTH_LEAVEALL)
			{
			    call_dissector(data_handle,
			        tvb_new_subset_remaining(tvb, offset), pinfo,
			        tree);
			    return;
			}
			break;

		     case GVRP_EVENT_JOINEMPTY:
		     case GVRP_EVENT_JOININ:
		     case GVRP_EVENT_LEAVEEMPTY:
		     case GVRP_EVENT_LEAVEIN:
		     case GVRP_EVENT_EMPTY:
			if (octet != GVRP_LENGTH_NON_LEAVEALL)
			{
			    call_dissector(data_handle,
			        tvb_new_subset_remaining(tvb, offset),pinfo,
			        tree);
			    return;
			}

			/* Show attribute value */
			proto_tree_add_item(gvrp_tree, hf_gvrp_attribute_value,
			    tvb, offset, sizeof(guint16), FALSE);

			offset += sizeof(guint16);
			length -= sizeof(guint16);
			break;

		     default:
			call_dissector(data_handle,
			    tvb_new_subset_remaining(tvb, offset), pinfo, tree);
			return;
		    }
		}

		proto_item_set_len(attr_item, offset - attr_start);

		attr_index++;
	    }

	    msg_index++;
	}
    }
}
Example #9
0
static int
zebra_route(proto_tree *tree, tvbuff_t *tvb, int offset, guint16 len,
	    guint8 family, guint8 version)
{
	guint32	prefix4;
	guint8 message, prefixlen, buffer6[16];

	if (version == 0) {
		proto_tree_add_item(tree, hf_zebra_type_v0, tvb,
				    offset, 1, ENC_BIG_ENDIAN);
	} else {
		proto_tree_add_item(tree, hf_zebra_type_v1, tvb,
				    offset, 1, ENC_BIG_ENDIAN);
	}
	offset += 1;

	proto_tree_add_item(tree, hf_zebra_rtflags, tvb,
			    offset, 1, ENC_BIG_ENDIAN);
	offset += 1;

	message = tvb_get_guint8(tvb, offset);
	offset = zebra_route_message(tree, tvb, offset);

	if (version > 1) {
		/* version 2 added safi */
		proto_tree_add_item(tree, hf_zebra_route_safi, tvb,
				    offset, 2, ENC_BIG_ENDIAN);
		offset += 2;
	}

	prefixlen = tvb_get_guint8(tvb, offset);
	proto_tree_add_uint(tree, hf_zebra_prefixlen, tvb,
			    offset, 1, prefixlen);
	offset += 1;

	if (family == ZEBRA_FAMILY_IPV6) {
		memset(buffer6, '\0', sizeof buffer6);
		tvb_memcpy(tvb, buffer6, offset,
			   MIN((unsigned) PSIZE(prefixlen), sizeof buffer6));
		proto_tree_add_ipv6(tree, hf_zebra_prefix6,
				    tvb, offset, PSIZE(prefixlen), (struct e_in6_addr *)buffer6);
	}else {
		prefix4 = 0;
		tvb_memcpy(tvb, (guint8 *)&prefix4, offset,
			   MIN((unsigned) PSIZE(prefixlen), sizeof prefix4));
		proto_tree_add_ipv4(tree, hf_zebra_prefix4,
				    tvb, offset, PSIZE(prefixlen), prefix4);
	}
	offset += PSIZE(prefixlen);

	if (message & ZEBRA_ZAPI_MESSAGE_NEXTHOP) {
		offset = zebra_route_nexthop(tree, tvb, offset, len);
	}
	if (message & ZEBRA_ZAPI_MESSAGE_IFINDEX) {
		offset = zebra_route_ifindex(tree, tvb, offset, len);
	}
	if (message & ZEBRA_ZAPI_MESSAGE_DISTANCE) {
		proto_tree_add_item(tree, hf_zebra_distance,
				    tvb, offset, 1, ENC_BIG_ENDIAN);
		offset += 1;
	}
	if (message & ZEBRA_ZAPI_MESSAGE_METRIC) {
		proto_tree_add_item(tree, hf_zebra_metric,
				    tvb, offset, 4, ENC_BIG_ENDIAN);
		offset += 4;
	}
	return offset;
}
Example #10
0
static void
dissect_fcp_cmnd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, proto_tree *tree, conversation_t *conversation, fc_hdr *fchdr, fcp_conv_data_t *fcp_conv_data)
{
    int          offset  = 0;
    int          add_len = 0;
    guint8       flags, rwflags, lun0;
    guint16      lun     = 0xffff;
    tvbuff_t    *cdb_tvb;
    int          tvb_len, tvb_rlen;
    fcp_request_data_t *request_data = NULL;
    proto_item  *hidden_item;
    fcp_proto_data_t *proto_data;

    /* Determine the length of the FCP part of the packet */
    flags = tvb_get_guint8(tvb, offset+10);
    if (flags) {
        add_len = tvb_get_guint8(tvb, offset+11) & 0x7C;
        add_len = add_len >> 2;
    }

    hidden_item = proto_tree_add_uint(tree, hf_fcp_type, tvb, offset, 0, 0);
    PROTO_ITEM_SET_HIDDEN(hidden_item);

    lun0 = tvb_get_guint8(tvb, offset);

    /* Display single-level LUNs in decimal for clarity */
    /* I'm taking a shortcut here by assuming that if the first byte of the
     * LUN field is 0, it is a single-level LUN. This is not true. For a
     * real single-level LUN, all 8 bytes except byte 1 must be 0.
     */
    if (lun0) {
      proto_tree_add_item(tree, hf_fcp_multilun, tvb, offset, 8, ENC_NA);
      lun = tvb_get_guint8(tvb, offset) & 0x3f;
      lun <<= 8;
      lun |= tvb_get_guint8(tvb, offset+1);
    } else {
      proto_tree_add_item(tree, hf_fcp_singlelun, tvb, offset+1,
                          1, ENC_BIG_ENDIAN);
      lun = tvb_get_guint8(tvb, offset+1);
    }

    if (fchdr->itlq)
        fchdr->itlq->lun = lun;

    if (!pinfo->fd->flags.visited) {
        proto_data = se_alloc(sizeof(fcp_proto_data_t));
        proto_data->lun = lun;
        p_add_proto_data(pinfo->fd, proto_fcp, proto_data);
    }

    request_data = (fcp_request_data_t*)se_tree_lookup32(fcp_conv_data->luns, lun);
    if (!request_data) {
        request_data = se_alloc(sizeof(fcp_request_data_t));
        request_data->request_frame = pinfo->fd->num;
        request_data->response_frame = 0;
        request_data->request_time = pinfo->fd->abs_ts;
        request_data->itl = se_alloc(sizeof(itl_nexus_t));
        request_data->itl->cmdset = 0xff;
        request_data->itl->conversation = conversation;
        se_tree_insert32(fcp_conv_data->luns, lun, request_data);
    }

    proto_tree_add_item(tree, hf_fcp_crn, tvb, offset+8, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_fcp_taskattr, tvb, offset+9, 1, ENC_BIG_ENDIAN);
    dissect_task_mgmt_flags(pinfo, tree, tvb, offset+10);
    proto_tree_add_item(tree, hf_fcp_addlcdblen, tvb, offset+11, 1, ENC_BIG_ENDIAN);
    rwflags = tvb_get_guint8(tvb, offset+11);
    if (fchdr->itlq) {
        if (rwflags & 0x02) {
            fchdr->itlq->task_flags |= SCSI_DATA_READ;
        }
        if (rwflags & 0x01) {
            fchdr->itlq->task_flags |= SCSI_DATA_WRITE;
        }
    }
    proto_tree_add_item(tree, hf_fcp_rddata, tvb, offset+11, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_fcp_wrdata, tvb, offset+11, 1, ENC_BIG_ENDIAN);

    tvb_len = tvb_length_remaining(tvb, offset+12);
    if (tvb_len > (16 + add_len))
      tvb_len = 16 + add_len;
    tvb_rlen = tvb_reported_length_remaining(tvb, offset+12);
    if (tvb_rlen > (16 + add_len))
      tvb_rlen = 16 + add_len;
    cdb_tvb = tvb_new_subset(tvb, offset+12, tvb_len, tvb_rlen);
    dissect_scsi_cdb(cdb_tvb, pinfo, parent_tree, SCSI_DEV_UNKNOWN, fchdr->itlq, request_data->itl);

    proto_tree_add_item(tree, hf_fcp_dl, tvb, offset+12+16+add_len,
                        4, ENC_BIG_ENDIAN);
    if (fchdr->itlq) {
        fchdr->itlq->data_length = tvb_get_ntohl(tvb, offset+12+16+add_len);
    }

    if ( ((rwflags & 0x03) == 0x03)
    &&  tvb_length_remaining(tvb, offset+12+16+add_len+4) >= 4) {
        proto_tree_add_item(tree, hf_fcp_bidir_dl, tvb, offset+12+16+add_len+4,
                            4, ENC_BIG_ENDIAN);
        if (fchdr->itlq) {
            fchdr->itlq->bidir_data_length = tvb_get_ntohl(tvb, offset+12+16+add_len+4);
        }

    }

}
Example #11
0
static void
dissect_dmx_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	col_set_str(pinfo->cinfo, COL_PROTOCOL, "DMX SIP");
	col_clear(pinfo->cinfo, COL_INFO);

	if (tree != NULL) {
		guint    offset = 0;
		guint    byte_count;
		guint    checksum, checksum_shouldbe;
		proto_item *item;
		proto_tree *checksum_tree;

		proto_tree *ti = proto_tree_add_item(tree, proto_dmx_sip, tvb,
							offset, -1, ENC_NA);
		proto_tree *dmx_sip_tree = proto_item_add_subtree(ti, ett_dmx_sip);


		byte_count = tvb_get_guint8(tvb, offset);
		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_byte_count, tvb,
							offset, 1, ENC_BIG_ENDIAN);
		offset++;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_control_bit_field, tvb,
							offset, 1, ENC_BIG_ENDIAN);
		offset++;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_prev_packet_checksum, tvb,
							offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_seq_nr, tvb,
							offset, 1, ENC_BIG_ENDIAN);
		offset++;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_dmx_universe_nr, tvb,
							offset, 1, ENC_BIG_ENDIAN);
		offset++;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_dmx_proc_level, tvb,
							offset, 1, ENC_BIG_ENDIAN);
		offset++;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_dmx_software_version, tvb,
							offset, 1, ENC_BIG_ENDIAN);
		offset++;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_dmx_packet_len, tvb,
							offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_dmx_nr_packets, tvb,
							offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_orig_dev_id, tvb,
							offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_sec_dev_id, tvb,
							offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_third_dev_id, tvb,
							offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_fourth_dev_id, tvb,
							offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_fifth_dev_id, tvb,
							offset, 2, ENC_BIG_ENDIAN);
		offset += 2;

		if (offset < byte_count) {
			proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_reserved, tvb,
							offset, byte_count - offset, ENC_NA);
			offset += (byte_count - offset);
		}

		dmx_sip_checksum(tvb, offset);

		checksum_shouldbe = dmx_sip_checksum(tvb, offset);
		checksum = tvb_get_guint8(tvb, offset);
		item = proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_checksum, tvb,
				offset, 1, ENC_BIG_ENDIAN);
		if (checksum == checksum_shouldbe) {
			proto_item_append_text(item, " [correct]");

			checksum_tree = proto_item_add_subtree(item, ett_dmx_sip);
			item = proto_tree_add_boolean(checksum_tree, hf_dmx_sip_checksum_good, tvb,
						offset, 1, TRUE);
			PROTO_ITEM_SET_GENERATED(item);
			item = proto_tree_add_boolean(checksum_tree, hf_dmx_sip_checksum_bad, tvb,
						offset, 1, FALSE);
			PROTO_ITEM_SET_GENERATED(item);
		} else {
			proto_item_append_text(item, " [incorrect, should be 0x%02x]", checksum_shouldbe);

			checksum_tree = proto_item_add_subtree(item, ett_dmx_sip);
			item = proto_tree_add_boolean(checksum_tree, hf_dmx_sip_checksum_good, tvb,
						offset, 1, FALSE);
			PROTO_ITEM_SET_GENERATED(item);
			item = proto_tree_add_boolean(checksum_tree, hf_dmx_sip_checksum_bad, tvb,
						offset, 1, TRUE);
			PROTO_ITEM_SET_GENERATED(item);
		}

		offset += 1;

		if (offset < tvb_captured_length(tvb))
			proto_tree_add_item(dmx_sip_tree, hf_dmx_sip_trailer, tvb,
					offset, -1, ENC_NA);
	}
}
Example #12
0
static void
dissect_rsp_flags(proto_tree *parent_tree, tvbuff_t *tvb, int offset)
{
    proto_item *item               = NULL;
    proto_tree *tree               = NULL;
    gboolean    bidi_resid_present = FALSE;
    guint8      flags;

    if (parent_tree) {
        item = proto_tree_add_item(parent_tree, hf_fcp_rspflags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
        tree = proto_item_add_subtree(item, ett_fcp_rsp_flags);
    }

    flags = tvb_get_guint8(tvb, offset);

    if (!flags)
        proto_item_append_text(item, " (No values set)");

    /* BIDI RSP */
    proto_tree_add_boolean(tree, hf_fcp_rsp_flags_bidi, tvb, offset, 1, flags);
    if (flags & 0x80) {
        bidi_resid_present = TRUE;
        proto_item_append_text(item, " BIDI_RSP");
        if (flags & (~( 0x80 )))
            proto_item_append_text(item, ",");
    }
    flags &= (~( 0x80 ));

    /* these two bits are only defined if the bidi bit is set */
    if (bidi_resid_present) {
        /* BIDI READ RESID UNDER */
        proto_tree_add_boolean(tree, hf_fcp_rsp_flags_bidi_rru, tvb, offset, 1, flags);
        if (flags & 0x40) {
            proto_item_append_text(item, " BIDI_RRU");
            if (flags & (~( 0x40 )))
                proto_item_append_text(item, ",");
        }
        flags &= (~( 0x40 ));

        /* BIDI READ RESID OVER */
        proto_tree_add_boolean(tree, hf_fcp_rsp_flags_bidi_rro, tvb, offset, 1, flags);
        if (flags & 0x20) {
            proto_item_append_text(item, " BIDI_RRO");
            if (flags & (~( 0x20 )))
                proto_item_append_text(item, ",");
        }
        flags &= (~( 0x20 ));
    }

    /* Conf Req */
    proto_tree_add_boolean(tree, hf_fcp_rsp_flags_conf_req, tvb, offset, 1, flags);
    if (flags & 0x10) {
        proto_item_append_text(item, " CONF REQ");
        if (flags & (~( 0x10 )))
            proto_item_append_text(item, ",");
    }
    flags &= (~( 0x10 ));

    /* Resid Under */
    proto_tree_add_boolean(tree, hf_fcp_rsp_flags_resid_under, tvb, offset, 1, flags);
    if (flags & 0x08) {
        proto_item_append_text(item, " RESID UNDER");
        if (flags & (~( 0x08 )))
            proto_item_append_text(item, ",");
    }
    flags &= (~( 0x08 ));

    /* Resid Over */
    proto_tree_add_boolean(tree, hf_fcp_rsp_flags_resid_over, tvb, offset, 1, flags);
    if (flags & 0x04) {
        proto_item_append_text(item, " RESID OVER");
        if (flags & (~( 0x04 )))
            proto_item_append_text(item, ",");
    }
    flags &= (~( 0x04 ));

    /* SNS len valid */
    proto_tree_add_boolean(tree, hf_fcp_rsp_flags_sns_vld, tvb, offset, 1, flags);
    if (flags & 0x02) {
        proto_item_append_text(item, " SNS VLD");
        if (flags & (~( 0x02 )))
            proto_item_append_text(item, ",");
    }
    flags &= (~( 0x02 ));

    /* rsp len valid */
    proto_tree_add_boolean(tree, hf_fcp_rsp_flags_res_vld, tvb, offset, 1, flags);
    if (flags & 0x01) {
        proto_item_append_text(item, " RES VLD");
        if (flags & (~( 0x01 )))
            proto_item_append_text(item, ",");
    }
    flags &= (~( 0x01 ));

    if (flags) {
        proto_item_append_text(item, " Unknown bitmap value 0x%x", flags);
    }
}
Example #13
0
static void
dissect_task_mgmt_flags(packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset)
{
    proto_item *item = NULL;
    proto_tree *tree = NULL;

    guint8 flags;

    if (parent_tree) {
        item = proto_tree_add_item(parent_tree, hf_fcp_taskmgmt, tvb, offset, 1, ENC_LITTLE_ENDIAN);
        tree = proto_item_add_subtree(item, ett_fcp_taskmgmt);
    }

    flags = tvb_get_guint8(tvb, offset);

    if (!flags)
        proto_item_append_text(item, " (No values set)");

    proto_tree_add_boolean(tree, hf_fcp_mgmt_flags_obsolete, tvb, offset, 1, flags);
    if (flags & 0x80) {
        proto_item_append_text(item, "  OBSOLETE");
        col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[FCP OBSOLETE] ");
    }
    flags &= (~( 0x80 ));

    proto_tree_add_boolean(tree, hf_fcp_mgmt_flags_clear_aca, tvb, offset, 1, flags);
    if (flags & 0x40) {
        proto_item_append_text(item, "  CLEAR ACA");
        col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[FCP CLEAR_ACA] ");
    }
    flags &= (~( 0x40 ));

    proto_tree_add_boolean(tree, hf_fcp_mgmt_flags_target_reset, tvb, offset, 1, flags);
    if (flags & 0x20) {
        proto_item_append_text(item, "  TARGET RESET");
        col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[FCP TARGET_RESET] ");
    }
    flags &= (~( 0x20 ));

    proto_tree_add_boolean(tree, hf_fcp_mgmt_flags_lu_reset, tvb, offset, 1, flags);
    if (flags & 0x10) {
        proto_item_append_text(item, "  LU RESET");
        col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[FCP LU_RESET] ");
    }
    flags &= (~( 0x10 ));

    proto_tree_add_boolean(tree, hf_fcp_mgmt_flags_rsvd, tvb, offset, 1, flags);
    if (flags & 0x08) {
        proto_item_append_text(item, "  RSVD");
        col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[FCP RSVD] ");
    }
    flags &= (~( 0x08 ));

    proto_tree_add_boolean(tree, hf_fcp_mgmt_flags_clear_task_set, tvb, offset, 1, flags);
    if (flags & 0x04) {
        proto_item_append_text(item, "  CLEAR TASK SET");
        col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[FCP CLEAR_TASK_SET] ");
    }
    flags &= (~( 0x04 ));

    proto_tree_add_boolean(tree, hf_fcp_mgmt_flags_abort_task_set, tvb, offset, 1, flags);
    if (flags & 0x02) {
        proto_item_append_text(item, "  ABORT TASK SET");
        col_prepend_fence_fstr(pinfo->cinfo, COL_INFO, "[FCP ABORT_TASK_SET] ");
    }
    flags &= (~( 0x02 ));

    if (flags) {
        proto_item_append_text(item, " Unknown bitmap value 0x%x", flags);
    }
}
Example #14
0
/* UCD dissector */
void dissect_mac_mgmt_msg_ucd_decoder(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint offset = 0;
	guint tvb_len, payload_type, length;
	guint ucd_config_change_count;
	guint ucd_ranging_backoff_start;
	guint ucd_ranging_backoff_end;
	guint ucd_request_backoff_start;
	guint ucd_request_backoff_end;
	gint  tlv_type, tlv_len, tlv_offset, tlv_value_offset;
	guint ul_burst_uiuc, utemp;
	proto_item *ucd_item = NULL;
	proto_tree *ucd_tree = NULL;
	proto_item *tlv_item = NULL;
	proto_tree *tlv_tree = NULL;
	proto_tree *sub_tree = NULL;
	tlv_info_t tlv_info;

	/* Ensure the right payload type */
	payload_type = tvb_get_guint8(tvb, offset);
	if(payload_type != MAC_MGMT_MSG_UCD)
	{
		return;
	}

	if(tree)
	{	/* we are being asked for details */
		/* Get the tvb reported length */
		tvb_len =  tvb_reported_length(tvb);
		/* display MAC payload type UCD */
		ucd_item = proto_tree_add_protocol_format(tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tvb_len, "Uplink Channel Descriptor (UCD) (%u bytes)", tvb_len);
		/* add MAC UCD subtree */
		ucd_tree = proto_item_add_subtree(ucd_item, ett_mac_mgmt_msg_ucd_decoder);
		/* Decode and display the Uplink Channel Descriptor (UCD) */
		/* display the Message Type */
		proto_tree_add_item(ucd_tree, hf_ucd_message_type, tvb, offset, 1, FALSE);
		/* move to next field */
		offset++;
		/* get the Configuration Change Count */
		ucd_config_change_count = tvb_get_guint8(tvb, offset);
		/* display the Configuration Change Count */
		proto_tree_add_text(ucd_tree, tvb, offset, 1, "Configuration Change Count: %u", ucd_config_change_count);
		/* move to next field */
		offset++;
		/* get the ranging backoff start */
		ucd_ranging_backoff_start = tvb_get_guint8(tvb, offset);
		/* display the ranging backoff start */
		proto_tree_add_text(ucd_tree, tvb, offset, 1, "Ranging Backoff Start: 2^%u = %u", ucd_ranging_backoff_start, (1 << ucd_ranging_backoff_start));
		/* move to next field */
		offset++;
		/* get the ranging backoff end */
		ucd_ranging_backoff_end = tvb_get_guint8(tvb, offset);
		/* display the ranging backoff end */
		proto_tree_add_text(ucd_tree, tvb, offset, 1, "Ranging Backoff End: 2^%u = %u", ucd_ranging_backoff_end, (1 << ucd_ranging_backoff_end));
		/* move to next field */
		offset++;
		/* get the request backoff start */
		ucd_request_backoff_start = tvb_get_guint8(tvb, offset);
		/* display the request backoff start */
		proto_tree_add_text(ucd_tree, tvb, offset, 1, "Request Backoff Start: 2^%u = %u", ucd_request_backoff_start, (1 << ucd_request_backoff_start));
		/* move to next field */
		offset++;
		/* get the request backoff end */
		ucd_request_backoff_end = tvb_get_guint8(tvb, offset);
		/* display the request backoff end */
		proto_tree_add_text(ucd_tree, tvb, offset, 1, "Request Backoff End: 2^%u = %u", ucd_request_backoff_end, (1 << ucd_request_backoff_end));
		/* move to next field */
		offset++;
		while(offset < tvb_len)
		{
			/* get the TLV information */
			init_tlv_info(&tlv_info, tvb, offset);
			/* get the TLV type */
			tlv_type = get_tlv_type(&tlv_info);
			/* get the TLV length */
			tlv_len = get_tlv_length(&tlv_info);
			if(tlv_type == -1 || tlv_len > MAX_TLV_LEN || tlv_len < 1)
			{	/* invalid tlv info */
				if(check_col(pinfo->cinfo, COL_INFO))
				{
					col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "UCD TLV error");
				}
				proto_tree_add_item(ucd_tree,hf_ucd_invalid_tlv, tvb, offset, (tvb_len - offset), FALSE);
				break;
			}
			/* get the TLV value offset */
			tlv_value_offset = get_tlv_value_offset(&tlv_info);
#ifdef DEBUG /* for debug only */
			tlv_item = proto_tree_add_protocol_format(ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, (tlv_len + tlv_value_offset), "UCD Type: %u (%u bytes, offset=%u, tvb_len=%u)", tlv_type, tlv_len, offset, tvb_len);
#endif
			/* update the offset */
			offset += tlv_value_offset;
			/* process UCD TLV Encoded information */
			if (include_cor2_changes)
			{
				switch (tlv_type)
				{
					case UCD_TLV_T_203_UL_PUSC_SUBCHANNEL_ROTATION:
					{
						tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_203_ul_pusc_subchannel_rotation, tvb, offset, tlv_len, FALSE);
						tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_203_ul_pusc_subchannel_rotation, tvb, offset, tlv_len, FALSE);
						break;
					}
					case UCD_TLV_T_205_RELATIVE_POWER_OFFSET_UL_HARQ_BURST:
					{
						tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_205_relative_power_offset_ul_harq_burst, tvb, offset, tlv_len, FALSE);
						tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_205_relative_power_offset_ul_harq_burst, tvb, offset, tlv_len, FALSE);
						break;
					}
					case UCD_TLV_T_206_RELATIVE_POWER_OFFSET_UL_BURST_CONTAINING_MAC_MGMT_MSG:
					{
						tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_206_relative_power_offset_ul_burst_containing_mac_mgmt_msg, tvb, offset, tlv_len, FALSE);
						tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_206_relative_power_offset_ul_burst_containing_mac_mgmt_msg, tvb, offset, tlv_len, FALSE);
						break;
					}
					case UCD_TLV_T_207_UL_INITIAL_TRANSMIT_TIMING:
					{
						tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_207_ul_initial_transmit_timing, tvb, offset, tlv_len, FALSE);
						tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_207_ul_initial_transmit_timing, tvb, offset, tlv_len, FALSE);
						break;
					}
					case UCD_TLV_T_210_FAST_FEEDBACK_REGION:
					{
						tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_210_fast_feedback_region, tvb, offset, tlv_len, FALSE);
						tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_210_fast_feedback_region, tvb, offset, tlv_len, FALSE);
						break;
					}
					case UCD_TLV_T_211_HARQ_ACK_REGION:
					{
						tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_211_harq_ack_region, tvb, offset, tlv_len, FALSE);
						tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_211_harq_ack_region, tvb, offset, tlv_len, FALSE);
						break;
					}
					case UCD_TLV_T_212_RANGING_REGION:
					{
						tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_212_ranging_region, tvb, offset, tlv_len, FALSE);
						tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_212_ranging_region, tvb, offset, tlv_len, FALSE);
						break;
					}
					case UCD_TLV_T_213_SOUNDING_REGION:
					{
						tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_213_sounding_region, tvb, offset, tlv_len, FALSE);
						tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_213_sounding_region, tvb, offset, tlv_len, FALSE);
						break;
					}
				}
			}
			switch (tlv_type)
			{
				case UCD_UPLINK_BURST_PROFILE:
				{
					/* get the UIUC */
					ul_burst_uiuc = tvb_get_guint8(tvb, offset) & 0x0F;
					/* add TLV subtree */
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "Uplink Burst Profile (UIUC = %u) (%u bytes)", ul_burst_uiuc, tlv_len);
					proto_tree_add_item(tlv_tree, hf_ucd_ul_burst_reserved, tvb, offset, 1, FALSE);
					proto_tree_add_item(tlv_tree, hf_ucd_ul_burst_uiuc, tvb, offset, 1, FALSE);
					for (tlv_offset = 1; tlv_offset < tlv_len;)
					{	/* get the TLV information */
						init_tlv_info(&tlv_info, tvb, (offset+tlv_offset));
						/* get the TLV type */
						tlv_type = get_tlv_type(&tlv_info);
						if(tlv_type == -1)
						{	/* invalid tlv info */
							if(check_col(pinfo->cinfo, COL_INFO))
							{
								col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "UL Burst Profile error");
							}
							proto_tree_add_item(tlv_tree, hf_ucd_invalid_tlv, tvb, offset, (tlv_len - offset - tlv_offset), FALSE);
							break;
						}
						/* get the TLV length */
						length = get_tlv_length(&tlv_info);
						/* update the offset */
						tlv_offset += get_tlv_value_offset(&tlv_info);
						switch (tlv_type)
						{
							case UCD_BURST_FEC:
							{
								sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, tlv_tree, hf_ucd_burst_fec, tvb, (offset+tlv_offset), 1, FALSE);
								tlv_item = proto_tree_add_item(sub_tree, hf_ucd_burst_fec, tvb, (offset+tlv_offset), 1, FALSE);
								break;
							}
							case UCD_BURST_RANGING_DATA_RATIO:
							{
								sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, tlv_tree, hf_ucd_burst_ranging_data_ratio, tvb, (offset+tlv_offset), 1, FALSE);
								tlv_item = proto_tree_add_item(sub_tree, hf_ucd_burst_ranging_data_ratio, tvb, (offset+tlv_offset), 1, FALSE);
								proto_item_append_text(tlv_item, " dB");
								break;
							}
#if 0 /* for OFDM */
							case UCD_BURST_POWER_BOOST:
							{
								sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, tlv_tree, hf_ucd_burst_power_boost, tvb, (offset+tlv_offset), 1, FALSE);
								tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_burst_power_boost, tvb, (offset+tlv_offset), length, FALSE);
								proto_item_append_text(tlv_item, " dB");
								break;
							}
							case UCD_BURST_TCS_ENABLE:
							{
								sub_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, tlv_tree, hf_ucd_burst_tcs_enable, tvb, (offset+tlv_offset), 1, FALSE);
								proto_tree_add_item(tlv_tree, hf_ucd_burst_tcs_enable, tvb, (offset+tlv_offset), 1, FALSE);
								break;
							}
#endif
							default:
								/* ??? */
								break;
						}
						tlv_offset += length;
					}
					break;
				}
				case UCD_RESERVATION_TIMEOUT:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_res_timeout, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_ucd_res_timeout, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_BW_REQ_SIZE:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_bw_req_size, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_bw_req_size, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " PS");
					break;
				}
				case UCD_RANGING_REQ_SIZE:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_ranging_req_size, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_ranging_req_size, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " PS");
					break;
				}
				case UCD_FREQUENCY:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_freq, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_freq, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " kHz");
					break;
				}
				case UCD_TLV_T_7_HO_RANGING_START:
				{
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "HO ranging start (SCa, OFDM, OFDMA (mobile only)) (%u byte(s))", tlv_len);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_text(tlv_tree, tvb, offset, tvb_len, "Initial Backoff Window Size for MS Performing Initial During Handover Process: 2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_8_RANGING_HO_END:
				{
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "HO ranging end (SCa, OFDM, OFDMA (mobile only)) (%u byte(s))", tlv_len);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_text(tlv_tree, tvb, offset, tvb_len, "Final Backoff Window Size for MS Performing Initial During Handover Process: 2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_158_OPTIONAL_PERMUTATION_UL_ALLOCATED_SUBCHANNELS_BITMAP:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_158_optional_permutation_ul_allocated_subchannels_bitmap, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_158_optional_permutation_ul_allocated_subchannels_bitmap, tvb, offset, tlv_len, FALSE);

					break;
				}
				case UCD_TLV_T_159_BAND_AMC_ALLOCATION_THRESHHOLD:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_159_band_amc_allocation_threshold, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_159_band_amc_allocation_threshold, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " dB");
					break;
				}
				case UCD_TLV_T_160_BAND_AMC_RELEASE_THRESHOLD:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_160_band_amc_release_threshold, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_160_band_amc_release_threshold, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " dB");
					break;
				}
				case UCD_TLV_T_161_BAND_AMC_ALLOCATION_TIMER:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_161_band_amc_allocation_timer, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_161_band_amc_allocation_timer, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " frames");
					break;
				}
				case UCD_TLV_T_162_BAND_AMC_RELEASE_TIMER:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_161_band_amc_allocation_timer, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_162_band_amc_release_timer, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " frames");
					break;
				}
				case UCD_TLV_T_163_BAND_STATUS_REPORT_MAX_PERIOD:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_163_band_status_report_max_period, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_163_band_status_report_max_period, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " frames");
					break;
				}
				case UCD_TLV_T_164_BAND_AMC_RETRY_TIMER:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_164_band_amc_retry_timer, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_164_band_amc_retry_timer, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " frames");
					break;
				}
				case UCD_TLV_T_170_SAFETY_CHANNEL_RETRY_TIMER:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_170_safety_channel_retry_timer, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_170_safety_channel_retry_timer, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " frames");
					break;
				}
				case UCD_TLV_T_171_HARQ_ACK_DELAY_FOR_DL_BURST:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_171_harq_ack_delay_dl_burst, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_171_harq_ack_delay_dl_burst, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " frames offset");
					break;
				}
				case UCD_TLV_T_172_CQICH_BAND_AMC_TRANSITION_DELAY:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_172_cqich_band_amc_transition_delay, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_172_cqich_band_amc_transition_delay, tvb, offset, tlv_len, FALSE);
					proto_item_append_text(tlv_item, " frames");
					break;
				}
				case UCD_TLV_T_174_MAXIMUM_RETRANSMISSION:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_174_maximum_retransmission, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_174_maximum_retransmission, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_176_SIZE_OF_CQICH_ID_FIELD:
				{
					utemp = tvb_get_guint8(tvb, offset);
					cqich_id_size = 0;	/* Default is 0 */
					if (utemp && utemp < 8) {
					    /* Set for CQICH_Alloc_IE */
					    cqich_id_size = utemp + 2;
					}
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_176_size_of_cqich_id_field, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_176_size_of_cqich_id_field, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_177_NORMALIZED_CN_OVERRIDE_2:
				{
					/* add TLV subtree */
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_177_normalized_cn_override2, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_177_normalized_cn_override2_first_line, tvb, offset + 2, 1, FALSE);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_177_normalized_cn_override2_list, tvb, offset + 3, 7, FALSE);
					break;
				}
				case UCD_TLV_T_186_UPPER_BOUND__AAS_PREAMBLE:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_186_upper_bound_aas_preamble, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_186_upper_bound_aas_preamble, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_187_LOWER_BOUND_AAS_PREAMBLE:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_187_lower_bound_aas_preamble, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_187_lower_bound_aas_preamble, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_188_ALLOW_AAS_BEAM_SELECT_MESSAGE:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_188_allow_aas_beam_select_message, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_188_allow_aas_beam_select_message, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_189_USE_CQICH_INDICATION_FLAG:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_189_use_cqich_indication_flag, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_189_use_cqich_indication_flag, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_190_MS_SPECIFIC_UP_POWER_OFFSET_ADJUSTMENT_STEP:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_190_ms_specific_up_power_addjustment_step, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_190_ms_specific_up_power_addjustment_step, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_191_MS_SPECIFIC_DOWN_POWER_OFSET_ADJUSTMENT_STEP:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_191_ms_specific_down_power_addjustment_step, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_191_ms_specific_down_power_addjustment_step, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_192_MIN_LEVEL_POWER_OFFSET_ADJUSTMENT:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_192_min_level_power_offset_adjustment, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_192_min_level_power_offset_adjustment, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_193_MAX_LEVEL_POWER_OFFSETR_ADJUSTMENT:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_193_max_level_power_offset_adjustment, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_193_max_level_power_offset_adjustment, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_194_HANDOVER_RANGING_CODES:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_194_handover_ranging_codes, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_194_handover_ranging_codes, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_195_INITIAL_RANGING_INTERVAL:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_195_initial_ranging_interval, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_195_initial_ranging_interval, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_196_TX_POWER_REPORT:
				{
					/* add TLV subtree */
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "Tx Power Report (%u bytes)", tlv_len);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_threshold, tvb, offset, 1, FALSE);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_interval, tvb , offset, 1, FALSE);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_a_p_avg, tvb, (offset + 1), 1, FALSE);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_threshold_icqch, tvb, (offset + 1), 1, FALSE);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_interval_icqch, tvb, (offset + 2), 1, FALSE);
					proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_196_tx_power_report_a_p_avg_icqch, tvb, (offset + 2), 1, FALSE);
					break;
				}
				case UCD_TLV_T_197_NORMALIZED_CN_FOR_CHANNEL_SOUNDING:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_195_initial_ranging_interval, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_197_normalized_cn_channel_sounding, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_198_INTIAL_RANGING_BACKOFF_START:
				{
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "Initial ranging backoff start (%u byte(s))", tlv_len);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_text(tlv_tree, tvb, offset, tvb_len, "Initial Ranging Backoff Start: 2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_199_INITIAL_RANGING_BACKOFF_END:
				{
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "Initial ranging backoff end (%u byte(s))", tlv_len);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_text(tlv_tree, tvb, offset, tvb_len, "Initial Ranging Backoff End: 2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_200_BANDWIDTH_REQUESET_BACKOFF_START:
				{
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "Bandwidth request backoff start (%u byte(s))", tlv_len);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_text(tlv_tree, tvb, offset, tvb_len, "Bandwidth Request Backoff Start: 2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_201_BANDWIDTH_REQUEST_BACKOFF_END:
				{
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "Bandwidth request backoff end (%u byte(s))", tlv_len);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_text(tlv_tree, tvb, offset, tvb_len, "Bandwidth Request Backoff End: 2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_TLV_T_202_UPLINK_BURST_PROFILE_FOR_MULTIPLE_FEC_TYPES:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_202_uplink_burst_profile_for_multiple_fec_types, tvb, offset, tlv_len, FALSE);
					tlv_item = proto_tree_add_item(tlv_tree, hf_ucd_tlv_t_202_uplink_burst_profile_for_multiple_fec_types, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_INITIAL_RANGING_CODES:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_150_initial_ranging_codes, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree,hf_ucd_tlv_t_150_initial_ranging_codes, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_PERIODIC_RANGING_CODES:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_151_periodic_ranging_codes, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree,hf_ucd_tlv_t_151_periodic_ranging_codes, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_BANDWIDTH_REQUEST_CODES:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_152_bandwidth_request_codes, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree,hf_ucd_tlv_t_152_bandwidth_request_codes, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_PERIODIC_RANGING_BACKOFF_START:
				{
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "Periodic ranging backoff start (%u byte(s))", tlv_len);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_text(tlv_tree, tvb, offset, tlv_len, "Periodic Ranging Backoff Start: 2^%u = %u", utemp, (1 << utemp));
					break;

				}
				case UCD_PERIODIC_RANGING_BACKOFF_END:
				{
					tlv_tree = add_protocol_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "Periodic ranging backoff end (%u bytes(s))", tlv_len);
					utemp = tvb_get_guint8(tvb, offset);
					proto_tree_add_text(tlv_tree, tvb, offset, tlv_len, "Periodic Ranging Backoff End: 2^%u = %u", utemp, (1 << utemp));
					break;
				}
				case UCD_START_OF_RANGING_CODES_GROUP:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_155_start_of_ranging_codes_group, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree,hf_ucd_tlv_t_155_start_of_ranging_codes_group, tvb, offset, tlv_len, FALSE);
					break;

				}
				case UCD_PERMUTATION_BASE:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_tlv_t_156_permutation_base, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree,hf_ucd_tlv_t_156_permutation_base, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_UL_ALLOCATED_SUBCHANNELS_BITMAP:
				{
					tlv_tree = add_tlv_subtree(&tlv_info, ett_mac_mgmt_msg_ucd_decoder, ucd_tree, hf_ucd_ul_allocated_subchannles_bitmap, tvb, offset, tlv_len, FALSE);
					proto_tree_add_item(tlv_tree, hf_ucd_ul_allocated_subchannles_bitmap, tvb, offset, tlv_len, FALSE);
					break;
				}
				case UCD_TLV_T_203_UL_PUSC_SUBCHANNEL_ROTATION:
				case UCD_TLV_T_205_RELATIVE_POWER_OFFSET_UL_HARQ_BURST:
				case UCD_TLV_T_206_RELATIVE_POWER_OFFSET_UL_BURST_CONTAINING_MAC_MGMT_MSG:
				case UCD_TLV_T_207_UL_INITIAL_TRANSMIT_TIMING:
				case UCD_TLV_T_210_FAST_FEEDBACK_REGION:
				case UCD_TLV_T_211_HARQ_ACK_REGION:
				case UCD_TLV_T_212_RANGING_REGION:
				case UCD_TLV_T_213_SOUNDING_REGION:
				{
					/* Unknown TLV type if cor2 not enabled. */
					if (!include_cor2_changes)
					{
						proto_tree_add_protocol_format(ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "Unknown TLV Type");
					}
					break;
				}
				default:
				{
					proto_tree_add_protocol_format(ucd_tree, proto_mac_mgmt_msg_ucd_decoder, tvb, offset, tlv_len, "Unknown TLV Type");
				}
			}	/* end of switch */
			offset += tlv_len;
		}	/* end of TLV process while loop */
	}
}
Example #15
0
        }
    }
}

static int
dissect_djiuav_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{
    proto_item		*ti;
    proto_tree		*djiuav_tree = NULL;
    guint32			offset = 0;
    guint32			pdu_length;
    guint8			packet_type;
    gboolean		is_cmd;

    is_cmd = (pinfo->match_uint == pinfo->destport);
    packet_type = tvb_get_guint8(tvb, 6);

    col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
    col_add_str(pinfo->cinfo, COL_INFO, is_cmd?"C: ":"R: ");
    col_append_str(pinfo->cinfo, COL_INFO, val_to_str(packet_type,
                   djiuav_pdu_type, "Type 0x%02x"));

    ti = proto_tree_add_item(tree, proto_djiuav, tvb, offset, -1, ENC_NA);
    djiuav_tree = proto_item_add_subtree(ti, ett_djiuav);

    request_response_handling(tvb, pinfo, djiuav_tree, offset);

    if (tree) {
        proto_tree_add_item(djiuav_tree, hf_djiuav_magic, tvb, offset, 2,
                            ENC_BIG_ENDIAN);
        offset += 2;
Example #16
0
/* Initialize the subtree pointers */
static gint ett_docsis_bpkmreq = -1;

static dissector_handle_t attrs_handle;

/* Dissection */
static int
dissect_bpkmreq (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void* data _U_)
{
  proto_item *it;
  proto_tree *bpkmreq_tree;
  guint8 code;
  tvbuff_t *attrs_tvb;

  code = tvb_get_guint8 (tvb, 0);

  col_add_fstr (pinfo->cinfo, COL_INFO, "BPKM Request (%s)",
                val_to_str (code, code_field_vals, "%d"));

  if (tree)
    {
      it =
        proto_tree_add_protocol_format (tree, proto_docsis_bpkmreq, tvb, 0, -1,
                                        "BPKM Request Message");
      bpkmreq_tree = proto_item_add_subtree (it, ett_docsis_bpkmreq);
      proto_tree_add_item (bpkmreq_tree, hf_docsis_bpkmreq_code, tvb, 0, 1,
                           ENC_BIG_ENDIAN);
      proto_tree_add_item (bpkmreq_tree, hf_docsis_bpkmreq_ident, tvb, 1, 1,
                           ENC_BIG_ENDIAN);
      proto_tree_add_item (bpkmreq_tree, hf_docsis_bpkmreq_length, tvb, 2, 2,
Example #17
0
static void
request_response_handling(tvbuff_t *tvb, packet_info *pinfo, proto_tree *djiuav_tree,
                          guint32 offset)
{
    conversation_t		*conversation;
    djiuav_conv_info_t	*djiuav_info;
    djiuav_transaction_t	*djiuav_trans;

    guint16			seq_no;
    gboolean		is_cmd;
    guint8			packet_type;

    is_cmd = (pinfo->match_uint == pinfo->destport);
    seq_no = tvb_get_letohs(tvb, offset + 4);
    packet_type = tvb_get_guint8(tvb, offset + 6);

    conversation = find_or_create_conversation(pinfo);
    djiuav_info = (djiuav_conv_info_t *)conversation_get_proto_data(conversation, proto_djiuav);
    if (!djiuav_info) {
        djiuav_info = wmem_new(wmem_file_scope(), djiuav_conv_info_t);
        djiuav_info->pdus=wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);

        conversation_add_proto_data(conversation, proto_djiuav, djiuav_info);
    }
    if (!pinfo->fd->flags.visited) {
        if (is_cmd) {
            djiuav_trans=wmem_new(wmem_file_scope(), djiuav_transaction_t);
            djiuav_trans->request_frame=pinfo->fd->num;
            djiuav_trans->reply_frame=0;
            djiuav_trans->request_time=pinfo->fd->abs_ts;
            djiuav_trans->seqno=seq_no;
            djiuav_trans->command=packet_type;
            wmem_map_insert(djiuav_info->pdus, GUINT_TO_POINTER((guint)seq_no), (void *)djiuav_trans);
        } else {
            djiuav_trans=(djiuav_transaction_t *)wmem_map_lookup(djiuav_info->pdus, GUINT_TO_POINTER((guint)seq_no));
            if (djiuav_trans) {
                /* Special case: djiuav seems to send 0x24 replies with seqno 0 and without a request */
                if (djiuav_trans->reply_frame == 0)
                    djiuav_trans->reply_frame=pinfo->fd->num;
            }
        }
    } else {
        djiuav_trans=(djiuav_transaction_t *)wmem_map_lookup(djiuav_info->pdus, GUINT_TO_POINTER((guint)seq_no));
    }

    /* djiuav_trans may be 0 in case it's a reply without a matching request */

    if (djiuav_tree && djiuav_trans) {
        if (is_cmd) {
            if (djiuav_trans->reply_frame) {
                proto_item *it;

                it = proto_tree_add_uint(djiuav_tree, hf_djiuav_response_in,
                                         tvb, 0, 0, djiuav_trans->reply_frame);
                PROTO_ITEM_SET_GENERATED(it);
            }
        } else {
            if (djiuav_trans->request_frame) {
                proto_item *it;
                nstime_t ns;

                it = proto_tree_add_uint(djiuav_tree, hf_djiuav_response_to,
                                         tvb, 0, 0, djiuav_trans->request_frame);
                PROTO_ITEM_SET_GENERATED(it);

                nstime_delta(&ns, &pinfo->fd->abs_ts, &djiuav_trans->request_time);
                it = proto_tree_add_time(djiuav_tree, hf_djiuav_response_time, tvb, 0, 0, &ns);
                PROTO_ITEM_SET_GENERATED(it);
            }
        }
    }
}
Example #18
0
static int hf_wow_realm_num_characters = -1;
static int hf_wow_realm_timezone = -1;

static gboolean wow_preference_desegment = TRUE;

static gint ett_wow = -1;
static gint ett_wow_realms = -1;

static guint
get_wow_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset, void *data _U_)
{
	gint8 size_field_offset = -1;
	guint8 cmd;
	guint16 pkt_len;

	cmd = tvb_get_guint8(tvb, offset);

	if(WOW_SERVER_TO_CLIENT && cmd == REALM_LIST)
		size_field_offset = 1;
	if(WOW_CLIENT_TO_SERVER && cmd == AUTH_LOGON_CHALLENGE)
		size_field_offset = 2;

	pkt_len = tvb_get_letohs(tvb, size_field_offset);

	return pkt_len + size_field_offset + 2;
}


static int
dissect_wow_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
Example #19
0
static int
dissect_btsmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    int          offset = 0;
    proto_item  *ti;
    proto_tree  *st;
    guint8      opcode;
    guint32     interface_id;
    guint32     adapter_id;
    gint        previous_proto;

    interface_id = HCI_INTERFACE_DEFAULT;
    adapter_id = HCI_ADAPTER_DEFAULT;
    previous_proto = (GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers)))));
    if (data && previous_proto == proto_btl2cap) {
        btl2cap_data_t *l2cap_data;

        l2cap_data = (btl2cap_data_t *) data;
        if (l2cap_data) {
            interface_id = l2cap_data->interface_id;
            adapter_id = l2cap_data->adapter_id;
        }
    }

    ti = proto_tree_add_item(tree, proto_btsmp, tvb, 0, tvb_captured_length(tvb), ENC_NA);
    st = proto_item_add_subtree(ti, ett_btsmp);

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMP");

    switch (pinfo->p2p_dir) {
    case P2P_DIR_SENT:
        col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
        break;
    case P2P_DIR_RECV:
        col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
        break;
    default:
        col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
        break;
    }

    if (tvb_reported_length(tvb) < 1)
        return FALSE;

    proto_tree_add_item(st, hf_btsmp_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN);
    opcode = tvb_get_guint8(tvb, 0);
    offset++;

    col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, opcode_vals, "<unknown>"));

    switch (opcode) {
    case 0x01: /* Pairing Request */
    case 0x02: /* Pairing Response */
    {
        col_append_str(pinfo->cinfo, COL_INFO, ": ");

        proto_tree_add_item(st, hf_btsmp_io_capabilities, tvb, offset, 1, ENC_LITTLE_ENDIAN);
        offset++;
        proto_tree_add_item(st, hf_btsmp_oob_data_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
        offset++;

        offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st);

        proto_tree_add_item(st, hf_btsmp_max_enc_key_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
        offset++;

        offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, TRUE);
        offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, FALSE);
        break;
    }

    case 0x03: /* Pairing Confirm */
        proto_tree_add_item(st, hf_btsmp_cfm_value, tvb, offset, 16, ENC_NA);
        offset += 16;
        break;

    case 0x04: /* Pairing Random */
        proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 16, ENC_NA);
        offset += 16;
        break;

    case 0x05: /* Pairing Failed */
        proto_tree_add_item(st, hf_btsmp_reason, tvb, offset, 1, ENC_LITTLE_ENDIAN);
        col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(tvb_get_guint8(tvb, offset), reason_vals, "<unknown>"));
        offset++;
        break;

    case 0x06: /* Encryption Information */
        proto_tree_add_item(st, hf_btsmp_long_term_key, tvb, offset, 16, ENC_NA);
        offset += 16;
        break;

    case 0x07: /* Master Identification */
        proto_tree_add_item(st, hf_btsmp_ediv, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;
        proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 8, ENC_NA);
        offset += 8;
        break;

    case 0x08: /* Identity Information */
        proto_tree_add_item(st, hf_btsmp_id_resolving_key, tvb, offset, 16, ENC_NA);
        offset += 16;
        break;

    case 0x09: /* Identity Address Information */
        proto_tree_add_item(st, hf_address_type, tvb, offset, 1, ENC_NA);
        offset += 1;

        offset = dissect_bd_addr(hf_bd_addr, pinfo, st, tvb, offset, FALSE, interface_id, adapter_id, NULL);
        break;

    case 0x0a: /* Signing Information */
        proto_tree_add_item(st, hf_btsmp_signature_key, tvb, offset, 16, ENC_NA);
        offset += 16;
        break;

    case 0x0b: /* Security Request */
        col_append_str(pinfo->cinfo, COL_INFO, ": ");
        offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st);
        break;

    default:
        break;
    }

    return offset;
}
Example #20
0
/* dissect a UHD header and hand payload off to respective dissector */
static void
dissect_uhd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	int	    ind;
	proto_item *ti;
	proto_tree *uhd_tree;
	guint32	    id;
	guint8	    i2c_bytes;

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "UHD");
	col_clear(pinfo->cinfo, COL_INFO);

	id = tvb_get_ntohl(tvb, 4);

	col_add_str(pinfo->cinfo, COL_INFO, val_to_str(id, uhd_ids, "Unknown UHD message type '%c'"));

	if (tree == NULL)
		return;

	ti = proto_tree_add_protocol_format(tree, proto_uhd, tvb, 0, 34, "UHD id = %c ", id);
	uhd_tree = proto_item_add_subtree(ti, ett_uhd);

	proto_tree_add_item(uhd_tree, hf_uhd_version, tvb, 0, 4, ENC_BIG_ENDIAN);
	proto_tree_add_item(uhd_tree, hf_uhd_id,      tvb, 4, 4, ENC_BIG_ENDIAN);
	proto_tree_add_item(uhd_tree, hf_uhd_seq,     tvb, 8, 4, ENC_BIG_ENDIAN);

	switch (id) {
		case UMTRX_CTRL_ID_REQUEST:
		case UMTRX_CTRL_ID_RESPONSE:
		case USRP2_CTRL_ID_WAZZUP_BRO:
		case USRP2_CTRL_ID_WAZZUP_DUDE:
			proto_tree_add_item(uhd_tree, hf_uhd_ip_addr,       tvb, 12, 4, ENC_BIG_ENDIAN);
			break;
		case USRP2_CTRL_ID_TRANSACT_ME_SOME_SPI_BRO:
		case USRP2_CTRL_ID_OMG_TRANSACTED_SPI_DUDE:
			proto_tree_add_item(uhd_tree, hf_uhd_spi_dev,	    tvb, 12, 4, ENC_BIG_ENDIAN);
			proto_tree_add_item(uhd_tree, hf_uhd_spi_data,	    tvb, 16, 4, ENC_BIG_ENDIAN);
			proto_tree_add_item(uhd_tree, hf_uhd_spi_miso_edge, tvb, 20, 1, ENC_BIG_ENDIAN);
			proto_tree_add_item(uhd_tree, hf_uhd_spi_mosi_edge, tvb, 21, 1, ENC_BIG_ENDIAN);
			proto_tree_add_item(uhd_tree, hf_uhd_spi_num_bits,  tvb, 22, 1, ENC_BIG_ENDIAN);
			proto_tree_add_item(uhd_tree, hf_uhd_spi_readback,  tvb, 23, 1, ENC_BIG_ENDIAN);
			break;
		case USRP2_CTRL_ID_DO_AN_I2C_READ_FOR_ME_BRO:
		case USRP2_CTRL_ID_HERES_THE_I2C_DATA_DUDE:
		case USRP2_CTRL_ID_WRITE_THESE_I2C_VALUES_BRO:
		case USRP2_CTRL_ID_COOL_IM_DONE_I2C_WRITE_DUDE:
			proto_tree_add_item(uhd_tree, hf_uhd_i2c_addr, tvb, 12, 1, ENC_BIG_ENDIAN);
			i2c_bytes = tvb_get_guint8(tvb, 13);
			proto_tree_add_item(uhd_tree, hf_uhd_i2c_bytes, tvb, 13, 1, ENC_BIG_ENDIAN);
			for (ind = 0; ind < i2c_bytes; ind++) {
				proto_tree_add_item(uhd_tree, hf_uhd_i2c_data, tvb, 14 + ind, 1, ENC_BIG_ENDIAN);
			}
			break;
		case USRP2_CTRL_ID_GET_THIS_REGISTER_FOR_ME_BRO:
		case USRP2_CTRL_ID_OMG_GOT_REGISTER_SO_BAD_DUDE:
			proto_tree_add_item(uhd_tree, hf_uhd_reg_addr,	 tvb, 12, 4, ENC_BIG_ENDIAN);
			proto_tree_add_item(uhd_tree, hf_uhd_reg_data,	 tvb, 16, 4, ENC_BIG_ENDIAN);
			proto_tree_add_item(uhd_tree, hf_uhd_reg_action, tvb, 20, 1, ENC_BIG_ENDIAN);
			break;
		case USRP2_CTRL_ID_HOLLER_AT_ME_BRO:
		case USRP2_CTRL_ID_HOLLER_BACK_DUDE:
		case USRP2_CTRL_ID_HUH_WHAT:
		case USRP2_CTRL_ID_PEACE_OUT:
			proto_tree_add_item(uhd_tree, hf_uhd_echo_len,   tvb, 12, 4, ENC_BIG_ENDIAN);
			break;
	}
}
Example #21
0
static guint16
dissect_channel_send(tvbuff_t *tvb, proto_tree *tree, int offset)
{
   guint16 send_type, awareness;
   guint na;

   send_type = tvb_get_ntohs(tvb, offset);
   proto_item_append_text(tree, ", %s", val_to_str(send_type, sendtypenames, "0x%04x"));
   proto_tree_add_item(tree, hf_sametime_channel_send_type, tvb, offset, 2, ENC_BIG_ENDIAN);
   offset += 2;

   switch (send_type)        {
      case SAMETIME_SENDTYPE_AWARE_ADD:
         offset += 8;
         awareness = tvb_get_ntohs(tvb, offset);
         proto_item_append_text(tree, ", %s", val_to_str(awareness, awarenessnames, "0x%04x"));
         proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN);
         offset += 2;
         add_text_item(tvb, tree, offset, hf_sametime_field_text);

         break;

      case SAMETIME_SENDTYPE_OPT_DO_SET:
         offset += 20;
         na = tvb_get_ntohl(tvb, offset);
         offset += 4;
         if (na == 0x33)        {
            offset += add_text_item(tvb, tree, offset, hf_sametime_location_country);
            offset += add_text_item(tvb, tree, offset, hf_sametime_location_postalcode);
            offset += add_text_item(tvb, tree, offset, hf_sametime_location_province);
            offset += add_text_item(tvb, tree, offset, hf_sametime_location_city);
            offset += add_text_item(tvb, tree, offset, hf_sametime_location_phone);
            offset += 1;
            offset += add_text_item(tvb, tree, offset, hf_sametime_location_name);
            add_text_item(tvb, tree, offset, hf_sametime_location_timezone);
         } else        {
            add_text_item(tvb, tree, offset, hf_sametime_field_text);
         }

         break;

      case SAMETIME_SENDTYPE_OPT_GOT_SET:
         offset += 8;
         awareness = tvb_get_ntohs(tvb, offset);
         proto_item_append_text(tree, ", %s", val_to_str(awareness, awarenessnames, "0x%04x"));
         proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN);
         offset += 2;
         while (tvb_reported_length_remaining(tvb, offset) > 2)        {
            int n = add_text_item(tvb, tree, offset, hf_sametime_field_text);
            offset += (n) ? n : 1;
         }

         break;

      case SAMETIME_SENDTYPE_AWARE_SNAPSHOT:
         offset += 12;
         awareness = tvb_get_ntohs(tvb, offset);
         proto_item_append_text(tree, ", %s", val_to_str(awareness, awarenessnames, "0x%04x"));
         proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN);
         offset += 2;
         add_text_item(tvb, tree, offset, hf_sametime_field_text);

         break;

      case SAMETIME_SENDTYPE_AWARE_UPDATE:
         offset += 4;
         offset += 4;
         awareness = tvb_get_ntohs(tvb, offset);
         proto_item_append_text(tree, ", %s", val_to_str(awareness, awarenessnames, "0x%04x"));
         proto_tree_add_item(tree, hf_sametime_channel_awareness, tvb, offset, 2, ENC_BIG_ENDIAN);
         offset += 2;
         offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
         offset += 4;
         if (tvb_get_guint8(tvb, offset))        {
            offset += 1;
            offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
            dissect_set_user_status(tvb, tree, offset);
         }

         break;

      case 0x0000:
         offset += 14;
         add_text_item(tvb, tree, offset, hf_sametime_field_text);

         break;

      case 0x0002:
         offset += 8;
         offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
         offset += 3;
         add_text_item(tvb, tree, offset, hf_sametime_field_text);

         break;

      case 0x0005:        /* XML */
         if (26 <= tvb_reported_length_remaining(tvb, offset + 2))        {
            offset += 26;
            add_text_item(tvb, tree, offset, hf_sametime_field_text);
         }

         break;

      case 0x0007:
         offset += 8;
         if (4 <= tvb_reported_length_remaining(tvb, offset + 2))        {
            offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
            offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
            offset += 3;
            offset += add_text_item(tvb, tree, offset, hf_sametime_field_text);
            add_text_item(tvb, tree, offset, hf_sametime_field_text);
         }

         break;

      case 0x025a:
         offset += 10;
         add_text_item(tvb, tree, offset, hf_sametime_field_text);

         break;

      default:
         break;
   }

   return send_type;
}
static void
dissect_ppi_antenna(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
    /* The fixed values up front */
    guint32 version;
    guint length;
    gint  length_remaining;

    proto_tree *ppi_antenna_tree = NULL;
    proto_tree *antennaflags_tree = NULL;
    proto_tree *pt, *my_pt;
    proto_item *ti = NULL;
    proto_item *antenna_line = NULL;


    /* bits */
    int bit;
    guint32 present, next_present;
    /* values actually read out, for displaying */
    guint8 gaindb;
    guint16 beamid;
    guint32 t_hbw, t_vbw, t_pgain, t_appspecific_num; /* temporary conversions */
    gdouble horizbw, vertbw, pgain;
    guint32 flags;
    gchar *curr_str;
    int offset = 0;

    static const int * ppi_antenna_present_flags[] = {
        &hf_ppi_antenna_present_flags,
        &hf_ppi_antenna_present_gaindb,
        &hf_ppi_antenna_present_horizbw,
        &hf_ppi_antenna_present_vertbw,
        &hf_ppi_antenna_present_pgain,
        &hf_ppi_antenna_present_beamid,
        &hf_ppi_antenna_present_serialnum,
        &hf_ppi_antenna_present_modelname,
        &hf_ppi_antenna_present_descstr,
        &hf_ppi_antenna_present_appspecific_num,
        &hf_ppi_antenna_present_appspecific_data,
        &hf_ppi_antenna_present_ext,
        NULL
    };

    /* Clear out stuff in the info column */
    col_clear(pinfo->cinfo,COL_INFO);

    /* pull out the first three fields of the BASE-GEOTAG-HEADER */
    version = tvb_get_guint8(tvb, offset);
    length  = tvb_get_letohs(tvb, offset+2);
    present = tvb_get_letohl(tvb, offset+4);

    /* Setup basic column info */
    col_add_fstr(pinfo->cinfo, COL_INFO, "PPI Antenna info v%u, Length %u",
                     version, length);


    /* Create the basic dissection tree*/
    if (tree) {
        ti = proto_tree_add_protocol_format(tree, proto_ppi_antenna,
                                            tvb, 0, length, "Antenna: ");
        antenna_line = ti; /* save this for later, we will fill it in with more detail */

        ppi_antenna_tree= proto_item_add_subtree(ti, ett_ppi_antenna);
        proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_version,
                            tvb, offset, 1, version);
        proto_tree_add_item(ppi_antenna_tree, hf_ppi_antenna_pad,
                            tvb, offset + 1, 1, ENC_LITTLE_ENDIAN);
        ti = proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_length,
                                 tvb, offset + 2, 2, length);
    }
    /* We support v1 and v2 of Antenna tags (identical) */
    if (! (version == 1 || version == 2) ) {
        if (tree)
            proto_item_append_text(ti, "invalid version (got %d,  expected 1 or 2)", version);
        return;
    }

    length_remaining = length;
    /* minimum length check, should atleast be a fixed-size geotagging-base header*/
    if (length_remaining < PPI_GEOBASE_MIN_HEADER_LEN) {
        /*
         * Base-geotag-header (Radiotap lookalike) is shorter than the fixed-length portion
         * plus one "present" bitset.
         */
        proto_item_append_text(ti, " (invalid - minimum length is 8)");
        return;
    }


    /* perform max length sanity checking */
    if (length > PPI_ANTENNA_MAXTAGLEN ) {
        proto_item_append_text(ti, "Invalid PPI-Antenna length  (got %d, %d max\n)", length, PPI_ANTENNA_MAXTAGLEN);
        return;
    }

    /* Subtree for the "present flags" bitfield. */
    pt = proto_tree_add_bitmask(ppi_antenna_tree, tvb, offset + 4, hf_ppi_antenna_present, ett_ppi_antenna_present, ppi_antenna_present_flags, ENC_LITTLE_ENDIAN);

    offset += PPI_GEOBASE_MIN_HEADER_LEN;
    length_remaining -= PPI_GEOBASE_MIN_HEADER_LEN;

    /* Now all of the fixed length, fixed location stuff is over. Loop over the bits */
    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  PPI_ANTENNA_ANTFLAGS:
            if (length_remaining < 4)
                break;
            flags = tvb_get_letohl(tvb, offset);
            if (tree) {
                my_pt = proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_flags, tvb, offset , 4, flags);
                /*Add antenna_flags bitfields here */
                antennaflags_tree= proto_item_add_subtree(my_pt, ett_ppi_antennaflags);

                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_mimo, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_horizpol, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_vertpol, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_circpol_l, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_circpol_r, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_steer_elec, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(antennaflags_tree, hf_ppi_antennaflags_steer_mech, tvb, offset, 4, ENC_LITTLE_ENDIAN);
            }
            offset+=4;
            length_remaining-=4;
            break;
        case PPI_ANTENNA_GAINDB:
            if (length_remaining < 1)
                break;
            gaindb=  tvb_get_guint8(tvb, offset);
            if (tree) {
                proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_gaindb, tvb, offset, 1, gaindb);
                proto_item_append_text(antenna_line, " Gain: %d", gaindb);

            }
            offset+=1;
            length_remaining-=1;
            break;
        case  PPI_ANTENNA_HORIZBW:
            if (length_remaining < 4)
                break;
            t_hbw = tvb_get_letohl(tvb, offset);
            horizbw =  ppi_fixed3_6_to_gdouble(t_hbw);
            if (tree) {
                proto_tree_add_double(ppi_antenna_tree, hf_ppi_antenna_horizbw, tvb, offset, 4, horizbw);
                proto_item_append_text(antenna_line, " HorizBw: %f", horizbw);
            }
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_ANTENNA_VERTBW:
            if (length_remaining < 4)
                break;
            t_vbw = tvb_get_letohl(tvb, offset);
            vertbw =  ppi_fixed3_6_to_gdouble(t_vbw);
            proto_tree_add_double(ppi_antenna_tree, hf_ppi_antenna_vertbw, tvb, offset, 4, vertbw);
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_ANTENNA_PGAIN:
            if (length_remaining < 4)
                break;
            t_pgain = tvb_get_letohl(tvb, offset);
            pgain   = ppi_fixed3_6_to_gdouble(t_pgain);
            proto_tree_add_double(ppi_antenna_tree, hf_ppi_antenna_pgain, tvb, offset, 4, pgain);
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_ANTENNA_BEAMID:
            if (length_remaining < 2)
                break;
            beamid= tvb_get_letohs(tvb, offset); /* convert endianess */
            proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_beamid, tvb, offset, 2, beamid);
            offset+=2;
            length_remaining-=2;
            break;
        case  PPI_ANTENNA_SERIALNUM:
            if (length_remaining < 32)
                break;
            proto_tree_add_item(ppi_antenna_tree, hf_ppi_antenna_serialnum, tvb, offset, 32, ENC_ASCII|ENC_NA);
            offset+=32;
            length_remaining-=32;
            break;

        case  PPI_ANTENNA_MODELSTR:
            if (length_remaining < 32)
                break;
            if (tree) {
                /* proto_tree_add_item(ppi_antenna_tree, hf_ppi_antenna_modelname, tvb, offset, 32, ENC_ASCII|ENC_NA); */
                curr_str = tvb_format_stringzpad(tvb, offset, 32);
                proto_tree_add_string(ppi_antenna_tree, hf_ppi_antenna_modelname, tvb, offset, 32, curr_str);
                proto_item_append_text(antenna_line, " (%s)", curr_str);
            }
            offset+=32;
            length_remaining-=32;
            break;
        case  PPI_ANTENNA_DESCSTR:
            if (length_remaining < 32)
                break;
            if (tree) {
                /*proto_tree_add_item(ppi_antenna_tree, hf_ppi_antenna_descstr, tvb, offset, 32, ENC_ASCII|ENC_NA);*/
                curr_str = tvb_format_stringzpad(tvb, offset, 32);
                proto_tree_add_string(ppi_antenna_tree, hf_ppi_antenna_descstr, tvb, offset, 32, curr_str);
                proto_item_append_text(antenna_line, " (%s)", curr_str);
            }
            offset+=32;
            length_remaining-=32;
            break;
        case  PPI_ANTENNA_APPID:
            if (length_remaining < 4)
                break;
            t_appspecific_num  = tvb_get_letohl(tvb, offset); /* application specific parsers may switch on this later */
            proto_tree_add_uint(ppi_antenna_tree, hf_ppi_antenna_appspecific_num, tvb, offset, 4, t_appspecific_num);
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_ANTENNA_APPDATA:
            if (length_remaining < 60)
                break;
            proto_tree_add_item(ppi_antenna_tree, hf_ppi_antenna_appspecific_data, tvb, offset, 60,  ENC_NA);
            offset+=60;
            length_remaining-=60;
            break;
        default:
            /*
             * This indicates a field whose size we do not
             * know, so we cannot proceed.
             */
            expert_add_info_format(pinfo, pt, &ei_ppi_antenna_present_bit,
                                "Error: PPI-ANTENNA: unknown bit (%d) set in present field.", bit);
            next_present = 0;
            continue;
        }

    };
    return;
}
Example #23
0
static void dissect_msproxy_request(tvbuff_t *tvb,
	proto_tree *tree, hash_entry_t *conv_info) {

	int offset = 0;
	int cmd;

	if ( tree) {
		proto_tree_add_text( tree, tvb, offset, 4, "Client id: 0x%0x",
			tvb_get_letohl( tvb, offset));
		offset += 4;

		proto_tree_add_text( tree, tvb, offset, 4, "Version: 0x%04x",
			tvb_get_letohl( tvb, offset));
		offset += 4;

		proto_tree_add_text( tree, tvb, offset, 4, "Server id: 0x%0x",
			tvb_get_letohl( tvb, offset));
		offset += 4;

		proto_tree_add_text( tree, tvb, offset, 1, "Server ack: %u",
			tvb_get_guint8( tvb, offset));
		offset += 4;

		proto_tree_add_text( tree, tvb, offset, 1, "Sequence Number: %u",
			tvb_get_guint8( tvb, offset));
		offset += 8;

		proto_tree_add_text( tree, tvb, offset, 4, "RWSP signature: %.4s",
			tvb_get_ephemeral_string( tvb, offset, 4));
		offset += 12;
	}
	else 			/* no tree */
		offset += 36;

	cmd = tvb_get_ntohs( tvb, offset);

	if ( tree)
		proto_tree_add_uint_format( tree, hf_msproxy_cmd, tvb, offset, 2,
			cmd, "Command: 0x%02x (%s)", cmd,
			get_msproxy_cmd_name( cmd, FROM_CLIENT));

	offset += 2;

	switch (cmd){
		case MSPROXY_AUTH:
			dissect_auth( tvb, offset, tree);
			break;

		case MSPROXY_BIND:
			dissect_bind( tvb, offset, tree, conv_info);
			break;

		case MSPROXY_UDP_BIND_REQ:
			dissect_udp_bind( tvb, offset, tree, conv_info);
			break;

		case MSPROXY_AUTH_2:	/*$$ this is probably wrong place for this */
		case MSPROXY_TCP_BIND:
			dissect_tcp_bind( tvb, offset, tree, conv_info);
			break;

		case MSPROXY_RESOLVE:
			dissect_request_resolve( tvb, offset, tree);
			break;

		case MSPROXY_CONNECT:
		case MSPROXY_LISTEN:
			dissect_request_connect( tvb, offset, tree,
				conv_info);
			break;

		case MSPROXY_BINDINFO_ACK:
			dissect_bind_info_ack( tvb, offset, tree);
			break;

		case MSPROXY_HELLO:
		case MSPROXY_HELLO_2:
			dissect_msproxy_request_1( tvb, offset, tree);
			break;

		case  MSPROXY_UDPASSOCIATE:
			dissect_udp_assoc( tvb, offset, tree, conv_info);
			break;
		default:
			if ( tree)
				proto_tree_add_text( tree, tvb, offset, 0,
					"Unhandled request command (report this, please)");
	}
}
Example #24
0
static void
dissect_fefd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item *ti;
    proto_tree *fefd_tree = NULL;
    int offset = 0;
    guint16 type;
    guint16 length;
    proto_item *tlvi;
    proto_tree *tlv_tree;
    int real_length;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "FEFD");
    col_clear(pinfo->cinfo, COL_INFO);

    if (tree) {
	proto_item *flags_ti;
	proto_tree *flags_tree;

	ti = proto_tree_add_item(tree, proto_fefd, tvb, offset, -1, FALSE);
	fefd_tree = proto_item_add_subtree(ti, ett_fefd);

	/* FEFD header */
	proto_tree_add_item(fefd_tree, hf_fefd_version, tvb, offset, 1, FALSE);
	proto_tree_add_item(fefd_tree, hf_fefd_opcode, tvb, offset, 1, FALSE);
	offset += 1;
	flags_ti = proto_tree_add_item(fefd_tree, hf_fefd_flags, tvb, offset, 1, FALSE);
	flags_tree = proto_item_add_subtree(ti, ett_fefd_flags);
	proto_tree_add_item(flags_tree, hf_fefd_flags_rt, tvb, offset, 1, FALSE);
	proto_tree_add_item(flags_tree, hf_fefd_flags_rsy, tvb, offset, 1, FALSE);
	offset += 1;
	proto_tree_add_item(fefd_tree, hf_fefd_checksum, tvb, offset, 2, FALSE);
	offset += 2;
    } else {
	offset += 4; /* The version/opcode/flags/checksum fields from above */
    }

	while (tvb_reported_length_remaining(tvb, offset) != 0) {
	    type = tvb_get_ntohs(tvb, offset + TLV_TYPE);
	    length = tvb_get_ntohs(tvb, offset + TLV_LENGTH);
	    if (length < 4) {
		if (tree) {
		    tlvi = proto_tree_add_text(fefd_tree, tvb, offset, 4,
			"TLV with invalid length %u (< 4)",
			length);
		    tlv_tree = proto_item_add_subtree(tlvi, ett_fefd_tlv);
		    proto_tree_add_uint(tlv_tree, hf_fefd_tlvtype, tvb,
				offset + TLV_TYPE, 2, type);
		    proto_tree_add_uint(tlv_tree, hf_fefd_tlvlength, tvb,
				offset + TLV_LENGTH, 2, length);
		}
		offset += 4;
		break;
	    }

	    switch (type) {

	    case TYPE_DEVICE_ID:
		/* Device ID */

		if (check_col(pinfo->cinfo, COL_INFO))
		    col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
				    "Device ID: %s",
				    tvb_format_stringzpad(tvb, offset + 4,
							  length - 4));

		if (tree) {
		    tlvi = proto_tree_add_text(fefd_tree, tvb, offset,
				length, "Device ID: %s",
				tvb_format_stringzpad(tvb, offset + 4, length - 4));
		    tlv_tree = proto_item_add_subtree(tlvi, ett_fefd_tlv);
		    proto_tree_add_uint(tlv_tree, hf_fefd_tlvtype, tvb,
				offset + TLV_TYPE, 2, type);
		    proto_tree_add_uint(tlv_tree, hf_fefd_tlvlength, tvb,
				offset + TLV_LENGTH, 2, length);
		    proto_tree_add_text(tlv_tree, tvb, offset + 4,
				length - 4, "Device ID: %s",
				tvb_format_stringzpad(tvb, offset + 4, length - 4));
		}
		offset += length;
		break;

	    case TYPE_PORT_ID:
		real_length = length;
		if (tvb_get_guint8(tvb, offset + real_length) != 0x00) {
		    /* The length in the TLV doesn't appear to be the
		       length of the TLV, as the byte just past it
		       isn't the first byte of a 2-byte big-endian
		       small integer; make the length of the TLV the length
		       in the TLV, plus 4 bytes for the TLV type and length,
		       minus 1 because that's what makes one capture work. */
		    real_length = length + 3;
		}

		if (check_col(pinfo->cinfo, COL_INFO))
		    col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL,
				    "Port ID: %s",
				    tvb_format_stringzpad(tvb, offset + 4, real_length - 4));

		if (tree) {
		    tlvi = proto_tree_add_text(fefd_tree, tvb, offset,
			    real_length, "Port ID: %s",
			    tvb_format_text(tvb, offset + 4, real_length - 4));
		    tlv_tree = proto_item_add_subtree(tlvi, ett_fefd_tlv);
		    proto_tree_add_uint(tlv_tree, hf_fefd_tlvtype, tvb,
			    offset + TLV_TYPE, 2, type);
		    proto_tree_add_uint(tlv_tree, hf_fefd_tlvlength, tvb,
			    offset + TLV_LENGTH, 2, length);
		    proto_tree_add_text(tlv_tree, tvb, offset + 4,
			    real_length - 4,
			    "Sent through Interface: %s",
			    tvb_format_text(tvb, offset + 4, real_length - 4));
		}
		offset += real_length;
		break;

	    case TYPE_ECHO:
	    case TYPE_MESSAGE_INTERVAL:
	    case TYPE_TIMEOUT_INTERVAL:
	    case TYPE_DEVICE_NAME:
	    case TYPE_SEQUENCE_NUMBER:
	    default:
		tlvi = proto_tree_add_text(fefd_tree, tvb, offset,
			length, "Type: %s, length: %u",
			val_to_str(type, type_vals, "Unknown (0x%04x)"),
			length);
		tlv_tree = proto_item_add_subtree(tlvi, ett_fefd_tlv);
		proto_tree_add_uint(tlv_tree, hf_fefd_tlvtype, tvb,
			offset + TLV_TYPE, 2, type);
		proto_tree_add_uint(tlv_tree, hf_fefd_tlvlength, tvb,
			offset + TLV_LENGTH, 2, length);
		if (length > 4) {
			proto_tree_add_text(tlv_tree, tvb, offset + 4,
				length - 4, "Data");
		} else {
			return;
		}
		offset += length;
	    }
	}

    call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo, fefd_tree);
}
Example #25
0
/*
 * Name: isis_dissect_isis_hello()
 *
 * Description:
 *	This procedure rips apart the various types of ISIS hellos.  L1H and
 *	L2H's are identical for the most part, while the PTP hello has
 *	a shorter header.
 *
 * Input:
 *	tvbuff_t * : tvbuffer for packet data
 *	proto_tree * : protocol display tree to add to.  May be NULL.
 *	int offset : our offset into packet data.
 *	int : hello type, a la packet-isis.h ISIS_TYPE_* values
 *	int : header length of packet.
 *	int : length of IDs in packet.
 *
 * Output:
 *	void, will modify proto_tree if not NULL.
 */
void
isis_dissect_isis_hello(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset,
	int hello_type, int header_length, int id_length)
{
	proto_item	*ti;
	proto_tree	*hello_tree = NULL;
	int 		len;
	guint8		octet;
	const guint8	*source_id;
	guint16		pdu_length;
	const guint8	*lan_id;

	if (tree) {
		ti = proto_tree_add_text(tree, tvb, offset, -1, "ISIS HELLO");
		hello_tree = proto_item_add_subtree(ti, ett_isis_hello);
		octet = tvb_get_guint8(tvb, offset);
		proto_tree_add_uint_format(hello_tree,
			hf_isis_hello_circuit_reserved,
			tvb, offset, 1, octet,
			"Circuit type              : %s, reserved(0x%02x == 0)",
				val_to_str(octet&ISIS_HELLO_CTYPE_MASK,
					isis_hello_circuit_type_vals,
					"Unknown (0x%x)"),
				octet&ISIS_HELLO_CT_RESERVED_MASK
			);
	}
	offset += 1;

	if (tree) {
		source_id = tvb_get_ptr(tvb, offset, id_length);
		proto_tree_add_bytes_format(hello_tree, hf_isis_hello_source_id, tvb,
			            offset, id_length, source_id,
			            "System-ID {Sender of PDU} : %s", 
			            print_system_id( source_id, id_length ) );
	}
	if (check_col(pinfo->cinfo, COL_INFO)) {
		col_append_fstr(pinfo->cinfo, COL_INFO, ", System-ID: %s",
			print_system_id( tvb_get_ptr(tvb, offset, id_length), id_length ) );
	}
	offset += id_length;

	if (tree) {
		proto_tree_add_item(hello_tree, hf_isis_hello_holding_timer, tvb,
			            offset, 2, FALSE);
	}
	offset += 2;

	pdu_length = tvb_get_ntohs(tvb, offset);
	if (tree) {
		proto_tree_add_uint(hello_tree, hf_isis_hello_pdu_length, tvb,
			            offset, 2, pdu_length);
	}
	offset += 2;

	if (hello_type == ISIS_TYPE_PTP_HELLO) {
		if (tree) {
			proto_tree_add_item(hello_tree, hf_isis_hello_local_circuit_id, tvb,
				         offset, 1, FALSE );
		}
		offset += 1;
	} else {
		if (tree) {
			octet = tvb_get_guint8(tvb, offset);
			proto_tree_add_uint_format(hello_tree, hf_isis_hello_priority_reserved, tvb,
				    offset, 1, octet,
				    "Priority                  : %d, reserved(0x%02x == 0)",
					octet&ISIS_HELLO_PRIORITY_MASK,
					octet&ISIS_HELLO_P_RESERVED_MASK );
		}
		offset += 1;

		if (tree) {
			lan_id = tvb_get_ptr(tvb, offset, id_length+1);
			proto_tree_add_bytes_format(hello_tree, hf_isis_hello_lan_id, tvb,
				     offset, id_length + 1, lan_id,
					 "System-ID {Designated IS} : %s",
					      print_system_id( lan_id, id_length + 1 ) );
		}
		offset += id_length + 1;
	}

	len = pdu_length;
	len -= header_length;
	if (len < 0) {
		isis_dissect_unknown(tvb, tree, offset,
			"Packet header length %d went beyond packet",
			header_length );
		return;
	}
	/*
	 * Now, we need to decode our CLVs.  We need to pass in
	 * our list of valid ones!
	 */
	if (hello_type == ISIS_TYPE_L1_HELLO){
		isis_dissect_clvs(tvb, hello_tree, offset,
			clv_l1_hello_opts, len, id_length,
			ett_isis_hello_clv_unknown);
	} else if (hello_type == ISIS_TYPE_L2_HELLO) {
		isis_dissect_clvs(tvb, hello_tree, offset,
			clv_l2_hello_opts, len, id_length,
			ett_isis_hello_clv_unknown);
	} else {
		isis_dissect_clvs(tvb, hello_tree, offset,
			clv_ptp_hello_opts, len, id_length,
			ett_isis_hello_clv_unknown);
	}
}
/* Decode LSC over UDP */
static void
dissect_lsc_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  dissect_lsc_common(tvb, pinfo, tree);
}

/* Determine length of LSC message */
static guint
get_lsc_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
{
  guint8 op_code;
  guint pdu_len;

  /* Get the op code */
  op_code = tvb_get_guint8(tvb, offset + 2);

  switch (op_code)
    {
      case LSC_PAUSE:
        pdu_len = LSC_PAUSE_LEN;
        break;
      case LSC_RESUME:
        pdu_len = LSC_RESUME_LEN;
        break;
      case LSC_STATUS:
        pdu_len = LSC_STATUS_LEN;
        break;
      case LSC_RESET:
        pdu_len = LSC_RESET_LEN;
        break;
Example #27
0
/* Code to actually dissect the packets */
static int
dissect_csm_encaps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
    proto_item  *ti;
    proto_tree  *csm_encaps_tree = NULL;
    guint16      function_code, channel, class_type;
    guint        control, type, sequence, length;
    guint        i;
    gboolean     show_error_param= FALSE;
    const gchar *str_function_name;


    function_code = tvb_get_letohs(tvb, 10);
    control = tvb_get_guint8(tvb, 3);

    class_type = tvb_get_guint8(tvb, 9);
    class_type = class_type<<8;
    class_type|= tvb_get_guint8(tvb, 8);

    type     = tvb_get_guint8(tvb, 8);
    sequence = tvb_get_guint8(tvb, 2);
    length   = tvb_get_guint8(tvb, 6);
    channel  = tvb_get_ntohs(tvb, 4);


    if (CSM_ENCAPS_CTRL_ACK&control)
        show_error_param= FALSE;
    else {
        if (csm_to_host(function_code, class_type)) /* exclusive messages to host */
/* Code to actually dissect the packets */
static void
dissect_lsc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_item *ti;
  proto_tree *lsc_tree;
  guint8 op_code;
  guint32 stream;
  guint expected_len;

  /* Protocol is LSC, packet summary is not yet known */
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "LSC");
  col_clear(pinfo->cinfo, COL_INFO);

  /* Too little data? */
  if (tvb_length(tvb) < LSC_MIN_LEN)
  {
    col_set_str(pinfo->cinfo, COL_INFO, "[Too short]");
    return;
  }

  /* Get the op code */
  op_code = tvb_get_guint8(tvb, 2);
  /* And the stream handle */
  stream = tvb_get_ntohl(tvb, 4);

  /* Check the data length against what we actually received */
  switch (op_code)
    {
      case LSC_PAUSE:
        expected_len = LSC_PAUSE_LEN;
        break;
      case LSC_RESUME:
        expected_len = LSC_RESUME_LEN;
        break;
      case LSC_STATUS:
        expected_len = LSC_STATUS_LEN;
        break;
      case LSC_RESET:
        expected_len = LSC_RESET_LEN;
        break;
      case LSC_JUMP:
        expected_len = LSC_JUMP_LEN;
        break;
      case LSC_PLAY:
        expected_len = LSC_PLAY_LEN;
        break;
      case LSC_DONE:
      case LSC_PAUSE_REPLY:
      case LSC_RESUME_REPLY:
      case LSC_STATUS_REPLY:
      case LSC_RESET_REPLY:
      case LSC_JUMP_REPLY:
      case LSC_PLAY_REPLY:
        expected_len = LSC_REPLY_LEN;
        break;
      default:
        /* Unrecognized op code */
        expected_len = LSC_MIN_LEN;
        break;
    }

  /* Display the op code in the summary */
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s, session %.8u",
                 val_to_str(op_code, op_code_vals, "Unknown op code (0x%x)"),
                 stream);

  if (tvb_length(tvb) < expected_len)
    col_append_str(pinfo->cinfo, COL_INFO, " [Too short]");
  else if (tvb_length(tvb) > expected_len)
    col_append_str(pinfo->cinfo, COL_INFO, " [Too long]");

  if (tree) {
    /* Create display subtree for the protocol */
    ti = proto_tree_add_item(tree, proto_lsc, tvb, 0, -1, ENC_NA);
    lsc_tree = proto_item_add_subtree(ti, ett_lsc);

    /* Add already fetched items to the tree */
    proto_tree_add_uint(lsc_tree, hf_lsc_op_code, tvb, 2, 1, op_code);
    proto_tree_add_uint_format_value(lsc_tree, hf_lsc_stream_handle, tvb, 4, 4,
                                     stream, "%.8u", stream);

    /* Add rest of LSC header */
    proto_tree_add_uint(lsc_tree, hf_lsc_version, tvb, 0, 1,
                        tvb_get_guint8(tvb, 0));
    proto_tree_add_uint(lsc_tree, hf_lsc_trans_id, tvb, 1, 1,
                        tvb_get_guint8(tvb, 1));

    /* Only replies contain a status code */
    if (isReply(op_code))
      proto_tree_add_uint(lsc_tree, hf_lsc_status_code, tvb, 3, 1,
                          tvb_get_guint8(tvb, 3));

    /* Add op code specific parts */
    switch (op_code)
      {
        case LSC_PAUSE:
          proto_tree_add_int(lsc_tree, hf_lsc_stop_npt, tvb, 8, 4,
                             tvb_get_ntohl(tvb, 8));
          break;
        case LSC_RESUME:
          proto_tree_add_int(lsc_tree, hf_lsc_start_npt, tvb, 8, 4,
                             tvb_get_ntohl(tvb, 8));
          proto_tree_add_int(lsc_tree, hf_lsc_scale_num, tvb, 12, 2,
                             tvb_get_ntohs(tvb, 12));
          proto_tree_add_uint(lsc_tree, hf_lsc_scale_denom, tvb, 14, 2,
                              tvb_get_ntohs(tvb, 14));
          break;
        case LSC_JUMP:
        case LSC_PLAY:
          proto_tree_add_int(lsc_tree, hf_lsc_start_npt, tvb, 8, 4,
                             tvb_get_ntohl(tvb, 8));
          proto_tree_add_int(lsc_tree, hf_lsc_stop_npt, tvb, 12, 4,
                             tvb_get_ntohl(tvb, 12));
          proto_tree_add_int(lsc_tree, hf_lsc_scale_num, tvb, 16, 2,
                             tvb_get_ntohs(tvb, 16));
          proto_tree_add_uint(lsc_tree, hf_lsc_scale_denom, tvb, 18, 2,
                              tvb_get_ntohs(tvb, 18));
          break;
        case LSC_DONE:
        case LSC_PAUSE_REPLY:
        case LSC_RESUME_REPLY:
        case LSC_STATUS_REPLY:
        case LSC_RESET_REPLY:
        case LSC_JUMP_REPLY:
        case LSC_PLAY_REPLY:
          proto_tree_add_int(lsc_tree, hf_lsc_current_npt, tvb, 8, 4,
                             tvb_get_ntohl(tvb, 8));
          proto_tree_add_int(lsc_tree, hf_lsc_scale_num, tvb, 12, 2,
                             tvb_get_ntohs(tvb, 12));
          proto_tree_add_uint(lsc_tree, hf_lsc_scale_denom, tvb, 14, 2,
                              tvb_get_ntohs(tvb, 14));
          proto_tree_add_uint(lsc_tree, hf_lsc_mode, tvb, 16, 1,
                              tvb_get_guint8(tvb, 16));
          break;
        default:
          break;
      }
  }
}
Example #29
0
static void
dissect_usb_midi_event(tvbuff_t *tvb, packet_info *pinfo,
                       proto_tree *usb_audio_tree, proto_tree *parent_tree,
                       gint offset)
{
    guint8      code;
    guint8      cable;
    gboolean    save_fragmented;
    proto_tree *tree = NULL;

    col_set_str(pinfo->cinfo, COL_INFO, "USB-MIDI Event Packets");

    code = tvb_get_guint8(tvb, offset);
    cable = (code & 0xF0) >> 4;
    code &= 0x0F;

    if (parent_tree)
    {
        proto_item *ti;

        ti = proto_tree_add_protocol_format(usb_audio_tree, proto_usb_audio, tvb, offset, 4, "USB Midi Event Packet");
        tree = proto_item_add_subtree(ti, ett_usb_audio);
        proto_tree_add_item(tree, hf_midi_cable_number, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_midi_code_index, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_midi_event, tvb, offset+1, 3, ENC_BIG_ENDIAN);
    }

    save_fragmented = pinfo->fragmented;

    /* Reassemble SysEx commands */
    if (is_sysex_code(code))
    {
        tvbuff_t* new_tvb = NULL;
        fragment_head *frag_sysex_msg = NULL;

        pinfo->fragmented = TRUE;

        if (code == 0x04)
        {
            frag_sysex_msg = fragment_add_seq_next(&midi_data_reassembly_table,
                                                   tvb, offset+1,
                                                   pinfo,
                                                   cable, /* ID for fragments belonging together */
                                                   NULL,
                                                   3,
                                                   TRUE);
        }
        else
        {
            frag_sysex_msg = fragment_add_seq_next(&midi_data_reassembly_table,
                                                   tvb, offset+1,
                                                   pinfo,
                                                   cable, /* ID for fragments belonging together */
                                                   NULL,
                                                   (gint)(code - 4),
                                                   FALSE);
        }

        if (is_last_sysex_packet_in_tvb(tvb, offset))
        {
            new_tvb = process_reassembled_data(tvb, offset+1, pinfo,
                                               "Reassembled Message", frag_sysex_msg, &sysex_msg_frag_items,
                                               NULL, usb_audio_tree);

            if (code != 0x04) { /* Reassembled */
                col_append_str(pinfo->cinfo, COL_INFO,
                               " (SysEx Reassembled)");
            } else { /* Not last packet of reassembled Short Message */
                col_append_str(pinfo->cinfo, COL_INFO,
                               " (SysEx fragment)");
            }

            if (new_tvb)
            {
                call_dissector(sysex_handle, new_tvb, pinfo, parent_tree);
            }
        }
    }

    pinfo->fragmented = save_fragmented;
}
Example #30
0
/*-----------------------------------------------------------------------------
  UA DISSECTOR
  ---------------------------------------------------------------------------*/
static void _dissect_ua_msg(tvbuff_t       *tvb,
                            packet_info    *pinfo,
                            proto_tree     *tree,
                            e_ua_direction  direction)
{
    gint        offset = 0;
    proto_item *ua_msg_item;
    proto_tree *ua_msg_tree;

    ua_msg_item = proto_tree_add_protocol_format(tree, proto_ua_msg, tvb, 0, -1,
        "Universal Alcatel Protocol, %s",
        ((direction == SYS_TO_TERM) ?
        "System -> Terminal" : "Terminal -> System"));

    ua_msg_tree = proto_item_add_subtree(ua_msg_item, ett_ua_msg);

    while (tvb_offset_exists(tvb, offset))
    {
        gint length;
        gint opcode;

        length = tvb_get_letohs(tvb, offset) + 2;
        opcode = tvb_get_guint8(tvb, offset+2);

        /* RTP/RTCP conversation setup */
        if (setup_conversations_enabled && (opcode==0x13) && (tvb_get_guint8(tvb, offset+3)==0x01))
        {
            address remote_rtp_addr;
            guint32 remote_rtp_port;
            gint    suboffset;

            remote_rtp_addr.data = NULL;
            remote_rtp_port = 0;

            /* StartRTP */
            suboffset = offset + 5;

            while (suboffset < offset+length)
            {
                switch (tvb_get_guint8(tvb, suboffset))
                {
                case 0x00: /* local port */
                    {
                    /*local_rtp_port = tvb_get_ntohs(tvb, suboffset+2);*/
                    break;
                    }
                case 0x01: /* remote IP */
                    {
                    remote_rtp_addr.type = AT_IPv4;
                    remote_rtp_addr.len  = 4;
                    remote_rtp_addr.data = tvb_get_ptr(tvb, suboffset+2, 4);
                    break;
                    }
                case 0x02: /* remote port */
                    {
                    remote_rtp_port = tvb_get_ntohs(tvb, suboffset+2);
                    break;
                    }
                }

            suboffset += tvb_get_guint8(tvb, suboffset+1) + 2;
            }

            if ((remote_rtp_addr.data != NULL) && (remote_rtp_port != 0))
            {
                rtp_add_address(pinfo, &remote_rtp_addr, remote_rtp_port, 0,
                        "UA", pinfo->fd->num, 0, NULL);
                rtcp_add_address(pinfo, &remote_rtp_addr, remote_rtp_port+1, 0,
                         "UA", pinfo->fd->num);
            }
        }

        uadecode(direction, ua_msg_tree, pinfo, tvb, offset, opcode, length);

        offset += length;
    }
}