Example #1
0
static void
dissect_smb_direct(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
		   enum SMB_DIRECT_HDR_TYPE hdr_type)

{
	proto_tree *tree = NULL;
	proto_item *item = NULL;
	proto_tree *neg_req_tree = NULL;
	proto_tree *neg_rep_tree = NULL;
	proto_tree *data_tree = NULL;
	int offset = 0;
	guint32 status = 0;
	guint32 remaining_length = 0;
	guint32 data_offset = 0;
	guint32 data_length = 0;
	guint rlen = tvb_reported_length(tvb);
	gint len = 0;
	tvbuff_t *next_tvb = NULL;
	static const int * flags[] = {
		&hf_smb_direct_flags_response_requested,
		NULL
	};

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

	if (parent_tree != NULL) {
		item = proto_tree_add_item(parent_tree, proto_smb_direct, tvb, 0, -1, ENC_NA);
		tree = proto_item_add_subtree(item, ett_smb_direct);
	}

	switch (hdr_type) {
	case SMB_DIRECT_HDR_UNKNOWN:
		break;

	case SMB_DIRECT_HDR_NEG_REQ:
		col_append_str(pinfo->cinfo, COL_INFO, "NegotiateRequest");

		if (tree == NULL) {
			break;
		}

		item = proto_tree_add_item(tree, hf_smb_direct_negotiate_request, tvb, 0, -1, ENC_NA);
		neg_req_tree = proto_item_add_subtree(item, ett_smb_direct_hdr);

		proto_tree_add_item(neg_req_tree, hf_smb_direct_min_version,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_req_tree, hf_smb_direct_max_version,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		/* 2 bytes reserved */
		offset += 2;

		proto_tree_add_item(neg_req_tree, hf_smb_direct_credits_requested,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_req_tree, hf_smb_direct_preferred_send_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_req_tree, hf_smb_direct_max_receive_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_req_tree, hf_smb_direct_max_fragmented_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		/* offset += 4; */
		break;

	case SMB_DIRECT_HDR_NEG_REP:
		col_append_str(pinfo->cinfo, COL_INFO, "NegotiateResponse");

		status = tvb_get_letohl(tvb, 12);
		if (status != 0) {
			col_append_fstr(
				pinfo->cinfo, COL_INFO, ", Error: %s",
				val_to_str(status, NT_errors, "Unknown (0x%08X)"));
		}

		if (tree == NULL) {
			break;
		}

		item = proto_tree_add_item(tree, hf_smb_direct_negotiate_response, tvb, 0, -1, ENC_NA);
		neg_rep_tree = proto_item_add_subtree(item, ett_smb_direct_hdr);

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_min_version,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_version,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_negotiated_version,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		/* 2 bytes reserved */
		offset += 2;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_credits_requested,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_credits_granted,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_status,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_read_write_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_preferred_send_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_receive_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		proto_tree_add_item(neg_rep_tree, hf_smb_direct_max_fragmented_size,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		/* offset += 4; */
		break;

	case SMB_DIRECT_HDR_DATA:
		col_append_str(pinfo->cinfo, COL_INFO, "DataMessage");

		if (tree == NULL) {
			break;
		}

		rlen = MIN(rlen, 24);

		item = proto_tree_add_item(tree, hf_smb_direct_data_message, tvb, 0, rlen, ENC_NA);
		data_tree = proto_item_add_subtree(item, ett_smb_direct_hdr);

		proto_tree_add_item(data_tree, hf_smb_direct_credits_requested,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_item(data_tree, hf_smb_direct_credits_granted,
				    tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		proto_tree_add_bitmask(tree, tvb, offset, hf_smb_direct_flags,
			       ett_smb_direct_flags, flags, ENC_LITTLE_ENDIAN);
		offset += 2;

		/* 2 bytes reserved */
		offset += 2;

		remaining_length = tvb_get_letohl(tvb, offset);
		proto_tree_add_item(data_tree, hf_smb_direct_remaining_length,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		data_offset = tvb_get_letohl(tvb, offset);
		proto_tree_add_item(data_tree, hf_smb_direct_data_offset,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		data_length = tvb_get_letohl(tvb, offset);
		proto_tree_add_item(data_tree, hf_smb_direct_data_length,
				    tvb, offset, 4, ENC_LITTLE_ENDIAN);
		offset += 4;

		if (data_length > 0 && data_offset > (guint32)offset) {
			len = tvb_reported_length_remaining(tvb, data_offset);
		}

		if (data_length <= (guint32)len) {
			next_tvb = tvb_new_subset_length(tvb, data_offset,
						  data_length);
		}

		if (next_tvb != NULL) {
			dissect_smb_direct_payload(next_tvb, pinfo,
						   parent_tree, remaining_length);
		}

		/* offset = data_offset + data_length; */
		break;
	}

	return;
}
Example #2
0
static void
dissect_itdm_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  tvbuff_t	*next_tvb;
  proto_item *itdm_ctl_item = NULL;
  proto_tree *itdm_ctl_tree = NULL;
  int offset;
  guint32 flowid;
  guint8 command;
  guint32 trans_id;
  guint32 paired_trans_id;
  guint32 allocd_flowid;

  col_set_str(pinfo->cinfo, COL_PROTOCOL, "ITDM-Control");

  flowid = tvb_get_ntoh24(tvb, ITDM_FLOWID_OFFSET);
  command = tvb_get_guint8(tvb, ITDM_CTL_CMD_OFFSET);
  allocd_flowid = tvb_get_ntoh24(tvb, ITDM_CTL_FLOWID_OFFSET);
  trans_id = tvb_get_ntohl(tvb, ITDM_CTL_TRANSID_OFFSET);
  paired_trans_id = tvb_get_ntohl(tvb, ITDM_CTL_PAIRED_TRANSID_OFFSET);

  if (check_col(pinfo->cinfo, COL_INFO))
  {
    col_add_fstr(pinfo->cinfo, COL_INFO,
      "Flow %d Command %s ",
      flowid, val_to_str(command, itdm_ctl_command_vals, "Reserved"));

    if (command != ITDM_CTL_CMD_AFI_REQ )
    {
      col_append_fstr(pinfo->cinfo, COL_INFO,
        " Alloc'd FlowID %d", allocd_flowid);
    }

    col_append_fstr(pinfo->cinfo, COL_INFO, " TransID 0x%x ", trans_id);

    if (command != ITDM_CTL_CMD_AFI_REQ )
    {
      col_append_fstr(pinfo->cinfo, COL_INFO,
        " Paired TransID 0x%x", paired_trans_id);
    }
  }

  offset = 0;

  if (tree)
  {
	itdm_ctl_item = proto_tree_add_item(tree, proto_itdm, tvb, 0, -1, ENC_NA);
	itdm_ctl_tree = proto_item_add_subtree(itdm_ctl_item, ett_itdm_ctl);

	/* These eventually should go into a SFP.0 dissector... */
	proto_tree_add_item(itdm_ctl_tree, hf_itdm_timestamp, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;
	proto_tree_add_item(itdm_ctl_tree, hf_itdm_seqnum, tvb, offset, 1, ENC_BIG_ENDIAN);
	offset += 1;
	proto_tree_add_item(itdm_ctl_tree, hf_itdm_sop_eop, tvb, offset, 1, ENC_BIG_ENDIAN);
	proto_tree_add_item(itdm_ctl_tree, hf_itdm_last_pack, tvb, offset, 1, ENC_BIG_ENDIAN);
	proto_tree_add_item(itdm_ctl_tree, hf_itdm_pktlen, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;
	proto_tree_add_item(itdm_ctl_tree, hf_itdm_chksum, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;
	proto_tree_add_item(itdm_ctl_tree, hf_itdm_uid, tvb, offset, 3, ENC_BIG_ENDIAN);
	offset += 3;

	proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_transid, tvb, offset, 4, ENC_BIG_ENDIAN);
	offset += 4;

	proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_command, tvb, offset, 1, ENC_BIG_ENDIAN);
	offset += 1;
	if (command != ITDM_CTL_CMD_AFI_REQ) {
		proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_flowid, tvb, offset, 3, ENC_BIG_ENDIAN);
	}
	offset += 3;
	proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_dm, tvb, offset, 1, ENC_BIG_ENDIAN);
	offset += 1;
	/* rsvd.. */
	offset += 1;
	proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_emts, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;
	proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_pktrate, tvb, offset, 4, ENC_BIG_ENDIAN);
	offset += 4;
	if (command != ITDM_CTL_CMD_AFI_REQ) {
		proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_ptid, tvb, offset, 4, ENC_BIG_ENDIAN);
	}
	offset += 4;
	/* rsvd.. */
	offset += 2;
	proto_tree_add_item(itdm_ctl_tree, hf_itdm_ctl_cksum, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;
  }

  next_tvb = tvb_new_subset_remaining(tvb, offset);
  call_dissector(data_handle, next_tvb, pinfo, tree);
}
Example #3
0
  proto_item *ti, *op_ti;
  gint start_offset, offset = 0;
  guint8 opcode;

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

  start_offset = offset;
  ti = proto_tree_add_item (tree, proto_nat_pmp, tvb, offset, -1, ENC_NA);
  nat_pmp_tree = proto_item_add_subtree (ti, ett_nat_pmp);

  proto_tree_add_item (nat_pmp_tree, hf_version, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset++;

  opcode = tvb_get_guint8 (tvb, offset);
  proto_item_append_text (ti, ", %s", val_to_str (opcode, opcode_vals, "Unknown opcode: %d"));
  op_ti = proto_tree_add_item (nat_pmp_tree, hf_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset++;

  col_add_str (pinfo->cinfo, COL_INFO, val_to_str (opcode, opcode_vals, "Unknown opcode: %d"));

  switch (opcode) {

  case EXTERNAL_ADDRESS_REQUEST:
    /* No more data */
    break;

  case EXTERNAL_ADDRESS_RESPONSE:
    proto_tree_add_item (nat_pmp_tree, hf_result_code, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;
Example #4
0
/*
 * dissect_pgm - The dissector for Pragmatic General Multicast
 */
static void
dissect_pgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint16 pgmhdr_sport;
	guint16 pgmhdr_dport;
	guint8 pgmhdr_type;
	guint8 pgmhdr_opts;
	guint16 pgmhdr_cksum;
	guint16 pgmhdr_tsdulen;
	guint32 sqn;
	guint16 afi;

	guint plen = 0;
	proto_item *ti;
	const char *pktname;
	const char *pollstname;
	char *gsi;
	gboolean isdata = FALSE;
	guint pgmlen, reportedlen;

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

	if (check_col(pinfo->cinfo, COL_INFO)) {
		col_clear(pinfo->cinfo, COL_INFO);
		if (tvb_reported_length_remaining(tvb, 0) < 18) {
			col_set_str(pinfo->cinfo, COL_INFO,
				"Packet too small");
			return;
		}
	}

	pinfo->srcport = pgmhdr_sport = tvb_get_ntohs(tvb, 0);
	pinfo->destport = pgmhdr_dport = tvb_get_ntohs(tvb, 2);

	pgmhdr_type = tvb_get_guint8(tvb, 4);
	pktname = val_to_str(pgmhdr_type, type_vals, "Unknown (0x%02x)");

	pgmhdr_opts = tvb_get_guint8(tvb, 5);
	pgmhdr_cksum = tvb_get_ntohs(tvb, 6);
	gsi = tvb_bytes_to_str(tvb, 8, 6);
	pgmhdr_tsdulen = tvb_get_ntohs(tvb, 14);
	sqn = tvb_get_ntohl(tvb, 16);

	switch(pgmhdr_type) {
	case PGM_SPM_PCKT:
	case PGM_NAK_PCKT:
	case PGM_NNAK_PCKT:
	case PGM_NCF_PCKT:
	case PGM_POLR_PCKT:
	case PGM_ACK_PCKT:
		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_fstr(pinfo->cinfo, COL_INFO,
				"%-5s sqn 0x%x gsi %s", pktname, sqn, gsi);
		}
		break;
	case PGM_RDATA_PCKT:
	case PGM_ODATA_PCKT:
		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_fstr(pinfo->cinfo, COL_INFO,
			    "%-5s sqn 0x%x gsi %s tsdulen %d", pktname, sqn, gsi,
			    pgmhdr_tsdulen);
		}
		isdata = TRUE;
		break;
	case PGM_POLL_PCKT: {
		guint16 poll_stype = tvb_get_ntohs(tvb, 22);
		pollstname = val_to_str(poll_stype, poll_subtype_vals, "Unknown (0x%02x)");

		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_fstr(pinfo->cinfo, COL_INFO,
				"%-5s sqn 0x%x gsi %s subtype %s",
					pktname, sqn, gsi, pollstname);
		}
		}
		break;
	default:
		return;
	}

	{
		proto_tree *pgm_tree = NULL;
		proto_tree *opt_tree = NULL;
		proto_tree *type_tree = NULL;
		proto_item *tf, *hidden_item;
		ptvcursor_t* cursor;

		ti = proto_tree_add_protocol_format(tree, proto_pgm,
			tvb, 0, -1,
			"Pragmatic General Multicast: Type %s"
			    " Src Port %u, Dst Port %u, GSI %s", pktname,
			pgmhdr_sport, pgmhdr_dport, gsi);

		pgm_tree = proto_item_add_subtree(ti, ett_pgm);

		cursor = ptvcursor_new(pgm_tree, tvb, 0);

		hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 0, 2, ENC_BIG_ENDIAN);
		PROTO_ITEM_SET_HIDDEN(hidden_item);
		hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 2, 2, ENC_BIG_ENDIAN);
		PROTO_ITEM_SET_HIDDEN(hidden_item);
		ptvcursor_add(cursor, hf_pgm_main_sport, 2, ENC_BIG_ENDIAN);
		ptvcursor_add(cursor, hf_pgm_main_dport, 2, ENC_BIG_ENDIAN);
		ptvcursor_add(cursor, hf_pgm_main_type, 1, ENC_BIG_ENDIAN);

		tf = proto_tree_add_uint_format(pgm_tree, hf_pgm_main_opts, tvb,
			ptvcursor_current_offset(cursor), 1, pgmhdr_opts, "Options: %s (0x%x)",
			optsstr(pgmhdr_opts), pgmhdr_opts);
		opt_tree = proto_item_add_subtree(tf, ett_pgm_optbits);
		ptvcursor_set_tree(cursor, opt_tree);

		ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_opt, 1, ENC_BIG_ENDIAN);
		ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_netsig, 1, ENC_BIG_ENDIAN);
		ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_varlen, 1, ENC_BIG_ENDIAN);
		ptvcursor_add(cursor, hf_pgm_main_opts_parity, 1, ENC_BIG_ENDIAN);
		ptvcursor_set_tree(cursor, pgm_tree);

