Example #1
0
static void
dissect_v5dl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*v5dl_tree, *addr_tree;
	proto_item	*v5dl_ti, *addr_ti;
	int		direction;
	guint		v5dl_header_len;
	guint16		control;
#if 0
	proto_tree	*checksum_tree;
	proto_item	*checksum_ti;
	guint16		checksum, checksum_calculated;
	guint		checksum_offset;
#endif
	guint16		addr, cr, eah, eal, v5addr;
	gboolean	is_response = 0;
#if 0
	guint		length, reported_length;
#endif
	tvbuff_t	*next_tvb;
	const char	*srcname = "?";
	const char	*dstname = "?";

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

	addr = tvb_get_ntohs(tvb, 0);
	cr = addr & V5DL_CR;
	eal = (addr & V5DL_EAL) >> V5DL_EAL_SHIFT;
	eah = (addr & V5DL_EAH) >> V5DL_EAH_SHIFT;
	v5addr = (eah << 7) + eal;
	v5dl_header_len = 2;	/* addr */

	direction = pinfo->p2p_dir;
	if (pinfo->p2p_dir == P2P_DIR_RECV) {
	    is_response = cr ? FALSE : TRUE;
	    srcname = "Network";
	    dstname = "User";
	}
	else if (pinfo->p2p_dir == P2P_DIR_SENT) {
	    is_response = cr ? TRUE : FALSE;
	    srcname = "User";
	    dstname = "Network";
	}

	col_set_str(pinfo->cinfo, COL_RES_DL_SRC, srcname);
	col_set_str(pinfo->cinfo, COL_RES_DL_DST, dstname);

	if (tree) {
		proto_item *direction_ti;

		v5dl_ti = proto_tree_add_item(tree, proto_v5dl, tvb, 0, -1,
		    ENC_NA);
		v5dl_tree = proto_item_add_subtree(v5dl_ti, ett_v5dl);

		/*
		 * Don't show the direction if we don't know it.
		 */
		if (direction != P2P_DIR_UNKNOWN) {
			direction_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_direction,
			                                   tvb, 0, 0, pinfo->p2p_dir);
			PROTO_ITEM_SET_GENERATED(direction_ti);
		}

		addr_ti = proto_tree_add_uint(v5dl_tree, hf_v5dl_ef, tvb,
		    0, 2, v5addr);
		addr_tree = proto_item_add_subtree(addr_ti, ett_v5dl_address);
		proto_tree_add_uint(addr_tree, hf_v5dl_eah, tvb, 0, 1, addr);
		proto_tree_add_uint(addr_tree, hf_v5dl_cr,  tvb, 0, 1, addr);
		proto_tree_add_uint(addr_tree, hf_v5dl_ea1, tvb, 0, 1, addr);
		proto_tree_add_uint(addr_tree, hf_v5dl_eal, tvb, 1, 1, addr);
		proto_tree_add_uint(addr_tree, hf_v5dl_ea2, tvb, 1, 1, addr);
	}
	else {
		v5dl_ti = NULL;
		v5dl_tree = NULL;
	}

	control = dissect_xdlc_control(tvb, 2, pinfo, v5dl_tree, hf_v5dl_control,
	    ett_v5dl_control, &v5dl_cf_items, &v5dl_cf_items_ext, NULL, NULL,
	    is_response, TRUE, FALSE);
	v5dl_header_len += XDLC_CONTROL_LEN(control, TRUE);

	if (tree)
		proto_item_set_len(v5dl_ti, v5dl_header_len);

	/*
	 * XXX - the sample capture supplied with bug 7027 does not
	 * appear to include checksums in the packets.
	 */
