#include "netdissect-stdinc.h"
+#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "ethertype.h"
#include "addrtoname.h"
#include "extract.h"
-struct ether_header {
- nd_mac_addr ether_dhost;
- nd_mac_addr ether_shost;
- nd_uint16_t ether_length_type;
-};
-
-#define ETHER_SA_OFFSET 12
#define ETHER_TYPE_LEN 2
#define BRCM_TAG_LEN 4
{ 1, "Untag" },
{ 2, "Header"},
{ 3, "Reserved" },
+ { 0, NULL }
};
static const struct tok brcm_tag_rc_values[] = {
{ 8, "prot term" },
{ 16, "prot snoop" },
{ 32, "exception" },
+ { 0, NULL }
};
-static int brcm_tag_print_full(netdissect_options *ndo, const u_char *bp,
- u_int length)
+static void
+brcm_tag_print(netdissect_options *ndo, const u_char *bp)
{
uint8_t tag[BRCM_TAG_LEN];
uint16_t dst_map;
unsigned int i;
- if (length < BRCM_TAG_LEN)
- return (1);
-
for (i = 0; i < BRCM_TAG_LEN; i++)
- tag[i] = EXTRACT_U_1(bp + i);
+ tag[i] = GET_U_1(bp + i);
ND_PRINT("BRCM tag OP: %s", tag[0] ? "IG" : "EG");
if (tag[0] & (1 << BRCM_OPCODE_SHIFT)) {
/* Ingress Broadcom tag */
ND_PRINT(", TC: %d", (tag[1] >> BRCM_IG_TC_SHIFT) &
- BRCM_IG_TC_MASK);
+ BRCM_IG_TC_MASK);
ND_PRINT(", TE: %s",
tok2str(brcm_tag_te_values, "unknown",
(tag[1] & BRCM_IG_TE_MASK)));
/* Egress Broadcom tag */
ND_PRINT(", CID: %d", tag[1]);
ND_PRINT(", RC: %s", tok2str(brcm_tag_rc_values,
- "reserved", tag[2]));
+ "reserved", tag[2]));
ND_PRINT(", TC: %d", (tag[3] >> BRCM_EG_TC_SHIFT) &
- BRCM_EG_TC_MASK);
+ BRCM_EG_TC_MASK);
ND_PRINT(", port: %d", tag[3] & BRCM_EG_PID_MASK);
}
ND_PRINT(", ");
-
- return (0);
}
-u_int
+void
brcm_tag_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *p)
{
- const struct ether_header *ehp;
- int old_eflag = ndo->ndo_eflag;
u_int caplen = h->caplen;
u_int length = h->len;
- int ret;
ndo->ndo_protocol = "brcm-tag";
- if (caplen < ETHER_SA_OFFSET + BRCM_TAG_LEN) {
- nd_print_trunc(ndo);
- return (caplen);
- }
-
- if (length < ETHER_SA_OFFSET + BRCM_TAG_LEN) {
- nd_print_trunc(ndo);
- return (length);
- }
-
- ehp = (const struct ether_header *)p;
- if (ndo->ndo_eflag)
- ND_PRINT("%s > %s, ",
- etheraddr_string(ndo, ehp->ether_shost),
- etheraddr_string(ndo, ehp->ether_dhost));
-
- if (brcm_tag_print_full(ndo, p + ETHER_SA_OFFSET,
- caplen - ETHER_SA_OFFSET))
- return (1);
-
- /* We printed the Ethernet header already */
- ndo->ndo_eflag = 0;
-
- /* Parse the Ethernet frame regularly telling how big the non
- * standard Ethernet header is.
- *
- * +-----------++-----------++----------------++--------------+
- * | MAC DA (6)|| MAC SA (6)||Broadcom tag (4)||Type/Length(2)|
- * +-----------++-----------++----------------++--------------+
- */
- ret = ether_print_hdr_len(ndo, p, length, caplen, NULL, NULL,
- ETHER_SA_OFFSET + BRCM_TAG_LEN + 2);
- ndo->ndo_eflag = old_eflag;
- return ret;
-}
-
-static void brcm_tag_print_encap(netdissect_options *ndo,
- const u_char *p)
-{
- brcm_tag_print_full(ndo, p, BRCM_TAG_LEN);
+ ndo->ndo_ll_hdr_len +=
+ ether_switch_tag_print(ndo, p, length, caplen,
+ brcm_tag_print, BRCM_TAG_LEN);
}
-u_int
+void
brcm_tag_prepend_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *p)
{
u_int length = h->len;
ndo->ndo_protocol = "brcm-tag-prepend";
- if (caplen < BRCM_TAG_LEN) {
- nd_print_trunc(ndo);
- return (caplen);
- }
+ ND_TCHECK_LEN(p, BRCM_TAG_LEN);
+ ndo->ndo_ll_hdr_len += BRCM_TAG_LEN;
- if (length < BRCM_TAG_LEN) {
- nd_print_trunc(ndo);
- return (length);
+ if (ndo->ndo_eflag) {
+ /* Print the prepended Broadcom tag. */
+ brcm_tag_print(ndo, p);
}
+ p += BRCM_TAG_LEN;
+ length -= BRCM_TAG_LEN;
+ caplen -= BRCM_TAG_LEN;
- /* Parse the Ethernet frame regularly and utilize the encapsulation
- * header printing facility to pring the pre-pended Broadcom tag.
- *
- * +-----------------++-----------++-----------++--------------+
- * | Broadcom tag (4)|| MAC DA (6)|| MAC SA (6)||Type/Length(2)|
- * +-----------------++-----------++-----------++--------------+
+ /*
+ * Now print the Ethernet frame following it.
*/
- return ether_print(ndo, p + BRCM_TAG_LEN,
- length - BRCM_TAG_LEN,
- caplen - BRCM_TAG_LEN, brcm_tag_print_encap, p);
+ ndo->ndo_ll_hdr_len +=
+ ether_print(ndo, p, length, caplen, NULL, NULL);
}