		/* Checksum may be 0 (not available), but not for DATA packets */
		if ((pgmhdr_type != PGM_RDATA_PCKT) && (pgmhdr_type != PGM_ODATA_PCKT) &&
		    (pgmhdr_cksum == 0))
		{
			proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb,
				ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: not available");
		} else {
			reportedlen = tvb_reported_length(tvb);
			pgmlen = tvb_length(tvb);
			if (pgm_check_checksum && pgmlen >= reportedlen) {
				vec_t cksum_vec[1];
				guint16 computed_cksum;

				cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pgmlen);
				cksum_vec[0].len = pgmlen;
				computed_cksum = in_cksum(&cksum_vec[0], 1);
				if (computed_cksum == 0) {
					proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb,
						ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: 0x%04x [correct]", pgmhdr_cksum);
				} else {
					hidden_item = proto_tree_add_boolean(pgm_tree, hf_pgm_main_cksum_bad, tvb,
					    ptvcursor_current_offset(cursor), 2, TRUE);
					PROTO_ITEM_SET_HIDDEN(hidden_item);
					proto_tree_add_uint_format(pgm_tree, hf_pgm_main_cksum, tvb,
					    ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: 0x%04x [incorrect, should be 0x%04x]",
						pgmhdr_cksum, in_cksum_shouldbe(pgmhdr_cksum, computed_cksum));
				}
			} else {
				ptvcursor_add_no_advance(cursor, hf_pgm_main_cksum, 2, ENC_BIG_ENDIAN);
			}
		}
		ptvcursor_advance(cursor, 2);

		ptvcursor_add(cursor, hf_pgm_main_gsi, 6, ENC_NA);
		ptvcursor_add(cursor, hf_pgm_main_tsdulen, 2, ENC_BIG_ENDIAN);

		tf = proto_tree_add_text(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, "%s Packet", pktname);
		switch(pgmhdr_type) {
		case PGM_SPM_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_spm);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_lead, 4, ENC_BIG_ENDIAN);
			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_spm_pathafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_res, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_spm_path, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_spm_path6, 16, ENC_NA);
				break;

			default:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				return;
			}
			break;
		case PGM_RDATA_PCKT:
		case PGM_ODATA_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_data);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN);
			break;
		case PGM_NAK_PCKT:
		case PGM_NNAK_PCKT:
		case PGM_NCF_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_nak);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_nak_sqn, 4, ENC_BIG_ENDIAN);
			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_nak_srcafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_nak_srcres, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_nak_src, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_nak_src6, 16, ENC_NA);
				break;

			default:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_nak_grpafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_nak_grpres, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_nak_grp, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_nak_grp6, 16, ENC_NA);
				break;

			default:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				return;
			}
			break;
		case PGM_POLL_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_poll);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_poll_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_round, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_subtype, 2, ENC_BIG_ENDIAN);
			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_poll_pathafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_res, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_poll_path, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_poll_path6, 16, ENC_NA);
				break;

			default:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			ptvcursor_add(cursor, hf_pgm_poll_backoff_ivl, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_rand_str, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_matching_bmask, 4, ENC_BIG_ENDIAN);
			break;
		case PGM_POLR_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_polr);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_polr_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_polr_round, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_polr_res, 2, ENC_BIG_ENDIAN);
			break;
		case PGM_ACK_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_ack);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_ack_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_ack_bitmap, 4, ENC_BIG_ENDIAN);
			break;
		}

		if (pgmhdr_opts & PGM_OPT)
			dissect_pgmopts(cursor, pktname);

		if (isdata)
			decode_pgm_ports(tvb, ptvcursor_current_offset(cursor), pinfo, tree, pgmhdr_sport, pgmhdr_dport);
	}
}
Example #5
0
static guint
dissect_ssprotocol_message(tvbuff_t *message_tvb, packet_info *pinfo, proto_tree *ssprotocol_tree)
{
  proto_item* flags_item;
  proto_tree* flags_tree;
  guint8      type;
  guint16     data_length;
  guint16     info_length;
  guint       total_length;

  type = tvb_get_guint8(message_tvb, MESSAGE_TYPE_OFFSET);
  if (pinfo && (check_col(pinfo->cinfo, COL_INFO))) {
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, message_type_values, "Unknown SSP type: %u"));
  }
  proto_tree_add_item(ssprotocol_tree, hf_message_type,   message_tvb, MESSAGE_TYPE_OFFSET,   MESSAGE_TYPE_LENGTH,   FALSE);
  flags_item = proto_tree_add_item(ssprotocol_tree, hf_message_flags,  message_tvb, MESSAGE_FLAGS_OFFSET,  MESSAGE_FLAGS_LENGTH,  FALSE);
  proto_tree_add_item(ssprotocol_tree, hf_message_length, message_tvb, MESSAGE_LENGTH_OFFSET, MESSAGE_LENGTH_LENGTH, FALSE);
  total_length = MESSAGE_LENGTH_OFFSET + MESSAGE_LENGTH_LENGTH;
  switch (type) {
    case SS_KEEPALIVE_ACK_TYPE:
    case SS_STATUS_TYPE:
      info_length = tvb_get_ntohs(message_tvb, MESSAGE_LENGTH_OFFSET) - MESSAGE_STATUS_OFFSET;
      if (info_length == MESSAGE_STATUS_LENGTH) {
        proto_tree_add_item(ssprotocol_tree, hf_message_status, message_tvb, MESSAGE_STATUS_OFFSET, MESSAGE_STATUS_LENGTH, FALSE);
        total_length += MESSAGE_STATUS_LENGTH;
      }
      break;
    case SS_UPLOAD_TYPE:
    case SS_DOWNLOAD_TYPE:
      data_length = tvb_get_ntohs(message_tvb, MESSAGE_LENGTH_OFFSET) - MESSAGE_DATA_OFFSET;
      if (data_length > 0) {
        proto_tree_add_item(ssprotocol_tree, hf_message_data, message_tvb, MESSAGE_DATA_OFFSET, data_length, FALSE);
        total_length += data_length;
      }
      break;
    case SS_READY_TYPE:
      info_length = tvb_get_ntohs(message_tvb, MESSAGE_LENGTH_OFFSET) - MESSAGE_RDY_INFO_OFFSET;
      if (info_length > 0) {
        proto_tree_add_item(ssprotocol_tree, hf_message_info, message_tvb, MESSAGE_RDY_INFO_OFFSET, info_length, FALSE);
        total_length += info_length;
      }
      break;
    case SS_NOTREADY_TYPE:
      info_length = tvb_get_ntohs(message_tvb, MESSAGE_LENGTH_OFFSET) - MESSAGE_NOTRDY_INFO_OFFSET;
      if (info_length > 0) {
        proto_tree_add_item(ssprotocol_tree, hf_message_reason, message_tvb, MESSAGE_NOTRDY_REASON_OFFSET, MESSAGE_NOTRDY_REASON_LENGTH, FALSE);
        proto_tree_add_item(ssprotocol_tree, hf_message_info,   message_tvb, MESSAGE_NOTRDY_INFO_OFFSET, info_length, FALSE);
        total_length += info_length;
      }
      break;
    case SS_ENVIRONMENT_TYPE:
        flags_tree = proto_item_add_subtree(flags_item, ett_environment_flags);
        proto_tree_add_item(flags_tree, hf_environment_u_bit, message_tvb, MESSAGE_FLAGS_OFFSET, MESSAGE_FLAGS_LENGTH, ENC_BIG_ENDIAN);
        proto_tree_add_item(ssprotocol_tree, hf_message_hash, message_tvb, MESSAGE_ENVIRON_HASH_OFFSET, MESSAGE_ENVIRON_HASH_LENGTH, FALSE);
      break;
    default:
      break;
  }

  return total_length;
}
static int
dissect_remunk_remqueryinterface_resp(tvbuff_t *tvb, int offset,
                                      packet_info *pinfo, proto_tree *tree, dcerpc_info *di, guint8 *drep)
{
    guint32      u32Pointer;
    guint32      u32ArraySize;
    guint32      u32ItemIdx;
    proto_item  *sub_item;
    proto_tree  *sub_tree;
    guint32      u32HResult;
    guint32      u32SubStart;
    e_uuid_t     iid;
    e_uuid_t     iid_null = DCERPC_UUID_NULL;
    remunk_remqueryinterface_call_t *call = (remunk_remqueryinterface_call_t *)di->call_data->private_data;
    guint64      oxid;
    guint64      oid;
    e_uuid_t     ipid;


    offset = dissect_dcom_that(tvb, offset, pinfo, tree, di, drep);

    offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, tree, di, drep,
                                         &u32Pointer);
    offset = dissect_dcom_dcerpc_array_size(tvb, offset, pinfo, tree, di, drep,
                                            &u32ArraySize);

    u32ItemIdx = 1;
    while (u32ArraySize--) {
        /* add subtree */
        sub_item = proto_tree_add_item(tree, hf_remunk_qiresult, tvb, offset, 0, ENC_NA);
        sub_tree = proto_item_add_subtree(sub_item, ett_remunk_rqi_result);

        /* REMQIRESULT */
        offset = dissect_dcom_HRESULT(tvb, offset, pinfo, sub_tree, di, drep,
                                      &u32HResult);
        u32SubStart = offset - 4;
        offset = dissect_dcom_dcerpc_pointer(tvb, offset, pinfo, sub_tree, di, drep,
                                             &u32Pointer);

        /* try to read the iid from the request */
        if(call != NULL && u32ItemIdx <= call->iid_count) {
            iid = call->iids[u32ItemIdx-1];
        } else {
            iid = iid_null;
        }

        /* XXX - this doesn't seem to be dependent on the pointer above?!? */
        /*if (u32Pointer) {*/
        offset = dissect_dcom_STDOBJREF(tvb, offset, pinfo, sub_tree, di, drep, 0 /* hfindex */,
                                        &oxid, &oid, &ipid);
        /*}*/

        /* add interface instance to database (we currently only handle IPv4) */
        if(pinfo->net_src.type == AT_IPv4) {
            dcom_interface_new(pinfo,
                               (guint8 *)pinfo->net_src.data,
                               &iid, oxid, oid, &ipid);
        }

        /* update subtree */
        proto_item_append_text(sub_item, "[%u]: %s",
                               u32ItemIdx,
                               val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)") );
        proto_item_set_len(sub_item, offset - u32SubStart);

        /* update column info now */
        col_append_fstr(pinfo->cinfo, COL_INFO, " %s[%u]",
                        val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)"),
                        u32ItemIdx);
        u32ItemIdx++;
    }

    /* HRESULT of call */
    offset = dissect_dcom_HRESULT(tvb, offset, pinfo, tree, di, drep,
                                  &u32HResult);

    /* update column info now */
    col_append_fstr(pinfo->cinfo, COL_INFO, " -> %s",
                    val_to_str(u32HResult, dcom_hresult_vals, "Unknown (0x%08x)"));

    return offset;
}
Example #7
0
static int
ros_try_string(const char *oid, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, struct SESSION_DATA_STRUCTURE* session)
{
	ros_info_t *rinfo;
	gint32     opcode_lcl = 0;
	const gchar *opname = NULL;
	const gchar *suffix = NULL;
	dissector_t opdissector = NULL;
	const value_string *lookup;
	proto_item *item=NULL;
	proto_tree *ros_tree=NULL;

	if((session != NULL) && ((rinfo = (ros_info_t*)g_hash_table_lookup(protocol_table, oid)) != NULL)) {

		if(tree){
			item = proto_tree_add_item(tree, *(rinfo->proto), tvb, 0, -1, ENC_NA);
			ros_tree = proto_item_add_subtree(item, *(rinfo->ett_proto));
		}

		col_set_str(pinfo->cinfo, COL_PROTOCOL, rinfo->name);

		/* if this is a bind operation */
		if((session->ros_op & ROS_OP_TYPE_MASK) == ROS_OP_BIND) {
			/* use the in-built operation codes */
			if((session->ros_op & ROS_OP_PDU_MASK) ==  ROS_OP_ERROR)
				opcode_lcl = err_ros_bind;
			else
				opcode_lcl = op_ros_bind;
		} else
			/* otherwise just take the opcode */
			opcode_lcl = session->ros_op & ROS_OP_OPCODE_MASK;

		/* default lookup in the operations */
		lookup = rinfo->opr_code_strings;

		switch(session->ros_op & ROS_OP_PDU_MASK) {
		case ROS_OP_ARGUMENT:
			opdissector = ros_lookup_opr_dissector(opcode_lcl, rinfo->opr_code_dissectors, TRUE);
			suffix = "_argument";
			break;
		case ROS_OP_RESULT:
			opdissector = ros_lookup_opr_dissector(opcode_lcl, rinfo->opr_code_dissectors, FALSE);
			suffix = "_result";
			break;
		case ROS_OP_ERROR:
			opdissector = ros_lookup_err_dissector(opcode_lcl, rinfo->err_code_dissectors);
			lookup = rinfo->err_code_strings;
			break;
		default:
			break;
		}

		if(opdissector) {

			opname = val_to_str(opcode_lcl, lookup, "Unknown opcode (%d)");

			col_set_str(pinfo->cinfo, COL_INFO, opname);
			if(suffix)
				col_append_str(pinfo->cinfo, COL_INFO, suffix);

			return (*opdissector)(tvb, pinfo, ros_tree, NULL);
		}
	}

	return 0;
}
Example #8
0
static gboolean
dissect_fcip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
              gboolean check_port)
{
    gint offset = 0,
         start  = 0,
         frame_len = 0;
    gint bytes_remaining = tvb_length (tvb);
    guint8 pflags, sof = 0, eof = 0;
   /* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti;
    proto_tree *fcip_tree = NULL;
    tvbuff_t *next_tvb;

    if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) {
        return FALSE;
    }

    if (check_port &&
        ((pinfo->srcport != fcip_port) && (pinfo->destport != fcip_port))) {
        return FALSE;
    }

    while (bytes_remaining > FCIP_ENCAP_HEADER_LEN) {
        if ((offset = get_next_fcip_header_offset (tvb, pinfo, offset)) == -1) {
            return FALSE;
        }
        else if (offset == -2) {
            /* We need more data to desegment */
            return (TRUE);
        }

        start = offset;
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCIP");

        frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;

        if (bytes_remaining < frame_len) {
            if(fcip_desegment && pinfo->can_desegment) {
                /*
                 * This frame doesn't have all of the data for
                 * this message, but we can do reassembly on it.
                 *
                 * Tell the TCP dissector where the data for this
                 * message starts in the data it handed us, and
                 * how many more bytes we need, and return.
                 */
                pinfo->desegment_offset = offset;
                pinfo->desegment_len = frame_len - bytes_remaining;
                return (TRUE);
            }
        }

        pflags = tvb_get_guint8 (tvb, start+8);

        if (tree) {
            if (FCIP_IS_SF (pflags)) {
                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP");
            }
            else if (tvb_bytes_exist (tvb, offset, offset+frame_len-4)) {
                sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);
                eof = tvb_get_guint8 (tvb, offset+frame_len - 4);

                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP (%s/%s)",
                                                     val_to_str (sof, fcip_sof_vals,
                                                                 "0x%x"),
                                                     val_to_str (eof, fcip_eof_vals,
                                                                 "0x%x"));
            }
            else {
                sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);

                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP (%s/%s)",
                                                     val_to_str (sof, fcip_sof_vals,
                                                                 "0x%x"),
                                                     "NA");
            }
            fcip_tree = proto_item_add_subtree (ti, ett_fcip);
            /* Dissect the Common FC Encap header */
            dissect_fcencap_header (tvb, fcip_tree, offset);

            offset += FCIP_ENCAP_HEADER_LEN;

            if (!FCIP_IS_SF (pflags)) {
                /* print SOF */
                proto_tree_add_item (fcip_tree, hf_fcip_sof, tvb, offset, 1, 0);
                proto_tree_add_item (fcip_tree, hf_fcip_sof_c, tvb, offset+2, 1, 0);
                /* print EOF */

                offset += (frame_len-FCIP_ENCAP_HEADER_LEN-4);
                if (tvb_bytes_exist (tvb, offset, 4)) {
                    proto_tree_add_item (fcip_tree, hf_fcip_eof, tvb, offset, 1, 0);
                    proto_tree_add_item (fcip_tree, hf_fcip_eof_c, tvb, offset+2, 1, 0);
                }
            }
        }

        /* Call the FC Dissector if this is carrying an FC frame */
        if (!FCIP_IS_SF(pflags)) {
            /* Set the SOF/EOF flags in the packet_info header */
            pinfo->sof_eof = 0;

            if (sof) {
                if ((sof == FCIP_SOFi3) || (sof == FCIP_SOFi2) || (sof == FCIP_SOFi4)) {
                    pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
                }
                else if (sof == FCIP_SOFf) {
                    pinfo->sof_eof = PINFO_SOF_SOFF;
                }

                if (eof != FCIP_EOFn) {
                    pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
                }
                else if (eof != FCIP_EOFt) {
                    pinfo->sof_eof |= PINFO_EOF_INVALID;
                }
            }

            /* Special frame bit is not set */
            next_tvb = tvb_new_subset_remaining (tvb, FCIP_ENCAP_HEADER_LEN+4);
            if (fc_handle) {
                call_dissector (fc_handle, next_tvb, pinfo, tree);
            }
            else if (data_handle) {
                call_dissector (data_handle, next_tvb, pinfo, tree);
            }
        }
        else {
            col_set_str(pinfo->cinfo, COL_INFO, "Special Frame");
            if (FCIP_IS_CH (pflags)) {
                col_append_str(pinfo->cinfo, COL_INFO, "(Changed)");
            }

            dissect_fcip_sf (tvb, fcip_tree, offset+4);
        }

        bytes_remaining -= frame_len;
    }

    return (TRUE);
}
Example #9
0
/* This function is only called from the IGMP dissector */
int
dissect_pimv1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
              int offset) {
    guint8 pim_type;
    guint8 pim_ver;
    guint length, pim_length;
    guint16 pim_cksum, computed_cksum;
    vec_t cksum_vec[1];
    proto_tree *pim_tree = NULL;
    proto_item *ti;
    proto_tree *pimopt_tree = NULL;
    proto_item *tiopt;

    if (!proto_is_protocol_enabled(find_protocol_by_id(proto_pim))) {
        /*
         * We are not enabled; skip entire packet to be nice to the
         * IGMP layer (so clicking on IGMP will display the data).
         */
        return offset+tvb_length_remaining(tvb, offset);
    }

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

    ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, FALSE);
    pim_tree = proto_item_add_subtree(ti, ett_pim);

    /* Put IGMP type, 0x14, into the tree */
    proto_tree_add_text(pim_tree, tvb, offset, 1,
                        "Type: PIM (0x14)");
    offset += 1;

    pim_type = tvb_get_guint8(tvb, offset);
    if (check_col(pinfo->cinfo, COL_INFO))
        col_add_str(pinfo->cinfo, COL_INFO,
                    val_to_str(pim_type, type1vals, "Unknown (%u)"));

    proto_tree_add_uint(pim_tree, hf_pim_code, tvb, offset, 1, pim_type);
    offset += 1;

    pim_cksum = tvb_get_ntohs(tvb, offset);
    pim_ver = PIM_VER(tvb_get_guint8(tvb, offset + 2));
    if (pim_ver != 1) {
        /*
         * Not PIMv1 - what gives?
         */
        proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb,
                            offset, 2, pim_cksum);

        offset += 2;
        proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, FALSE);
        return offset+tvb_length_remaining(tvb, offset);
    }

    /*
     * Well, it's PIM v1, so we can check whether this is a
     * Register message, and thus can figure out how much to
     * checksum and whether to make the columns read-only.
     */
    length = tvb_length(tvb);
    if (pim_type == 1) {
        /*
         * Register message - the PIM header is 8 bytes long.
         * Also set the columns non-writable. Otherwise the IPv4 or
         * IPv6 dissector for the encapsulated packet that caused
         * this register will overwrite the PIM info in the columns.
         */
        pim_length = 8;
        col_set_writable(pinfo->cinfo, FALSE);
    } else {
        /*
         * Other message - checksum the entire packet.
         */
        pim_length = tvb_reported_length(tvb);
    }

    if (!pinfo->fragmented && length >= pim_length) {
        /*
         * The packet isn't part of a fragmented datagram and isn't
         * truncated, so we can checksum it.
         */
        cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length);
        cksum_vec[0].len = pim_length;
        computed_cksum = in_cksum(&cksum_vec[0], 1);
        if (computed_cksum == 0) {
            proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
                                       offset, 2, pim_cksum,
                                       "Checksum: 0x%04x [correct]",
                                       pim_cksum);
        } else {
            proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
                                       offset, 2, pim_cksum,
                                       "Checksum: 0x%04x [incorrect, should be 0x%04x]",
                                       pim_cksum, in_cksum_shouldbe(pim_cksum, computed_cksum));
        }
    } else {
        proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb,
                            offset, 2, pim_cksum);
    }
    offset += 2;

    proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, FALSE);
    offset += 1;

    offset += 3;        /* skip reserved stuff */

    if (tvb_reported_length_remaining(tvb, offset) > 0) {
        tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1, "PIM options");
        pimopt_tree = proto_item_add_subtree(tiopt, ett_pim_opts);
    } else
        goto done;

    /* version 1 decoder */
    switch (pim_type) {
    case 0:     /* query */
    {
        guint16 holdtime;

        proto_tree_add_item(pimopt_tree, hf_pim_mode, tvb, offset, 1, FALSE);
        offset += 2;

        holdtime = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
        offset += 2;
        break;
    }

    case 1:     /* register */
    {
        guint8 v_hl;
        tvbuff_t *next_tvb;

        /*
         * The rest of the packet is a multicast data packet.
         */
        next_tvb = tvb_new_subset_remaining(tvb, offset);

        /*
         * It's an IP packet - determine whether it's IPv4 or IPv6.
         */
        v_hl = tvb_get_guint8(tvb, offset);
        switch((v_hl & 0xf0) >> 4) {
        case 0:     /* Null-Register dummy header.
                     * Has the same address family as the encapsulating PIM packet,
                     * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet.
                     */
            if (pinfo->src.type == AT_IPv4) {
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "IPv4 dummy header");
                proto_tree_add_text(pimopt_tree, tvb, offset + 12, 4,
                                    "Source: %s",
                                    tvb_ip_to_str(tvb, offset + 12));
                proto_tree_add_text(pimopt_tree, tvb, offset + 16, 4,
                                    "Group: %s",
                                    tvb_ip_to_str(tvb, offset + 16));
            } else if (pinfo->src.type == AT_IPv6) {
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "IPv6 dummy header");
                proto_tree_add_text(pimopt_tree, tvb,
                                    offset + 8, 16,
                                    "Source: %s",
                                    tvb_ip6_to_str(tvb, offset + 8));
                proto_tree_add_text(pimopt_tree, tvb,
                                    offset + 8 + 16, 16,
                                    "Group: %s",
                                    tvb_ip6_to_str(tvb, offset + 8));
            } else
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "Dummy header for an unknown protocol");
            break;
        case 4: /* IPv4 */
#if 0
            call_dissector(ip_handle, next_tvb, pinfo, tree);
#else
            call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree);
#endif
            break;
        case 6: /* IPv6 */
#if 0
            call_dissector(ipv6_handle, next_tvb, pinfo, tree);
#else
            call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree);
