diff options
Diffstat (limited to 'print-bcm-li.c')
-rw-r--r-- | print-bcm-li.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/print-bcm-li.c b/print-bcm-li.c new file mode 100644 index 0000000..12b1ebb --- /dev/null +++ b/print-bcm-li.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* \summary: Broadcom LI Printer */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "netdissect-stdinc.h" + +#define ND_LONGJMP_FROM_TCHECK +#include "netdissect.h" +#include "addrtoname.h" +#include "extract.h" + +#define BCM_LI_SHIM_LEN 4 + +static const struct tok bcm_li_direction_values[] = { + { 1, "unused" }, + { 2, "egress" }, + { 3, "ingress" }, + { 0, NULL} +}; + +#define BCM_LI_PKT_TYPE_UNDECIDED 4 +#define BCM_LI_PKT_TYPE_IPV4 5 +#define BCM_LI_PKT_TYPE_IPV6 6 +#define BCM_LI_PKT_TYPE_ETHERNET 7 + +static const struct tok bcm_li_pkt_type_values[] = { + { BCM_LI_PKT_TYPE_UNDECIDED, "undecided" }, + { BCM_LI_PKT_TYPE_IPV4, "ipv4" }, + { BCM_LI_PKT_TYPE_IPV6, "ipv6" }, + { BCM_LI_PKT_TYPE_ETHERNET, "ethernet" }, + { 0, NULL} +}; + +static const struct tok bcm_li_pkt_subtype_values[] = { + { 1, "single VLAN tag" }, + { 2, "double VLAN tag" }, + { 3, "untagged" }, + { 0, NULL} +}; + +void +bcm_li_print(netdissect_options *ndo, + const u_char *bp, u_int length) +{ + u_int shim, direction, pkt_type, pkt_subtype, li_id; + + ndo->ndo_protocol = "bcm_li"; + if (length < BCM_LI_SHIM_LEN) { + ND_PRINT(" (length %u < %u)", length, BCM_LI_SHIM_LEN); + goto invalid; + } + shim = GET_BE_U_4(bp); + + direction = (shim >> 29) & 0x7; + pkt_type = (shim >> 25) & 0xf; + pkt_subtype = (shim >> 22) & 0x7; + li_id = shim & 0x3fffff; + + length -= BCM_LI_SHIM_LEN; + bp += BCM_LI_SHIM_LEN; + + ND_PRINT("%sBCM-LI-SHIM: direction %s, pkt-type %s, pkt-subtype %s, li-id %u%s", + ndo->ndo_vflag ? "\n " : "", + tok2str(bcm_li_direction_values, "unknown", direction), + tok2str(bcm_li_pkt_type_values, "unknown", pkt_type), + tok2str(bcm_li_pkt_subtype_values, "unknown", pkt_subtype), + li_id, + ndo->ndo_vflag ? "\n ": ""); + + if (!ndo->ndo_vflag) { + ND_TCHECK_LEN(bp, length); + return; + } + + switch (pkt_type) { + case BCM_LI_PKT_TYPE_ETHERNET: + ether_print(ndo, bp, length, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL); + break; + case BCM_LI_PKT_TYPE_IPV4: + ip_print(ndo, bp, length); + break; + case BCM_LI_PKT_TYPE_IPV6: + ip6_print(ndo, bp, length); + break; + case BCM_LI_PKT_TYPE_UNDECIDED: + + /* + * Guess IP version from first nibble. + */ + if ((GET_U_1(bp) >> 4) == 4) { + ip_print(ndo, bp, length); + } else if ((GET_U_1(bp) >> 4) == 6) { + ip6_print(ndo, bp, length); + } else { + ND_PRINT("unknown payload"); + } + break; + + default: + goto invalid; + } + + return; +invalid: + nd_print_invalid(ndo); +} + |