X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/01017da63c1c0d4b241ea29a43e5d5bd1a3a53dd..371e1fca312ecc698f01dfa16f81c48cb48f7c55:/print-ether.c diff --git a/print-ether.c b/print-ether.c index d6dd9572..8e07bb32 100644 --- a/print-ether.c +++ b/print-ether.c @@ -106,7 +106,8 @@ const struct tok ethertype_values[] = { static void ether_hdr_print(netdissect_options *ndo, - const u_char *bp, u_int length) + const u_char *bp, u_int length, + u_int hdrlen) { const struct ether_header *ehp; uint16_t length_type; @@ -117,7 +118,7 @@ ether_hdr_print(netdissect_options *ndo, etheraddr_string(ndo, ehp->ether_shost), etheraddr_string(ndo, ehp->ether_dhost)); - length_type = EXTRACT_BE_U_2(ehp->ether_length_type); + length_type = GET_BE_U_2(bp + (hdrlen - sizeof(ehp->ether_length_type))); if (!ndo->ndo_qflag) { if (length_type <= MAX_ETHERNET_LENGTH_VAL) { ND_PRINT(", 802.3"); @@ -138,7 +139,8 @@ ether_hdr_print(netdissect_options *ndo, } /* - * Print an Ethernet frame. + * Print an Ethernet frame while specyfing a non-standard Ethernet header + * length. * This might be encapsulated within another frame; we might be passed * a pointer to a function that can print header information for that * frame's protocol, and an argument to pass to that function. @@ -146,46 +148,51 @@ ether_hdr_print(netdissect_options *ndo, * FIXME: caplen can and should be derived from ndo->ndo_snapend and p. */ u_int -ether_print(netdissect_options *ndo, +ether_print_hdr_len(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen, void (*print_encap_header)(netdissect_options *ndo, const u_char *), - const u_char *encap_header_arg) + const u_char *encap_header_arg, u_int hdrlen) { const struct ether_header *ehp; u_int orig_length; u_short length_type; - u_int hdrlen; int llc_hdrlen; struct lladdr_info src, dst; - ndo->ndo_protocol = "ether"; - if (caplen < ETHER_HDRLEN) { + /* Unless specified otherwise, assume a standard Ethernet header */ + if (hdrlen == ETHER_HDRLEN) + ndo->ndo_protocol = "ether"; + + if (caplen < hdrlen) { nd_print_trunc(ndo); return (caplen); } - if (length < ETHER_HDRLEN) { + if (length < hdrlen) { nd_print_trunc(ndo); return (length); } + /* If the offset is set, then the upper printer is responsible for + * printing the relevant part of the Ethernet header. + */ if (ndo->ndo_eflag) { if (print_encap_header != NULL) (*print_encap_header)(ndo, encap_header_arg); - ether_hdr_print(ndo, p, length); + ether_hdr_print(ndo, p, length, hdrlen); } + orig_length = length; - length -= ETHER_HDRLEN; - caplen -= ETHER_HDRLEN; + length -= hdrlen; + caplen -= hdrlen; ehp = (const struct ether_header *)p; - p += ETHER_HDRLEN; - hdrlen = ETHER_HDRLEN; + p += hdrlen; src.addr = ehp->ether_shost; src.addr_string = etheraddr_string; dst.addr = ehp->ether_dhost; dst.addr_string = etheraddr_string; - length_type = EXTRACT_BE_U_2(ehp->ether_length_type); + length_type = GET_BE_U_2((const u_char *)ehp + (hdrlen - sizeof(ehp->ether_length_type))); recurse: /* @@ -220,12 +227,12 @@ recurse: return (hdrlen + length); } if (ndo->ndo_eflag) { - uint16_t tag = EXTRACT_BE_U_2(p); + uint16_t tag = GET_BE_U_2(p); ND_PRINT("%s, ", ieee8021q_tci_string(tag)); } - length_type = EXTRACT_BE_U_2(p + 2); + length_type = GET_BE_U_2(p + 2); if (ndo->ndo_eflag && length_type > MAX_ETHERNET_LENGTH_VAL) ND_PRINT("ethertype %s, ", tok2str(ethertype_values,"0x%04x", length_type)); p += 4; @@ -258,7 +265,8 @@ recurse: if (!ndo->ndo_eflag) { if (print_encap_header != NULL) (*print_encap_header)(ndo, encap_header_arg); - ether_hdr_print(ndo, (const u_char *)ehp, orig_length); + ether_hdr_print(ndo, (const u_char *)ehp, orig_length, + hdrlen); } if (!ndo->ndo_suppress_default_print) @@ -268,6 +276,25 @@ recurse: return (hdrlen); } +/* + * Print an Ethernet frame. + * This might be encapsulated within another frame; we might be passed + * a pointer to a function that can print header information for that + * frame's protocol, and an argument to pass to that function. + * + * FIXME: caplen can and should be derived from ndo->ndo_snapend and p. + */ +u_int +ether_print(netdissect_options *ndo, + const u_char *p, u_int length, u_int caplen, + void (*print_encap_header)(netdissect_options *ndo, const u_char *), + const u_char *encap_header_arg) +{ + return (ether_print_hdr_len(ndo, p, length, caplen, + print_encap_header, encap_header_arg, + ETHER_HDRLEN)); +} + /* * This is the top level routine of the printer. 'p' points * to the ether header of the packet, 'h->len' is the length