#endif
            break;
        default:
            proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                "Unknown IP version %d", (v_hl & 0xf0) >> 4);
            break;
        }
        break;
    }

    case 2:     /* register-stop */
    {
        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Group: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;
        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Source: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;
        break;
    }

    case 3:     /* join/prune */
    case 6:     /* graft */
    case 7:     /* graft-ack */
    {
        int off;
        const char *s;
        int ngroup, i, njoin, nprune, j;
        guint16 holdtime;
        guint8 mask_len;
        guint8 adr_len;
        proto_tree *grouptree = NULL;
        proto_item *tigroup;
        proto_tree *subtree = NULL;
        proto_item *tisub;

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Upstream-neighbor: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        offset += 2;    /* skip reserved stuff */

        holdtime = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
        offset += 2;

        offset += 1;    /* skip reserved stuff */

        mask_len = tvb_get_guint8(tvb, offset);
        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Mask length: %u", mask_len);
        offset += 1;

        adr_len = tvb_get_guint8(tvb, offset);
        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Address length: %u", adr_len);
        offset += 1;

        ngroup = tvb_get_guint8(tvb, offset);
        proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, FALSE);
        offset += 1;

        for (i = 0; i < ngroup; i++) {
            /*
             * XXX - does the group address have the length "adr_len"
             * and the group mask the length "mask_len"?
             */
            tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                                          "Group %d: %s", i,
                                          tvb_ip_to_str(tvb, offset));
            grouptree = proto_item_add_subtree(tigroup, ett_pim);
            offset += 4;

            proto_tree_add_text(grouptree, tvb, offset, 4,
                                "Group %d Mask: %s", i,
                                tvb_ip_to_str(tvb, offset));
            offset += 4;

            njoin = tvb_get_ntohs(tvb, offset);
            nprune = tvb_get_ntohs(tvb, offset + 2);
            tisub = proto_tree_add_item(grouptree, hf_pim_numjoins, tvb,
                                        offset, 2, FALSE);
            subtree = proto_item_add_subtree(tisub, ett_pim);
            off = offset + 4;
            for (j = 0; j < njoin; j++) {
                s = dissect_pimv1_addr(tvb, off);
                proto_tree_add_text(subtree, tvb, off, 6,
                                    "IP address: %s", s);
                off += 6;
            }

            tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb,
                                        offset + 2, 2, FALSE);
            subtree = proto_item_add_subtree(tisub, ett_pim);
            for (j = 0; j < nprune; j++) {
                s = dissect_pimv1_addr(tvb, off);
                proto_tree_add_text(subtree, tvb, off, 6,
                                    "IP address: %s", s);
                off += 6;
            }
            offset = off;
        }
        break;
    }

    case 4:     /* rp-reachability */
    {
        guint16 holdtime;

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Group Address: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Group Mask: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "RP Address: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        offset += 2;    /* skip reserved stuff */

        holdtime = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
        offset += 2;
        break;
    }

    case 5:     /* assert */
    {
        guint32 pref;

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Group Address: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Group Mask: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, FALSE);
        pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff;
        proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb,
                                   offset, 4, pref,
                                   "Metric Preference: %u", pref);
        offset += 4;

        proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, FALSE);
        offset += 4;
        break;
    }

    default:
        break;
    }
done:;

    return offset+tvb_length_remaining(tvb, offset);
}
Example #10
0
static void
dissect_eapol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  int         offset = 0;
  guint8      eapol_type;
  guint8      keydesc_type;
  guint16     eapol_len;
  guint       len;
  guint16     eapol_key_len, eapol_data_len;
  guint8      key_index;
  guint16     keyinfo;
  proto_tree *ti = NULL;
  proto_tree *eapol_tree = NULL;
  proto_tree *keyinfo_item = NULL;
  proto_tree *keyinfo_tree = NULL;
  proto_tree *key_index_tree, *keydes_tree;
  tvbuff_t   *next_tvb;

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

  if (tree) {
    ti = proto_tree_add_item(tree, proto_eapol, tvb, 0, -1, ENC_NA);
    eapol_tree = proto_item_add_subtree(ti, ett_eapol);

    proto_tree_add_item(eapol_tree, hf_eapol_version, tvb, offset, 1, ENC_BIG_ENDIAN);
  }
  offset++;

  eapol_type = tvb_get_guint8(tvb, offset);
  if (tree)
    proto_tree_add_uint(eapol_tree, hf_eapol_type, tvb, offset, 1, eapol_type);
  if (check_col(pinfo->cinfo, COL_INFO))
    col_add_str(pinfo->cinfo, COL_INFO,
		val_to_str(eapol_type, eapol_type_vals, "Unknown type (0x%02X)"));
  offset++;

  eapol_len = tvb_get_ntohs(tvb, offset);
  len = EAPOL_HDR_LEN + eapol_len;
  set_actual_length(tvb, len);
  if (tree) {
    proto_item_set_len(ti, len);
    proto_tree_add_uint(eapol_tree, hf_eapol_len, tvb, offset, 2, eapol_len);
  }
  offset += 2;

  switch (eapol_type) {

  case EAP_PACKET:
    next_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector(eap_handle, next_tvb, pinfo, eapol_tree);
    break;

  case EAPOL_KEY:
    if (tree) {
      keydesc_type = tvb_get_guint8(tvb, offset);
      proto_tree_add_item(eapol_tree, hf_eapol_keydes_type, tvb, offset, 1, ENC_BIG_ENDIAN);
      offset += 1;
      if (keydesc_type == EAPOL_WPA_KEY || keydesc_type == EAPOL_RSN_KEY) {
	keyinfo = tvb_get_ntohs(tvb, offset);
	if (check_col(pinfo->cinfo, COL_INFO)) {
          if (keyinfo & KEY_INFO_REQUEST_MASK) {
            col_set_str(pinfo->cinfo, COL_INFO, "Key (Request)");
            if (keyinfo & KEY_INFO_ERROR_MASK)
              col_set_str(pinfo->cinfo, COL_INFO, "Key (Request, Error)");
          } else if (keyinfo & KEY_INFO_KEY_TYPE_MASK) {
            guint16 masked;
            masked = keyinfo &
              (KEY_INFO_INSTALL_MASK | KEY_INFO_KEY_ACK_MASK |
               KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK);
            switch (masked) {
            case KEY_INFO_KEY_ACK_MASK:
              col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 1/4)");
              break;
            case KEY_INFO_KEY_MIC_MASK:
              col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 2/4)");
              break;
            case (KEY_INFO_INSTALL_MASK | KEY_INFO_KEY_ACK_MASK |
                  KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK):
              col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 3/4)");
              break;
            case (KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK):
              col_set_str(pinfo->cinfo, COL_INFO, "Key (msg 4/4)");
              break;
            }
          } else {
            if (keyinfo & KEY_INFO_KEY_ACK_MASK)
              col_set_str(pinfo->cinfo, COL_INFO, "Key (Group msg 1/2)");
            else
              col_set_str(pinfo->cinfo, COL_INFO, "Key (Group msg 2/2)");
          }
        }
	keyinfo_item =
	  proto_tree_add_uint(eapol_tree, hf_eapol_wpa_keydes_keyinfo, tvb,
			      offset, 2, keyinfo);

	keyinfo_tree = proto_item_add_subtree(keyinfo_item, ett_keyinfo);
	proto_tree_add_uint(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_keydes_ver, tvb, offset, 2, keyinfo);
	proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_type, tvb, offset, 2, keyinfo);
	proto_tree_add_uint(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_index, tvb, offset, 2, keyinfo);
	proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_install, tvb, offset, 2, keyinfo);
	proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_ack, tvb, offset, 2, keyinfo);
	proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_mic, tvb, offset, 2, keyinfo);
	proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_secure, tvb, offset, 2, keyinfo);
	proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_error, tvb, offset, 2, keyinfo);
	proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_request, tvb, offset, 2, keyinfo);
	proto_tree_add_boolean(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_encr_key_data, tvb, offset, 2, keyinfo);

        offset += 2;
        proto_tree_add_uint(eapol_tree, hf_eapol_keydes_keylen, tvb, offset,
        		    2, tvb_get_ntohs(tvb, offset));
        offset += 2;
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb,
        		    offset, 8, ENC_BIG_ENDIAN);
        offset += 8;
        proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_nonce, tvb, offset,
        		    32, ENC_NA);
        offset += 32;
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb,
        		    offset, 16, ENC_NA);
        offset += 16;
        proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_rsc, tvb, offset,
        		    8, ENC_NA);
        offset += 8;
        proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_id, tvb, offset, 8,
        		    ENC_NA);
        offset += 8;
        proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_mic, tvb, offset,
        		    16, ENC_NA);
        offset += 16;
        eapol_data_len = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint(eapol_tree, hf_eapol_wpa_keydes_datalen, tvb,
        		    offset, 2, eapol_data_len);
        offset += 2;
        if (eapol_data_len != 0) {
          ti = proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_data,
          	tvb, offset, eapol_data_len, ENC_NA);
	  if ((keyinfo & KEY_INFO_ENCR_KEY_DATA_MASK) ||
	      !(keyinfo & KEY_INFO_KEY_TYPE_MASK)) {
	    /* RSN: EAPOL-Key Key Data is encrypted.
	     * WPA: Group Keys use encrypted Key Data.
	     * Cannot parse this without knowing the key.
	     * IEEE 802.11i-2004 8.5.2.
	     */
	  } else {
	    keydes_tree = proto_item_add_subtree(ti, ett_eapol_keydes_data);
	    ieee_80211_add_tagged_parameters(tvb, offset, pinfo, keydes_tree,
					     eapol_data_len, -1);
	  }
        }
      } else {
        eapol_key_len = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint(eapol_tree, hf_eapol_keydes_keylen, tvb, offset, 2, eapol_key_len);
        offset += 2;
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb,
  			  offset, 8, ENC_BIG_ENDIAN);
        offset += 8;
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb,
  			  offset, 16, ENC_NA);
        offset += 16;
        key_index = tvb_get_guint8(tvb, offset);
        ti = proto_tree_add_text(eapol_tree, tvb, offset, 1,
  			       "Key Index: %s, index %u",
  			       (key_index & 0x80) ? "unicast" : "broadcast",
  			       key_index & 0x7F);
        key_index_tree = proto_item_add_subtree(ti, ett_eapol_key_index);
        proto_tree_add_boolean(key_index_tree, hf_eapol_keydes_key_index_keytype,
  			     tvb, offset, 1, key_index);
        proto_tree_add_uint(key_index_tree, hf_eapol_keydes_key_index_indexnum,
  			     tvb, offset, 1, key_index);
        offset += 1;
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_signature, tvb,
  			  offset, 16, ENC_NA);
        offset += 16;
        if (eapol_key_len != 0) {
          if (eapol_len > 44) { /* Size of rc4 key with no key content */
            proto_tree_add_item(eapol_tree, hf_eapol_keydes_key, tvb, offset,
  			    eapol_key_len, ENC_NA);
          } else {
		/* IEEE 802.1X-2004 7.6.3.6: If no bytes remain, then  */
		proto_tree_add_text(eapol_tree, tvb, offset, 0, "Key: Use key locally generated by peer");
          }
        }
      }
    }
    break;

  case EAPOL_ENCAP_ASF_ALERT:	/* XXX - is this an SNMP trap? */
  default:
    next_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector(data_handle, next_tvb, pinfo, eapol_tree);
    break;
  }
}
Example #11
0
/* XXX: Are all the tests against tvb_length() really the right way to handle invalid fields ?
 *      It seems to me that invalid fields should just add an expert item
 *        or cause a "Malformed" exception.
 */
