X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/8b1d184e10263b5889ffcfbc4887ca82d7ca07df..3d1bade63b45bc1a0fc0ea49949e0d165b2383b0:/print-ether.c diff --git a/print-ether.c b/print-ether.c index aed2bea8..ba488343 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,8 @@ 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 = EXTRACT_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 +140,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,45 +149,52 @@ 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) + void (*print_encap_header)(netdissect_options *ndo, const u_char *), + 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) { - ND_PRINT("[|ether]"); + /* 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) { - ND_PRINT("[|ether]"); + 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 = EXTRACT_BE_U_2((const u_char *)ehp + + (hdrlen - sizeof(ehp->ether_length_type))); recurse: /* @@ -209,11 +219,13 @@ recurse: * the enclosed type field. */ if (caplen < 4) { - ND_PRINT("[|vlan]"); + ndo->ndo_protocol = "vlan"; + nd_print_trunc(ndo); return (hdrlen + caplen); } if (length < 4) { - ND_PRINT("[|vlan]"); + ndo->ndo_protocol = "vlan"; + nd_print_trunc(ndo); return (hdrlen + length); } if (ndo->ndo_eflag) { @@ -255,7 +267,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) @@ -265,6 +278,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 @@ -296,8 +328,8 @@ netanalyzer_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, * Fail if we don't have enough data for the Hilscher pseudo-header. */ ndo->ndo_protocol = "netanalyzer_if"; - if (h->len < 4 || h->caplen < 4) { - ND_PRINT("[|netanalyzer]"); + if (h->caplen < 4) { + nd_print_trunc(ndo); return (h->caplen); } @@ -325,8 +357,8 @@ netanalyzer_transparent_if_print(netdissect_options *ndo, * preamble, and SOF. */ ndo->ndo_protocol = "netanalyzer_transparent_if"; - if (h->len < 12 || h->caplen < 12) { - ND_PRINT("[|netanalyzer-transparent]"); + if (h->caplen < 12) { + nd_print_trunc(ndo); return (h->caplen); } @@ -383,7 +415,8 @@ ethertype_print(netdissect_options *ndo, case ETHERTYPE_ISO: if (length == 0 || caplen == 0) { - ND_PRINT(" [|osi]"); + ndo->ndo_protocol = "isoclns"; + nd_print_trunc(ndo); return (1); } isoclns_print(ndo, p + 1, length - 1);