#if 0
	/*
	 * Check the checksum, if available.
	 * The checksum is a CCITT CRC-16 at the end of the packet, so
	 * if we don't have the entire packet in the capture - i.e., if
	 * tvb_captured_length(tvb) != tvb_reported_length(tvb) we can't check it.
	 */
	length = tvb_captured_length(tvb);
	reported_length = tvb_reported_length(tvb);

	/*
	 * If the reported length isn't big enough for the V5DL header
	 * and 2 bytes of checksum, the packet is malformed, as the
	 * checksum overlaps the header.
	 */
	if (reported_length < v5dl_header_len + 2)
		THROW(ReportedBoundsError);

	if (length == reported_length) {
		/*
		 * There's no snapshot length cutting off any of the
		 * packet.
		 */
		checksum_offset = reported_length - 2;
		checksum = tvb_get_ntohs(tvb, checksum_offset);
		checksum_calculated = crc16_ccitt_tvb(tvb, checksum_offset);
		checksum_calculated = g_htons(checksum_calculated);  /* Note: g_htons() macro may eval arg multiple times */

		if (checksum == checksum_calculated) {
			checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset,
								 2, 0,
								 "0x%04x [correct]",
								 checksum);
			checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum);
			proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, TRUE);
			proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, FALSE);
		} else {
			checksum_ti = proto_tree_add_uint_format_value(v5dl_tree, hf_v5dl_checksum, tvb, checksum_offset,
								 2, 0,
								 "0x%04x [incorrect, should be 0x%04x]",
								 checksum, checksum_calculated);
			checksum_tree = proto_item_add_subtree(checksum_ti, ett_v5dl_checksum);
			proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_good, tvb, checksum_offset, 2, FALSE);
			proto_tree_add_boolean(checksum_tree, hf_v5dl_checksum_bad, tvb, checksum_offset, 2, TRUE);
		}

		/*
		 * Remove the V5DL header *and* the checksum.
		 */
		next_tvb = tvb_new_subset(tvb, v5dl_header_len,
		    tvb_captured_length_remaining(tvb, v5dl_header_len) - 2,
		    tvb_reported_length_remaining(tvb, v5dl_header_len) - 2);
	} else {
		/*
		 * Some or all of the packet is cut off by a snapshot
		 * length.
		 */
		if (length == reported_length - 1) {
			/*
			 * One byte is cut off, so there's only one
			 * byte of checksum in the captured data.
			 * Remove that byte from the captured length
			 * and both bytes from the reported length.
			 */
			next_tvb = tvb_new_subset(tvb, v5dl_header_len,
			    tvb_captured_length_remaining(tvb, v5dl_header_len) - 1,
			    tvb_reported_length_remaining(tvb, v5dl_header_len) - 2);
		} else {
			/*
			 * Two or more bytes are cut off, so there are
			 * no bytes of checksum in the captured data.
			 * Just remove the checksum from the reported
			 * length.
			 */
			next_tvb = tvb_new_subset(tvb, v5dl_header_len,
			    tvb_captured_length_remaining(tvb, v5dl_header_len),
			    tvb_reported_length_remaining(tvb, v5dl_header_len) - 2);
		}
	}
#else
	next_tvb = tvb_new_subset_remaining(tvb, v5dl_header_len);
#endif

	if (XDLC_IS_INFORMATION(control)) {
		/* call V5.2 dissector */
	        call_dissector(v52_handle, next_tvb, pinfo, tree);
	}
}
Example #2
0
/* Code to actually dissect the packets */
static void
dissect_ehdlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	int  offset = 4;

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

	while (tvb_reported_length_remaining(tvb, offset) > 0) {
		proto_item *ti            = NULL;
		proto_tree *ehdlc_tree    = NULL;
		guint16     len, msg_type;
		tvbuff_t   *next_tvb;
		guint16     control;
		gboolean    is_response   = FALSE, is_extended = TRUE;
		gint        header_length = 2; /* Address + Length field */

		msg_type      = tvb_get_guint8(tvb, offset);
		len           = tvb_get_guint8(tvb, offset+1);
#if 0
		col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
		                val_to_str(msg_type, ehdlc_protocol_vals,
		                           "unknown 0x%02x"));
