Пример #1
0
static void
dissect_vntag(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint16     encap_proto;
	proto_tree *vntag_tree = NULL;

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

	if (tree) {
		proto_item *ti = proto_tree_add_item(tree, proto_vntag, tvb, 0, 4, ENC_NA);

		vntag_tree = proto_item_add_subtree(ti, ett_vntag);

		/* XXX, 4 bytes of data */

		/* from scapy (http://hg.secdev.org/scapy-com/rev/37acec891993) GPLv2:

		   BitField("dir",     0, 1),
		   BitField("ptr",     0, 1),
		   BitField("dst",     0, 14),
		   BitField("looped",  0, 1),
		   BitField("r",       0, 1),
		   BitField("version", 0, 2),
		   BitField("src",     0, 12) ]
		*/
		/* another: http://www.definethecloud.net/access-layer-network-virtualization-vn-tag-and-vepa */
	}

	encap_proto = tvb_get_ntohs(tvb, 4);

	/* copied from packet-vlan.c do we need it also for VNTAG? */
#if 0
	if (encap_proto <= IEEE_802_3_MAX_LEN) {
		gboolean is_802_2;

		/* Is there an 802.2 layer? I can tell by looking at the first 2
		   bytes after the VLAN header. If they are 0xffff, then what
		   follows the VLAN header is an IPX payload, meaning no 802.2.
		   (IPX/SPX is they only thing that can be contained inside a
		   straight 802.3 packet, so presumably the same applies for
		   Ethernet VLAN packets). A non-0xffff value means that there's an
		   802.2 layer inside the VLAN layer */
		is_802_2 = TRUE;

		/* Don't throw an exception for this check (even a BoundsError) */
		if (tvb_length_remaining(tvb, 4) >= 2) {
			if (tvb_get_ntohs(tvb, 4) == 0xffff)
				is_802_2 = FALSE;
		}

		dissect_802_3(encap_proto, is_802_2, tvb, 4, pinfo, tree, vntag_tree, hf_vntag_len, hf_vntag_trailer, 0);
	} else
#endif
		ethertype(encap_proto, tvb, 6, pinfo, tree, vntag_tree, hf_vntag_etype, hf_vntag_trailer, 0);
}
static void
dissect_cmd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    guint16 encap_proto;
    ethertype_data_t ethertype_data;

    proto_tree *cmd_tree = NULL;
    gint offset = 0;

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

    if (tree) {
        proto_item *ti = proto_tree_add_item(tree, proto_cmd, tvb, 0, 6, ENC_NA);

        cmd_tree = proto_item_add_subtree(ti, ett_cmd);
        proto_tree_add_item(cmd_tree, hf_cmd_version, tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;
        proto_tree_add_item(cmd_tree, hf_cmd_length, tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;
        proto_tree_add_item(cmd_tree, hf_cmd_options, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;
        proto_tree_add_item(cmd_tree, hf_cmd_sgt, tvb, offset, 2, ENC_BIG_ENDIAN);
        /*offset += 2;*/
    }

    encap_proto = tvb_get_ntohs(tvb, 6);

/* This Logic to identify and decode IEEE 802.3 frames is not working correctly. Carry over code from packet-vlan.c
 * Commenting it out for now will display as Unknown for L2 control frames instead of showing a wrong decode.
 */
#if 0
    if (encap_proto <= IEEE_802_3_MAX_LEN) {
        gboolean is_802_2 = TRUE;

        /* Don't throw an exception for this check (even a BoundsError) */
        if (tvb_length_remaining(tvb, 4) >= 2) {
            if (tvb_get_ntohs(tvb, 4) == 0xffff)
                is_802_2 = FALSE;
        }

        dissect_802_3(encap_proto, is_802_2, tvb, 4, pinfo, tree, cmd_tree, hf_eth_type, hf_cmd_trailer, 0);
    } else {
#endif

    ethertype_data.etype = encap_proto;
    ethertype_data.offset_after_ethertype = 8;
    ethertype_data.fh_tree = cmd_tree;
    ethertype_data.etype_id = hf_eth_type;
    ethertype_data.trailer_id = hf_cmd_trailer;
    ethertype_data.fcs_len = 0;

    call_dissector_with_data(ethertype_handle, tvb, pinfo, tree, &ethertype_data);
}

void
proto_register_cmd(void)
{
    static hf_register_info hf[] = {
        { &hf_cmd_version,
            { "Version", "cmd.version", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
        },
        { &hf_cmd_length,
            { "Length", "cmd.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }
        },
        { &hf_cmd_options,
            { "Options", "cmd.options", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }
        },
        { &hf_cmd_sgt,
            { "SGT", "cmd.sgt", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }
        },
        { &hf_eth_type,
            { "Type", "cmd.type", FT_UINT16, BASE_HEX, VALS(etype_vals), 0x0, NULL, HFILL }
        },
        { &hf_cmd_trailer,
            { "Trailer", "cmd.trailer", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }
        },
    };

    static gint *ett[] = {
        &ett_cmd
    };

    proto_cmd = proto_register_protocol("Cisco MetaData", "Cisco MetaData", "cmd");
    proto_register_field_array(proto_cmd, hf, array_length(hf));
    proto_register_subtree_array(ett, array_length(ett));
}

void
proto_reg_handoff_cmd(void)
{
    dissector_handle_t cmd_handle;

    ethertype_handle = find_dissector("ethertype");

    cmd_handle = create_dissector_handle(dissect_cmd, proto_cmd);
    dissector_add_uint("ethertype", ETHERTYPE_CMD, cmd_handle);
}
Пример #3
0
static void
dissect_eth_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree,
    int fcs_len)
{
  proto_item        *ti = NULL;
  eth_hdr           *ehdr;
  gboolean          is_802_2;
  proto_tree        *fh_tree = NULL;
  const guint8      *src_addr, *dst_addr;
  static eth_hdr    ehdrs[4];
  static int        ehdr_num=0;
  proto_tree        *tree;
  proto_item        *addr_item;
  proto_tree        *addr_tree=NULL;

  ehdr_num++;
  if(ehdr_num>=4){
     ehdr_num=0;
  }
  ehdr=&ehdrs[ehdr_num];

  tree=parent_tree;

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

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

  ehdr->type = tvb_get_ntohs(tvb, 12);

  tap_queue_packet(eth_tap, pinfo, ehdr);

  /*
   * In case the packet is a non-Ethernet packet inside
   * Ethernet framing, allow heuristic dissectors to take
   * a first look before we assume that it's actually an
   * Ethernet packet.
   */
  if (dissector_try_heuristic(heur_subdissector_list, tvb, pinfo, parent_tree, NULL))
    return;

  if (ehdr->type <= IEEE_802_3_MAX_LEN) {
    /* Oh, yuck.  Cisco ISL frames require special interpretation of the
       destination address field; fortunately, they can be recognized by
       checking the first 5 octets of the destination address, which are
       01-00-0C-00-00 for ISL frames. */
    if ((tvb_get_guint8(tvb, 0) == 0x01 ||
      tvb_get_guint8(tvb, 0) == 0x0C) &&
      tvb_get_guint8(tvb, 1) == 0x00 &&
      tvb_get_guint8(tvb, 2) == 0x0C &&
      tvb_get_guint8(tvb, 3) == 0x00 &&
      tvb_get_guint8(tvb, 4) == 0x00) {
      dissect_isl(tvb, pinfo, parent_tree, fcs_len);
      return;
    }
  }

  /*
   * If the type/length field is <= the maximum 802.3 length,
   * and is not zero, this is an 802.3 frame, and it's a length
   * field; it might be an Novell "raw 802.3" frame, with no
   * 802.2 LLC header, or it might be a frame with an 802.2 LLC
   * header.
   *
   * If the type/length field is >= the minimum Ethernet II length,
   * this is an Ethernet II frame, and it's a type field.
   *
   * If the type/length field is > maximum 802.3 length and < minimum
   * Ethernet II length, then this is an invalid packet.
   *
   * If the type/length field is zero (ETHERTYPE_UNK), this is
   * a frame used internally by the Cisco MDS switch to contain
   * Fibre Channel ("Vegas").  We treat that as an Ethernet II
   * frame; the dissector for those frames registers itself with
   * an ethernet type of ETHERTYPE_UNK.
   */
  if (ehdr->type > IEEE_802_3_MAX_LEN && ehdr->type < ETHERNET_II_MIN_LEN) {
    tvbuff_t *next_tvb;

    col_add_fstr(pinfo->cinfo, COL_INFO,
        "Ethernet Unknown: Invalid length/type: 0x%04x (%d)",
        ehdr->type, ehdr->type);
    ti = proto_tree_add_protocol_format(tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
        "Ethernet Unknown, Src: %s (%s), Dst: %s (%s)",
        get_ether_name(src_addr), ether_to_str(src_addr),
        get_ether_name(dst_addr), ether_to_str(dst_addr));
    fh_tree = proto_item_add_subtree(ti, ett_ether);
    addr_item = proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr);
    if (addr_item)
        addr_tree = proto_item_add_subtree(addr_item, ett_addr);
    proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 0, 6, dst_addr);
    proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 0, 3, ENC_BIG_ENDIAN);
    proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 0, 3, ENC_BIG_ENDIAN);

    addr_item = proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr);
    if (addr_item)
        addr_tree = proto_item_add_subtree(addr_item, ett_addr);
    proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 6, 6, src_addr);
    proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 6, 3, ENC_BIG_ENDIAN);
    proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 6, 3, ENC_BIG_ENDIAN);

    ti = proto_tree_add_item(fh_tree, hf_eth_invalid_lentype, tvb, 12, 2, ENC_BIG_ENDIAN);
    expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN,
        "Invalid length/type: 0x%04x (%d)", ehdr->type, ehdr->type);
    next_tvb = tvb_new_subset_remaining(tvb, 14);
    call_dissector(data_handle, next_tvb, pinfo, parent_tree);
    return;
  }

  if (ehdr->type <= IEEE_802_3_MAX_LEN && ehdr->type != ETHERTYPE_UNK) {

    is_802_2 = check_is_802_2(tvb, fcs_len);

     col_add_fstr(pinfo->cinfo, COL_INFO, "IEEE 802.3 Ethernet %s",
        (is_802_2 ? "" : "Raw "));
    if (tree) {
      ti = proto_tree_add_protocol_format(tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
        "IEEE 802.3 Ethernet %s", (is_802_2 ? "" : "Raw "));

      fh_tree = proto_item_add_subtree(ti, ett_ieee8023);
    }

    /* if IP is not referenced from any filters we dont need to worry about
       generating any tree items.  We must do this after we created the actual
       protocol above so that proto hier stat still works though.
    */
    if(!proto_field_is_referenced(parent_tree, proto_eth)){
      tree=NULL;
      fh_tree=NULL;
    }

    addr_item=proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr);
    if(addr_item){
        addr_tree = proto_item_add_subtree(addr_item, ett_addr);
    }
    proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 0, 6, dst_addr);
    proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 0, 3, ENC_BIG_ENDIAN);
    proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 0, 3, ENC_BIG_ENDIAN);

    addr_item=proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr);
    if(addr_item){
        addr_tree = proto_item_add_subtree(addr_item, ett_addr);
    }
    proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 6, 6, src_addr);
    proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 6, 3, ENC_BIG_ENDIAN);
    proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 6, 3, ENC_BIG_ENDIAN);

    dissect_802_3(ehdr->type, is_802_2, tvb, ETH_HEADER_SIZE, pinfo,
        parent_tree, fh_tree, hf_eth_len, hf_eth_trailer, fcs_len);
  } else {
    if (eth_interpret_as_fw1_monitor) {
        if ((dst_addr[0] == 'i') || (dst_addr[0] == 'I') ||
            (dst_addr[0] == 'o') || (dst_addr[0] == 'O')) {
            call_dissector(fw1_handle, tvb, pinfo, parent_tree);
            return;
        }
    }

    col_set_str(pinfo->cinfo, COL_INFO, "Ethernet II");
    if (parent_tree) {
        if (PTREE_DATA(parent_tree)->visible) {
            ti = proto_tree_add_protocol_format(parent_tree, proto_eth, tvb, 0, ETH_HEADER_SIZE,
                "Ethernet II, Src: %s (%s), Dst: %s (%s)",
                get_ether_name(src_addr), ether_to_str(src_addr),
                get_ether_name(dst_addr), ether_to_str(dst_addr));
      }
      else {
            ti = proto_tree_add_item(parent_tree, proto_eth, tvb, 0, ETH_HEADER_SIZE, ENC_NA);
      }
      fh_tree = proto_item_add_subtree(ti, ett_ether2);
    }

    addr_item=proto_tree_add_ether(fh_tree, hf_eth_dst, tvb, 0, 6, dst_addr);
    if(addr_item){
        addr_tree = proto_item_add_subtree(addr_item, ett_addr);
    }
    proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 0, 6, dst_addr);
    proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 0, 3, ENC_BIG_ENDIAN);
    proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 0, 3, ENC_BIG_ENDIAN);

    addr_item=proto_tree_add_ether(fh_tree, hf_eth_src, tvb, 6, 6, src_addr);
    if(addr_item){
        addr_tree = proto_item_add_subtree(addr_item, ett_addr);
        if (tvb_get_guint8(tvb, 6) & 0x01) {
            expert_add_info_format(pinfo, addr_item, PI_PROTOCOL, PI_WARN,
                "Source MAC must not be a group address: IEEE 802.3-2002, Section 3.2.3(b)");
        }
    }
    proto_tree_add_ether(addr_tree, hf_eth_addr, tvb, 6, 6, src_addr);
    proto_tree_add_item(addr_tree, hf_eth_lg, tvb, 6, 3, ENC_BIG_ENDIAN);
    proto_tree_add_item(addr_tree, hf_eth_ig, tvb, 6, 3, ENC_BIG_ENDIAN);

    ethertype(ehdr->type, tvb, ETH_HEADER_SIZE, pinfo, parent_tree, fh_tree, hf_eth_type,
          hf_eth_trailer, fcs_len);
  }
}
Пример #4
0
static void
dissect_edsa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint8 edsa_tag;
	guint8 edsa_tagged;
	guint8 edsa_dev;
	guint8 edsa_port;
	guint8 edsa_trunk;
	guint8 edsa_cfi;
	guint8 edsa_prio;
	guint8 edsa_vid;
	guint8 edsa_code;
	guint16 edsa_ethtype;
	gboolean is_802_2;

	proto_tree  *edsa_tree = NULL;
	proto_item  *ti;

	edsa_tag 	= tvb_get_bits8(tvb, (8 * 2) + 0 , 2);
	edsa_tagged 	= tvb_get_bits8(tvb, (8 * 2) + 2, 1);
	edsa_dev 	= tvb_get_bits8(tvb, (8 * 2) + 3, 5);
	edsa_port 	= tvb_get_bits8(tvb, (8 * 3) + 0, 5);
	edsa_trunk 	= tvb_get_bits8(tvb, (8 * 3) + 5, 1);
	edsa_cfi 	= tvb_get_bits8(tvb, (8 * 3) + 7, 0);
	edsa_prio	= tvb_get_bits8(tvb, (8 * 4) + 0, 3);
	edsa_vid 	= tvb_get_bits16(tvb, (8 * 4) + 4, 12, TRUE);

	edsa_code	= (tvb_get_bits8(tvb, (8 * 3) + 5, 2) << 2 |
			   tvb_get_bits8(tvb, (8 * 4) + 3, 1));
	edsa_ethtype	= tvb_get_ntohs(tvb, 6);

	if (tree) {
		ti = proto_tree_add_protocol_format(
			tree, proto_edsa, tvb, 0, EDSA_HEADER_SIZE,
			"EtherType Distributed Switch Architecture, %s Dev: %d Port: %d VID: %d",
			val_to_str(edsa_tag, tag_vals, "tag %d"),
			edsa_dev, edsa_port, edsa_vid);
		edsa_tree = proto_item_add_subtree(ti, ett_edsa);
		proto_tree_add_uint(edsa_tree, hf_edsa_tag,
				    tvb, 2, 1, edsa_tag);
		switch (edsa_tag) {
		case TAG_TO_CPU:
			proto_tree_add_boolean(
				edsa_tree, hf_edsa_tagged, tvb, 2, 1,
				edsa_tagged);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_dev, tvb, 2, 1, edsa_dev);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_port, tvb, 3, 1, edsa_port);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_vid, tvb, 4, 2, edsa_vid);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_code, tvb, 3, 2, edsa_code);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_prio, tvb, 4, 1, edsa_prio);
			proto_tree_add_boolean(
				edsa_tree, hf_edsa_cfi, tvb, 3, 1, edsa_cfi);
			break;
		case TAG_FROM_CPU:
			proto_tree_add_boolean(
				edsa_tree, hf_edsa_tagged, tvb, 2, 1,
				edsa_tagged);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_dev, tvb, 2, 1, edsa_dev);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_port, tvb, 3, 1, edsa_port);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_vid, tvb, 4, 2, edsa_vid);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_prio, tvb, 4, 1, edsa_prio);
			proto_tree_add_boolean(
				edsa_tree, hf_edsa_cfi, tvb, 3, 1, edsa_cfi);
			break;
		case TAG_FORWARD:
			proto_tree_add_boolean(
				edsa_tree, hf_edsa_tagged, tvb, 2, 1,
				edsa_tagged);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_dev, tvb, 2, 1, edsa_dev);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_port, tvb, 3, 1, edsa_port);
			proto_tree_add_boolean(
				edsa_tree, hf_edsa_trunk, tvb, 3, 1,
				edsa_trunk);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_vid, tvb, 4, 2, edsa_vid);
			proto_tree_add_uint(
				edsa_tree, hf_edsa_prio, tvb, 4, 1, edsa_prio);
			proto_tree_add_boolean(
				edsa_tree, hf_edsa_cfi, tvb, 3, 1, edsa_cfi);
			break;
		}
	}
	if (edsa_ethtype <= IEEE_802_3_MAX_LEN) {
		/* Is there an 802.2 layer? I can tell by looking at
		   the first 2 bytes after the VLAN header. If they
		   are 0xffff, then what follows the VLAN header is an
		   IPX payload, meaning no 802.2.  (IPX/SPX is they
		   only thing that can be contained inside a straight
		   802.3 packet, so presumably the same applies for
		   Ethernet VLAN packets). A non-0xffff value means
		   that there's an 802.2 layer inside the VLAN
		   layer */
		is_802_2 = TRUE;

		/* Don't throw an exception for this check (even a
		 * BoundsError) */
		if (tvb_captured_length_remaining(tvb, 8) >= 2) {
			if (tvb_get_ntohs(tvb, 8) == 0xffff) {
				is_802_2 = FALSE;
			}
			dissect_802_3(edsa_ethtype, is_802_2, tvb, 8, pinfo,
				      tree, edsa_tree, hf_edsa_len,
				      hf_edsa_trailer, &ei_edsa_len, 0);
		}
	} else {
		ethertype_data_t ethertype_data;

		ethertype_data.etype = edsa_ethtype;
		ethertype_data.offset_after_ethertype = 8;
		ethertype_data.fh_tree = edsa_tree;
		ethertype_data.etype_id = hf_edsa_ethtype;
		ethertype_data.trailer_id = hf_edsa_trailer;
		ethertype_data.fcs_len = 0;

		call_dissector_with_data(ethertype_handle, tvb, pinfo, tree,
					 &ethertype_data);
  }
}