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, ðertype_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); }
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); } }
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, ðertype_data); } }