#endif
		if (tree) {
			/* Use MIN(...,...) in the following to prevent a premature */
			/* exception before we try to dissect whatever is available. */
			ti = proto_tree_add_protocol_format(tree, proto_ehdlc,
					tvb, offset, MIN(len, tvb_length_remaining(tvb,offset)),
					"Ericsson HDLC protocol, type: %s",
					val_to_str(msg_type, ehdlc_protocol_vals,
						   "unknown 0x%02x"));
			ehdlc_tree = proto_item_add_subtree(ti, ett_ehdlc);
			proto_tree_add_item(ehdlc_tree, hf_ehdlc_protocol,
					    tvb, offset, 1, ENC_BIG_ENDIAN);
#if 0
			proto_tree_add_item(ehdlc_tree, hf_ehdlc_sapi,
					    tvb, offset, 1, ENC_BIG_ENDIAN);
			proto_tree_add_item(ehdlc_tree, hf_ehdlc_c_r,
					    tvb, offset, 1, ENC_BIG_ENDIAN);
#endif
			proto_tree_add_item(ehdlc_tree, hf_ehdlc_data_len,
					    tvb, offset+1, 1, ENC_BIG_ENDIAN);
		}

		control = dissect_xdlc_control(tvb, offset+2, pinfo, ehdlc_tree, hf_ehdlc_control,
					       ett_ehdlc_control, &ehdlc_cf_items, &ehdlc_cf_items_ext,
					       NULL, NULL, is_response, is_extended, FALSE);
		header_length += XDLC_CONTROL_LEN(control, is_extended);

		if (XDLC_IS_INFORMATION(control)) {
			next_tvb = tvb_new_subset(tvb, offset+header_length,
						  len-header_length, len-header_length);

			switch (msg_type) {
			case 0x20:
				/* len == 4 seems to be some kind of ACK */
				if (len <= 4)
					break;
				call_dissector(sub_handles[SUB_RSL], next_tvb, pinfo, tree);
				break;
			case 0xbc:
			case 0xdc:
			case 0xa0:
			case 0xc0:
				/* len == 4 seems to be some kind of ACK */
				if (len <= 4)
					break;
				call_dissector(sub_handles[SUB_OML], next_tvb, pinfo, tree);
				break;
			default:
				call_dissector(sub_handles[SUB_DATA], next_tvb, pinfo, tree);
				break;
			}
		} else if (control == (XDLC_U | XDLC_XID)) {
			/* XID is formatted like ISO 8885, typically we see
 			 * something like
			 * 82		format identifier
			 * 80		group identifier
			 * 00 09 	length
			 * 07 01 05 	Window Size Tx
			 * 09 01 04	Ack Timer (msec)
			 * 08 01 05	Window Size Rx */
			proto_tree_add_item(ehdlc_tree, hf_ehdlc_xid_payload,
					    tvb, offset+header_length,
					    len-header_length, ENC_NA);
		}

		if (len == 0)
			len = 1;
		offset += len;
	}
}
Example #3
0
void
capture_llc(const guchar *pd, int offset, int len, packet_counts *ld) {

	int		is_snap;
	guint16		control;
	int		llc_header_len;

	if (!BYTES_ARE_IN_FRAME(offset, len, 2)) {
		ld->other++;
		return;
	}
	is_snap = (pd[offset] == SAP_SNAP) && (pd[offset+1] == SAP_SNAP);
	llc_header_len = 2;	/* DSAP + SSAP */

	/*
	 * XXX - the page referred to in the comment above about the
	 * Command/Response bit also implies that LLC Type 2 always
	 * uses extended operation, so we don't need to determine
	 * whether it's basic or extended operation; is that the case?
	 */
	control = get_xdlc_control(pd, offset+2, pd[offset+1] & SSAP_CR_BIT);
	llc_header_len += XDLC_CONTROL_LEN(control, TRUE);
	if (!BYTES_ARE_IN_FRAME(offset, len, llc_header_len)) {
		ld->other++;
		return;
	}

	if (!XDLC_IS_INFORMATION(control)) {
		ld->other++;
		return;
	}
	if (is_snap)
		capture_snap(pd, offset+llc_header_len, len, ld);
	else {
		/* non-SNAP */
		switch (pd[offset]) {

		case SAP_IP:
			capture_ip(pd, offset + llc_header_len, len, ld);
			break;

		case SAP_NETWARE1:
		case SAP_NETWARE2:
			capture_ipx(ld);
			break;

		case SAP_NETBIOS:
			capture_netbios(ld);
			break;

		case SAP_VINES1:
		case SAP_VINES2:
			capture_vines(ld);
			break;

		default:
			ld->other++;
			break;
		}
	}
}
Example #4
0
static void
dissect_sdlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*sdlc_tree;
	proto_item	*sdlc_ti;
	guint8		addr;
	guint16		control;
	int		sdlc_header_len;
	gboolean	is_response;
	tvbuff_t	*next_tvb;

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

	addr = tvb_get_guint8(tvb, 0);
	sdlc_header_len = 1;	/* address */

	/*
	 * XXX - is there something in the SDLC header that indicates
	 * how to interpret "command vs. response" based on the
	 * direction?
	 */
	if (pinfo->p2p_dir == P2P_DIR_SENT) {
		is_response = FALSE;
		col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
		col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
	}
	else {
		/* XXX - what if the direction is unknown? */
		is_response = TRUE;
		col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
		col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
	}

	if (tree) {
		sdlc_ti = proto_tree_add_item(tree, proto_sdlc, tvb, 0, -1,
		    FALSE);
		sdlc_tree = proto_item_add_subtree(sdlc_ti, ett_sdlc);

		proto_tree_add_uint(sdlc_tree, hf_sdlc_address, tvb, 0, 1,
		    addr);
	} else {
		sdlc_ti = NULL;
		sdlc_tree = NULL;
	}

	/*
	 * XXX - SDLC has a mod-128 mode as well as a mod-7 mode.
	 * We can infer the mode from an SNRM/SRME frame, but if
	 * we don't see one of them, we may have to have a preference
	 * to control what to use.
	 */
	control = dissect_xdlc_control(tvb, 1, pinfo, sdlc_tree, hf_sdlc_control,
	    ett_sdlc_control, &sdlc_cf_items, NULL, NULL, NULL,
	    is_response, FALSE, FALSE);
	sdlc_header_len += XDLC_CONTROL_LEN(control, FALSE);

	if (tree)
		proto_item_set_len(sdlc_ti, sdlc_header_len);

	/*
	 * XXX - is there an FCS at the end, at least in Sniffer
	 * captures?  (There doesn't appear to be.)
	 */
	next_tvb = tvb_new_subset_remaining(tvb, sdlc_header_len);
	if (XDLC_IS_INFORMATION(control)) {
		/* call the SNA dissector */
		call_dissector(sna_handle, next_tvb, pinfo, tree);
	} else
		call_dissector(data_handle, next_tvb, pinfo, tree);
}
Example #5
0
static void
dissect_llc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*llc_tree = NULL;
	proto_item	*ti = NULL;
	int		is_snap;
	guint16		control;
	int		llc_header_len;
	guint8		dsap, ssap, format;
	tvbuff_t	*next_tvb;

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

	dsap = tvb_get_guint8(tvb, 0);
	if (tree) {
		ti = proto_tree_add_item(tree, proto_llc, tvb, 0, -1, ENC_NA);
		llc_tree = proto_item_add_subtree(ti, ett_llc);
		proto_tree_add_uint(llc_tree, hf_llc_dsap, tvb, 0,
			1, dsap & SAP_MASK);
		proto_tree_add_boolean(llc_tree, hf_llc_dsap_ig, tvb, 0,
			1, dsap & DSAP_GI_BIT);
	} else
		llc_tree = NULL;

	ssap = tvb_get_guint8(tvb, 1);
	if (tree) {
		proto_tree_add_uint(llc_tree, hf_llc_ssap, tvb, 1,
			1, ssap & SAP_MASK);
		proto_tree_add_boolean(llc_tree, hf_llc_ssap_cr, tvb, 1,
			1, ssap & SSAP_CR_BIT);
	} else
		llc_tree = NULL;

	is_snap = (dsap == SAP_SNAP) && (ssap == SAP_SNAP);
	llc_header_len = 2;	/* DSAP + SSAP */

	/*
	 * XXX - the page referred to in the comment above about the
	 * Command/Response bit also implies that LLC Type 2 always
	 * uses extended operation, so we don't need to determine
	 * whether it's basic or extended operation; is that the case?
	 */
	control = dissect_xdlc_control(tvb, 2, pinfo, llc_tree,
				hf_llc_ctrl, ett_llc_ctrl,
				&llc_cf_items, &llc_cf_items_ext,
				NULL, NULL, ssap & SSAP_CR_BIT, TRUE, FALSE);
	llc_header_len += XDLC_CONTROL_LEN(control, TRUE);
	if (is_snap)
		llc_header_len += 5;	/* 3 bytes of OUI, 2 bytes of protocol ID */

	if (tree)
		proto_item_set_len(ti, llc_header_len);

	if (is_snap) {
		dissect_snap(tvb, 2+XDLC_CONTROL_LEN(control, TRUE), pinfo, tree, llc_tree, control,
		    hf_llc_oui, hf_llc_type, hf_llc_pid, 2);
	}
	else {
		col_append_fstr(pinfo->cinfo, COL_INFO,
			    "; DSAP %s %s, SSAP %s %s",
			    val_to_str(dsap & SAP_MASK, sap_vals, "0x%02x"),
			    dsap & DSAP_GI_BIT ?
			      "Group" : "Individual",
			    val_to_str(ssap & SAP_MASK, sap_vals, "0x%02x"),
			    ssap & SSAP_CR_BIT ?
			      "Response" : "Command"
			);

		if (tvb_length_remaining(tvb, llc_header_len) > 0) {
			next_tvb = tvb_new_subset_remaining(tvb, llc_header_len);
			if (XDLC_IS_INFORMATION(control)) {
				/*
				 * Non-SNAP I or UI frame.
				 * Try the regular LLC subdissector table
				 * with the DSAP.
				 */
				if (!dissector_try_uint(dsap_subdissector_table,
				    dsap, next_tvb, pinfo, tree)) {
					call_dissector(data_handle, next_tvb,
					    pinfo, tree);
				}
			} else if ((control & (XDLC_U_MODIFIER_MASK|XDLC_U))
			    == (XDLC_XID|XDLC_U)) {
				/*
				 * Non-SNAP XID frame.
				 * Test for LLC basic format first
				 */
				format = tvb_get_guint8(next_tvb, 0);
				if (format == 0x81) {
				    dissect_basicxid(next_tvb, pinfo, tree);
				} else {
				/*
				 * Try the XID LLC subdissector table
				 * with the DSAP.
				 */
				    if (!dissector_try_uint(
					xid_subdissector_table, dsap, next_tvb,
					pinfo, tree)) {
					    call_dissector(data_handle,
						next_tvb, pinfo, tree);
				    }
				}
			} else {
				call_dissector(data_handle, next_tvb, pinfo,
				    tree);
			}
		}
	}
}