From 7d298976beff0cce310fb53a430f82b53f43a394 Mon Sep 17 00:00:00 2001
From: Guy Harris <gharris@sonic.net>
Date: Fri, 14 Feb 2025 19:12:24 -0800
Subject: [PATCH 2/2] Linux: handle other DSA tags.

Many of those entries need their own LINKTYPE_/DLT_? values, including
tcpdump and Wireshark support for same, but at least this lets you see
raw hex data from a capture.

Fixes #1367.

Supercedes #1451.
---
 pcap-linux.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 280 insertions(+), 4 deletions(-)

--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -5267,23 +5267,299 @@ iface_get_offload(pcap_t *handle _U_)
 }
 #endif /* SIOCETHTOOL */
 
+/*
+ * As per
+ *
+ *    https://www.kernel.org/doc/html/latest/networking/dsa/dsa.html#switch-tagging-protocols
+ *
+ * Type 1 means that the tag is prepended to the Ethernet packet.
+ * LINKTYPE_ETHERNET/DLT_EN10MB doesn't work, as it would try to
+ * dissect the tag data as the Ethernet header.  These should get
+ * their own LINKTYPE_DLT_ values.
+ *
+ * Type 2 means that the tag is inserted into the Ethernet header
+ * after the source address and before the type/length field.
+ *
+ * Type 3 means that tag is a packet trailer.  LINKTYPE_ETHERNET/DLT_EN10MB
+ * works,  unless the next-layer protocol has no length field of its own,
+ * so that the tag might be treated as part of the payload. These should
+ * get their own LINKTYPE_/DLT_ values.
+ *
+ * If you get an "unsupported DSA tag" error, please add the tag to here,
+ * complete with a full comment indicating whether it's type 1, 2, or 3,
+ * and, for type 2, indicating whether it has an Ethertype and, if so
+ * what that type is, and whether it's registered with the IEEE or is
+ * self-assigned. Also, point to *something* that indicates the format
+ * of the tag.
+ */
 static struct dsa_proto {
 	const char *name;
 	bpf_u_int32 linktype;
 } dsa_protos[] = {
 	/*
-	 * None is special and indicates that the interface does not have
-	 * any tagging protocol configured, and is therefore a standard
-	 * Ethernet interface.
+	 * Type 1. See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ar9331.c
+	 */
+	{ "ar9331", DLT_EN10MB },
+
+	/*
+	 * Type 2, without an Ethertype at the beginning,
+	 * assigned a LINKTYPE_/DLT_ value.
 	 */
-	{ "none", DLT_EN10MB },
 	{ "brcm", DLT_DSA_TAG_BRCM },
+
+	/*
+	 * Type 2, with Ethertype 0x8874, assigned to Broadcom.
+	 *
+	 * This doies not require a LINKTYPE_/DLT_ value, it
+	 * just requires that Ethertype 0x8874 be dissected
+	 * properly.
+	 */
+	{ "brcm-legacy", DLT_EN10MB },
+
+	/*
+	 * Type 1.
+	 */
 	{ "brcm-prepend", DLT_DSA_TAG_BRCM_PREPEND },
+
+	/*
+	 * Type 2, without an Etherype at he beginning,
+	 * assigned a LINKTYPE_/DLT_ value.
+	 */
 	{ "dsa", DLT_DSA_TAG_DSA },
+
+	/*
+	 * Type 2, with an Ethertype field, but without
+	 * an assigned Ethertype value that can be relied
+	 * on; assigned a LINKTYPE_/DLT_ value.
+	 */
 	{ "edsa", DLT_DSA_TAG_EDSA },
+
+	/*
+	 * Type 1, with different transmit and receive headers,
+	 * so can't really be handled well with the current
+	 * libpcap API and with pcap files.  Use DLT_LINUX_SLL,
+	 * to get the direction?
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_gswip.c
+	 */
+	{ "gswip", DLT_EN10MB },
+
+	/*
+	 * Type 3. See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_hellcreek.c
+	 */
+	{ "hellcreek", DLT_EN10MB },
+
+	/*
+	 * Type 3, with different transmit and receive headers,
+	 * so can't really be handled well with the current
+	 * libpcap API and with pcap files.  Use DLT_LINUX_SLL,
+	 * to get the direction?
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ksz.c#L102
+	 */
+	{ "ksz8795", DLT_EN10MB },
+
+	/*
+	 * Type 3, with different transmit and receive headers,
+	 * so can't really be handled well with the current
+	 * libpcap API and with pcap files.  Use DLT_LINUX_SLL,
+	 * to get the direction?
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ksz.c#L160
+	 */
+	{ "ksz9477", DLT_EN10MB },
+
+	/*
+	 * Type 3, with different transmit and receive headers,
+	 * so can't really be handled well with the current
+	 * libpcap API and with pcap files.  Use DLT_LINUX_SLL,
+	 * to get the direction?
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ksz.c#L341
+	 */
+	{ "ksz9893", DLT_EN10MB },
+
+	/*
+	 * Type 3, with different transmit and receive headers,
+	 * so can't really be handled well with the current
+	 * libpcap API and with pcap files.  Use DLT_LINUX_SLL,
+	 * to get the direction?
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ksz.c#L386
+	 */
+	{ "lan937x", DLT_EN10MB },
+
+	/*
+	 * Type 2, with Ethertype 0x8100; the VID can be interpreted
+	 * as per
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_lan9303.c#L24
+	 *
+	 * so giving its own LINKTYPE_/DLT_ value would allow a
+	 * dissector to do so.
+	 */
+	{ "lan9303", DLT_EN10MB },
+
+	/*
+	 * Type 2, without an Etherype at he beginning,
+	 * should be assigned a LINKTYPE_/DLT_ value.
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_mtk.c#L15
+	 */
+	{ "mtk", DLT_EN10MB },
+
+	/*
+	 * None is special and indicates that the interface does not have
+	 * any tagging protocol configured, and is therefore a standard
+	 * Ethernet interface.
+	 */
+	{ "none", DLT_EN10MB },
+
+	/*
+	 * Type 1.
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ocelot.c
+	 */
+	{ "ocelot", DLT_EN10MB },
+
+	/*
+	 * Type 1.
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_ocelot.c
+	 */
+	{ "seville", DLT_EN10MB },
+
+	/*
+	 * Type 2, with Ethertype 0x8100; the VID can be interpreted
+	 * as per
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_8021q.c#L15
+	 *
+	 * so giving its own LINKTYPE_/DLT_ value would allow a
+	 * dissector to do so.
+	 */
+	{ "ocelot-8021q", DLT_EN10MB },
+
+	/*
+	 * Type 2, without an Etherype at he beginning,
+	 * should be assigned a LINKTYPE_/DLT_ value.
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_qca.c
+	 */
+	{ "qca", DLT_EN10MB },
+
+	/*
+	 * Type 2, with Ethertype 0x8899, assigned to Realtek;
+	 * they use it for several on-the-Ethernet protocols
+	 * as well, but there are fields that allow the two
+	 * tag formats, and all the protocols in question,
+	 * to be distinguiished from one another.
+	 *
+	 * This doies not require a LINKTYPE_/DLT_ value, it
+	 * just requires that Ethertype 0x8899 be dissected
+	 * properly.
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_rtl4_a.c
+	 *
+	 *    http://realtek.info/pdf/rtl8306sd%28m%29_datasheet_1.1.pdf
+	 *
+	 * and various pages in tcpdump's print-realtek.c and Wireshark's
+	 * epan/dissectors/packet-realtek.c for the other protocols.
+	 */
 	{ "rtl4a", DLT_EN10MB },
+
+	/*
+	 * Type 2, with Ethertype 0x8899, assigned to Realtek;
+	 * see above.
+	 */
 	{ "rtl8_4", DLT_EN10MB },
+
+	/*
+	 * Type 3, with the same tag format as rtl8_4.
+	 */
 	{ "rtl8_4t", DLT_EN10MB },
+
+	/*
+	 * Type 2, with Ethertype 0xe001; that's probably
+	 * self-assigned, so this really should ahve its
+	 * own LINKTYPE_/DLT_ value.
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_rzn1_a5psw.c
+	 */
+	{ "a5psw", DLT_EN10MB },
+
+	/*
+	 * Type 2, with Ethertype 0x8100 or the self-assigned
+	 * 0xdadb, so this really should ahve its own
+	 * LINKTYPE_/DLT_ value; that would also allow the
+	 * VID of the tag to be dissected as per
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_8021q.c#L15
+	 */
+	{ "sja1105", DLT_EN10MB },
+
+	/*
+	 * Type "none of the above", with both a header and trailer,
+	 * with different transmit and receive tags.  Has
+	 * Ethertype 0xdadc, which is probably self-assigned.
+	 * This should really have its own LINKTYPE_/DLT_ value.
+	 */
+	{ "sja1110", DLT_EN10MB },
+
+	/*
+	 * Type 3, as the name suggests.
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_trailer.c
+	 */
+	{ "trailer", DLT_EN10MB },
+
+	/*
+	 * Type 2, with Ethertype 0x8100; the VID can be interpreted
+	 * as per
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_8021q.c#L15
+	 *
+	 * so giving its own LINKTYPE_/DLT_ value would allow a
+	 * dissector to do so.
+	 */
+	{ "vsc73xx-8021q", DLT_EN10MB },
+
+	/*
+	 * Type 3.
+	 *
+	 * See
+	 *
+	 *    https://elixir.bootlin.com/linux/v6.13.2/source/net/dsa/tag_xrs700x.c
+	 */
+	{ "xrs700x", DLT_EN10MB },
 };
 
 static int