static void
dissect_elcom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
        gboolean    is_request, length_ok;
        proto_tree *elcom_tree;
        proto_item *ti, *hidden_item;
        gint        offset = 0;
        guint       elcom_len;
        guint8      elcom_msg_type;
        guint8     *suffix;

        /* Check that there's enough data */
        if (tvb_length(tvb) < 3)
                return;

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

        is_request = (pinfo->match_port == pinfo->destport);
        elcom_len  = tvb_get_ntohs(tvb, 0);
        length_ok  = (tvb_reported_length(tvb) == (elcom_len+2));

        col_add_fstr(pinfo->cinfo, COL_INFO, "%s Len=%d%s",
                             is_request ? "Request" : "Response",
                             elcom_len,
                             length_ok ? "" : " (incorrect)");

        elcom_msg_type = tvb_get_guint8(tvb, 2);
        switch (elcom_msg_type) {
                case P_CONRQ:
                case P_CONRS:

                        /* starting after elcom_len and elcom_msg_type,
                           initiator + responder + userdata fields must be there */
                        if (tvb_length_remaining(tvb, 3+TOTAL_LEN+TOTAL_LEN+3) < 0) return;
                        /* check also that those field lengths are valid */
                        if (tvb_get_guint8(tvb, 3)  != LOWADR_LEN) return;
                        if (tvb_get_guint8(tvb, 3+1+LOWADR_LEN) != SUFFIX_LEN) return;
                        if (tvb_get_guint8(tvb, 3+TOTAL_LEN) != LOWADR_LEN) return;
                        if (tvb_get_guint8(tvb, 3+1+TOTAL_LEN+LOWADR_LEN) != SUFFIX_LEN) return;

                        /* finally believe that there is valid suffix */
                        suffix = tvb_get_string(wmem_packet_scope(), tvb, 3+2+LOWADR_LEN, 2);
                        col_append_fstr(pinfo->cinfo, COL_INFO, " %s Connect", suffix);
                        break;

                case P_RELRQ:
                case P_RELRS:
                        col_append_str(pinfo->cinfo, COL_INFO, " Release");
                        break;

                case P_DATRQ:
                        col_append_str(pinfo->cinfo, COL_INFO, " Data");
                        break;
                }

                switch (elcom_msg_type) {
                case P_CONRQ:
                case P_RELRQ:
                        col_append_str(pinfo->cinfo, COL_INFO, " Request");
                        break;

                case P_CONRS:
                case P_RELRS:
                        col_append_str(pinfo->cinfo, COL_INFO, " Response");
                        break;
        }

        if (!tree)
                return;

        ti = proto_tree_add_item(tree, proto_elcom, tvb, offset, -1, ENC_NA);
        elcom_tree = proto_item_add_subtree(ti, ett_elcom);

        hidden_item = proto_tree_add_boolean(elcom_tree,
                                             is_request ? hf_elcom_request : hf_elcom_response,
                                             tvb, 0, 0, TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);

        /* 2 first bytes are the frame length */
        offset = 0;
        ti = proto_tree_add_item(elcom_tree, hf_elcom_length, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset = +2;
        if (! length_ok) {
                proto_item_append_text(ti, " (incorrect)");
        }

        elcom_msg_type = tvb_get_guint8(tvb, offset);
        ti = proto_tree_add_item(elcom_tree, hf_elcom_type, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_item_append_text(elcom_tree, " ( %s)", val_to_str(elcom_msg_type, type_vals, "Unknown %d"));

        offset++;
        if (tvb_length_remaining(tvb, offset) <= 0)
                return;

        switch (elcom_msg_type) {
        case P_CONRQ:
        case P_CONRS:
                /*
                 * Connection request/release assiciated PDU's,
                 * /ELCOM-90 P Protocol spec/ p. 85...
                 */

                /* We need the length here, hardcode the LOWADR_LEN = 21 */
                ti = proto_tree_add_item(elcom_tree, hf_elcom_initiator, tvb, offset, TOTAL_LEN, ENC_BIG_ENDIAN);
                offset = dissect_lower_address(ti, ett_elcom_initiator, tvb, offset,
                                               hf_elcom_initiator_endian,
                                               hf_elcom_initiator_ip,
                                               hf_elcom_initiator_port,
                                               hf_elcom_initiator_suff);
                if (tvb_length_remaining(tvb, offset) <= 0)
                        return;

                ti = proto_tree_add_item(elcom_tree, hf_elcom_responder, tvb, offset, TOTAL_LEN, ENC_BIG_ENDIAN);
                offset = dissect_lower_address(ti, ett_elcom_responder, tvb, offset,
                                               hf_elcom_responder_endian,
                                               hf_elcom_responder_ip,
                                               hf_elcom_responder_port,
                                               hf_elcom_responder_suff);
                if (tvb_length_remaining(tvb, offset) <= 0)
                        return;

                /* Rest of the payload is USER-DATA, 0..82 bytes */
                ti = proto_tree_add_item(elcom_tree, hf_elcom_userdata, tvb, offset, -1, ENC_NA);
                offset = dissect_userdata(ti, ett_elcom_userdata, tvb, offset);

                break;

        case P_RELRQ:

                proto_tree_add_item(elcom_tree, hf_elcom_release_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                break;
        case P_RELRS:

                proto_tree_add_item(elcom_tree, hf_elcom_release_result, tvb, offset, 1, ENC_BIG_ENDIAN);

                offset += 1;

                break;

        case P_DATRQ:
                ti = proto_tree_add_item(elcom_tree, hf_elcom_datarequest, tvb, offset, -1, ENC_NA);
                offset = dissect_datarequest(ti, ett_elcom_datarequest, tvb, offset);
                break;

        default:
                proto_item_append_text(ti, " <<--- meaning WHAT??");
                break;
        }


        if (tvb_length_remaining(tvb, offset) <= 0)
                return;

        /* We should not get here, but if we do, show what is left over: */
        ti = proto_tree_add_item(elcom_tree, hf_elcom_strangeleftover, tvb, offset, -1, ENC_NA);
        while (tvb_length_remaining(tvb, offset) > 0) {
                proto_item_append_text(ti, elcom_show_hex ? " %02x" : " %03o",
                                       tvb_get_guint8(tvb, offset));
                offset++;
        }
}
Example #12
0
static void
dissect_http2_frame_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
{
        proto_item *ti;
        proto_tree *http2_tree;
        guint32 offset = 0;
    
        http2_frame_header frame;

        /* tvb_memeql makes certain there are enough bytes in the buffer.
         * returns -1 if there are not enough bytes or if there is not a
         * match.  Returns 0 on a match */
        if ( tvb_memeql( tvb, offset, kMagicHello, MAGIC_FRAME_LENGTH ) == 0 )
        {
                col_append_sep_str( pinfo->cinfo, COL_INFO, ", ", "Magic" );
                
                ti = proto_tree_add_item(tree, proto_http2, tvb, offset, MAGIC_FRAME_LENGTH, ENC_NA);
                proto_item_append_text( ti, ", Magic" );
                
                http2_tree = proto_item_add_subtree(ti, ett_http2);
                
                proto_tree_add_item(http2_tree, hf_http2_magic, tvb,
                                    offset, MAGIC_FRAME_LENGTH, ENC_BIG_ENDIAN);
                return;
        }


        frame.length   = tvb_get_ntohs( tvb, offset + 0 );
        frame.type     = tvb_get_guint8( tvb, offset + 2 );
        frame.flags    = tvb_get_guint8( tvb, offset + 3 );
        frame.streamid = tvb_get_ntohl( tvb, offset + 4 );

        col_append_sep_fstr( pinfo->cinfo, COL_INFO, ", ", "%s",
                             val_to_str( frame.type, frametypenames, "Unknown (0x%02X)" ) );

    
        /* create display subtree for the protocol */
        ti = proto_tree_add_item(tree, proto_http2, tvb, offset, FRAME_HEADER_LENGTH + frame.length, ENC_NA);

        proto_item_append_text( ti, ", %s", val_to_str( frame.type, frametypenames, "Unknown (0x%02X)" ) );
        proto_item_append_text( ti, ", Length: %d, Flags: %d, streamid: %d",
                                frame.length, frame.flags, frame.streamid );
    
        http2_tree = proto_item_add_subtree(ti, ett_http2);

        /* Add an item to the subtree, see section 1.6 of README.developer for more
         * information. */
        proto_tree_add_item(http2_tree, hf_http2_length, tvb,
                            offset + 0, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(http2_tree, hf_http2_type, tvb,
                            offset + 2, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(http2_tree, hf_http2_flags, tvb,
                            offset + 3, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(http2_tree, hf_http2_streamid, tvb,
                            offset + 4, 4, ENC_BIG_ENDIAN);
        proto_tree_add_item(http2_tree, hf_http2_payload, tvb,
                            offset + 8, frame.length, ENC_BIG_ENDIAN);

        offset += frame.length + FRAME_HEADER_LENGTH;

        return;
}
Example #13
0
/* Dissector for xcsl */
static void dissect_xcsl_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {

    guint        offset = 0;
    gint         length_remaining;
    guint8       idx;
    gboolean     request;
    guint8       par;
    guint8       str[MAXLEN];
    guint8       result;
    const gchar *code;
    guint        len;
    gint         next_offset;
    proto_tree  *xcsl_tree = NULL;

    /* color support */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Xcsl");
    col_clear(pinfo->cinfo, COL_INFO);

    /* Create display tree for the xcsl protocol */
    if (tree) {
        proto_item  *xcsl_item;
        xcsl_item = proto_tree_add_item(tree, hfi_xcsl, tvb, offset, -1, ENC_NA);
        xcsl_tree = proto_item_add_subtree(xcsl_item, ett_xcsl);
    }

    /* reset idx */
    idx = 0;

    /* reset the parameter count */
    par = 0;

    /* switch whether it concerns a command or an answer */
    request = FALSE;

    while ((length_remaining = tvb_reported_length_remaining(tvb, offset)) > 0) {

        /* get next item */
        if (!(get_next_item(tvb, offset, length_remaining, str, &next_offset, &len))) {
            /* do not continue when get_next_item returns false */
            return;
        }

        /* do not add to the tree when the string is of zero length */
        if ( strlen(str) == 0 ) {
            offset = next_offset + 1;
            continue;
        }

        /* Xcsl (Call Specification Language) protocol in brief :
         *
         * Request :
         *
         *    <xcsl-version>;<transaction-id>;<command>;[parameter1;parameter2;parameter3;....]
         *
         * Reply :
         *
         *    <xcsl-version>;transaction-id;<result>;[answer data;answer data];...
         *
         * If result is one or more digits, this is determined as a Reply.
         *
         * Example :
         *
         * -->      xcsl-1.0;1000;offhook;+31356871234
         * <--      xcsl-1.0;1000;0                              <- success
         *
         * -->      xcsl-1.0;1001;dial;+31356871234;+31356875678
         * <--      xcsl-1.0;1001;0                              <- success
         *
         *
         * index :  0        1    2    3            4
         *
         * Index 2 represents the return code (see the xcsl_action_vals[] definitions)
         *
         */

        /* One by one go through each item ';' separated */
        switch (idx) {

            /* This is the protocol item */
            case 0:
                proto_tree_add_item(xcsl_tree, &hfi_xcsl_protocol_version, tvb, offset, len, ENC_ASCII|ENC_NA);
                break;

                /* This should be the transaction ID, if non-digit, it is treated as info */
            case 1:
                if ( g_ascii_isdigit(str[0]) ) {
                    proto_tree_add_item(xcsl_tree, &hfi_xcsl_transaction_id, tvb, offset, len, ENC_ASCII|ENC_NA);
                } else {
                    proto_tree_add_item(xcsl_tree, &hfi_xcsl_information, tvb, offset, len, ENC_ASCII|ENC_NA);
                }
                col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",str);
                break;

                /* Starting with non-digit -> Command, if it starts with a digit -> reply */
            case 2:
                if ( g_ascii_isdigit(str[0]) ) {
                    proto_item *xcsl_item;

                    request = FALSE;
                    result = atoi(str);
                    if ( result >= XCSL_NONE ) {
                        result = XCSL_UNDEFINED;
                    }
                    code = val_to_str(result, xcsl_action_vals, "Unknown: %d");

                    /* Print result code and description */
                    xcsl_item = proto_tree_add_item(xcsl_tree, &hfi_xcsl_result, tvb, offset, len, ENC_ASCII|ENC_NA);
                    proto_item_append_text(xcsl_item, " (%s)", code);

                    if (result != 0)
                        col_append_fstr(pinfo->cinfo, COL_INFO, "[%s] ", code);

                } else {

                    request = TRUE;
                    proto_tree_add_item(xcsl_tree, &hfi_xcsl_command, tvb, offset, len, ENC_ASCII|ENC_NA);

                    col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);

                }
                break;

                /* This is a command parameter */
            default:
                proto_tree_add_item(xcsl_tree, &hfi_xcsl_parameter, tvb, offset, len, ENC_ASCII|ENC_NA);

                if ( request == TRUE ) {
                    col_append_fstr(pinfo->cinfo, COL_INFO, ": %s ",str);
                } else {
                    if (par == 0) {
                        col_append_fstr(pinfo->cinfo, COL_INFO, "reply: %s ",str);
                    } else {
                        col_append_fstr(pinfo->cinfo, COL_INFO, ": %s ",str);
                    }
                }

                /* increment the parameter count */
                par++;

                break;
        }

        offset = next_offset + 1;
        idx++;

    }


    return;
}
Example #14
0
static const true_false_string hub_port_status_indicator_meaning = {
	"Software-controlled color",
	"Default colors"
};

/* Dissector for ClearHubFeature, Chapter 11.24.2.1 Clear Hub Feature */
static void
dissect_usb_hub_clear_hub_feature(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean is_request, usb_trans_info_t *usb_trans_info _U_, usb_conv_info_t *usb_conv_info _U_)
{
	proto_item *item = NULL;
	proto_tree *subtree = NULL;
	const gchar* feature_name;

	feature_name = val_to_str(usb_trans_info->setup.wValue,
								hub_class_feature_selectors_recipient_hub_vals,
								"UNKNOWN (0x%x)");
	col_append_fstr(pinfo->cinfo, COL_INFO, " [Hub: %s]", feature_name);

	if (is_request) {
		item = proto_tree_add_item(tree, hf_usb_hub_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
		subtree = proto_item_add_subtree(item, ett_usb_hub_wValue);
		proto_tree_add_item(subtree, hf_usb_hub_hub_feature_selector, tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		item = proto_tree_add_item(tree, hf_usb_hub_index, tvb, offset, 2, ENC_LITTLE_ENDIAN);
		subtree = proto_item_add_subtree(item, ett_usb_hub_wIndex);
		proto_tree_add_item(subtree, hf_usb_hub_zero, tvb, offset, 2, ENC_LITTLE_ENDIAN);
		offset += 2;

		item = proto_tree_add_item(tree, hf_usb_hub_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
Example #15
0
static int
dissect_skype_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item *ti;
	proto_tree *skype_tree = NULL;
	guint32 offset = 0;
	guint32 packet_length;
	guint8 packet_type, packet_unk;

	conversation_t   *conversation = NULL;
	skype_udp_conv_info_t *skype_udp_info;

	/* look up the conversation */
	conversation = find_or_create_conversation(pinfo);

	/* if conversation found get the data pointer that you stored */
	skype_udp_info = conversation_get_proto_data(conversation, proto_skype);
	if (!skype_udp_info) {
		/* new conversation create local data structure */
		skype_udp_info = se_alloc(sizeof(skype_udp_conv_info_t));
		skype_udp_info->global_src_ip = 0;
		skype_udp_info->global_dst_ip = 0;
		conversation_add_proto_data(conversation, proto_skype,
			skype_udp_info);
	}
	/* at this point the conversation data is ready */

	packet_type = tvb_get_guint8(tvb, 2) & SKYPE_SOM_TYPE_MASK;
	packet_unk = (tvb_get_guint8(tvb, 2) & SKYPE_SOM_UNK_MASK) >> 4;

	packet_length = tvb_length(tvb);

	col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
	col_add_str(pinfo->cinfo, COL_INFO, val_to_str(packet_type,
		skype_type_vals, "Type 0x%1x"));
	if (packet_unk) {
		col_append_fstr(pinfo->cinfo, COL_INFO, " Unk: %1x", packet_unk);
	}

	if (tree) {
		/* Start of message dissection */
		ti = proto_tree_add_item(tree, proto_skype, tvb, offset, -1,
		    ENC_NA);
		skype_tree = proto_item_add_subtree(ti, ett_skype);

		proto_tree_add_item(skype_tree, hf_skype_som_id, tvb, offset, 2,
			ENC_BIG_ENDIAN);
		offset += 2;
		proto_tree_add_item(skype_tree, hf_skype_som_unk, tvb, offset, 1,
			ENC_NA);
		proto_tree_add_item(skype_tree, hf_skype_som_type, tvb, offset, 1,
			ENC_NA);
		offset += 1;

		/* Body dissection */
		switch (packet_type) {

		case SKYPE_TYPE_UNKNOWN_0:
			proto_tree_add_item(skype_tree, hf_skype_unknown_0_unk1, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		case SKYPE_TYPE_PAYLOAD:
			proto_tree_add_item(skype_tree, hf_skype_payload_iv, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_payload_crc, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_payload_enc_data, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		case SKYPE_TYPE_FFR:
			proto_tree_add_item(skype_tree, hf_skype_ffr_num, tvb, offset, 1,
				ENC_NA);
			offset += 1;
			proto_tree_add_item(skype_tree, hf_skype_ffr_unk1, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_ffr_iv, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_ffr_crc, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_ffr_enc_data, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		case SKYPE_TYPE_NAT_INFO:
			proto_tree_add_item(skype_tree, hf_skype_natinfo_srcip, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			skype_udp_info->global_src_ip = tvb_get_ipv4(tvb, offset);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_natinfo_dstip, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			skype_udp_info->global_dst_ip = tvb_get_ipv4(tvb, offset);
			offset += 4;
			break;
		case SKYPE_TYPE_NAT_REPEAT:
			proto_tree_add_item(skype_tree, hf_skype_natrequest_srcip, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			skype_udp_info->global_src_ip = tvb_get_ipv4(tvb, offset);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_natrequest_dstip, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			skype_udp_info->global_dst_ip = tvb_get_ipv4(tvb, offset);
			offset += 4;
			break;
		case SKYPE_TYPE_AUDIO:
			proto_tree_add_item(skype_tree, hf_skype_audio_unk1, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		case SKYPE_TYPE_UNKNOWN_F:
			proto_tree_add_item(skype_tree, hf_skype_unknown_f_unk1, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		default:
			proto_tree_add_item(skype_tree, hf_skype_unknown_packet, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		}
	}
	return offset;
}
Example #16
0
/*
 * For PIM v2, see RFC 4601, RFC 3973 and draft-ietf-pim-sm-v2-new-03
 * (when PIM is run over IPv6, the rules for computing the PIM checksum
 * from the draft in question, not from RFC 2362, should be used).
 */
static void
dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
    int offset = 0;
    guint8 pim_typever;
    guint length, pim_length;
    guint16 pim_cksum, computed_cksum;
    vec_t cksum_vec[4];
    guint32 phdr[2];
    const char *typestr;
    proto_tree *pim_tree = NULL;
    proto_item *ti;
    proto_tree *pimopt_tree = NULL;
    proto_item *tiopt;

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

    pim_typever = tvb_get_guint8(tvb, 0);

    switch (PIM_VER(pim_typever)) {
    case 2:
        typestr = val_to_str(PIM_TYPE(pim_typever), type2vals, "Unknown (%u)");
        break;
    case 1:     /* PIMv1 - we should never see this */
    default:
        typestr = "Unknown";
        break;
    }

    if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
        col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "PIMv%d",
                     PIM_VER(pim_typever));
    }
    if (check_col(pinfo->cinfo, COL_INFO))
        col_add_str(pinfo->cinfo, COL_INFO, typestr);

    ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, FALSE);
    pim_tree = proto_item_add_subtree(ti, ett_pim);

    proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, FALSE);
    proto_tree_add_item(pim_tree, hf_pim_type, tvb, offset, 1, FALSE);
    proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset + 1, 1, FALSE);
    pim_cksum = tvb_get_ntohs(tvb, offset + 2);
    length = tvb_length(tvb);
    if (PIM_VER(pim_typever) == 2) {
        /*
         * Well, it's PIM v2, so we can check whether this is a Register
         * message, and thus can figure out how much to checksum and
         * whether to make the columns read-only.
         */
        if (PIM_TYPE(pim_typever) == 1) {
            /*
             * Register message - the PIM header is 8 bytes long.
             * Also set the columns non-writable. Otherwise the IPv4 or
             * IPv6 dissector for the encapsulated packet that caused
             * this register will overwrite the PIM info in the columns.
             */
            pim_length = 8;
            col_set_writable(pinfo->cinfo, FALSE);
        } else {
            /*
             * Other message - checksum the entire packet.
             */
            pim_length = tvb_reported_length(tvb);
        }
    } else {
        /*
         * We don't know what type of message this is, so say that
         * the length is 0, to force it not to be checksummed.
         */
        pim_length = 0;
    }
    if (!pinfo->fragmented && length >= pim_length) {
        /*
         * The packet isn't part of a fragmented datagram and isn't
         * truncated, so we can checksum it.
         */

        switch (pinfo->src.type) {
        case AT_IPv4:
            cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length);
            cksum_vec[0].len = pim_length;
            computed_cksum = in_cksum(&cksum_vec[0], 1);
            break;
        case AT_IPv6:
            /* Set up the fields of the pseudo-header. */
            cksum_vec[0].ptr = pinfo->src.data;
            cksum_vec[0].len = pinfo->src.len;
            cksum_vec[1].ptr = pinfo->dst.data;
            cksum_vec[1].len = pinfo->dst.len;
            cksum_vec[2].ptr = (const guint8 *)&phdr;
            phdr[0] = g_htonl(pim_length);
            phdr[1] = g_htonl(IP_PROTO_PIM);
            cksum_vec[2].len = 8;
            cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, pim_length);
            cksum_vec[3].len = pim_length;
            computed_cksum = in_cksum(&cksum_vec[0], 4);
            break;
        default:
            /* PIM is available for IPv4 and IPv6 right now */
            computed_cksum = 0; /* squelch GCC complaints */
            DISSECTOR_ASSERT_NOT_REACHED();
            break;
        }

        if (computed_cksum == 0) {
            proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
                                       offset + 2, 2, pim_cksum,
                                       "Checksum: 0x%04x [correct]",
                                       pim_cksum);
        } else {
            proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
                                       offset + 2, 2, pim_cksum,
                                       "Checksum: 0x%04x [incorrect, should be 0x%04x]",
                                       pim_cksum, in_cksum_shouldbe(pim_cksum, computed_cksum));
        }
    } else {
        proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb,
                            offset + 2, 2, pim_cksum);
    }

    offset += 4;

    if (tvb_reported_length_remaining(tvb, offset) > 0) {
        tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1, "PIM options");
        pimopt_tree = proto_item_add_subtree(tiopt, ett_pim_opts);
    } else
        goto done;

    if (PIM_VER(pim_typever) != 2)
        goto done;

    /* version 2 decoder */
    switch (PIM_TYPE(pim_typever)) {
    case 0:     /*hello*/
    {
        int opt_count = 0;

        while (tvb_reported_length_remaining(tvb, offset) >= 2) {
            guint16 hello_opt, opt_len;
            guint16 opt_value;
            proto_item *opt_item;
            proto_tree *opt_tree;

            opt_count++;
            hello_opt = tvb_get_ntohs(tvb, offset);
            opt_len = tvb_get_ntohs(tvb, offset + 2);
            opt_item = proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len,
                                           "Option %u: %s", hello_opt,
                                           val_to_str(hello_opt, pim_opt_vals, "Unknown: %u"));
            opt_tree = proto_item_add_subtree(opt_item, ett_pim_opt);
            proto_tree_add_item(opt_tree, hf_pim_optiontype, tvb, offset, 2, FALSE);
            proto_tree_add_item(opt_tree, hf_pim_optionlength, tvb, offset + 2, 2, FALSE);

            switch(hello_opt) {
            case 1: /* Hello Hold Time Option */
                opt_value = tvb_get_ntohs(tvb, offset + 4);
                proto_tree_add_uint_format(opt_tree, hf_pim_holdtime, tvb,
                                           offset + 4, opt_len, opt_value,
                                           "Holdtime: %us %s", opt_value, opt_value == 0 ? "(goodbye)" :
                                           opt_value == 0xffff ? "(infinity)": "");
                proto_item_append_text(opt_item, ": %us %s", opt_value,
                                       opt_value == 0 ? "(goodbye)" :
                                       opt_value == 0xffff ? "(infinity)": "");
                break;

            case 2: /* LAN Prune Delay Option */
                proto_tree_add_item(opt_tree, hf_pim_t, tvb, offset + 4, 1, FALSE);
                proto_tree_add_item(opt_tree, hf_pim_propagation_delay, tvb, offset + 4, 2, FALSE);
                proto_tree_add_item(opt_tree, hf_pim_override_interval, tvb, offset + 6, 2, FALSE);
                proto_item_append_text(opt_item,
                                       ": T = %u, Propagation Delay = %ums, Override Interval = %ums",
                                       tvb_get_guint8(tvb, offset + 4) & 0x80 ? 1 : 0,
                                       tvb_get_ntohs(tvb, offset + 4) & 0x7fff,
                                       tvb_get_ntohs(tvb, offset + 6));
                break;

            case 19: /* DR priority */
                proto_tree_add_item(opt_tree, hf_pim_dr_priority, tvb, offset + 4, 4, FALSE);
                proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4));
                break;

            case 20: /* Generation ID */
                proto_tree_add_item(opt_tree, hf_pim_generation_id, tvb, offset + 4, 4, FALSE);
                proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4));
                break;

            case 21: /* State Refresh Capable Option */
                proto_tree_add_item(opt_tree, hf_pim_state_refresh_version, tvb, offset + 4, 1, FALSE);
                proto_tree_add_item(opt_tree, hf_pim_state_refresh_interval, tvb, offset + 5, 1, FALSE);
                proto_tree_add_item(opt_tree, hf_pim_state_refresh_reserved, tvb, offset + 6, 2, FALSE);
                proto_item_append_text(opt_item, ": Version = %u, Interval = %us",
                                       tvb_get_guint8(tvb, offset + 4),
                                       tvb_get_guint8(tvb, offset + 5));
                break;

            case 24: /* address list */
            case 65001: /* address list (old implementations) */
            {
                int i;
                proto_tree *sub_tree = NULL;
                proto_item *addrlist_option;

                addrlist_option = proto_tree_add_text(opt_tree, tvb, offset, 4 + opt_len,
                                                      "%sAddress List (%u)",
                                                      hello_opt == 65001 ? "old " : "",
                                                      hello_opt);
                sub_tree = proto_item_add_subtree(addrlist_option, ett_pim_opt);
                for (i = offset + 4; i < offset + 4 + opt_len; ) {
                    int advance;
                    const char *s;

                    s = dissect_pim_addr(tvb, i, pimv2_unicast, &advance);
                    if (s == NULL)
                        break;
                    proto_tree_add_text(sub_tree, tvb, offset,
                                        advance, "Address: %s", s);
                    i += advance;
                }
                break;
            }

            default:
                if (opt_len)
                    proto_tree_add_item(opt_tree, hf_pim_optionvalue, tvb,
                                        offset + 4, opt_len, FALSE);
                break;
            }
            offset += 4 + opt_len;
        }
        proto_item_append_text(tiopt, ": %u", opt_count);
        break;
    }

    case 1:     /* register */
    {
        guint32 flags;
        guint8 v_hl;
        tvbuff_t *next_tvb;
        proto_tree *flag_tree = NULL;
        proto_item *tiflag;

        flags = tvb_get_ntohl(tvb, offset);
        tiflag = proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                                     "Flags: 0x%08x", flags);
        flag_tree = proto_item_add_subtree(tiflag, ett_pim);
        proto_tree_add_text(flag_tree, tvb, offset, 1, "%s",
                            decode_boolean_bitfield(flags, 0x80000000, 32,
                                                    "Border", "Not border"));
        proto_tree_add_text(flag_tree, tvb, offset, 1, "%s",
                            decode_boolean_bitfield(flags, 0x40000000, 32,
                                                    "Null-Register", "Not Null-Register"));
        offset += 4;

        /*
         * The rest of the packet is a multicast data packet.
         */
        next_tvb = tvb_new_subset_remaining(tvb, offset);

        /*
         * It's an IP packet - determine whether it's IPv4 or IPv6.
         */
        v_hl = tvb_get_guint8(tvb, offset);
        switch((v_hl & 0xf0) >> 4) {
        case 0:     /* Null-Register dummy header.
                     * Has the same address family as the encapsulating PIM packet,
                     * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet.
                     */
            if (pinfo->src.type == AT_IPv4) {
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "IPv4 dummy header");
                proto_tree_add_text(pimopt_tree, tvb, offset + 12, 4,
                                    "Source: %s",
                                    tvb_ip_to_str(tvb, offset + 12));
                proto_tree_add_text(pimopt_tree, tvb, offset + 16, 4,
                                    "Group: %s",
                                    tvb_ip_to_str(tvb, offset + 16));
            } else if (pinfo->src.type == AT_IPv6) {
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "IPv6 dummy header");
                proto_tree_add_text(pimopt_tree, tvb,
                                    offset + 8, 16,
                                    "Source: %s",
                                    tvb_ip6_to_str(tvb, offset + 8));
                proto_tree_add_text(pimopt_tree, tvb,
                                    offset + 8 + 16, 16,
                                    "Group: %s",
                                    tvb_ip6_to_str(tvb, offset + 8 + 16));
            } else
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "Dummy header for an unknown protocol");
            break;
        case 4: /* IPv4 */
