/* \summary: Ethernet printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
+#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "extract.h"
#include "addrtoname.h"
* Structure of an Ethernet header.
*/
struct ether_header {
- nd_mac_addr ether_dhost;
- nd_mac_addr ether_shost;
+ nd_mac48 ether_dhost;
+ nd_mac48 ether_shost;
nd_uint16_t ether_length_type;
};
{ ETHERTYPE_PPPOED, "PPPoE D" },
{ ETHERTYPE_PPPOES, "PPPoE S" },
{ ETHERTYPE_EAPOL, "EAPOL" },
- { ETHERTYPE_RRCP, "RRCP" },
+ { ETHERTYPE_REALTEK, "Realtek protocols" },
{ ETHERTYPE_MS_NLB_HB, "MS NLB heartbeat" },
{ ETHERTYPE_JUMBO, "Jumbo" },
{ ETHERTYPE_NSH, "NSH" },
const u_char *dst)
{
ND_PRINT("%s > %s, ",
- GET_ETHERADDR_STRING(src), GET_ETHERADDR_STRING(dst));
+ GET_MAC48_STRING(src), GET_MAC48_STRING(dst));
}
static void
int llc_hdrlen;
struct lladdr_info src, dst;
- if (caplen < ETHER_HDRLEN + switch_tag_len) {
- nd_print_trunc(ndo);
- return (caplen);
+ if (length < caplen) {
+ ND_PRINT("[length %u < caplen %u]", length, caplen);
+ nd_print_invalid(ndo);
+ return length;
}
- if (length < ETHER_HDRLEN + switch_tag_len) {
+ if (caplen < ETHER_HDRLEN + switch_tag_len) {
nd_print_trunc(ndo);
- return (length);
+ return caplen;
}
if (print_encap_header != NULL)
*/
ehp = (const struct ether_header *)p;
src.addr = ehp->ether_shost;
- src.addr_string = etheraddr_string;
+ src.addr_string = mac48_string;
dst.addr = ehp->ether_dhost;
- dst.addr_string = etheraddr_string;
+ dst.addr_string = mac48_string;
- length -= 2*MAC_ADDR_LEN;
- caplen -= 2*MAC_ADDR_LEN;
- p += 2*MAC_ADDR_LEN;
- hdrlen = 2*MAC_ADDR_LEN;
+ length -= 2*MAC48_LEN;
+ caplen -= 2*MAC48_LEN;
+ p += 2*MAC48_LEN;
+ hdrlen = 2*MAC48_LEN;
if (ndo->ndo_eflag)
ether_addresses_print(ndo, src.addr, dst.addr);
p += 2;
hdrlen += 2;
+ /*
+ * Process 802.1AE MACsec headers.
+ */
+ printed_length = 0;
if (length_type == ETHERTYPE_MACSEC) {
/*
* MACsec, aka IEEE 802.1AE-2006
* Print the header, and try to print the payload if it's not encrypted
*/
- int ret = macsec_print(ndo, &p, &length, &caplen, &hdrlen, &length_type);
+ if (ndo->ndo_eflag) {
+ ether_type_print(ndo, length_type);
+ ND_PRINT(", length %u: ", orig_length);
+ printed_length = 1;
+ }
+
+ int ret = macsec_print(ndo, &p, &length, &caplen, &hdrlen,
+ &src, &dst);
if (ret == 0) {
- /* Payload is encrypted; just quit. */
- return (hdrlen + caplen);
+ /* Payload is encrypted; print it as raw data. */
+ if (!ndo->ndo_suppress_default_print)
+ ND_DEFAULTPRINT(p, caplen);
+ return hdrlen;
} else if (ret > 0) {
/* Problem printing the header; just quit. */
- return (ret);
+ return ret;
+ } else {
+ /*
+ * Keep processing type/length fields.
+ */
+ length_type = GET_BE_U_2(p);
+
+ ND_ICHECK_U(caplen, <, 2);
+ length -= 2;
+ caplen -= 2;
+ p += 2;
+ hdrlen += 2;
}
}
/*
* Process VLAN tag types.
*/
- printed_length = 0;
while (length_type == ETHERTYPE_8021Q ||
length_type == ETHERTYPE_8021Q9100 ||
length_type == ETHERTYPE_8021Q9200 ||
if (caplen < 4) {
ndo->ndo_protocol = "vlan";
nd_print_trunc(ndo);
- return (hdrlen + caplen);
+ return hdrlen + caplen;
}
if (length < 4) {
ndo->ndo_protocol = "vlan";
nd_print_trunc(ndo);
- return (hdrlen + length);
+ return hdrlen + length;
}
if (ndo->ndo_eflag) {
uint16_t tag = GET_BE_U_2(p);
* Cut off the snapshot length to the end of the
* payload.
*/
- nd_push_snapend(ndo, p + length);
+ if (!nd_push_snaplen(ndo, p, length)) {
+ (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
+ "%s: can't push snaplen on buffer stack", __func__);
+ }
if (ndo->ndo_eflag) {
ND_PRINT("802.3");
} else if (length_type == ETHERTYPE_ARISTA) {
if (caplen < 2) {
ND_PRINT("[|arista]");
- return (hdrlen + caplen);
+ return hdrlen + caplen;
}
if (length < 2) {
ND_PRINT("[|arista]");
- return (hdrlen + length);
+ return hdrlen + length;
}
ether_type_print(ndo, length_type);
ND_PRINT(", length %u: ", orig_length);
ND_PRINT(", ");
}
if (ethertype_print(ndo, length_type, p, length, caplen, &src, &dst) == 0) {
-raw:
/* type not known, print raw packet */
if (!ndo->ndo_eflag) {
/*
ND_DEFAULTPRINT(p, caplen);
}
}
- return (hdrlen);
+invalid:
+ return hdrlen;
}
/*
- * Print an Ethernet frame while specyfing a non-standard Ethernet header
+ * Print an Ethernet frame while specifying 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
void (*print_switch_tag)(netdissect_options *, const u_char *),
u_int switch_tag_len)
{
- return (ether_common_print(ndo, p, length, caplen, print_switch_tag,
- switch_tag_len, NULL, NULL));
+ return ether_common_print(ndo, p, length, caplen, print_switch_tag,
+ switch_tag_len, NULL, NULL);
}
/*
const u_char *encap_header_arg)
{
ndo->ndo_protocol = "ether";
- return (ether_common_print(ndo, p, length, caplen, NULL, 0,
- print_encap_header, encap_header_arg));
+ return ether_common_print(ndo, p, length, caplen, NULL, 0,
+ print_encap_header, encap_header_arg);
}
/*
* of the packet off the wire, and 'h->caplen' is the number
* of bytes actually captured.
*/
-u_int
+void
ether_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *p)
{
- ndo->ndo_protocol = "ether_if";
- return (ether_print(ndo, p, h->len, h->caplen, NULL, NULL));
+ ndo->ndo_protocol = "ether";
+ ndo->ndo_ll_hdr_len +=
+ ether_print(ndo, p, h->len, h->caplen, NULL, NULL);
}
/*
* This is for DLT_NETANALYZER, which has a 4-byte pseudo-header
* before the Ethernet header.
*/
-u_int
+void
netanalyzer_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
const u_char *p)
{
/*
* Fail if we don't have enough data for the Hilscher pseudo-header.
*/
- ndo->ndo_protocol = "netanalyzer_if";
- if (h->caplen < 4) {
- nd_print_trunc(ndo);
- return (h->caplen);
- }
+ ndo->ndo_protocol = "netanalyzer";
+ ND_TCHECK_4(p);
/* Skip the pseudo-header. */
- return (4 + ether_print(ndo, p + 4, h->len - 4, h->caplen - 4, NULL, NULL));
+ ndo->ndo_ll_hdr_len += 4;
+ ndo->ndo_ll_hdr_len +=
+ ether_print(ndo, p + 4, h->len - 4, h->caplen - 4, NULL, NULL);
}
/*
* pseudo-header, a 7-byte Ethernet preamble, and a 1-byte Ethernet SOF
* before the Ethernet header.
*/
-u_int
+void
netanalyzer_transparent_if_print(netdissect_options *ndo,
const struct pcap_pkthdr *h,
const u_char *p)
* Fail if we don't have enough data for the Hilscher pseudo-header,
* preamble, and SOF.
*/
- ndo->ndo_protocol = "netanalyzer_transparent_if";
- if (h->caplen < 12) {
- nd_print_trunc(ndo);
- return (h->caplen);
- }
+ ndo->ndo_protocol = "netanalyzer_transparent";
+ ND_TCHECK_LEN(p, 12);
/* Skip the pseudo-header, preamble, and SOF. */
- return (12 + ether_print(ndo, p + 12, h->len - 12, h->caplen - 12, NULL, NULL));
+ ndo->ndo_ll_hdr_len += 12;
+ ndo->ndo_ll_hdr_len +=
+ ether_print(ndo, p + 12, h->len - 12, h->caplen - 12, NULL, NULL);
}
/*
nd_print_trunc(ndo);
return (1);
}
+ /* At least one byte is required */
+ /* FIXME: Reference for this byte? */
+ ND_TCHECK_1(p);
isoclns_print(ndo, p + 1, length - 1);
return(1);
return (1);
case ETHERTYPE_EAPOL:
- eap_print(ndo, p, length);
+ eapol_print(ndo, p);
return (1);
- case ETHERTYPE_RRCP:
- rrcp_print(ndo, p, length, src, dst);
+ case ETHERTYPE_REALTEK:
+ rtl_print(ndo, p, length, src, dst);
return (1);
case ETHERTYPE_PPP: