static int dissect_ProtocolIEFieldValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    return (dissector_try_port(pcap_ies_dissector_table, ProtocolIE_ID, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
}
static int dissect_InitiatingMessageValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    return (dissector_try_port(pcap_proc_imsg_dissector_table, ProcedureCode, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
}
static int dissect_OutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    return (dissector_try_port(pcap_proc_out_dissector_table, ProcedureCode, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
}
Beispiel #4
0
static void
dissect_ieee802a(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*ieee802a_tree = NULL;
	proto_item	*ti;
	int		offset = 0;
	tvbuff_t	*next_tvb;
	guint32		oui;
	guint16		etype;
	oui_info_t	*oui_info;
	dissector_table_t subdissector_table;
	int		hf;

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

	if (tree) {
		ti = proto_tree_add_item(tree, proto_ieee802a, tvb, 0, -1, FALSE);
		ieee802a_tree = proto_item_add_subtree(ti, ett_ieee802a);
	} else
		ieee802a_tree = NULL;

	oui =	tvb_get_ntoh24(tvb, offset);
	etype = tvb_get_ntohs(tvb, offset+3);

	if (check_col(pinfo->cinfo, COL_INFO)) {
		col_add_fstr(pinfo->cinfo, COL_INFO,
		    "OUI 0x%06X (%s), PID 0x%04X",
		    oui, val_to_str(oui, oui_vals, "Unknown"), etype);
	}
	if (tree) {
		proto_tree_add_uint(ieee802a_tree, hf_ieee802a_oui,
		    tvb, offset, 3, oui);
	}

	/*
	 * Do we have information for this OUI?
	 */
	if (oui_info_table != NULL &&
	    (oui_info = g_hash_table_lookup(oui_info_table,
	      GUINT_TO_POINTER(oui))) != NULL) {
		/*
		 * Yes - use it.
		 */
		hf = *oui_info->field_info->p_id;
		subdissector_table = oui_info->table;
	} else {
		/*
		 * No, use hf_ieee802a_pid for the PID and just dissect
		 * the payload as data.
		 */
		hf = hf_ieee802a_pid;
		subdissector_table = NULL;
	}
	if (tree)
		proto_tree_add_uint(ieee802a_tree, hf, tvb, offset+3, 2, etype);
	next_tvb = tvb_new_subset_remaining(tvb, offset+5);
	if (subdissector_table != NULL) {
		/* do lookup with the subdissector table */
		if (dissector_try_port(subdissector_table, etype, next_tvb,
		    pinfo, tree))
			return;
	}
	call_dissector(data_handle, next_tvb, pinfo, tree);
}
static int dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    return (dissector_try_port(pcap_extension_dissector_table, ProtocolExtensionID, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
}
Beispiel #6
0
static void
dissect_sita(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item	*ti;
	guchar		flags, signals, errors1, errors2, proto;
	gchar		*errors1_string, *errors2_string, *signals_string, *flags_string;
	proto_tree	*sita_tree			= NULL;
	proto_tree	*sita_flags_tree	= NULL;
	proto_tree	*sita_errors1_tree	= NULL;
	proto_tree	*sita_errors2_tree	= NULL;
	proto_tree	*sita_signals_tree	= NULL;
	const gchar	*rx_errors1_str[]	= {"Framing",		"Parity",	"Collision",	"Long-frame",	"Short-frame",	"",			"",		""				};
	const gchar	*rx_errors2_str[]	= {"Non-Aligned",	"Abort",	"CD-lost",		"DPLL",			"Overrun",		"Length",	"CRC",	"Break"			};
	/*const gchar	*tx_errors1_str[]	= {"",				"",			"",				"",				"",				"",			"",		""				}; */
	const gchar	*tx_errors2_str[]	= {"Underrun",		"CTS-lost",	"UART",			"ReTx-limit",	"",				"",			"",		""				};
	const gchar	*signals_str[]		= {"DSR",			"DTR",		"CTS",			"RTS",			"DCD",			"",			"",		""				};
	const gchar	*flags_str[]		= {"",				"",			"",				"",				"",				"",			"",		"No-buffers"	};

	col_clear(pinfo->cinfo, COL_PROTOCOL);		/* erase the protocol */
	col_clear(pinfo->cinfo, COL_INFO);			/* and info columns so that the next decoder can fill them in */

	flags	= pinfo->pseudo_header->sita.flags;
	signals	= pinfo->pseudo_header->sita.signals;
	errors1	= pinfo->pseudo_header->sita.errors1;
	errors2	= pinfo->pseudo_header->sita.errors2;
	proto	= pinfo->pseudo_header->sita.proto;

	if (check_col(pinfo->cinfo, COL_DEF_SRC)) {
		if ((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) {
			col_set_str(pinfo->cinfo, COL_DEF_SRC, IOP);				/* set the source (direction) column accordingly */
		} else {
			col_set_str(pinfo->cinfo, COL_DEF_SRC, REMOTE);
		}
	}

	if (check_col(pinfo->cinfo, COL_INFO))
		col_set_str(pinfo->cinfo, COL_INFO, "");

	if (tree) {
		ti = proto_tree_add_protocol_format(tree, proto_sita, tvb, 0, 0, "Link Layer");
		sita_tree = proto_item_add_subtree(ti, ett_sita);

		proto_tree_add_uint(sita_tree, hf_proto, tvb, 0, 0, proto);

		flags_string = format_flags_string(flags, flags_str);
		ti = proto_tree_add_text(sita_tree, tvb, 0, 0, "Flags: 0x%02x (From %s)%s%s",
				flags,
				((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) ? IOP : REMOTE,
				strlen(flags_string) ? ", " : "",
				flags_string);
		sita_flags_tree = proto_item_add_subtree(ti, ett_sita_flags);
		proto_tree_add_boolean(sita_flags_tree, hf_droppedframe,	tvb, 0, 0, flags);
		proto_tree_add_boolean(sita_flags_tree, hf_dir,				tvb, 0, 0, flags);

		signals_string = format_flags_string(signals, signals_str);
		ti = proto_tree_add_text(sita_tree, tvb, 0, 0, "Signals: 0x%02x %s", signals, signals_string);
		sita_signals_tree = proto_item_add_subtree(ti, ett_sita_signals);
	   	proto_tree_add_boolean(sita_signals_tree, hf_dcd,		tvb, 0, 0, signals);
	   	proto_tree_add_boolean(sita_signals_tree, hf_rts,		tvb, 0, 0, signals);
	   	proto_tree_add_boolean(sita_signals_tree, hf_cts,		tvb, 0, 0, signals);
	   	proto_tree_add_boolean(sita_signals_tree, hf_dtr,		tvb, 0, 0, signals);
	   	proto_tree_add_boolean(sita_signals_tree, hf_dsr,		tvb, 0, 0, signals);

		if ((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_RXED) {
			errors1_string = format_flags_string(errors1, rx_errors1_str);
			ti = proto_tree_add_text(sita_tree, tvb, 0, 0, "Receive Status: 0x%02x %s", errors1, errors1_string);
			sita_errors1_tree = proto_item_add_subtree(ti, ett_sita_errors1);
			proto_tree_add_boolean(sita_errors1_tree, hf_shortframe,	tvb, 0, 0, errors1);
			proto_tree_add_boolean(sita_errors1_tree, hf_longframe,		tvb, 0, 0, errors1);
			proto_tree_add_boolean(sita_errors1_tree, hf_collision,		tvb, 0, 0, errors1);
			proto_tree_add_boolean(sita_errors1_tree, hf_parity,		tvb, 0, 0, errors1);
			proto_tree_add_boolean(sita_errors1_tree, hf_framing,		tvb, 0, 0, errors1);

			errors2_string = format_flags_string(errors2, rx_errors2_str);
			ti = proto_tree_add_text(sita_tree, tvb, 0, 0, "Receive Status: 0x%02x %s", errors2, errors2_string);
			sita_errors2_tree = proto_item_add_subtree(ti, ett_sita_errors2);
			proto_tree_add_boolean(sita_errors2_tree, hf_break,			tvb, 0, 0, errors2);
			proto_tree_add_boolean(sita_errors2_tree, hf_crc,			tvb, 0, 0, errors2);
			proto_tree_add_boolean(sita_errors2_tree, hf_length,		tvb, 0, 0, errors2);
			proto_tree_add_boolean(sita_errors2_tree, hf_overrun,		tvb, 0, 0, errors2);
			proto_tree_add_boolean(sita_errors2_tree, hf_rxdpll,		tvb, 0, 0, errors2);
			proto_tree_add_boolean(sita_errors2_tree, hf_lostcd,		tvb, 0, 0, errors2);
			proto_tree_add_boolean(sita_errors2_tree, hf_abort,			tvb, 0, 0, errors2);
			proto_tree_add_boolean(sita_errors2_tree, hf_nonaligned,	tvb, 0, 0, errors2);
		} else {
			errors2_string = format_flags_string(errors2, tx_errors2_str);
			ti = proto_tree_add_text(sita_tree, tvb, 0, 0, "Transmit Status: 0x%02x %s", errors2, errors2_string);
			sita_errors1_tree = proto_item_add_subtree(ti, ett_sita_errors1);
			proto_tree_add_boolean(sita_errors1_tree, hf_rtxlimit,		tvb, 0, 0, errors2);
			proto_tree_add_boolean(sita_errors1_tree, hf_uarterror,		tvb, 0, 0, errors2);
			proto_tree_add_boolean(sita_errors1_tree, hf_lostcts,		tvb, 0, 0, errors2);
			proto_tree_add_boolean(sita_errors1_tree, hf_underrun,		tvb, 0, 0, errors2);
		}
	}

	if (!dissector_try_port(sita_dissector_table, pinfo->pseudo_header->sita.proto, tvb, pinfo, tree)) {		/* try to find and run an applicable dissector */
		if (check_col(pinfo->cinfo, COL_PROTOCOL))																/* if one can't be found... tell them we don't */
			col_set_str(pinfo->cinfo, COL_PROTOCOL, "UKNOWN");													/* know how to decode this protocol */
		if (check_col(pinfo->cinfo, COL_INFO))
			col_add_fstr(pinfo->cinfo, COL_INFO, "IOP protocol number: %u", pinfo->pseudo_header->sita.proto);	/* and give them the details then */
		call_dissector(data_handle, tvb, pinfo, tree);															/* call the generic (hex display) decoder instead */
	}
}
void dissect_nhrp_mand(tvbuff_t *tvb,
					   packet_info *pinfo,
					   proto_tree *tree,
					   gint *pOffset,
					   gint mandLen,
					   oui_info_t *oui_info,
					   e_nhrp_hdr *hdr,
					   guint *srcLen,
					   gboolean codeinfo)
{
	gint	offset = *pOffset;
	gint	mandEnd = offset + mandLen;
	guint8	ssl, shl;
	guint16	flags;
	guint	dstLen;
	gboolean isReq = 0;
	gboolean isErr = 0;
	gboolean isInd = 0;

	proto_item *nhrp_tree_item = NULL;
	proto_item *flag_item = NULL;
	proto_tree *nhrp_tree = NULL;
	proto_tree *flag_tree = NULL;

	tvb_ensure_bytes_exist(tvb, offset, mandLen);

	switch (hdr->ar_op_type)
	{
	case NHRP_RESOLUTION_REPLY:
	case NHRP_REGISTRATION_REPLY:
	case NHRP_PURGE_REPLY:
		break;
	case NHRP_RESOLUTION_REQ:
	case NHRP_REGISTRATION_REQ:
	case NHRP_PURGE_REQ:
		isReq = 1;
		break;
	case NHRP_ERROR_INDICATION:	/* This needs special treatment */
		isErr = 1;
		isInd = 1;
		break;
	case NHRP_TRAFFIC_INDICATION:
		isInd = 1;
		break;
	}
	nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, mandLen, "NHRP Mandatory Part");
	nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_mand);

	*srcLen = tvb_get_guint8(tvb, offset);
	proto_tree_add_item(nhrp_tree, hf_nhrp_src_proto_len, tvb, offset, 1, FALSE);
	offset += 1;

	dstLen = tvb_get_guint8(tvb, offset);
	proto_tree_add_item(nhrp_tree, hf_nhrp_dst_proto_len, tvb, offset, 1, FALSE);
	offset += 1;

	if (!isInd) {
		flags = tvb_get_ntohs(tvb, offset);
		flag_item = proto_tree_add_uint(nhrp_tree, hf_nhrp_flags, tvb, offset, 2, flags);
		flag_tree = proto_item_add_subtree(flag_item, ett_nhrp_mand_flag);

		switch (hdr->ar_op_type)
		{
		case NHRP_RESOLUTION_REQ:
		case NHRP_RESOLUTION_REPLY:
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_Q, tvb, offset, 2, flags);
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_A, tvb, offset, 2, flags);
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_D, tvb, offset, 2, flags);
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_U1, tvb, offset, 2, flags);
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_S, tvb, offset, 2, flags);
			break;
		case NHRP_REGISTRATION_REQ:
		case NHRP_REGISTRATION_REPLY:
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_U2, tvb, offset, 2, flags);
			break;

		case NHRP_PURGE_REQ:
		case NHRP_PURGE_REPLY:
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_N, tvb, offset, 2, flags);
			break;
		}
		proto_tree_add_boolean(flag_tree, hf_nhrp_flag_NAT, tvb, offset, 2, flags);

		offset += 2;

		col_append_fstr(pinfo->cinfo, COL_INFO, ", ID=%u", tvb_get_ntohl(tvb, offset));
		proto_tree_add_item(nhrp_tree, hf_nhrp_request_id, tvb, offset, 4, FALSE);
		offset += 4;
	}
	else if (isErr) {
		offset += 2;

		col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
			val_to_str(tvb_get_ntohs(tvb, offset), nhrp_error_code_vals, "Unknown Error (%u)"));
		proto_tree_add_item(nhrp_tree, hf_nhrp_error_code, tvb, offset, 2, FALSE);
		offset += 2;

		proto_tree_add_item(nhrp_tree, hf_nhrp_error_offset, tvb, offset, 2, FALSE);
		offset += 2;
	}
	else {
		offset += 6;
	}

	shl = NHRP_SHTL_LEN(hdr->ar_shtl);
	if (shl) {
		switch (hdr->ar_afn) {

		case AFNUM_INET:
			if (shl == 4)
				proto_tree_add_item(nhrp_tree, hf_nhrp_src_nbma_addr, tvb, offset, 4, FALSE);
			else {
				proto_tree_add_text(nhrp_tree, tvb, offset, shl,
				    "Source NBMA Address: %s",
				    tvb_bytes_to_str(tvb, offset, shl));
			}
			break;

		default:
			proto_tree_add_text(nhrp_tree, tvb, offset, shl,
			    "Source NBMA Address: %s",
			    tvb_bytes_to_str(tvb, offset, shl));
			break;
		}
		offset += shl;
	}

	ssl = NHRP_SHTL_LEN(hdr->ar_sstl);
	if (ssl) {
		proto_tree_add_text(nhrp_tree, tvb, offset, ssl,
							"Source NBMA Sub Address: %s",
							tvb_bytes_to_str(tvb, offset, ssl));
		offset += ssl;
	}

	if (*srcLen == 4) {
		proto_tree_add_item(nhrp_tree, hf_nhrp_src_prot_addr, tvb, offset, 4, FALSE);
		offset += 4;
	}
	else if (*srcLen) {
		proto_tree_add_text(nhrp_tree, tvb, offset, *srcLen,
							"Source Protocol Address: %s",
							tvb_bytes_to_str(tvb, offset, *srcLen));
		offset += *srcLen;
	}

	if (dstLen == 4) {
		proto_tree_add_item(nhrp_tree, hf_nhrp_dst_prot_addr, tvb, offset, 4, FALSE);
		offset += 4;
	}
	else if (dstLen) {
		proto_tree_add_text(nhrp_tree, tvb, offset, dstLen,
							"Destination Protocol Address: %s",
							tvb_bytes_to_str(tvb, offset, dstLen));
		offset += dstLen;
	}

	if (isInd) {
		gboolean save_in_error_pkt;
		gint pkt_len = mandEnd - offset;
		proto_item *ind_tree_item = proto_tree_add_text(tree, tvb, offset, pkt_len, "Packet Causing Indication");
		proto_tree *ind_tree = proto_item_add_subtree(ind_tree_item, ett_nhrp_indication);
		gboolean dissected;
		tvbuff_t *sub_tvb;

		save_in_error_pkt = pinfo->in_error_pkt;
		pinfo->in_error_pkt = TRUE;
		sub_tvb = tvb_new_subset_remaining(tvb, offset);
		if (isErr) {
			_dissect_nhrp(sub_tvb, pinfo, ind_tree, TRUE, FALSE);
		}
		else {
			if (hdr->ar_pro_type <= 0xFF) {
				/* It's an NLPID */
				if (hdr->ar_pro_type == NLPID_SNAP) {
					/*
					 * Dissect based on the SNAP OUI
					 * and PID.
					 */
					if (hdr->ar_pro_type_oui == 0x000000) {
						/*
						 * "Should not happen", as
						 * the protocol type should
						 * be the Ethertype, but....
						 */
						dissected = dissector_try_port(
						    ethertype_subdissector_table,
						    hdr->ar_pro_type_pid,
						    sub_tvb, pinfo, ind_tree);
					} else {
						/*
						 * If we have a dissector
						 * table, use it, otherwise
						 * just dissect as data.
						 */
						if (oui_info != NULL) {
							dissected = dissector_try_port(
							    oui_info->table,
							    hdr->ar_pro_type_pid,
							    sub_tvb, pinfo,
							    ind_tree);
						} else
							dissected = FALSE;
					}
				} else {
					/*
					 * Dissect based on the NLPID.
					 */
					dissected = dissector_try_port(
					    osinl_subdissector_table,
					    hdr->ar_pro_type, sub_tvb, pinfo,
					    ind_tree) ||
					            dissector_try_port(
					    osinl_excl_subdissector_table,
					    hdr->ar_pro_type, sub_tvb, pinfo,
					    ind_tree);
				}
			} else if (hdr->ar_pro_type <= 0x3FF) {
				/* Reserved for future use by the IETF */
				dissected = FALSE;
			} else if (hdr->ar_pro_type <= 0x04FF) {
				/* Allocated for use by the ATM Forum */
				dissected = FALSE;
			} else if (hdr->ar_pro_type <= 0x05FF) {
				/* Experimental/Local use */
				dissected = FALSE;
			} else {
				dissected = dissector_try_port(
				    ethertype_subdissector_table,
				    hdr->ar_pro_type, sub_tvb, pinfo, ind_tree);
			}
			if (!dissected) {
				call_dissector(data_handle, sub_tvb, pinfo,
				    ind_tree);
			}
		}
		pinfo->in_error_pkt = save_in_error_pkt;
		offset = mandEnd;
	}

	/* According to RFC 2332, section 5.2.7, there shouldn't be any extensions
	 * in the Error Indication packet. */
	if (isErr && tvb_reported_length_remaining(tvb, offset)) {
		expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
			"Extensions not allowed per RFC2332 section 5.2.7");
	}

	dissect_cie_list(tvb, pinfo, nhrp_tree, offset, mandEnd, hdr, isReq, codeinfo);

	*pOffset = mandEnd;
}
Beispiel #8
0
static int
dissect_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

	proto_item *ti;
	proto_item *ti_bdt;
	proto_item *ti_fdt;
	proto_tree *bvlc_tree;
	proto_tree *bdt_tree; /* Broadcast Distribution Table */
	proto_tree *fdt_tree; /* Foreign Device Table */

	gint offset;
	guint8 bvlc_type;
	guint8 bvlc_function;
	guint16 bvlc_length;
	guint16 packet_length;
	guint npdu_length;
	guint length_remaining;
	guint16 bvlc_result;
	tvbuff_t *next_tvb;

	offset = 0;

	bvlc_type =  tvb_get_guint8(tvb, offset);

	/*
	 * Simple sanity check - make sure the type is one we know about.
	 */
	if (match_strval(bvlc_type, bvlc_types) == NULL)
		return 0;

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

	col_set_str(pinfo->cinfo, COL_INFO, "BACnet Virtual Link Control");

	bvlc_function = tvb_get_guint8(tvb, offset+1);
	packet_length = tvb_get_ntohs(tvb, offset+2);
	length_remaining = tvb_length_remaining(tvb, offset);
	if (bvlc_function > 0x08) {
		/*  We have a constant header length of BVLC of 4 in every
		 *  BVLC-packet forewarding an NPDU. Beware: Changes in the
		 *  BACnet-IP-standard may break this.
		 *  At the moment, no functions above 0x0b
		 *  exist (Addendum 135a to ANSI/ASHRAE 135-1995 - BACnet)
		 */
		bvlc_length = 4;
	} else if(bvlc_function == 0x04) {
		/* 4 Bytes + 6 Bytes for B/IP Address of Originating Device */
		bvlc_length = 10;
	} else {
		/*  BVLC-packets with function below 0x09 contain
		 *  routing-level data (e.g. Broadcast Distribution)
		 *  but no NPDU for BACnet, so bvlc_length goes up to the end
		 *  of the captured frame.
		 */
		bvlc_length = packet_length;
	}

	if (tree) {
		if (bvlc_length < 4) {
			proto_tree_add_text(tree, tvb, 2, 2,
				"Bogus length: %d", bvlc_length);
			return tvb_length(tvb);	/* XXX - reject? */
		}
		ti = proto_tree_add_item(tree, proto_bvlc, tvb, 0,
			bvlc_length, FALSE);
		bvlc_tree = proto_item_add_subtree(ti, ett_bvlc);
		proto_tree_add_uint(bvlc_tree, hf_bvlc_type, tvb, offset, 1,
			bvlc_type);
		offset ++;
		proto_tree_add_uint(bvlc_tree, hf_bvlc_function, tvb,
			offset, 1, bvlc_function);
		offset ++;
		if (length_remaining != packet_length)
			proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset,
				2, bvlc_length, 
				"%d of %d bytes (invalid length - expected %d bytes)",
				bvlc_length, packet_length, length_remaining);
		else		
			proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset,
				2, bvlc_length, "%d of %d bytes BACnet packet length",
				bvlc_length, packet_length);
		offset += 2;
		switch (bvlc_function) {
		case 0x00: /* BVLC-Result */
			bvlc_result = tvb_get_ntohs(tvb, offset);
			/* I dont know why the result code is encoded in 4 nibbles,
			 * but only using one: 0x00r0. Shifting left 4 bits.
			 */
			/* We should bitmask the result correctly when we have a
		 	* packet to dissect, see README.developer, 1.6.2, FID */
			proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_result, tvb,
				offset, 2, bvlc_result,"0x%04x (%s)",
				bvlc_result, val_to_str(bvlc_result,
					bvlc_result_names, "Unknown"));
			offset += 2;
			break;
		case 0x01: /* Write-Broadcast-Distribution-Table */
		case 0x03: /* Read-Broadcast-Distribution-Table-Ack */
			/* List of BDT Entries:	N*10-octet */
			ti_bdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb,
				offset, bvlc_length-4, FALSE);
			bdt_tree = proto_item_add_subtree(ti_bdt, ett_bdt);
			/* List of BDT Entries:	N*10-octet */
			while ((bvlc_length - offset) > 9) {
				proto_tree_add_item(bdt_tree, hf_bvlc_bdt_ip,
					tvb, offset, 4, FALSE);
				offset += 4;
				proto_tree_add_item(bdt_tree, hf_bvlc_bdt_port,
					tvb, offset, 2, FALSE);
				offset += 2;
				proto_tree_add_item(bdt_tree,
					hf_bvlc_bdt_mask, tvb, offset, 4,
					FALSE);
				offset += 4;
			}
			/* We check this if we get a BDT-packet somewhere */
			break;
		case 0x02: /* Read-Broadcast-Distribution-Table */
			/* nothing to do here */
			break;
		case 0x05: /* Register-Foreign-Device */
			/* Time-to-Live	2-octets T, Time-to-Live T, in seconds */
			proto_tree_add_item(bvlc_tree, hf_bvlc_reg_ttl,
				tvb, offset, 2, FALSE);
			offset += 2;
			break;
		case 0x06: /* Read-Foreign-Device-Table */
			/* nothing to do here */
			break;
		case 0x07: /* Read-Foreign-Device-Table-Ack */
			/* List of FDT Entries:	N*10-octet */
			/* N indicates the number of entries in the FDT whose
			 * contents are being returned. Each returned entry
			 * consists of the 6-octet B/IP address of the registrant;
			 * the 2-octet Time-to-Live value supplied at the time of
			 * registration; and a 2-octet value representing the
			 * number of seconds remaining before the BBMD will purge
			 * the registrant's FDT entry if no re-registration occurs.
			 */
			ti_fdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb,
				offset, bvlc_length -4, FALSE);
			fdt_tree = proto_item_add_subtree(ti_fdt, ett_fdt);
			/* List of FDT Entries:	N*10-octet */
			while ((bvlc_length - offset) > 9) {
				proto_tree_add_item(fdt_tree, hf_bvlc_fdt_ip,
					tvb, offset, 4, FALSE);
				offset += 4;
				proto_tree_add_item(fdt_tree, hf_bvlc_fdt_port,
					tvb, offset, 2, FALSE);
				offset += 2;
				proto_tree_add_item(fdt_tree,
					hf_bvlc_fdt_ttl, tvb, offset, 2,
					FALSE);
				offset += 2;
				proto_tree_add_item(fdt_tree,
					hf_bvlc_fdt_timeout, tvb, offset, 2,
					FALSE);
				offset += 2;
			}
			/* We check this if we get a FDT-packet somewhere */
			break;
		case 0x08: /* Delete-Foreign-Device-Table-Entry */
			/* FDT Entry:	6-octets */
			proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_ip,
				tvb, offset, 4, FALSE);
			offset += 4;
			proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_port,
				tvb, offset, 2, FALSE);
			offset += 2;
			break;
			/* We check this if we get a FDT-packet somewhere */
		case 0x04:	/* Forwarded-NPDU
				 * Why is this 0x04? It would have been a better
				 * idea to append all forewarded NPDUs at the
				 * end of the function table in the B/IP-standard!
				 */
			/* proto_tree_add_bytes_format(); */
			proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_ip,
				tvb, offset, 4, FALSE);
			offset += 4;
			proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_port,
				tvb, offset, 2, FALSE);
			offset += 2;
		default:/* Distribute-Broadcast-To-Network
			 * Original-Unicast-NPDU
			 * Original-Broadcast-NPDU
			 * Going to the next dissector...
			 */
			break;
		}

	}