#if 0
            call_dissector(ip_handle, next_tvb, pinfo, tree);
#else
            call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree);
#endif
            break;
        case 6: /* IPv6 */
#if 0
            call_dissector(ipv6_handle, next_tvb, pinfo, tree);
#else
            call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree);
#endif
            break;
        default:
            proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                "Unknown IP version %d", (v_hl & 0xf0) >> 4);
            break;
        }
        break;
    }

    case 2:     /* register-stop */
    {
        int advance;
        const char *s;

        s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s);
        offset += advance;
        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s);
        break;
    }

    case 3:     /* join/prune */
    case 6:     /* graft */
    case 7:     /* graft-ack */
    {
        int advance;
        int off;
        const char *s;
        int ngroup, i, njoin, nprune, j;
        guint16 holdtime;
        proto_tree *grouptree = NULL;
        proto_item *tigroup;
        proto_tree *subtree = NULL;
        proto_item *tisub;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Upstream-neighbor: %s", s);
        offset += advance;

        proto_tree_add_item(pimopt_tree, hf_pim_res_bytes, tvb, offset, 1, FALSE);
        offset += 1;    /* skip reserved field */

        ngroup = tvb_get_guint8(tvb, offset);
        proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, FALSE);
        offset += 1;

        holdtime = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
        offset += 2;

        for (i = 0; i < ngroup; i++) {
            s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
            if (s == NULL)
                goto breakbreak3;
            tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                                          "Group %d: %s", i, s);
            grouptree = proto_item_add_subtree(tigroup, ett_pim);
            offset += advance;

            njoin = tvb_get_ntohs(tvb, offset);
            nprune = tvb_get_ntohs(tvb, offset + 2);
            tisub = proto_tree_add_item(grouptree, hf_pim_numjoins, tvb,
                                        offset, 2, FALSE);
            subtree = proto_item_add_subtree(tisub, ett_pim);
            off = offset + 4;
            for (j = 0; j < njoin; j++) {
                s = dissect_pim_addr(tvb, off, pimv2_source, &advance);
                if (s == NULL)
                    goto breakbreak3;
                proto_tree_add_text(subtree, tvb, off, advance,
                                    "IP address: %s", s);
                off += advance;
            }

            tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb,
                                        offset + 2, 2, FALSE);
            subtree = proto_item_add_subtree(tisub, ett_pim);
            for (j = 0; j < nprune; j++) {
                s = dissect_pim_addr(tvb, off, pimv2_source, &advance);
                if (s == NULL)
                    goto breakbreak3;
                proto_tree_add_text(subtree, tvb, off, advance,
                                    "IP address: %s", s);
                off += advance;
            }
            offset = off;
        }
    breakbreak3:
        break;
    }

    case 4:     /* bootstrap */
    {
        const char *s;
        int advance;
        int i, j;
        int frpcnt;
        guint16 holdtime;
        proto_tree *grouptree = NULL;
        proto_item *tigroup;

        proto_tree_add_text(pimopt_tree, tvb, offset, 2,
                            "Fragment tag: 0x%04x", tvb_get_ntohs(tvb, offset));
        offset += 2;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Hash mask len: %u", tvb_get_guint8(tvb, offset));
        offset += 1;
        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "BSR priority: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "BSR: %s", s);
        offset += advance;

        for (i = 0; tvb_reported_length_remaining(tvb, offset) > 0; i++) {
            s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
            if (s == NULL)
                goto breakbreak4;
            tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                                          "Group %d: %s", i, s);
            grouptree = proto_item_add_subtree(tigroup, ett_pim);
            offset += advance;

            proto_tree_add_text(grouptree, tvb, offset, 1,
                                "RP count: %u", tvb_get_guint8(tvb, offset));
            offset += 1;
            frpcnt = tvb_get_guint8(tvb, offset);
            proto_tree_add_text(grouptree, tvb, offset, 1,
                                "FRP count: %u", frpcnt);
            offset += 3;

            for (j = 0; j < frpcnt; j++) {
                s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
                if (s == NULL)
                    goto breakbreak4;
                proto_tree_add_text(grouptree, tvb, offset, advance,
                                    "RP %d: %s", j, s);
                offset += advance;

                holdtime = tvb_get_ntohs(tvb, offset);
                proto_tree_add_uint_format(grouptree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
                offset += 2;
                proto_tree_add_text(grouptree, tvb, offset, 1,
                                    "Priority: %u", tvb_get_guint8(tvb, offset));
                offset += 2;    /* also skips reserved field */
            }
        }

    breakbreak4:
        break;
    }

    case 5:     /* assert */
    {
        const char *s;
        int advance;
        guint32 pref;

        s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s);
        offset += advance;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s);
        offset += advance;

        proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, FALSE);
        pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff;
        proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb,
                                   offset, 4, pref,
                                   "Metric Preference: %u", pref);
        offset += 4;

        proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, FALSE);
        offset += 4;
        break;
    }

    case 8:     /* Candidate-RP-Advertisement */
    {
        const char *s;
        int advance;
        int pfxcnt;
        guint16 holdtime;
        int i;

        pfxcnt = tvb_get_guint8(tvb, offset);
        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Prefix-count: %u", pfxcnt);
        offset += 1;
        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Priority: %u", tvb_get_guint8(tvb, offset));
        offset += 1;
        holdtime = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
        offset += 2;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "RP: %s", s);
        offset += advance;

        for (i = 0; i < pfxcnt; i++) {
            s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
            if (s == NULL)
                goto breakbreak8;
            proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                                "Group %d: %s", i, s);
            offset += advance;
        }
    breakbreak8:
        break;
    }

    case 9:     /* State-Refresh */
    {
        const char *s;
        int advance;
        guint32 pref;

        s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Group: %s", s);
        offset += advance;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Source: %s", s);
        offset += advance;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Originator: %s", s);
        offset += advance;

        proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, FALSE);
        pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff;
        proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb,
                                   offset, 4, pref,
                                   "Metric Preference: %u", pref);
        offset += 4;

        proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, FALSE);
        offset += 4;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Masklen: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "TTL: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune indicator %s",
                            decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x80, 8,
                                                    "set", "clear"));
        proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune now %s",
                            decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x40, 8,
                                                    "set", "clear"));
        proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Assert override %s",
                            decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x20, 8,
                                                    "set", "clear"));
        offset += 1;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Interval: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        break;
    }

    default:
        break;
    }
done:;
}
Example #17
0
static void
dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_tree     *clnp_tree = NULL;
  proto_item     *ti;
  guint8          cnf_proto_id;
  guint8          cnf_hdr_len;
  guint8          cnf_vers;
  guint8          cnf_ttl;
  guint8          cnf_type;
  char            flag_string[6+1];
  const char     *pdu_type_string;
  proto_tree     *type_tree;
  guint16         segment_length;
  guint16         du_id = 0;
  guint16         segment_offset = 0;
  guint16         cnf_cksum;
  cksum_status_t  cksum_status;
  int             offset;
  guchar          src_len, dst_len, nsel, opt_len = 0;
  const guint8   *dst_addr, *src_addr;
  guint           next_length;
  proto_tree     *discpdu_tree;
  gboolean        save_in_error_pkt;
  fragment_data  *fd_head;
  tvbuff_t       *next_tvb;
  gboolean        update_col_info = TRUE;
  gboolean        save_fragmented;

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

  cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
  if (cnf_proto_id == NLPID_NULL) {
    col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset");
    if (tree) {
      ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, ENC_NA);
      clnp_tree = proto_item_add_subtree(ti, ett_clnp);
      proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
                                 cnf_proto_id,
                                 "Inactive subset");
    }
    next_tvb = tvb_new_subset_remaining(tvb, 1);
    if (call_dissector(ositp_inactive_handle, next_tvb, pinfo, tree) == 0)
      call_dissector(data_handle,tvb, pinfo, tree);
    return;
  }

  /* return if version not known */
  cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
  if (cnf_vers != ISO8473_V1) {
    call_dissector(data_handle,tvb, pinfo, tree);
    return;
  }

  /* fixed part decoding */
  cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
  opt_len = cnf_hdr_len;

  if (tree) {
    ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA);
    clnp_tree = proto_item_add_subtree(ti, ett_clnp);
    proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
                        cnf_proto_id);
    proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
                        cnf_hdr_len);
    proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
                        cnf_vers);
    cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
    proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
                               cnf_ttl,
                               "Holding Time : %u (%u.%u secs)",
                               cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
  }

  cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
  pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
                               "Unknown (0x%02x)");
  flag_string[0] = '\0';
  if (cnf_type & CNF_SEG_OK)
    g_strlcat(flag_string, "S ", 7);
  if (cnf_type & CNF_MORE_SEGS)
    g_strlcat(flag_string, "M ", 7);
  if (cnf_type & CNF_ERR_OK)
    g_strlcat(flag_string, "E ", 7);
  if (tree) {
    ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
                                    cnf_type,
                                    "PDU Type     : 0x%02x (%s%s)",
                                    cnf_type,
                                    flag_string,
                                    pdu_type_string);
    type_tree = proto_item_add_subtree(ti, ett_clnp_type);
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_SEG_OK, 8,
                                                "Segmentation permitted",
                                                "Segmentation not permitted"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_MORE_SEGS, 8,
                                                "More segments",
                                                "Last segment"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_ERR_OK, 8,
                                                "Report error if PDU discarded",
                                                "Don't report error if PDU discarded"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_enumerated_bitfield(cnf_type, CNF_TYPE, 8,
                                                   npdu_type_vals, "%s"));
  }

  /* If we don't have the full header - i.e., not enough to see the
     segmentation part and determine whether this datagram is segmented
     or not - set the Info column now; we'll get an exception before
     we set it otherwise. */

  if (tvb_length(tvb) < cnf_hdr_len) {
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
  }

  segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
  cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
  cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
  if (tree) {
    proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
                        segment_length);
    switch (cksum_status) {

    default:
      /*
       * No checksum present, or not enough of the header present to
       * checksum it.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x",
                                 cnf_cksum);
      break;

    case CKSUM_OK:
      /*
       * Checksum is correct.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x (correct)",
                                 cnf_cksum);
      break;

    case CKSUM_NOT_OK:
      /*
       * Checksum is not correct.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x (incorrect)",
                                 cnf_cksum);
      break;
    }
    opt_len -= 9; /* Fixed part of Hesder */
  } /* tree */

  /* address part */

  offset = P_CLNP_ADDRESS_PART;
  dst_len  = tvb_get_guint8(tvb, offset);
  dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len);
  nsel     = tvb_get_guint8(tvb, offset + dst_len);
  src_len  = tvb_get_guint8(tvb, offset + dst_len + 1);
  src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len);

  if (tree) {
    proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
                        dst_len);
    proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len,
                                dst_addr,
                                " DA : %s",
                                print_nsap_net(dst_addr, dst_len));
    proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
                        offset + 1 + dst_len, 1, src_len);
    proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb,
                                offset + dst_len + 2, src_len,
                                src_addr,
                                " SA : %s",
                                print_nsap_net(src_addr, src_len));

    opt_len -= dst_len + src_len +2;
  }

  SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr);
  SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr);
  SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr);
  SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr);

  /* Segmentation Part */

  offset += dst_len + src_len + 2;

  if (cnf_type & CNF_SEG_OK) {
#if 0
    struct clnp_segment seg;                                /* XXX - not used */
    tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg));   /* XXX - not used */
