| /* | 
 |  * 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); | 
 | } | 
 |  |