/* Ok, no routing information BVLC packet. Dissect as
 * BACnet NPDU
 */
	npdu_length = packet_length - bvlc_length;
	next_tvb = tvb_new_subset(tvb,bvlc_length,-1,npdu_length);
	/* Code from Guy Harris */
	if (!dissector_try_port(bvlc_dissector_table,
	    bvlc_function, next_tvb, pinfo, tree)) {
		/* Unknown function - dissect the paylod as data */
		call_dissector(data_handle,next_tvb, pinfo, tree);
	}
	return tvb_length(tvb);
}
Beispiel #9
0
static void
dissect_tzsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree *tzsp_tree = NULL;
	proto_item *ti = NULL;
	int pos = 0;
	tvbuff_t *next_tvb;
	guint16 encapsulation = 0;
	int wtap_encap;
	dissector_handle_t encap_dissector;
	const char *encap_name;
	const char *info;
	guint8 type;

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

	type = tvb_get_guint8(tvb, 1);

	/* Find the dissector. */
	encapsulation = tvb_get_ntohs(tvb, 2);
	if (encapsulation != 0) {
		wtap_encap = tzsp_encap_to_wtap_encap(encapsulation);
		if (wtap_encap != -1 &&
		    (encap_dissector = dissector_get_port_handle(encap_dissector_table, wtap_encap))) {
			encap_name = dissector_handle_get_short_name(encap_dissector);
		}
		else {
			encap_name = "Unknown";
		}
		info = encap_name;
	}
	else {
		wtap_encap = -1;
		encap_name = "Nothing";
		info = val_to_str(type, tzsp_type, "Unknown (%u)");
	}

	col_add_str(pinfo->cinfo, COL_INFO, info);

	if (tree) {
		/* Adding TZSP item and subtree */
		ti = proto_tree_add_protocol_format(tree, proto_tzsp, tvb, 0,
		    -1, "TZSP: %s: ", info);
		tzsp_tree = proto_item_add_subtree(ti, ett_tzsp);

		proto_tree_add_item (tzsp_tree, hf_tzsp_version, tvb, 0, 1,
					FALSE);
		proto_tree_add_uint (tzsp_tree, hf_tzsp_type, tvb, 1, 1,
					type);
		proto_tree_add_uint_format (tzsp_tree, hf_tzsp_encap, tvb, 2, 2,
					encapsulation, "Encapsulates: %s (%d)",
					encap_name, encapsulation);
	}

	if (type != 4 && type != 5) {
		pos = add_option_info(tvb, 4, tzsp_tree, ti);

		if (tree)
			proto_item_set_end(ti, tvb, pos);
		next_tvb = tvb_new_subset_remaining(tvb, pos);
		if (encapsulation != 0
		    && (wtap_encap == -1
			|| !dissector_try_port(encap_dissector_table, wtap_encap,
				next_tvb, pinfo, tree))) {

			col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
			if (check_col(pinfo->cinfo, COL_INFO))
				col_add_fstr(pinfo->cinfo, COL_INFO, "TZSP_ENCAP = %u",
				    encapsulation);
			call_dissector(data_handle, next_tvb, pinfo, tree);
		}
	}
}
Beispiel #10
0
void
ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype,
		packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
		int etype_id, int trailer_id, int fcs_len)
{
	const char		*description;
	tvbuff_t		*volatile next_tvb;
	guint			length_before;
	gint			captured_length, reported_length;
	volatile gboolean	dissector_found = FALSE;
	const char		*volatile saved_proto;

	/* Add the Ethernet type to the protocol tree */
	if (tree) {
		proto_tree_add_uint(fh_tree, etype_id, tvb,
		    offset_after_etype - 2, 2, etype);
	}

	/* Get the captured length and reported length of the data
	   after the Ethernet type. */
	captured_length = tvb_length_remaining(tvb, offset_after_etype);
	reported_length = tvb_reported_length_remaining(tvb,
	    offset_after_etype);

	/* Remember how much data there is after the Ethernet type,
	   including any trailer and FCS. */
	length_before = reported_length;

	/* Construct a tvbuff for the payload after the Ethernet type.
	   If the FCS length is positive, remove the FCS.
	   (If it's zero, there's no FCS; if it's negative,
	   we don't know whether there's an FCS, so we'll
	   guess based on the length of the trailer.) */
	if (fcs_len > 0) {
		if (captured_length >= 0 && reported_length >= 0) {
			if (reported_length >= fcs_len)
				reported_length -= fcs_len;
			if (captured_length > reported_length)
				captured_length = reported_length;
		}
	}
	next_tvb = tvb_new_subset(tvb, offset_after_etype, captured_length,
	    reported_length);

	pinfo->ethertype = etype;

	/* Look for sub-dissector, and call it if found.
	   Catch exceptions, so that if the reported length of "next_tvb"
	   was reduced by some dissector before an exception was thrown,
	   we can still put in an item for the trailer. */
	saved_proto = pinfo->current_proto;
	TRY {
		dissector_found = dissector_try_port(ethertype_dissector_table,
		    etype, next_tvb, pinfo, tree);
	}
	CATCH(BoundsError) {
		/* Somebody threw BoundsError, which means that:

		     1) a dissector was found, so we don't need to
		        dissect the payload as data or update the
		        protocol or info columns;

		     2) dissecting the payload found that the packet was
		        cut off by a snapshot length before the end of
		        the payload.  The trailer comes after the payload,
		        so *all* of the trailer is cut off, and we'll
		        just get another BoundsError if we add the trailer.

		   Therefore, we just rethrow the exception so it gets
		   reported; we don't dissect the trailer or do anything
		   else. */
		 RETHROW;
	}
	CATCH(OutOfMemoryError) {
		 RETHROW;
	}
	CATCH_ALL {
		/* Somebody threw an exception other than BoundsError, which
		   means that a dissector was found, so we don't need to
		   dissect the payload as data or update the protocol or info
		   columns.  We just show the exception and then drive on
		   to show the trailer, after noting that a dissector was
		   found and restoring the protocol value that was in effect
		   before we called the subdissector. */
		show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
		dissector_found = TRUE;
		pinfo->current_proto = saved_proto;
	}
	ENDTRY;

	if (!dissector_found) {
		/* No sub-dissector found.
		   Label rest of packet as "Data" */
		call_dissector(data_handle,next_tvb, pinfo, tree);

		/* Label protocol */
		if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
			col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x",
			    etype);
		}
		if (check_col(pinfo->cinfo, COL_INFO)) {
			description = match_strval(etype, etype_vals);
			if (description) {
				col_add_str(pinfo->cinfo, COL_INFO,
				    description);
			}
		}
	}

	add_dix_trailer(pinfo, fh_tree, trailer_id, tvb, next_tvb, offset_after_etype,
	    length_before, fcs_len);
}
/* Code to actually dissect the packets */
static void dissect_t2sf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  tvbuff_t *next_tvb;
  int available_length;
  guint8 sf_payload_length = 0;
  guint8 sf_type;
  
  /* Set up structures needed to add the protocol subtree and manage it */
  proto_item *ti;
  proto_tree *t2sf_tree;
  
  /* check if this is sf packet is really sane. If length is incorrect this might be another packet */
  if (tvb_get_guint8(tvb, 0)+1 != tvb_length(tvb)) {
    call_dissector(data_handle, tvb, pinfo, tree);
    return;
  }
  
  sf_payload_length = tvb_get_guint8(tvb, T2_SF_HEADER_LENGTH_OFFSET)+1;
  sf_type = tvb_get_guint8(tvb, T2_SF_HEADER_TYPE_OFFSET);

  /* Make entries in Protocol column and Info column on summary display */
  if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "T2 SF");

  if (check_col(pinfo->cinfo, COL_INFO)) 
    col_set_str(pinfo->cinfo, COL_INFO, "TinyOS 2 SerialForwarder Packet");

  if (tree) {

    /* create display subtree for the protocol */
    ti = proto_tree_add_item(tree, proto_t2sf, tvb, 0, -1, FALSE);
    t2sf_tree = proto_item_add_subtree(ti, ett_t2sf);

    /* add items to the subtree */
    proto_tree_add_item(t2sf_tree, hf_t2sf_length, tvb, T2_SF_HEADER_LENGTH_OFFSET, T2_SF_LENGTH_NUM_BYTES, FALSE);
    proto_tree_add_item(t2sf_tree, hf_t2sf_type, tvb, T2_SF_HEADER_TYPE_OFFSET, T2_SF_TYPE_NUM_BYTES, FALSE);
 
    /*
      if (sf_length > 0) {
      proto_tree_add_item(t2sf_tree, hf_t2sf_data, tvb, SERIAL_AM_DATA_OFFSET, serial_am_payload_length, FALSE);
      }
    */
  }
  
  /* Calculate the available data in the packet, 
     set this to -1 to use all the data in the tv_buffer */
  available_length = tvb_length(tvb) - T2_SF_HEADER_LEN;

  /* Create the tvbuffer for the next dissector */
  next_tvb = tvb_new_subset(tvb, T2_SF_HEADER_LEN, MIN(available_length, sf_payload_length), sf_payload_length);
  
  /* check if message has type field */
  if (dissector_try_port(t2sf_type_dissector_table, sf_type, next_tvb, pinfo, tree)) {
    return;
  }

  /* try "heuristics */
  if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)) {
    return;
  }
  
  /* call the next dissector */
  call_dissector(data_handle, next_tvb, pinfo, tree);
  return;
}
/* Code to actually dissect the packets */
static void
dissect_macmgmt (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
{

  const guint8 *src, *dst;
  guint16 msg_len;
  proto_item *mgt_hdr_it;
  proto_tree *mgt_hdr_tree;
  tvbuff_t *payload_tvb;
  guint8 type;
  col_set_str (pinfo->cinfo, COL_PROTOCOL, "DOCSIS MGMT");

  col_clear(pinfo->cinfo, COL_INFO);


  src = tvb_get_ptr (tvb, 6, 6);
  dst = tvb_get_ptr (tvb, 0, 6);
  SET_ADDRESS (&pinfo->dl_src, AT_ETHER, 6, src);
  SET_ADDRESS (&pinfo->src, AT_ETHER, 6, src);
  SET_ADDRESS (&pinfo->dl_dst, AT_ETHER, 6, dst);
  SET_ADDRESS (&pinfo->dst, AT_ETHER, 6, dst);

  if (tree)
    {
      mgt_hdr_it =
	proto_tree_add_protocol_format (tree, proto_docsis_mgmt, tvb, 0, 20,
					"Mac Management");
      mgt_hdr_tree = proto_item_add_subtree (mgt_hdr_it, ett_docsis_mgmt);
      proto_tree_add_item (mgt_hdr_tree, hf_docsis_mgt_dst_addr, tvb, 0, 6,
			   FALSE);
      proto_tree_add_item (mgt_hdr_tree, hf_docsis_mgt_src_addr, tvb, 6, 6,
			   FALSE);
      proto_tree_add_item (mgt_hdr_tree, hf_docsis_mgt_msg_len, tvb, 12, 2,
			   FALSE);
      proto_tree_add_item (mgt_hdr_tree, hf_docsis_mgt_dsap, tvb, 14, 1,
			   FALSE);
      proto_tree_add_item (mgt_hdr_tree, hf_docsis_mgt_ssap, tvb, 15, 1,
			   FALSE);
      proto_tree_add_item (mgt_hdr_tree, hf_docsis_mgt_control, tvb, 16, 1,
			   FALSE);
      proto_tree_add_item (mgt_hdr_tree, hf_docsis_mgt_version, tvb, 17, 1,
			   FALSE);
      proto_tree_add_item (mgt_hdr_tree, hf_docsis_mgt_type, tvb, 18, 1,
			   FALSE);
      proto_tree_add_item (mgt_hdr_tree, hf_docsis_mgt_rsvd, tvb, 19, 1,
			   FALSE);

    }
  /* Code to Call subdissector */
  /* sub-dissectors are based on the type field */
  type = tvb_get_guint8 (tvb, 18);
  msg_len = tvb_get_ntohs (tvb, 12);
  payload_tvb = tvb_new_subset (tvb, 20, msg_len - 6, msg_len - 6);

  if (dissector_try_port
      (docsis_mgmt_dissector_table, type, payload_tvb, pinfo, tree))
    return;
  else
    call_dissector (data_handle, payload_tvb, pinfo, tree);


}
Beispiel #13
0
static void
dissect_nettl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
      proto_tree *nettl_tree;
      proto_item *nettl_item;

      pinfo->current_proto = "nettl";

      if (tree) {
	    nettl_item = proto_tree_add_protocol_format(tree, proto_nettl, tvb,
		0, -1, "HP-UX Network Tracing and Logging (nettl) header");
	    nettl_tree = proto_item_add_subtree(nettl_item, ett_nettl);
            proto_tree_add_uint_format(nettl_tree, hf_nettl_subsys, tvb,
		0, 0, pinfo->pseudo_header->nettl.subsys,
		"Subsystem: %d (%s)", pinfo->pseudo_header->nettl.subsys,
		val_to_str(pinfo->pseudo_header->nettl.subsys, subsystem, "Unknown"));
            proto_tree_add_int(nettl_tree, hf_nettl_devid, tvb,
		0, 0, pinfo->pseudo_header->nettl.devid);
            proto_tree_add_uint_format(nettl_tree, hf_nettl_kind, tvb,
		0, 0, pinfo->pseudo_header->nettl.kind,
		"Trace Kind: 0x%08x (%s)", pinfo->pseudo_header->nettl.kind,
		val_to_str(pinfo->pseudo_header->nettl.kind & ~NETTL_HDR_SUBSYSTEM_BITS_MASK, trace_kind, "Unknown"));
            proto_tree_add_int(nettl_tree, hf_nettl_pid, tvb,
		0, 0, pinfo->pseudo_header->nettl.pid);
            proto_tree_add_uint(nettl_tree, hf_nettl_uid, tvb,
		0, 0, pinfo->pseudo_header->nettl.uid);

      }

      switch (pinfo->fd->lnk_t) {
         case WTAP_ENCAP_NETTL_ETHERNET:
            call_dissector(eth_withoutfcs_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_TOKEN_RING:
            call_dissector(tr_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_FDDI:
            if (!dissector_try_port(wtap_dissector_table,
			WTAP_ENCAP_FDDI_BITSWAPPED, tvb, pinfo, tree))
	            call_dissector(data_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_RAW_IP:
            if ( (pinfo->pseudo_header->nettl.kind & NETTL_HDR_PDU_MASK) == 0 )
                    /* not actually a data packet (PDU) trace record */
	            call_dissector(data_handle, tvb, pinfo, tree);
            else if (pinfo->pseudo_header->nettl.subsys == NETTL_SUBSYS_NS_LS_SCTP )
                    call_dissector(sctp_handle, tvb, pinfo, tree);
            else if (!dissector_try_port(wtap_dissector_table,
			WTAP_ENCAP_RAW_IP, tvb, pinfo, tree))
	            call_dissector(data_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_RAW_ICMP:
            if (!dissector_try_port(ip_proto_dissector_table,
			IP_PROTO_ICMP, tvb, pinfo, tree))
	            call_dissector(data_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_RAW_ICMPV6:
            if (!dissector_try_port(ip_proto_dissector_table,
	                IP_PROTO_ICMPV6, tvb, pinfo, tree))
	            call_dissector(data_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_X25:
	    if (pinfo->pseudo_header->nettl.kind == NETTL_HDR_PDUIN)
            	pinfo->p2p_dir = P2P_DIR_RECV;
	    else if (pinfo->pseudo_header->nettl.kind == NETTL_HDR_PDUOUT)
            	pinfo->p2p_dir = P2P_DIR_SENT;
	    if (pinfo->pseudo_header->nettl.subsys == NETTL_SUBSYS_SX25L2)
            	call_dissector(lapb_handle, tvb, pinfo, tree);
	    else
            	call_dissector(x25_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_RAW_TELNET:
            if (!dissector_try_port(tcp_subdissector_table,
	                TCP_PORT_TELNET, tvb, pinfo, tree))
	            call_dissector(data_handle, tvb, pinfo, tree);
            break;
         default:
            col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
            if (check_col(pinfo->cinfo, COL_INFO))
                col_add_fstr(pinfo->cinfo, COL_INFO,
		"Unsupported nettl subsytem: %d (%s)",
                pinfo->pseudo_header->nettl.subsys,
		val_to_str(pinfo->pseudo_header->nettl.subsys, subsystem, "Unknown"));
            call_dissector(data_handle, tvb, pinfo, tree);
      }
}
static void dissect_packetlogger (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_tree *packetlogger_tree = NULL;
  tvbuff_t   *next_tvb;
  proto_item *ti = NULL;
  guint8      pl_type;
  gint        len;

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

  ti = proto_tree_add_item (tree, proto_packetlogger, tvb, 0, -1, FALSE);
  packetlogger_tree = proto_item_add_subtree (ti, ett_packetlogger);

  pl_type = tvb_get_guint8 (tvb, 0);
  proto_tree_add_item (packetlogger_tree, hf_type, tvb, 0, 1, FALSE);
  proto_item_append_text (ti, " %s", val_to_str (pl_type, type_vals, "Unknown 0x%02x"));

  len = tvb_length_remaining (tvb, 1);
  next_tvb = tvb_new_subset (tvb, 1, len, len);

  if (pl_type <= PKT_RECV_ACL_DATA) {
    /* HCI H1 packages */
    switch (pl_type) {
    case PKT_HCI_COMMAND:
      pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_COMMAND;
      pinfo->pseudo_header->bthci.sent = P2P_DIR_SENT;
      pinfo->p2p_dir = P2P_DIR_SENT;
      break;
    case PKT_HCI_EVENT:
      pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_EVENT;
      pinfo->pseudo_header->bthci.sent = P2P_DIR_RECV;
      pinfo->p2p_dir = P2P_DIR_RECV;
      break;
    case PKT_SENT_ACL_DATA:
      pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_ACL;
      pinfo->pseudo_header->bthci.sent = P2P_DIR_SENT;
      pinfo->p2p_dir = P2P_DIR_SENT;
      break;
    case PKT_RECV_ACL_DATA:
      pinfo->pseudo_header->bthci.channel = BTHCI_CHANNEL_ACL;
      pinfo->pseudo_header->bthci.sent = P2P_DIR_RECV;
      pinfo->p2p_dir = P2P_DIR_RECV;
      break;
    default:
      pinfo->pseudo_header->bthci.channel = pl_type;
      pinfo->pseudo_header->bthci.sent = P2P_DIR_UNKNOWN;
      pinfo->p2p_dir = P2P_DIR_UNKNOWN;
      break;
    }
    proto_item_set_len (ti, 1);

    col_add_fstr (pinfo->cinfo, COL_INFO, "%s", val_to_str(pl_type, type_vals, "Unknown 0x%02x"));
    if (!dissector_try_port (hci_h1_table, pinfo->pseudo_header->bthci.channel, next_tvb, pinfo, tree)) {
      call_dissector (data_handle, next_tvb, pinfo, tree);
    }
  } else {
    /* PacketLogger data */
    switch (pl_type) {
    case PKT_INFO:
    case PKT_NEW_CONTROLLER:
      proto_tree_add_item (packetlogger_tree, hf_info, next_tvb, 0, len, FALSE);
      col_set_str (pinfo->cinfo, COL_INFO, tvb_format_stringzpad_wsp (next_tvb, 0, len));
      break;
    default:
      call_dissector (data_handle, next_tvb, pinfo, tree);
      col_add_fstr (pinfo->cinfo, COL_INFO, "Unknown 0x%02x", pl_type);
      break;
    }
  }
}