#endif

    segment_offset = tvb_get_ntohs(tvb, offset + 2);
    du_id = tvb_get_ntohs(tvb, offset);
    if (tree) {
      proto_tree_add_text(clnp_tree, tvb, offset, 2,
                          "Data unit identifier: %06u",
                          du_id);
      proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
                          "Segment offset      : %6u",
                          segment_offset);
      proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
                          "Total length        : %6u",
                          tvb_get_ntohs(tvb, offset + 4));
    }

    offset  += 6;
    opt_len -= 6;
  }

  if (tree) {
    /* To do : decode options  */
#if 0
    proto_tree_add_text(clnp_tree, tvb, offset,
                        cnf_hdr_len - offset,
                        "Options/Data: <not shown>");
#endif
/* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/

    dissect_osi_options( opt_len,
                         tvb, offset, clnp_tree );
  }

  offset = cnf_hdr_len;

  /* If clnp_reassemble is on, this is a segment, we have all the
   * data in the segment, and the checksum is valid, then just add the
   * segment to the hashtable.
   */
  save_fragmented = pinfo->fragmented;
  if (clnp_reassemble && (cnf_type & CNF_SEG_OK) &&
      ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) &&
      tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) &&
      segment_length > cnf_hdr_len &&
      cksum_status != CKSUM_NOT_OK) {
    fd_head = fragment_add_check(tvb, offset, pinfo, du_id, clnp_segment_table,
                                 clnp_reassembled_table, segment_offset,
                                 segment_length - cnf_hdr_len,
                                 cnf_type & CNF_MORE_SEGS);

    next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP",
                                        fd_head, &clnp_frag_items, &update_col_info, clnp_tree);
  } else {
    /* If this is the first segment, dissect its contents, otherwise
       just show it as a segment.

       XXX - if we eventually don't save the reassembled contents of all
       segmented datagrams, we may want to always reassemble. */
    if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
      /* Not the first segment - don't dissect it. */
      next_tvb = NULL;
    } else {
      /* First segment, or not segmented.  Dissect what we have here. */

      /* Get a tvbuff for the payload. */
      next_tvb = tvb_new_subset_remaining(tvb, offset);

      /*
       * If this is the first segment, but not the only segment,
       * tell the next protocol that.
       */
      if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS))
        pinfo->fragmented = TRUE;
      else
        pinfo->fragmented = FALSE;
    }
  }

  if (next_tvb == NULL) {
    /* Just show this as a segment. */
    col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
                 pdu_type_string, flag_string, segment_offset);

    /* As we haven't reassembled anything, we haven't changed "pi", so
       we don't have to restore it. */
    call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo,
                   tree);
    pinfo->fragmented = save_fragmented;
    return;
  }

  if (tvb_offset_exists(tvb, offset)) {
    switch (cnf_type & CNF_TYPE) {

    case DT_NPDU:
    case MD_NPDU:
      /* Continue with COTP if any data.
         XXX - if this isn't the first Derived PDU of a segmented Initial
         PDU, skip that? */

      if (nsel == (guchar)tp_nsap_selector || always_decode_transport) {
        if (call_dissector(ositp_handle, next_tvb, pinfo, tree) != 0) {
          pinfo->fragmented = save_fragmented;
          return;       /* yes, it appears to be COTP or CLTP */
        }
      }
      if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb,
                                  pinfo, tree)) {
          pinfo->fragmented = save_fragmented;
          return;       /* yes, it appears to be one of the protocols in the heuristic list */
      }

      break;

    case ER_NPDU:
      /* The payload is the header and "none, some, or all of the data
         part of the discarded PDU", i.e. it's like an ICMP error;
         dissect it as a CLNP PDU. */

      col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
      next_length = tvb_length_remaining(tvb, offset);
      if (next_length != 0) {
          /* We have payload; dissect it. */
          ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length,
            "Discarded PDU");
          discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu);

          /* Save the current value of the "we're inside an error packet"
             flag, and set that flag; subdissectors may treat packets
             that are the payload of error packets differently from
             "real" packets. */
          save_in_error_pkt = pinfo->flags.in_error_pkt;
          pinfo->flags.in_error_pkt = TRUE;

          call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);

          /* Restore the "we're inside an error packet" flag. */
          pinfo->flags.in_error_pkt = save_in_error_pkt;
      }
      pinfo->fragmented = save_fragmented;
      return;   /* we're done with this PDU */

    case ERQ_NPDU:
    case ERP_NPDU:
      /* XXX - dissect this */
      break;
    }
  }
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
  call_dissector(data_handle,next_tvb, pinfo, tree);
  pinfo->fragmented = save_fragmented;
} /* dissect_clnp */
Example #18
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 #19
0
/* Code to actually dissect the PAGP packets */
static void
dissect_pagp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
      guint32 raw_word;
      guint16 raw_half_word;
      guint16 num_tlvs;
      guint16 tlv;
      guint16 len;
      guint16 i;
      guint16 offset = PAGP_FIRST_TLV;
      guint8  raw_octet;

      guint8  flags;

      struct _address device_id;

      const guint8 *p_sys;

      guchar *ch;

      proto_tree *pagp_tree = NULL;
      proto_item *pagp_item;
      proto_tree *flags_tree;
      proto_item *flags_item;
      proto_tree *tlv_tree;
      proto_item *tlv_item;


      const char *sep;


      device_id.type = AT_ETHER;
      device_id.len = 6;

      if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
	    col_set_str(pinfo->cinfo, COL_PROTOCOL, "PAGP"); /* PAGP Protocol */
      }

      col_clear(pinfo->cinfo, COL_INFO);

      pinfo->current_proto = "PAGP";

      raw_octet = tvb_get_guint8(tvb, PAGP_VERSION_NUMBER);
      if (tree) {
	    pagp_item = proto_tree_add_protocol_format(tree, proto_pagp, tvb,
				0, -1, "Port Aggregation Protocol");
	    pagp_tree = proto_item_add_subtree(pagp_item, ett_pagp);
	    proto_tree_add_uint(pagp_tree, hf_pagp_version_number, tvb,
				PAGP_VERSION_NUMBER, 1, raw_octet);
      } 
      if (check_col(pinfo->cinfo, COL_INFO)) {
         col_append_str(pinfo->cinfo, COL_INFO,
  	       val_to_str(raw_octet, pdu_vers, "Unknown PDU version"));
      }

      if (raw_octet == PAGP_FLUSH_PDU) {

         device_id.data = tvb_get_ptr(tvb, PAGP_FLUSH_LOCAL_DEVICE_ID, 6);
         if (check_col(pinfo->cinfo, COL_INFO)) {
            col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s",
               address_to_str(&device_id));
         }
         if (tree) {
	       proto_tree_add_ether(pagp_tree, hf_pagp_flush_local_device_id, tvb,
			   PAGP_FLUSH_LOCAL_DEVICE_ID, 6, device_id.data);
         }

         device_id.data = tvb_get_ptr(tvb, PAGP_FLUSH_PARTNER_DEVICE_ID, 6);
         if (check_col(pinfo->cinfo, COL_INFO)) {
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s",
               address_to_str(&device_id));
         }
         if (tree) {
	    proto_tree_add_ether(pagp_tree, hf_pagp_flush_partner_device_id, tvb,
			   PAGP_FLUSH_PARTNER_DEVICE_ID, 6, device_id.data);
         }

         raw_word = tvb_get_ntohl(tvb, PAGP_FLUSH_TRANSACTION_ID);
	 if (check_col(pinfo->cinfo, COL_INFO)) {
            col_append_fstr(pinfo->cinfo, COL_INFO,
		"; Transaction ID: 0x%x ", raw_word);
	 }
         if (tree) {
	    proto_tree_add_uint(pagp_tree, hf_pagp_flush_transaction_id, tvb,
			   PAGP_FLUSH_TRANSACTION_ID, 4, raw_word);
	 }
         return;
      }

      /* Info PDU */

      flags = tvb_get_guint8(tvb, PAGP_FLAGS);
      if (check_col(pinfo->cinfo, COL_INFO)) {
         col_append_fstr(pinfo->cinfo, COL_INFO, "; Flags 0x%x", flags);
      }

      if (tree) {
         flags_item = proto_tree_add_uint(pagp_tree, hf_pagp_flags, tvb,
			PAGP_FLAGS, 1, flags);
         flags_tree = proto_item_add_subtree(flags_item, ett_pagp_flags);

	 sep = initial_sep;

	 APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_SLOW_HELLO, flags_item, "%sSlow Hello");
	 proto_tree_add_boolean(flags_tree, hf_pagp_flags_slow_hello, tvb,
			PAGP_FLAGS, 1, flags);

	 APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_AUTO_MODE, flags_item, "%sAuto Mode");
	 proto_tree_add_boolean(flags_tree, hf_pagp_flags_auto_mode, tvb,
			PAGP_FLAGS, 1, flags);

	 APPEND_BOOLEAN_FLAG(flags & PAGP_FLAGS_CONSISTENT_STATE, flags_item,
			"%sConsistent State");
	 proto_tree_add_boolean(flags_tree, hf_pagp_flags_consistent_state, tvb,
				PAGP_FLAGS, 1, flags);

	 sep = cont_sep;
	 if (sep != initial_sep) {
            /* We put something in; put in the terminating ")" */
            proto_item_append_text(flags_item, ")");
	 }
      }

      device_id.data = tvb_get_ptr(tvb, PAGP_LOCAL_DEVICE_ID, 6);
      if (check_col(pinfo->cinfo, COL_INFO)) {
         col_append_fstr(pinfo->cinfo, COL_INFO, "; Local DevID: %s",
            address_to_str(&device_id));
      }
      if (tree) {
	    proto_tree_add_ether(pagp_tree, hf_pagp_local_device_id, tvb,
				PAGP_LOCAL_DEVICE_ID, 6, device_id.data);
      }

      if (tree) {
	    raw_octet = tvb_get_guint8(tvb, PAGP_LOCAL_LEARN_CAP);
	    proto_tree_add_uint(pagp_tree, hf_pagp_local_learn_cap, tvb,
				PAGP_LOCAL_LEARN_CAP, 1, raw_octet);

	    raw_octet = tvb_get_guint8(tvb, PAGP_LOCAL_PORT_PRIORITY);
	    proto_tree_add_uint(pagp_tree, hf_pagp_local_port_priority, tvb,
				PAGP_LOCAL_PORT_PRIORITY, 1, raw_octet);

	    raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_SENT_PORT_IFINDEX);
	    proto_tree_add_uint(pagp_tree, hf_pagp_local_sent_port_ifindex, tvb,
				PAGP_LOCAL_SENT_PORT_IFINDEX, 4, raw_word);

	    raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_GROUP_CAPABILITY);
	    proto_tree_add_uint(pagp_tree, hf_pagp_local_group_capability, tvb,
				PAGP_LOCAL_GROUP_CAPABILITY, 4, raw_word);

	    raw_word = tvb_get_ntohl(tvb, PAGP_LOCAL_GROUP_IFINDEX);
	    proto_tree_add_uint(pagp_tree, hf_pagp_local_group_ifindex, tvb,
				PAGP_LOCAL_GROUP_IFINDEX, 4, raw_word);
      }

      device_id.data = tvb_get_ptr(tvb, PAGP_PARTNER_DEVICE_ID, 6);
      if (check_col(pinfo->cinfo, COL_INFO)) {
         col_append_fstr(pinfo->cinfo, COL_INFO, ", Partner DevID: %s",
  	       address_to_str(&device_id));
      }
      if (tree) {
	    proto_tree_add_ether(pagp_tree, hf_pagp_partner_device_id, tvb,
				PAGP_PARTNER_DEVICE_ID, 6, device_id.data);
      }

      if (tree) {
	    raw_octet = tvb_get_guint8(tvb, PAGP_PARTNER_LEARN_CAP);
	    proto_tree_add_uint(pagp_tree, hf_pagp_partner_learn_cap, tvb,
				PAGP_PARTNER_LEARN_CAP, 1, raw_octet);

	    raw_octet = tvb_get_guint8(tvb, PAGP_PARTNER_PORT_PRIORITY);
	    proto_tree_add_uint(pagp_tree, hf_pagp_partner_port_priority, tvb,
				PAGP_PARTNER_PORT_PRIORITY, 1, raw_octet);

	    raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_SENT_PORT_IFINDEX);
	    proto_tree_add_uint(pagp_tree, hf_pagp_partner_sent_port_ifindex, tvb,
				PAGP_PARTNER_SENT_PORT_IFINDEX, 4, raw_word);

	    raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_GROUP_CAPABILITY);
	    proto_tree_add_uint(pagp_tree, hf_pagp_partner_group_capability, tvb,
				PAGP_PARTNER_GROUP_CAPABILITY, 4, raw_word);

	    raw_word = tvb_get_ntohl(tvb, PAGP_PARTNER_GROUP_IFINDEX);
	    proto_tree_add_uint(pagp_tree, hf_pagp_partner_group_ifindex, tvb,
				PAGP_PARTNER_GROUP_IFINDEX, 4, raw_word);

	    raw_half_word = tvb_get_ntohs(tvb, PAGP_PARTNER_COUNT);
	    proto_tree_add_uint(pagp_tree, hf_pagp_partner_count, tvb,
				PAGP_PARTNER_COUNT, 2, raw_half_word);

	    num_tlvs = tvb_get_ntohs(tvb, PAGP_NUM_TLVS);
	    proto_tree_add_uint(pagp_tree, hf_pagp_num_tlvs, tvb,
				PAGP_NUM_TLVS, 2, num_tlvs);

	    /* dump TLV entries */

	    for ( i = 1; i <= num_tlvs; i++ ) {

		tlv = tvb_get_ntohs(tvb, offset);
		len = tvb_get_ntohs(tvb, offset + 2);
		if ( len == 0 ) {
		   proto_tree_add_text(pagp_tree, tvb, offset, -1,
			               "Unknown data - TLV len=0");
		   return;
		}

		tlv_item = proto_tree_add_text (pagp_tree, tvb, offset, len,
			   "TLV Entry #%d", i);
                                                                                
		tlv_tree = proto_item_add_subtree (tlv_item, ett_pagp_tlvs);
		proto_tree_add_uint_format (tlv_tree, hf_pagp_tlv, tvb,
			offset,2,tlv,"Type = %d (%s)", tlv,
			val_to_str(tlv,tlv_types, "Unknown")) ;
		proto_tree_add_text (tlv_tree, tvb, offset+2, 2,
			"Length = %u bytes (includes Type and Length)", len) ;
		if ( tvb_reported_length_remaining(tvb, offset) < len ) {
		   proto_tree_add_text(tlv_tree, tvb, offset, -1,
			               "TLV length too large");
		   return;
		}
                                                                                
		switch (tlv) {
		   case PAGP_TLV_DEVICE_NAME:
			ch = tvb_get_ephemeral_string(tvb, offset+4, len-4);
			proto_tree_add_string(tlv_tree, hf_pagp_tlv_device_name,
			   tvb, offset+4, len-4, ch);
			break;
		   case PAGP_TLV_PORT_NAME:
			ch = tvb_get_ephemeral_string(tvb, offset+4, len-4);
			proto_tree_add_string(tlv_tree, hf_pagp_tlv_port_name,
			   tvb, offset+4, len-4, ch);
			break;
		   case PAGP_TLV_AGPORT_MAC:
			p_sys = tvb_get_ptr(tvb, offset+4, 6);
			proto_tree_add_ether(tlv_tree, hf_pagp_tlv_agport_mac,
			   tvb, offset+4, 6, p_sys);
			break;
		   case PAGP_TLV_RESERVED:
			break;
		}

		offset += len;

	    }
      }
}
Example #20
0
	guint32		dsi_reserved;
	struct		aspinfo aspinfo;


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

	dsi_flags = tvb_get_guint8(tvb, 0);
	dsi_command = tvb_get_guint8(tvb, 1);
	dsi_requestid = tvb_get_ntohs(tvb, 2);
	dsi_code = tvb_get_ntohl(tvb, 4);
	dsi_length = tvb_get_ntohl(tvb, 8);
	dsi_reserved = tvb_get_ntohl(tvb, 12);

	col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s (%u)",
			val_to_str(dsi_flags, flag_vals,
				   "Unknown flag (0x%02x)"),
			val_to_str_ext(dsi_command, &func_vals_ext,
				   "Unknown function (0x%02x)"),
			dsi_requestid);

	ti = proto_tree_add_item(tree, proto_dsi, tvb, 0, -1, ENC_NA);
	dsi_tree = proto_item_add_subtree(ti, ett_dsi);

	if (tree) {
		proto_tree_add_uint(dsi_tree, hf_dsi_flags, tvb,
			0, 1, dsi_flags);
		proto_tree_add_uint(dsi_tree, hf_dsi_command, tvb,
			1, 1, dsi_command);
		proto_tree_add_uint(dsi_tree, hf_dsi_requestid, tvb,
			2, 2, dsi_requestid);
		switch (dsi_flags) {
Example #21
0
static void
dissect_pgmopts(ptvcursor_t* cursor, const char *pktname)
{
	proto_item *tf;
	proto_tree *opts_tree = NULL;
	proto_tree *opt_tree = NULL;
	tvbuff_t *tvb = ptvcursor_tvbuff(cursor);

	gboolean theend = FALSE;

	guint16 opts_total_len;
	guint8 genopts_type;
	guint8 genopts_len;
	guint8 opts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));

	if (opts_type != PGM_OPT_LENGTH) {
		proto_tree_add_text(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), 1,
		    "%s Options - initial option is %s, should be %s",
		    pktname,
		    val_to_str(opts_type, opt_vals, "Unknown (0x%02x)"),
		    val_to_str(PGM_OPT_LENGTH, opt_vals, "Unknown (0x%02x)"));
		return;
	}

	opts_total_len = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)+2);

	if (opts_total_len < 4) {
		proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor)+2, 2,
			"%s Options (Total Length %u - invalid, must be >= 4)",
			pktname, opts_total_len);
		return;
	}

	tf = proto_tree_add_text(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), opts_total_len,
		"%s Options (Total Length %d)", pktname, opts_total_len);
	opts_tree = proto_item_add_subtree(tf, ett_pgm_opts);
	ptvcursor_set_tree(cursor, opts_tree);
	ptvcursor_add(cursor, hf_pgm_opt_type, 1, ENC_BIG_ENDIAN);
	ptvcursor_add(cursor, hf_pgm_opt_len, 1, ENC_BIG_ENDIAN);
	ptvcursor_add(cursor, hf_pgm_opt_tlen, 2, ENC_BIG_ENDIAN);

	for (opts_total_len -= 4; !theend && opts_total_len != 0;){
		if (opts_total_len < 4) {
			proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), opts_total_len,
			    "Remaining total options length doesn't have enough for an options header");
			break;
		}

		genopts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
		genopts_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)+1);

		if (genopts_type & PGM_OPT_END)  {
			genopts_type &= ~PGM_OPT_END;
			theend = TRUE;
		}
		if (genopts_len < 4) {
			proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len,
				"Option: %s, Length: %u (invalid, must be >= 4)",
				val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"),
				genopts_len);
			break;
		}
		if (opts_total_len < genopts_len) {
			proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len,
			    "Option: %s, Length: %u (> remaining total options length)",
			    val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"),
			    genopts_len);
			break;
		}
		tf = proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len,
			"Option: %s, Length: %u",
			val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"),
			genopts_len);

		switch(genopts_type) {
		case PGM_OPT_JOIN:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_join);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_JOIN_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_JOIN_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_join_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_join_minjoin, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_PARITY_PRM:{
			guint8 optdata_po;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_parityprm);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);


			if (genopts_len < PGM_OPT_PARITY_PRM_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, ptvcursor_tvbuff(cursor),
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PARITY_PRM_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			optdata_po = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
			proto_tree_add_uint_format(opt_tree, hf_pgm_opt_parity_prm_po, tvb,
				ptvcursor_current_offset(cursor), 1, optdata_po, "Parity Parameters: %s (0x%x)",
				paritystr(optdata_po), optdata_po);
			ptvcursor_advance(cursor, 1);

			ptvcursor_add(cursor, hf_pgm_opt_parity_prm_prmtgsz, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_PARITY_GRP:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_paritygrp);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PARITY_GRP_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PARITY_GRP_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_parity_grp_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_parity_grp_prmgrp, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_NAK_LIST:{
			guint8 optdata_len;
			guint32 naklist[PGM_MAX_NAK_LIST_SZ+1];
			unsigned char *nakbuf;
			gboolean firsttime;
			int i, j, naks, soffset;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_naklist);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			optdata_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_res, 1, ENC_BIG_ENDIAN);

			optdata_len -= PGM_OPT_NAK_LIST_SIZE;
			tvb_memcpy(tvb, (guint8 *)naklist, ptvcursor_current_offset(cursor), optdata_len);
			firsttime = TRUE;
			soffset = 0;
			naks = (optdata_len/sizeof(guint32));
			nakbuf = ep_alloc(8192);
			j = 0;
			/*
			 * Print out 8 per line
			 */
			for (i=0; i < naks; i++) {
				soffset += MIN(8192-soffset,
					g_snprintf(nakbuf+soffset, 8192-soffset, "0x%lx ",
						(unsigned long)g_ntohl(naklist[i])));
				if ((++j % 8) == 0) {
					if (firsttime) {
						proto_tree_add_bytes_format(opt_tree,
							hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
							nakbuf, "List(%d): %s", naks, nakbuf);
						soffset = 0;
						firsttime = FALSE;
					} else {
						proto_tree_add_bytes_format(opt_tree,
							hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
							nakbuf, "List: %s", nakbuf);
						soffset = 0;
					}
					ptvcursor_advance(cursor, j*4);
					j = 0;
				}
			}
			if (j) {
				if (firsttime) {
					proto_tree_add_bytes_format(opt_tree,
						hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
						nakbuf, "List(%d): %s", naks, nakbuf);
				} else {
					proto_tree_add_bytes_format(opt_tree,
						hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
						nakbuf, "List: %s", nakbuf);
				}
				ptvcursor_advance(cursor, j*4);
			}
			break;
		}
		case PGM_OPT_PGMCC_DATA:{
			guint16 optdata_afi;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PGMCC_DATA_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PGMCC_DATA_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_tsp, 4, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_res2, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker6, 16, ENC_NA);
				break;

			default:
				proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			break;
		}
		case PGM_OPT_PGMCC_FEEDBACK:{
			guint16 optdata_afi;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PGMCC_FEEDBACK_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PGMCC_FEEDBACK_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_tsp, 4, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_lossrate, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker6, 16, ENC_NA);
				break;

			default:
				proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			break;
		}
		case PGM_OPT_NAK_BO_IVL:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_ivl);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_NAK_BO_IVL_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_NAK_BO_IVL_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl_sqn, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_NAK_BO_RNG:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_rng);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_NAK_BO_RNG_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_NAK_BO_RNG_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_min_bo_ivl, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_max_bo_ivl, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_REDIRECT:{
			guint16 optdata_afi;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_redirect);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_REDIRECT_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_REDIRECT_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_redirect_res, 1, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_opt_redirect_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_redirect_res2, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr6, 16, ENC_NA);
				break;

			default:
				proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			break;
		}
		case PGM_OPT_FRAGMENT:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_fragment);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_FRAGMENT_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_FRAGMENT_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_first_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_offset, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_total_length, 4, ENC_BIG_ENDIAN);

			break;
		}
		default:{
			ptvcursor_advance(cursor, genopts_len);
			break;
		}
		}

		opts_total_len -= genopts_len;
	}
	return;
}
Example #22
0
static void
dissect_ata_pdu(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, gboolean response, guint32 tag)
{
  proto_item *tmp_item;
  guint8 aflags;
  guint64 lba;
  ata_info_t *ata_info=NULL;
  conversation_t *conversation;

  /* only create a conversation for ATA commands */
  conversation = find_or_create_conversation(pinfo);

  if( !(pinfo->fd->flags.visited) ){
    if(!response){
      ata_info_t *tmp_ata_info;
      /* first time we see this request so add a struct for request/response
         matching */
      ata_info=wmem_new(wmem_file_scope(), ata_info_t);
      ata_info->tag=tag;
      ata_info->conversation=conversation;
      ata_info->request_frame=pinfo->fd->num;
      ata_info->response_frame=0;
      ata_info->cmd=tvb_get_guint8(tvb, offset+3);
      ata_info->req_time=pinfo->fd->abs_ts;

      tmp_ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_unmatched, ata_info);
      if(tmp_ata_info){
        g_hash_table_remove(ata_cmd_unmatched, tmp_ata_info);
      }
      g_hash_table_insert(ata_cmd_unmatched, ata_info, ata_info);
    } else {
      ata_info_t tmp_ata_info;
      /* first time we see this response so see if we can match it with
         a request */
      tmp_ata_info.tag=tag;
      tmp_ata_info.conversation=conversation;
      ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_unmatched, &tmp_ata_info);
      /* woo hoo we could, so no need to store this in unmatched any more,
         move both request and response to the matched table */
      if(ata_info){
        ata_info->response_frame=pinfo->fd->num;
        g_hash_table_remove(ata_cmd_unmatched, ata_info);
        g_hash_table_insert(ata_cmd_matched, GUINT_TO_POINTER(ata_info->request_frame), ata_info);
        g_hash_table_insert(ata_cmd_matched, GUINT_TO_POINTER(ata_info->response_frame), ata_info);
      }
    }
  } else {
    ata_info=(ata_info_t *)g_hash_table_lookup(ata_cmd_matched, GUINT_TO_POINTER(pinfo->fd->num));
  }

  if(ata_info){
    if(response){
      if(ata_info->request_frame){
        nstime_t delta_ts;
        tmp_item=proto_tree_add_uint(tree, hf_aoe_response_to, tvb, 0, 0, ata_info->request_frame);
        PROTO_ITEM_SET_GENERATED(tmp_item);
        nstime_delta(&delta_ts, &pinfo->fd->abs_ts, &ata_info->req_time);
        tmp_item=proto_tree_add_time(tree, hf_aoe_time, tvb, offset, 0, &delta_ts);
        PROTO_ITEM_SET_GENERATED(tmp_item);
      }
    } else {
      if(ata_info->response_frame){
        tmp_item=proto_tree_add_uint(tree, hf_aoe_response_in, tvb, 0, 0, ata_info->response_frame);
        PROTO_ITEM_SET_GENERATED(tmp_item);
      }
    }
  }

  /* aflags */
  aflags=tvb_get_guint8(tvb, offset);
  proto_tree_add_item(tree, hf_aoe_aflags_e, tvb, offset, 1, ENC_BIG_ENDIAN);
  if(aflags&AOE_AFLAGS_E){
    proto_tree_add_item(tree, hf_aoe_aflags_d, tvb, offset, 1, ENC_BIG_ENDIAN);
  }
  if(aflags&AOE_AFLAGS_W){
    proto_tree_add_item(tree, hf_aoe_aflags_a, tvb, offset, 1, ENC_BIG_ENDIAN);
  }
  proto_tree_add_item(tree, hf_aoe_aflags_w, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset++;

  /* err/feature */
  proto_tree_add_item(tree, hf_aoe_err_feature, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset++;

  /* sector count */
  proto_tree_add_item(tree, hf_aoe_sector_count, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset++;

  /* ata command/status */
  if(!response){
    proto_tree_add_item(tree, hf_aoe_acmd, tvb, offset, 1, ENC_BIG_ENDIAN);
    col_append_fstr(pinfo->cinfo, COL_INFO, " ATA:%s", val_to_str(tvb_get_guint8(tvb, offset), ata_cmd_vals, " Unknown ATA<0x%02x>"));
  } else {
    proto_tree_add_item(tree, hf_aoe_astatus, tvb, offset, 1, ENC_BIG_ENDIAN);
    if(ata_info != NULL && ata_info->request_frame){
      /* we don't know what command it was unless we saw the request_frame */
      tmp_item=proto_tree_add_uint(tree, hf_aoe_acmd, tvb, 0, 0, ata_info->cmd);
      PROTO_ITEM_SET_GENERATED(tmp_item);
      col_append_fstr(pinfo->cinfo, COL_INFO, " ATA:%s", val_to_str(ata_info->cmd, ata_cmd_vals, " Unknown ATA<0x%02x>"));
    }
  }
  offset++;

  /*lba   probably complete wrong */
  lba=tvb_get_letohs(tvb, offset+4);
  lba=(lba<<32)|tvb_get_letohl(tvb, offset);
  offset+=8;
  proto_tree_add_uint64(tree, hf_aoe_lba, tvb, offset-8, 6, lba);

}
Example #23
0
dissect_brp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
{

    proto_item *brp_item    = NULL;
    proto_tree *brp_tree    = NULL;
    gint        offset      = 0;
    guint8      type        = 0;
    guint8      packet_type = tvb_get_guint8(tvb, 0);

    /* If there is a "tree" requested, we handle that request. */

    col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_BRP);
    /* We add some snazzy bizness to the info field to quickly ascertain
        what type of message was sent to/from the BRS/BRC. */
    col_add_fstr(pinfo->cinfo, COL_INFO, "Message Type - %s",
            val_to_str(packet_type, brp_packettype_names, "Unknown (0x%02x)"));

    /* This call adds our tree to the main dissection tree. */

    if (tree) { /* we are being asked for details */

        /* Here we add our tree/subtree so we can have a collapsible branch. */
        brp_item = proto_tree_add_item( tree, proto_brp, tvb, 0, -1, ENC_NA );
        brp_tree = proto_item_add_subtree( brp_item, ett_brp);

        /* We use tvb_get_guint8 to get our type value out. */
        type = tvb_get_guint8(tvb, offset);
        offset += 0;

        brp_item = proto_tree_add_item( brp_tree, hf_brp_type, tvb, offset, 1, ENC_BIG_ENDIAN );
        offset += 1;
Example #24
0
static void
dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree *prism_tree = NULL, *prism_did_tree = NULL;
    proto_item *ti = NULL, *ti_did = NULL;
    tvbuff_t *next_tvb;
    int offset;
    guint32 msgcode, msglen, did;
    guint16 status;
    guint8 *devname_p;

    offset = 0;
    did = 0;

    /* handle the AVS header */
    msgcode = tvb_get_ntohl(tvb, offset);
    if ((msgcode == WLANCAP_MAGIC_COOKIE_V1) ||
        (msgcode == WLANCAP_MAGIC_COOKIE_V2)) {
      call_dissector(wlancap_handle, tvb, pinfo, tree);
      return;
    }

    /*
     * If we don't see a valid message type, assume the Prism or AVS
     * header was omitted and just hand off to the 802.11 dissector;
     * at least one capture has AVS headers on some packets and no
     * radio headers on others (incoming vs. outgoing?).
     *
     * XXX - check for both byte orders and use that to determine
     * the byte order of the fields in the Prism header?
     */
    msgcode = tvb_get_letohl(tvb, offset);
    if ((msgcode != PRISM_TYPE1_MSGCODE) &&
        (msgcode != PRISM_TYPE2_MSGCODE)) {
        call_dissector(ieee80211_handle, tvb, pinfo, tree);
        return;
    }

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

    if(tree) {
        ti = proto_tree_add_item(tree, proto_prism, tvb, 0, 144, ENC_NA);
        prism_tree = proto_item_add_subtree(ti, ett_prism);
    }

    /* Message Code */
    if(tree) {
        proto_tree_add_item(prism_tree, hf_ieee80211_prism_msgcode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
    }
    msgcode = tvb_get_letohl(tvb, offset);
    offset += 4;

    /* Message Length */
    if(tree) {
        proto_tree_add_item(prism_tree, hf_ieee80211_prism_msglen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
    }
    msglen = tvb_get_letohl(tvb, offset);
    offset += 4;

    /* Device Name */
    if(tree) {
       proto_tree_add_item(prism_tree, hf_ieee80211_prism_devname, tvb, offset, 16, ENC_ASCII|ENC_NA);
    }
    devname_p = tvb_get_string(wmem_packet_scope(), tvb, offset, 16);
    offset += 16;

    col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %s, Message 0x%x, Length %d", devname_p, msgcode, msglen);


    while(offset < PRISM_HEADER_LENGTH)
    {
        /* DID */
        if(tree) {
            ti_did = proto_tree_add_item(prism_tree, hf_ieee80211_prism_did, tvb, offset, 12, ENC_NA);
            prism_did_tree = proto_item_add_subtree(ti_did, ett_prism_did);

            proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
            did = tvb_get_letohl(tvb, offset);
            proto_item_append_text(ti_did, " %s", val_to_str(did, prism_did_vals, "Unknown %x") );
        }
        offset += 4;


        /* Status */
        status = tvb_get_letohs(tvb, offset);
        if(tree) {
            proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_status, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        }
        offset += 2;

        /* Length */
        if(tree) {
            proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        }
        offset += 2;

        /* Data, if present... */
        if (status == 0) {
            switch(did){
              case PRISM_TYPE1_HOSTTIME:
              case PRISM_TYPE2_HOSTTIME:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_hosttime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_MACTIME:
              case PRISM_TYPE2_MACTIME:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_mactime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_CHANNEL:
              case PRISM_TYPE2_CHANNEL:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_channel, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
                }
                col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", tvb_get_letohl(tvb, offset));
              break;

              case PRISM_TYPE1_RSSI:
              case PRISM_TYPE2_RSSI:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rssi, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
                }
                col_add_fstr(pinfo->cinfo, COL_RSSI, "%d", tvb_get_letohl(tvb, offset));
              break;

              case PRISM_TYPE1_SQ:
              case PRISM_TYPE2_SQ:
                 if(tree){
                      proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_sq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                      proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_SIGNAL:
              case PRISM_TYPE2_SIGNAL:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_signal, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_NOISE:
              case PRISM_TYPE2_NOISE:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_noise, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_RATE:
              case PRISM_TYPE2_RATE:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " %s Mb/s", prism_rate_return(tvb_get_letohl(tvb, offset)) );
                }
                col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%s", prism_rate_return(tvb_get_letohl(tvb, offset)) );
              break;

              case PRISM_TYPE1_ISTX:
              case PRISM_TYPE2_ISTX:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_istx, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_FRMLEN:
              case PRISM_TYPE2_FRMLEN:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_frmlen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
                }
              break;

              default:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_unknown, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                }
              break;
            }
        }
        offset += 4;
    }

    /* dissect the 802.11 header next */
    next_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector(ieee80211_handle, next_tvb, pinfo, tree);
}
Example #25
0
static void
dissect_itdm_125usec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  tvbuff_t	*next_tvb;
  proto_item *itdm_item = NULL;
  proto_tree *itdm_tree = NULL;
  int offset;
  guint32 flowid;
  guint32 chanid;
  guint16 chloc1;
  guint16 chloc2;
  guint8 chcmd;
  guint8 actbit;
  guint8 ackbit;


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

  flowid = tvb_get_ntoh24(tvb, ITDM_FLOWID_OFFSET);
  chanid = tvb_get_ntoh24(tvb, ITDM_CHANID_OFFSET);
  chcmd  = tvb_get_guint8(tvb, ITDM_CHCMD_OFFSET);
  chloc1 = tvb_get_ntohs(tvb, ITDM_CHLOC1_OFFSET);
  actbit = (chcmd & 0x10) ? 1 : 0;
  ackbit = (chcmd & 0x20) ? 1 : 0;
  chcmd  = chcmd & 0x0f;

  if (check_col(pinfo->cinfo, COL_INFO))
  {
    col_add_fstr(pinfo->cinfo, COL_INFO,
      "Flow %d Chan %d ACT %d ACK %d %s",
      flowid, chanid, actbit, ackbit,
      val_to_str(chcmd, chcmd_vals, "Reserved"));
    if (chcmd == ITDM_CMD_NEW_CHAN ||
        chcmd == ITDM_CMD_CLOSE_CHAN ||
        chcmd == ITDM_CMD_CYCLIC_REAF)
    {
      col_append_fstr(pinfo->cinfo, COL_INFO,
        " Loc1 %d", chloc1);
    }
    else if (chcmd == ITDM_CMD_RELOC_CHAN)
    {
      chloc2 = tvb_get_ntohs(tvb, ITDM_CHLOC2_OFFSET);
      col_append_fstr(pinfo->cinfo, COL_INFO,
        " Loc1 %d Loc2 %d", chloc1, chloc2);
    }
  }

  offset = 0;

  if (tree)
  {
	itdm_item = proto_tree_add_item(tree, proto_itdm, tvb, 0, -1, ENC_NA);
	itdm_tree = proto_item_add_subtree(itdm_item, ett_itdm);

	proto_tree_add_item(itdm_tree, hf_itdm_timestamp, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;
	proto_tree_add_item(itdm_tree, hf_itdm_seqnum, tvb, offset, 1, ENC_BIG_ENDIAN);
	offset += 1;
	proto_tree_add_item(itdm_tree, hf_itdm_sop_eop, tvb, offset, 1, ENC_BIG_ENDIAN);
	proto_tree_add_item(itdm_tree, hf_itdm_last_pack, tvb, offset, 1, ENC_BIG_ENDIAN);
	proto_tree_add_item(itdm_tree, hf_itdm_pktlen, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;
	proto_tree_add_item(itdm_tree, hf_itdm_chksum, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;
	proto_tree_add_item(itdm_tree, hf_itdm_uid, tvb, offset, 3, ENC_BIG_ENDIAN);
	offset += 3;
	proto_tree_add_item(itdm_tree, hf_itdm_ack, tvb, offset, 1, ENC_BIG_ENDIAN);
	proto_tree_add_item(itdm_tree, hf_itdm_act, tvb, offset, 1, ENC_BIG_ENDIAN);
	proto_tree_add_item(itdm_tree, hf_itdm_chcmd, tvb, offset, 1, ENC_BIG_ENDIAN);
	offset += 1;
	proto_tree_add_item(itdm_tree, hf_itdm_chid, tvb, offset, 3, ENC_BIG_ENDIAN);
	offset += 3;
	if (chcmd == ITDM_CMD_PACKET_RATE)
	{
		proto_tree_add_item(itdm_tree, hf_itdm_pktrate, tvb, offset, 4, ENC_BIG_ENDIAN);
		offset += 4;
	}
	else
	{
		proto_tree_add_item(itdm_tree, hf_itdm_chloc1, tvb, offset, 2, ENC_BIG_ENDIAN);
		offset += 2;
		if (chcmd == ITDM_CMD_CYCLIC_REAF ||
		    chcmd == ITDM_CMD_NEW_CHAN ||
		    chcmd == ITDM_CMD_CLOSE_CHAN)
		{
			proto_tree_add_item(itdm_tree, hf_itdm_cxnsize, tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
		}
		else
		{
			proto_tree_add_item(itdm_tree, hf_itdm_chloc2, tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
		}
	}
  }

  next_tvb = tvb_new_subset_remaining(tvb, offset);
  call_dissector(data_handle, next_tvb, pinfo, tree);
}
Example #26
0
static void
dissect_cups(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree   *cups_tree = NULL;
    proto_tree   *ptype_subtree = NULL;
    proto_item   *ti = NULL;
    gint          offset = 0;
    gint          next_offset;
    guint         len;
    const guint8 *str;
    cups_ptype_t  ptype;
    unsigned int  state;

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

    ti = proto_tree_add_item(tree, proto_cups, tvb, offset, -1, ENC_NA);
    cups_tree = proto_item_add_subtree(ti, ett_cups);

    /* Format (1450 bytes max.):  */
    /* type state uri ["location" ["info" ["make-and-model"]]]\n */

    ptype = get_hex_uint(tvb, offset, &next_offset);
    len = next_offset - offset;
    if (len != 0) {
        ti = proto_tree_add_uint(cups_tree, hf_cups_ptype, tvb, offset, len, ptype);
        ptype_subtree = proto_item_add_subtree(ti, ett_cups_ptype);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_default, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_implicit, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_variable, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_large, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_medium, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_small, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_sort, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_bind, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_cover, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_punch, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_collate, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_copies, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_staple, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_duplex, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_color, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_bw, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_remote, tvb, offset, len, ENC_BIG_ENDIAN);
        proto_tree_add_item(ptype_subtree, hf_cups_ptype_class, tvb, offset, len, ENC_BIG_ENDIAN);
    }
    offset = next_offset;

    if (!skip_space(tvb, offset, &next_offset))
        return;    /* end of packet */
    offset = next_offset;

    state = get_hex_uint(tvb, offset, &next_offset);
    len = next_offset - offset;
    if (len != 0) {
        proto_tree_add_uint(cups_tree, hf_cups_state, tvb, offset, len, state);
    }
    offset = next_offset;

    if (!skip_space(tvb, offset, &next_offset))
        return;    /* end of packet */
    offset = next_offset;

    str = get_unquoted_string(tvb, offset, &next_offset, &len);
    if (str == NULL)
        return;    /* separator/terminator not found */

    proto_tree_add_string(cups_tree, hf_cups_uri, tvb, offset, len, str);
    col_add_fstr(pinfo->cinfo, COL_INFO, "%.*s (%s)",
            (guint16) len, str, val_to_str(state, cups_state_values, "0x%x"));
    offset = next_offset;

    if (!cups_tree)
        return;

    if (!skip_space(tvb, offset, &next_offset))
        return;    /* end of packet */
    offset = next_offset;

    str = get_quoted_string(tvb, offset, &next_offset, &len);
    if (str == NULL)
        return;    /* separator/terminator not found */
    proto_tree_add_string(cups_tree, hf_cups_location, tvb, offset+1, len, str);
    offset = next_offset;

    if (!skip_space(tvb, offset, &next_offset))
        return;    /* end of packet */
    offset = next_offset;

    str = get_quoted_string(tvb, offset, &next_offset, &len);
    if (str == NULL)
        return;    /* separator/terminator not found */
    proto_tree_add_string(cups_tree, hf_cups_information, tvb, offset+1, len, str);
    offset = next_offset;

    if (!skip_space(tvb, offset, &next_offset))
        return;    /* end of packet */
    offset = next_offset;

    str = get_quoted_string(tvb, offset, &next_offset, &len);
    if (str == NULL)
        return;    /* separator/terminator not found */
    proto_tree_add_string(cups_tree, hf_cups_make_model, tvb, offset+1, len, str);
}
Example #27
0
static void
dissect_forces(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
{
    /* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti, *tlv_item;
    proto_tree *forces_tree, *forces_flags_tree;
    proto_tree *forces_main_header_tree, *forces_tlv_tree, *tlv_tree;
    gint        length_count;

    guint8      message_type;
    guint16     tlv_type;

    /* Make entries in Protocol column and Info column on summary display */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "ForCES");
    col_clear(pinfo->cinfo, COL_INFO);

    ti = proto_tree_add_item(tree, proto_forces, tvb, 0, -1, ENC_NA);
    forces_tree = proto_item_add_subtree(ti, ett_forces);

    ti = proto_tree_add_text(forces_tree, tvb, 0, ForCES_HEADER_LENGTH, "Common Header");
    forces_main_header_tree = proto_item_add_subtree(ti, ett_forces_main_header);

    proto_tree_add_item(forces_main_header_tree, hf_forces_version, tvb, 0, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_main_header_tree, hf_forces_rsvd,    tvb, 0, 1, ENC_BIG_ENDIAN);

    message_type = tvb_get_guint8(tvb, offset+1);
    proto_tree_add_item( forces_main_header_tree, hf_forces_messagetype, tvb, offset+1, 1, ENC_BIG_ENDIAN);

    length_count = tvb_get_ntohs(tvb, offset+2) * 4;  /*multiply 4 DWORD*/
    ti = proto_tree_add_uint_format( forces_main_header_tree, hf_forces_length,
                                     tvb, offset+2, 2, length_count, "Length: %u Bytes", length_count);
    if (length_count != tvb_reported_length_remaining(tvb, offset))
        expert_add_info_format(pinfo, ti, &ei_forces_length, "Bogus: ForCES Header length (%u bytes) is wrong),should be (%u bytes)",
                               length_count, tvb_reported_length_remaining(tvb, offset));
    if (length_count < 24)
        expert_add_info_format(pinfo, ti, &ei_forces_length, "Bogus: ForCES Header length (%u bytes) is less than 24bytes)", length_count);

    col_add_fstr(pinfo->cinfo, COL_INFO, "Message Type: %s, Total Length:  %u Bytes",
                 val_to_str(message_type, message_type_vals, "Unknown messagetype 0x%x"), length_count);

    proto_tree_add_item( forces_main_header_tree, hf_forces_sid,        tvb, offset+4,  4, ENC_BIG_ENDIAN);
    proto_tree_add_item( forces_main_header_tree, hf_forces_did,        tvb, offset+8,  4, ENC_BIG_ENDIAN);
    proto_tree_add_item( forces_main_header_tree, hf_forces_correlator, tvb, offset+12, 8, ENC_BIG_ENDIAN);

    /*Add flags tree*/
    ti = proto_tree_add_item(forces_main_header_tree, hf_forces_flags, tvb, offset+20, 4, ENC_BIG_ENDIAN);
    forces_flags_tree = proto_item_add_subtree(ti, ett_forces_flags);

    proto_tree_add_item(forces_flags_tree, hf_forces_flags_ack,      tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_at,       tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_em,       tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_pri,      tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_reserved, tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_rsrvd,    tvb, offset+20, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(forces_flags_tree, hf_forces_flags_tp,       tvb, offset+20, 4, ENC_BIG_ENDIAN);

    offset += 24;
    while (tvb_reported_length_remaining(tvb, offset) >= TLV_TL_LENGTH)
    {
        ti = proto_tree_add_text(forces_tree, tvb, offset, TLV_TL_LENGTH, "TLV");
        forces_tlv_tree = proto_item_add_subtree(ti, ett_forces_tlv);

        tlv_type = tvb_get_ntohs(tvb, offset);
        tlv_item = proto_tree_add_item(forces_tlv_tree, hf_forces_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN);
        length_count = tvb_get_ntohs(tvb, offset+2) * 4;
        proto_item_set_len(ti, length_count);
        ti = proto_tree_add_uint_format_value(forces_tlv_tree, hf_forces_tlv_length,
                                              tvb, offset+2, 2, length_count, "%u Bytes", length_count);
        if (tvb_reported_length_remaining(tvb, offset) < length_count)
            expert_add_info_format(pinfo, ti, &ei_forces_tlv_length, "Bogus: Main TLV length (%u bytes) is wrong", length_count);

        if (length_count < TLV_TL_LENGTH)
        {
            expert_add_info_format(pinfo, ti, &ei_forces_tlv_length, "Bogus TLV length: %u", length_count);
            break;
        }

        offset       += TLV_TL_LENGTH;
        length_count -= TLV_TL_LENGTH;

        switch(tlv_type)
        {
        case LFBselect_TLV:
            ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "LFB select TLV");
            tlv_tree = proto_item_add_subtree(ti, ett_forces_lfbselect_tlv_type);
            dissect_lfbselecttlv(tvb, pinfo, tlv_tree, offset, length_count);
            break;

        case REDIRECT_TLV:
            ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "Redirect TLV");
            tlv_tree = proto_item_add_subtree(ti, ett_forces_redirect_tlv_type);
            dissect_redirecttlv(tvb, pinfo, tlv_tree, offset);
            break;

        case ASResult_TLV:
            ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "ASResult TLV");
            tlv_tree = proto_item_add_subtree(ti, ett_forces_asresult_tlv);
            proto_tree_add_item(tlv_tree, hf_forces_asresult_association_setup_result, tvb, offset, 4, ENC_BIG_ENDIAN);
            break;

        case ASTreason_TLV:
            ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "ASTreason TLV");
            tlv_tree = proto_item_add_subtree(ti, ett_forces_astreason_tlv);
            proto_tree_add_item(tlv_tree, hf_forces_astreason_tlv_teardown_reason, tvb, offset, 4, ENC_BIG_ENDIAN);
            break;

        default:
            expert_add_info(pinfo, tlv_item, &ei_forces_tlv_type);
            ti = proto_tree_add_text(forces_tlv_tree, tvb, offset, length_count, "Unknown TLV");
            tlv_tree = proto_item_add_subtree(ti, ett_forces_unknown_tlv);
            proto_tree_add_item(tlv_tree, hf_forces_unknown_tlv, tvb, offset, length_count, ENC_NA);
            break;
        }

        offset += length_count;
    }
}
Example #28
0
/*
 * Name: dissect_esis()
 *
 * Description:
 *   Main entry area for esis de-mangling.  This will build the
 *   main esis tree data and call the sub-protocols as needed.
 *
 * Input:
 *   tvbuff *      : tvbuff referring to packet data
 *   packet_info * : info for current packet
 *   proto_tree *  : tree of display data.  May be NULL.
 *
 * Output:
 *   void, but we will add to the proto_tree if it is not NULL.
 */
static void
dissect_esis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
  const char *pdu_type_string        = NULL;
  const char *pdu_type_format_string = "PDU Type      : %s (R:%s%s%s)";
  esis_hdr_t  ehdr;
  proto_item *ti;
  proto_tree *esis_tree    = NULL;
  guint8      variable_len;
  guint       tmp_uint     = 0;
  const char *cksum_status;

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

  tvb_memcpy(tvb, (guint8 *)&ehdr, 0, sizeof ehdr);

  if (tree) {
    ti = proto_tree_add_item(tree, proto_esis, tvb, 0, -1, ENC_NA);
    esis_tree = proto_item_add_subtree(ti, ett_esis);

    if (ehdr.esis_version != ESIS_REQUIRED_VERSION){
      esis_dissect_unknown(tvb, esis_tree,
                           "Unknown ESIS version (%u vs %u)",
                           ehdr.esis_version, ESIS_REQUIRED_VERSION );
      return;
    }

    if (ehdr.esis_length < ESIS_HDR_FIXED_LENGTH) {
      esis_dissect_unknown(tvb, esis_tree,
                           "Bogus ESIS length (%u, must be >= %u)",
                           ehdr.esis_length, ESIS_HDR_FIXED_LENGTH );
      return;
    }
    proto_tree_add_uint( esis_tree, hf_esis_nlpi, tvb, 0, 1, ehdr.esis_nlpi );
    proto_tree_add_uint( esis_tree, hf_esis_length, tvb,
                         1, 1, ehdr.esis_length );
    proto_tree_add_uint( esis_tree, hf_esis_version, tvb, 2, 1,
                         ehdr.esis_version );
    proto_tree_add_uint( esis_tree, hf_esis_reserved, tvb, 3, 1,
                         ehdr.esis_reserved );

    pdu_type_string = val_to_str(ehdr.esis_type&OSI_PDU_TYPE_MASK,
                                 esis_vals, "Unknown (0x%x)");

    proto_tree_add_uint_format( esis_tree, hf_esis_type, tvb, 4, 1,
                                ehdr.esis_type,
                                pdu_type_format_string,
                                pdu_type_string,
                                (ehdr.esis_type&BIT_8) ? "1" : "0",
                                (ehdr.esis_type&BIT_7) ? "1" : "0",
                                (ehdr.esis_type&BIT_6) ? "1" : "0");

    tmp_uint = pntohs( ehdr.esis_holdtime );
    proto_tree_add_uint_format(esis_tree, hf_esis_holdtime, tvb, 5, 2,
                               tmp_uint, "Holding Time  : %u seconds",
                               tmp_uint );

    tmp_uint = pntohs( ehdr.esis_checksum );

    switch (calc_checksum( tvb, 0, ehdr.esis_length, tmp_uint )) {

    case NO_CKSUM:
      cksum_status = "Not Used";
      break;

    case DATA_MISSING:
      cksum_status = "Not checkable - not all of packet was captured";
      break;

    case CKSUM_OK:
      cksum_status = "Is good";
      break;

    case CKSUM_NOT_OK:
      cksum_status = "Is wrong";
      break;

    default:
      cksum_status = NULL;
      DISSECTOR_ASSERT_NOT_REACHED();
    }
    proto_tree_add_uint_format( esis_tree, hf_esis_checksum, tvb, 7, 2,
                                tmp_uint, "Checksum      : 0x%x ( %s )",
                                tmp_uint, cksum_status );
  }


  /*
   * Let us make sure we use the same names for all our decodes
   * here.  First, dump the name into info column, and THEN
   * dispatch the sub-type.
   */
  col_add_str(pinfo->cinfo, COL_INFO,
                val_to_str( ehdr.esis_type&OSI_PDU_TYPE_MASK, esis_vals,
                            "Unknown (0x%x)" ) );

  variable_len = ehdr.esis_length - ESIS_HDR_FIXED_LENGTH;

  switch (ehdr.esis_type & OSI_PDU_TYPE_MASK) {
  case ESIS_ESH_PDU:
    esis_dissect_esh_pdu( variable_len, tvb, esis_tree);
    break;
  case ESIS_ISH_PDU:
    esis_dissect_ish_pdu( variable_len, tvb, esis_tree);
    break;
  case ESIS_RD_PDU:
    esis_dissect_redirect_pdu( variable_len, tvb, esis_tree);
    break;
  default:
    esis_dissect_unknown(tvb, esis_tree,
                         "Unknown ESIS packet type 0x%x",
                         ehdr.esis_type & OSI_PDU_TYPE_MASK );
  }
} /* dissect_esis */
Example #29
0
dissect_q932_ie(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
  gint offset;
  proto_item *ti;
  proto_tree *ie_tree;
  guint8 ie_type, ie_len;

  offset = 0;

  ti = proto_tree_add_item(tree, proto_q932, tvb, offset, -1, ENC_NA);
  proto_item_set_hidden(ti);

  ie_type = tvb_get_guint8(tvb, offset);
  ie_len = tvb_get_guint8(tvb, offset + 1);

  ie_tree = proto_tree_add_subtree(tree, tvb, offset, -1, ett_q932_ie, NULL,
            val_to_str(ie_type, VALS(q932_str_ie_type), "unknown (0x%02X)"));

  proto_tree_add_item(ie_tree, hf_q932_ie_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(ie_tree, hf_q932_ie_len, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
  offset += 2;
  if (tvb_reported_length_remaining(tvb, offset) <= 0)
    return offset;
  switch (ie_type) {
    case Q932_IE_FACILITY :
      dissect_q932_facility_ie(tvb, offset, pinfo, ie_tree, ie_len);
      break;
    case Q932_IE_NOTIFICATION_INDICATOR :
      dissect_q932_ni_ie(tvb, offset, pinfo, ie_tree, ie_len);
      break;
    default:
      if (ie_len > 0) {
Example #30
0
static int
dissect_openvpn_msg_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *openvpn_tree, proto_tree *parent_tree, gint offset)
{
  gboolean       tls_auth;
  guint          openvpn_keyid;
  guint          openvpn_opcode;
  guint32        msg_mpid      = -1;
  guint32        msg_sessionid = -1;
  guint8         openvpn_predict_tlsauth_arraylength;
  proto_item    *ti2;
  proto_tree    *packetarray_tree, *type_tree;
  guint32        msg_length_remaining;
  gboolean       msg_lastframe;
  fragment_head *frag_msg;
  tvbuff_t      *new_tvb;
  gboolean       save_fragmented;

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

  /* read opcode and write to info column */
  openvpn_opcode = tvb_get_bits8(tvb, offset*8, 5);
  col_append_fstr(pinfo->cinfo, COL_INFO, "MessageType: %s",
                  val_to_str_const(openvpn_opcode, openvpn_message_types, "Unknown Messagetype"));


  openvpn_keyid = tvb_get_bits8(tvb, offset*8 + 5, 3);
  proto_item_append_text(parent_tree, ", Opcode: %s, Key ID: %d",
                         val_to_str(openvpn_opcode, openvpn_message_types, "Unknown (0x%02x)"),
                         openvpn_keyid);

  ti2 = proto_tree_add_item(openvpn_tree, hf_openvpn_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  proto_item_append_text(ti2, " [opcode/key_id]");

  type_tree = proto_item_add_subtree(ti2, ett_openvpn_type);
  proto_tree_add_item(type_tree, hf_openvpn_opcode, tvb, offset, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(type_tree, hf_openvpn_keyid, tvb, offset, 1, ENC_BIG_ENDIAN);
  offset += 1;

  if (openvpn_opcode == P_DATA_V2) {
    proto_tree_add_item(openvpn_tree, hf_openvpn_peerid, tvb, offset, 3, ENC_BIG_ENDIAN);
    offset += 3;
  } else if (openvpn_opcode != P_DATA_V1) {
    /* if we have a P_CONTROL or P_ACK packet */

    /* read sessionid */
    msg_sessionid = tvb_get_bits32(tvb, offset*8+32, 32, ENC_BIG_ENDIAN);
    proto_tree_add_item(openvpn_tree, hf_openvpn_sessionid, tvb, offset, 8, ENC_BIG_ENDIAN);
    offset += 8;

    /* tls-auth detection (this can be overridden by preferences */
    openvpn_predict_tlsauth_arraylength = tvb_get_guint8(tvb, offset);
    /* if the first 4 bytes that would, if tls-auth is used, contain part of the hmac,
       lack entropy, we asume no tls-auth is used */
    if (pref_tls_auth_override == FALSE) {
      if ((openvpn_opcode != P_DATA_V1)
          && (openvpn_predict_tlsauth_arraylength > 0)
          && check_for_valid_hmac(tvb_get_ntohl(tvb, offset))) {
        tls_auth = TRUE;
      } else {
        tls_auth = FALSE;
      }
    } else {
      tls_auth = pref_tls_auth;
    }

    if (tls_auth == TRUE) {
      proto_tree_add_item(openvpn_tree, hf_openvpn_hmac, tvb, offset, tls_auth_hmac_size, ENC_NA);
      offset += tls_auth_hmac_size;

      if (tvb_reported_length_remaining(tvb, offset) >= 8) {
        proto_tree_add_item(openvpn_tree, hf_openvpn_pid, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;

        if (pref_long_format) {
          proto_tree_add_item(openvpn_tree, hf_openvpn_net_time, tvb, offset, 4, ENC_BIG_ENDIAN);
          offset += 4;
        }
      }
    }

    if (tvb_reported_length_remaining(tvb, offset) >= 1) {
      /* read P_ACK packet-id array length */
      gint pid_arraylength = tvb_get_guint8(tvb, offset);
      gint i;
      proto_tree_add_item(openvpn_tree, hf_openvpn_mpid_arraylength, tvb, offset, 1, ENC_BIG_ENDIAN);
      offset += 1;

      if (pid_arraylength > 0) {

        packetarray_tree = proto_tree_add_subtree(openvpn_tree, tvb, offset, 0, ett_openvpn_packetarray, NULL, "Packet-ID Array");
        for (i = 0; i < pid_arraylength; i++) {
          proto_tree_add_item(packetarray_tree, hf_openvpn_mpid_arrayelement, tvb, offset, 4, ENC_BIG_ENDIAN);
          offset += 4;
        }

        if (tvb_reported_length_remaining(tvb, offset) >= 8) {
          proto_tree_add_item(openvpn_tree, hf_openvpn_rsessionid, tvb, offset, 8, ENC_BIG_ENDIAN);
          offset += 8;
        }
      }
    }

    /* if we have a P_CONTROL packet */
    if (openvpn_opcode != P_ACK_V1) {
      /* read Message Packet-ID */
      if (tvb_reported_length_remaining(tvb, offset) >= 4) {
        msg_mpid = tvb_get_bits32(tvb, offset*8, 32, ENC_BIG_ENDIAN);
        proto_tree_add_item(openvpn_tree, hf_openvpn_mpid, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;
      }
    }
  }

  /* if we have more data left, determine what to do */
  msg_length_remaining = tvb_reported_length_remaining(tvb, offset);

  if (msg_length_remaining == 0) {
    return tvb_captured_length(tvb);
  }

  if (openvpn_opcode != P_CONTROL_V1) {
    proto_tree *data_tree;
    data_tree = proto_tree_add_subtree_format(openvpn_tree, tvb, offset, -1,
                              ett_openvpn_data, NULL, "Data (%d bytes)",
                              tvb_captured_length_remaining(tvb, offset));

    proto_tree_add_item(data_tree, hf_openvpn_data, tvb, offset, -1, ENC_NA);
    return tvb_captured_length(tvb);
  }

  /* Try to reassemble */

  /* an ordinary openvpn control packet contains 100 bytes only if it is part of a
     fragmented message and is not the last fragment of the current transmission.
     Note that the tvb contains exactly one openvpn PDU:
     UDP: by definition;
     TCP: because of the use of tcp_dissect_pdus().
  */
  if (msg_length_remaining == 100) {
    msg_lastframe = FALSE;
  } else {
    msg_lastframe = TRUE;
  }

  save_fragmented = pinfo->fragmented;
  pinfo->fragmented = TRUE;

  frag_msg = fragment_add_seq_next(
    &msg_reassembly_table,
    tvb,
    offset,
    pinfo,
    msg_sessionid,         /* ID for fragments belonging together */
    NULL,
    msg_length_remaining,  /* fragment length - to the end        */
    !(msg_lastframe));     /* More fragments ?                    */

  /* show "data" fragment on tree unless "reassembled" message has just one part.       */
  /* i.e., show if ("not reassembled") or ("reassembled" and "has multiple fragments")  */
  if ((frag_msg == NULL) || (frag_msg->next != NULL)) {
    proto_tree *data_tree;
    data_tree = proto_tree_add_subtree_format(openvpn_tree, tvb, offset, -1,
                              ett_openvpn_data, NULL, "Message fragment (%d bytes)",
                              tvb_captured_length_remaining(tvb, offset));

    proto_tree_add_item(data_tree, hf_openvpn_fragment_bytes, tvb, offset, -1, ENC_NA);
    }

  new_tvb = NULL;
  if (frag_msg) {
    if (msg_lastframe) { /* Reassembled */
      new_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled Message",
                                         frag_msg, &openvpn_frag_items, NULL, openvpn_tree);
      if (frag_msg->next != NULL) { /* multiple frags ? */
        col_append_str(pinfo->cinfo, COL_INFO, " (Message Reassembled "); /* overwritten by next dissector */
      }

    } else { /* Not last packet of reassembled Short Message */
      col_append_fstr(pinfo->cinfo, COL_INFO, " (Message fragment %d) ", msg_mpid);
      if (pinfo->num != frag_msg->reassembled_in) {
        /* Add a "Reassembled in" link if not reassembled in this frame */
        proto_tree_add_uint(openvpn_tree, hf_openvpn_reassembled_in,
                            tvb, 0, 0, frag_msg->reassembled_in);
      }
    }
  } /* if (frag_msg) */

  pinfo->fragmented = save_fragmented;

  /* Now see if we need to call subdissector.
     new_tvb is non-null if we "reassembled* a message (even just one fragment) */

  if (new_tvb) {
    /* call SSL/TLS dissector if we just processed the last fragment */
    call_dissector(ssl_handle, new_tvb, pinfo, parent_tree);
  }

  return tvb_captured_length(tvb);
}