xref: /aosp_15_r20/external/tcpdump/print-ether.c (revision 05b00f6010a2396e3db2409989fc67270046269f)
1*05b00f60SXin Li /*
2*05b00f60SXin Li  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
3*05b00f60SXin Li  *	The Regents of the University of California.  All rights reserved.
4*05b00f60SXin Li  *
5*05b00f60SXin Li  * Redistribution and use in source and binary forms, with or without
6*05b00f60SXin Li  * modification, are permitted provided that: (1) source code distributions
7*05b00f60SXin Li  * retain the above copyright notice and this paragraph in its entirety, (2)
8*05b00f60SXin Li  * distributions including binary code include the above copyright notice and
9*05b00f60SXin Li  * this paragraph in its entirety in the documentation or other materials
10*05b00f60SXin Li  * provided with the distribution, and (3) all advertising materials mentioning
11*05b00f60SXin Li  * features or use of this software display the following acknowledgement:
12*05b00f60SXin Li  * ``This product includes software developed by the University of California,
13*05b00f60SXin Li  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14*05b00f60SXin Li  * the University nor the names of its contributors may be used to endorse
15*05b00f60SXin Li  * or promote products derived from this software without specific prior
16*05b00f60SXin Li  * written permission.
17*05b00f60SXin Li  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18*05b00f60SXin Li  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19*05b00f60SXin Li  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20*05b00f60SXin Li  */
21*05b00f60SXin Li 
22*05b00f60SXin Li /* \summary: Ethernet printer */
23*05b00f60SXin Li 
24*05b00f60SXin Li #ifdef HAVE_CONFIG_H
25*05b00f60SXin Li #include <config.h>
26*05b00f60SXin Li #endif
27*05b00f60SXin Li 
28*05b00f60SXin Li #include "netdissect-stdinc.h"
29*05b00f60SXin Li 
30*05b00f60SXin Li #define ND_LONGJMP_FROM_TCHECK
31*05b00f60SXin Li #include "netdissect.h"
32*05b00f60SXin Li #include "extract.h"
33*05b00f60SXin Li #include "addrtoname.h"
34*05b00f60SXin Li #include "ethertype.h"
35*05b00f60SXin Li 
36*05b00f60SXin Li /*
37*05b00f60SXin Li  * Structure of an Ethernet header.
38*05b00f60SXin Li  */
39*05b00f60SXin Li struct	ether_header {
40*05b00f60SXin Li 	nd_mac_addr	ether_dhost;
41*05b00f60SXin Li 	nd_mac_addr	ether_shost;
42*05b00f60SXin Li 	nd_uint16_t	ether_length_type;
43*05b00f60SXin Li };
44*05b00f60SXin Li 
45*05b00f60SXin Li /*
46*05b00f60SXin Li  * Length of an Ethernet header; note that some compilers may pad
47*05b00f60SXin Li  * "struct ether_header" to a multiple of 4 bytes, for example, so
48*05b00f60SXin Li  * "sizeof (struct ether_header)" may not give the right answer.
49*05b00f60SXin Li  */
50*05b00f60SXin Li #define ETHER_HDRLEN		14
51*05b00f60SXin Li 
52*05b00f60SXin Li const struct tok ethertype_values[] = {
53*05b00f60SXin Li     { ETHERTYPE_IP,		"IPv4" },
54*05b00f60SXin Li     { ETHERTYPE_MPLS,		"MPLS unicast" },
55*05b00f60SXin Li     { ETHERTYPE_MPLS_MULTI,	"MPLS multicast" },
56*05b00f60SXin Li     { ETHERTYPE_IPV6,		"IPv6" },
57*05b00f60SXin Li     { ETHERTYPE_8021Q,		"802.1Q" },
58*05b00f60SXin Li     { ETHERTYPE_8021Q9100,	"802.1Q-9100" },
59*05b00f60SXin Li     { ETHERTYPE_8021QinQ,	"802.1Q-QinQ" },
60*05b00f60SXin Li     { ETHERTYPE_8021Q9200,	"802.1Q-9200" },
61*05b00f60SXin Li     { ETHERTYPE_MACSEC,		"802.1AE MACsec" },
62*05b00f60SXin Li     { ETHERTYPE_VMAN,		"VMAN" },
63*05b00f60SXin Li     { ETHERTYPE_PUP,            "PUP" },
64*05b00f60SXin Li     { ETHERTYPE_ARP,            "ARP"},
65*05b00f60SXin Li     { ETHERTYPE_REVARP,         "Reverse ARP"},
66*05b00f60SXin Li     { ETHERTYPE_NS,             "NS" },
67*05b00f60SXin Li     { ETHERTYPE_SPRITE,         "Sprite" },
68*05b00f60SXin Li     { ETHERTYPE_TRAIL,          "Trail" },
69*05b00f60SXin Li     { ETHERTYPE_MOPDL,          "MOP DL" },
70*05b00f60SXin Li     { ETHERTYPE_MOPRC,          "MOP RC" },
71*05b00f60SXin Li     { ETHERTYPE_DN,             "DN" },
72*05b00f60SXin Li     { ETHERTYPE_LAT,            "LAT" },
73*05b00f60SXin Li     { ETHERTYPE_SCA,            "SCA" },
74*05b00f60SXin Li     { ETHERTYPE_TEB,            "TEB" },
75*05b00f60SXin Li     { ETHERTYPE_LANBRIDGE,      "Lanbridge" },
76*05b00f60SXin Li     { ETHERTYPE_DECDNS,         "DEC DNS" },
77*05b00f60SXin Li     { ETHERTYPE_DECDTS,         "DEC DTS" },
78*05b00f60SXin Li     { ETHERTYPE_VEXP,           "VEXP" },
79*05b00f60SXin Li     { ETHERTYPE_VPROD,          "VPROD" },
80*05b00f60SXin Li     { ETHERTYPE_ATALK,          "Appletalk" },
81*05b00f60SXin Li     { ETHERTYPE_AARP,           "Appletalk ARP" },
82*05b00f60SXin Li     { ETHERTYPE_IPX,            "IPX" },
83*05b00f60SXin Li     { ETHERTYPE_PPP,            "PPP" },
84*05b00f60SXin Li     { ETHERTYPE_MPCP,           "MPCP" },
85*05b00f60SXin Li     { ETHERTYPE_SLOW,           "Slow Protocols" },
86*05b00f60SXin Li     { ETHERTYPE_PPPOED,         "PPPoE D" },
87*05b00f60SXin Li     { ETHERTYPE_PPPOES,         "PPPoE S" },
88*05b00f60SXin Li     { ETHERTYPE_EAPOL,          "EAPOL" },
89*05b00f60SXin Li     { ETHERTYPE_REALTEK,        "Realtek protocols" },
90*05b00f60SXin Li     { ETHERTYPE_MS_NLB_HB,      "MS NLB heartbeat" },
91*05b00f60SXin Li     { ETHERTYPE_JUMBO,          "Jumbo" },
92*05b00f60SXin Li     { ETHERTYPE_NSH,            "NSH" },
93*05b00f60SXin Li     { ETHERTYPE_LOOPBACK,       "Loopback" },
94*05b00f60SXin Li     { ETHERTYPE_ISO,            "OSI" },
95*05b00f60SXin Li     { ETHERTYPE_GRE_ISO,        "GRE-OSI" },
96*05b00f60SXin Li     { ETHERTYPE_CFM_OLD,        "CFM (old)" },
97*05b00f60SXin Li     { ETHERTYPE_CFM,            "CFM" },
98*05b00f60SXin Li     { ETHERTYPE_IEEE1905_1,     "IEEE1905.1" },
99*05b00f60SXin Li     { ETHERTYPE_LLDP,           "LLDP" },
100*05b00f60SXin Li     { ETHERTYPE_TIPC,           "TIPC"},
101*05b00f60SXin Li     { ETHERTYPE_GEONET_OLD,     "GeoNet (old)"},
102*05b00f60SXin Li     { ETHERTYPE_GEONET,         "GeoNet"},
103*05b00f60SXin Li     { ETHERTYPE_CALM_FAST,      "CALM FAST"},
104*05b00f60SXin Li     { ETHERTYPE_AOE,            "AoE" },
105*05b00f60SXin Li     { ETHERTYPE_PTP,            "PTP" },
106*05b00f60SXin Li     { ETHERTYPE_ARISTA,         "Arista Vendor Specific Protocol" },
107*05b00f60SXin Li     { 0, NULL}
108*05b00f60SXin Li };
109*05b00f60SXin Li 
110*05b00f60SXin Li static void
ether_addresses_print(netdissect_options * ndo,const u_char * src,const u_char * dst)111*05b00f60SXin Li ether_addresses_print(netdissect_options *ndo, const u_char *src,
112*05b00f60SXin Li 		      const u_char *dst)
113*05b00f60SXin Li {
114*05b00f60SXin Li 	ND_PRINT("%s > %s, ",
115*05b00f60SXin Li 		 GET_ETHERADDR_STRING(src), GET_ETHERADDR_STRING(dst));
116*05b00f60SXin Li }
117*05b00f60SXin Li 
118*05b00f60SXin Li static void
ether_type_print(netdissect_options * ndo,uint16_t type)119*05b00f60SXin Li ether_type_print(netdissect_options *ndo, uint16_t type)
120*05b00f60SXin Li {
121*05b00f60SXin Li 	if (!ndo->ndo_qflag)
122*05b00f60SXin Li 		ND_PRINT("ethertype %s (0x%04x)",
123*05b00f60SXin Li 			 tok2str(ethertype_values, "Unknown", type), type);
124*05b00f60SXin Li 	else
125*05b00f60SXin Li 		ND_PRINT("%s",
126*05b00f60SXin Li 			 tok2str(ethertype_values, "Unknown Ethertype (0x%04x)", type));
127*05b00f60SXin Li }
128*05b00f60SXin Li 
129*05b00f60SXin Li /*
130*05b00f60SXin Li  * Common code for printing Ethernet frames.
131*05b00f60SXin Li  *
132*05b00f60SXin Li  * It can handle Ethernet headers with extra tag information inserted
133*05b00f60SXin Li  * after the destination and source addresses, as is inserted by some
134*05b00f60SXin Li  * switch chips, and extra encapsulation header information before
135*05b00f60SXin Li  * printing Ethernet header information (such as a LANE ID for ATM LANE).
136*05b00f60SXin Li  */
137*05b00f60SXin Li static u_int
ether_common_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen,void (* print_switch_tag)(netdissect_options * ndo,const u_char *),u_int switch_tag_len,void (* print_encap_header)(netdissect_options * ndo,const u_char *),const u_char * encap_header_arg)138*05b00f60SXin Li ether_common_print(netdissect_options *ndo, const u_char *p, u_int length,
139*05b00f60SXin Li     u_int caplen,
140*05b00f60SXin Li     void (*print_switch_tag)(netdissect_options *ndo, const u_char *),
141*05b00f60SXin Li     u_int switch_tag_len,
142*05b00f60SXin Li     void (*print_encap_header)(netdissect_options *ndo, const u_char *),
143*05b00f60SXin Li     const u_char *encap_header_arg)
144*05b00f60SXin Li {
145*05b00f60SXin Li 	const struct ether_header *ehp;
146*05b00f60SXin Li 	u_int orig_length;
147*05b00f60SXin Li 	u_int hdrlen;
148*05b00f60SXin Li 	u_short length_type;
149*05b00f60SXin Li 	int printed_length;
150*05b00f60SXin Li 	int llc_hdrlen;
151*05b00f60SXin Li 	struct lladdr_info src, dst;
152*05b00f60SXin Li 
153*05b00f60SXin Li 	if (length < caplen) {
154*05b00f60SXin Li 		ND_PRINT("[length %u < caplen %u]", length, caplen);
155*05b00f60SXin Li 		nd_print_invalid(ndo);
156*05b00f60SXin Li 		return length;
157*05b00f60SXin Li 	}
158*05b00f60SXin Li 	if (caplen < ETHER_HDRLEN + switch_tag_len) {
159*05b00f60SXin Li 		nd_print_trunc(ndo);
160*05b00f60SXin Li 		return caplen;
161*05b00f60SXin Li 	}
162*05b00f60SXin Li 
163*05b00f60SXin Li 	if (print_encap_header != NULL)
164*05b00f60SXin Li 		(*print_encap_header)(ndo, encap_header_arg);
165*05b00f60SXin Li 
166*05b00f60SXin Li 	orig_length = length;
167*05b00f60SXin Li 
168*05b00f60SXin Li 	/*
169*05b00f60SXin Li 	 * Get the source and destination addresses, skip past them,
170*05b00f60SXin Li 	 * and print them if we're printing the link-layer header.
171*05b00f60SXin Li 	 */
172*05b00f60SXin Li 	ehp = (const struct ether_header *)p;
173*05b00f60SXin Li 	src.addr = ehp->ether_shost;
174*05b00f60SXin Li 	src.addr_string = etheraddr_string;
175*05b00f60SXin Li 	dst.addr = ehp->ether_dhost;
176*05b00f60SXin Li 	dst.addr_string = etheraddr_string;
177*05b00f60SXin Li 
178*05b00f60SXin Li 	length -= 2*MAC_ADDR_LEN;
179*05b00f60SXin Li 	caplen -= 2*MAC_ADDR_LEN;
180*05b00f60SXin Li 	p += 2*MAC_ADDR_LEN;
181*05b00f60SXin Li 	hdrlen = 2*MAC_ADDR_LEN;
182*05b00f60SXin Li 
183*05b00f60SXin Li 	if (ndo->ndo_eflag)
184*05b00f60SXin Li 		ether_addresses_print(ndo, src.addr, dst.addr);
185*05b00f60SXin Li 
186*05b00f60SXin Li 	/*
187*05b00f60SXin Li 	 * Print the switch tag, if we have one, and skip past it.
188*05b00f60SXin Li 	 */
189*05b00f60SXin Li 	if (print_switch_tag != NULL)
190*05b00f60SXin Li 		(*print_switch_tag)(ndo, p);
191*05b00f60SXin Li 
192*05b00f60SXin Li 	length -= switch_tag_len;
193*05b00f60SXin Li 	caplen -= switch_tag_len;
194*05b00f60SXin Li 	p += switch_tag_len;
195*05b00f60SXin Li 	hdrlen += switch_tag_len;
196*05b00f60SXin Li 
197*05b00f60SXin Li 	/*
198*05b00f60SXin Li 	 * Get the length/type field, skip past it, and print it
199*05b00f60SXin Li 	 * if we're printing the link-layer header.
200*05b00f60SXin Li 	 */
201*05b00f60SXin Li recurse:
202*05b00f60SXin Li 	length_type = GET_BE_U_2(p);
203*05b00f60SXin Li 
204*05b00f60SXin Li 	length -= 2;
205*05b00f60SXin Li 	caplen -= 2;
206*05b00f60SXin Li 	p += 2;
207*05b00f60SXin Li 	hdrlen += 2;
208*05b00f60SXin Li 
209*05b00f60SXin Li 	/*
210*05b00f60SXin Li 	 * Process 802.1AE MACsec headers.
211*05b00f60SXin Li 	 */
212*05b00f60SXin Li 	printed_length = 0;
213*05b00f60SXin Li 	if (length_type == ETHERTYPE_MACSEC) {
214*05b00f60SXin Li 		/*
215*05b00f60SXin Li 		 * MACsec, aka IEEE 802.1AE-2006
216*05b00f60SXin Li 		 * Print the header, and try to print the payload if it's not encrypted
217*05b00f60SXin Li 		 */
218*05b00f60SXin Li 		if (ndo->ndo_eflag) {
219*05b00f60SXin Li 			ether_type_print(ndo, length_type);
220*05b00f60SXin Li 			ND_PRINT(", length %u: ", orig_length);
221*05b00f60SXin Li 			printed_length = 1;
222*05b00f60SXin Li 		}
223*05b00f60SXin Li 
224*05b00f60SXin Li 		int ret = macsec_print(ndo, &p, &length, &caplen, &hdrlen,
225*05b00f60SXin Li 				       &src, &dst);
226*05b00f60SXin Li 
227*05b00f60SXin Li 		if (ret == 0) {
228*05b00f60SXin Li 			/* Payload is encrypted; print it as raw data. */
229*05b00f60SXin Li 			if (!ndo->ndo_suppress_default_print)
230*05b00f60SXin Li 				ND_DEFAULTPRINT(p, caplen);
231*05b00f60SXin Li 			return hdrlen;
232*05b00f60SXin Li 		} else if (ret > 0) {
233*05b00f60SXin Li 			/* Problem printing the header; just quit. */
234*05b00f60SXin Li 			return ret;
235*05b00f60SXin Li 		} else {
236*05b00f60SXin Li 			/*
237*05b00f60SXin Li 			 * Keep processing type/length fields.
238*05b00f60SXin Li 			 */
239*05b00f60SXin Li 			length_type = GET_BE_U_2(p);
240*05b00f60SXin Li 
241*05b00f60SXin Li 			ND_LCHECK_U(caplen, 2);
242*05b00f60SXin Li 			length -= 2;
243*05b00f60SXin Li 			caplen -= 2;
244*05b00f60SXin Li 			p += 2;
245*05b00f60SXin Li 			hdrlen += 2;
246*05b00f60SXin Li 		}
247*05b00f60SXin Li 	}
248*05b00f60SXin Li 
249*05b00f60SXin Li 	/*
250*05b00f60SXin Li 	 * Process VLAN tag types.
251*05b00f60SXin Li 	 */
252*05b00f60SXin Li 	while (length_type == ETHERTYPE_8021Q  ||
253*05b00f60SXin Li 		length_type == ETHERTYPE_8021Q9100 ||
254*05b00f60SXin Li 		length_type == ETHERTYPE_8021Q9200 ||
255*05b00f60SXin Li 		length_type == ETHERTYPE_8021QinQ) {
256*05b00f60SXin Li 		/*
257*05b00f60SXin Li 		 * It has a VLAN tag.
258*05b00f60SXin Li 		 * Print VLAN information, and then go back and process
259*05b00f60SXin Li 		 * the enclosed type field.
260*05b00f60SXin Li 		 */
261*05b00f60SXin Li 		if (caplen < 4) {
262*05b00f60SXin Li 			ndo->ndo_protocol = "vlan";
263*05b00f60SXin Li 			nd_print_trunc(ndo);
264*05b00f60SXin Li 			return hdrlen + caplen;
265*05b00f60SXin Li 		}
266*05b00f60SXin Li 		if (length < 4) {
267*05b00f60SXin Li 			ndo->ndo_protocol = "vlan";
268*05b00f60SXin Li 			nd_print_trunc(ndo);
269*05b00f60SXin Li 			return hdrlen + length;
270*05b00f60SXin Li 		}
271*05b00f60SXin Li 		if (ndo->ndo_eflag) {
272*05b00f60SXin Li 			uint16_t tag = GET_BE_U_2(p);
273*05b00f60SXin Li 
274*05b00f60SXin Li 			ether_type_print(ndo, length_type);
275*05b00f60SXin Li 			if (!printed_length) {
276*05b00f60SXin Li 				ND_PRINT(", length %u: ", orig_length);
277*05b00f60SXin Li 				printed_length = 1;
278*05b00f60SXin Li 			} else
279*05b00f60SXin Li 				ND_PRINT(", ");
280*05b00f60SXin Li 			ND_PRINT("%s, ", ieee8021q_tci_string(tag));
281*05b00f60SXin Li 		}
282*05b00f60SXin Li 
283*05b00f60SXin Li 		length_type = GET_BE_U_2(p + 2);
284*05b00f60SXin Li 		p += 4;
285*05b00f60SXin Li 		length -= 4;
286*05b00f60SXin Li 		caplen -= 4;
287*05b00f60SXin Li 		hdrlen += 4;
288*05b00f60SXin Li 	}
289*05b00f60SXin Li 
290*05b00f60SXin Li 	/*
291*05b00f60SXin Li 	 * We now have the final length/type field.
292*05b00f60SXin Li 	 */
293*05b00f60SXin Li 	if (length_type <= MAX_ETHERNET_LENGTH_VAL) {
294*05b00f60SXin Li 		/*
295*05b00f60SXin Li 		 * It's a length field, containing the length of the
296*05b00f60SXin Li 		 * remaining payload; use it as such, as long as
297*05b00f60SXin Li 		 * it's not too large (bigger than the actual payload).
298*05b00f60SXin Li 		 */
299*05b00f60SXin Li 		if (length_type < length) {
300*05b00f60SXin Li 			length = length_type;
301*05b00f60SXin Li 			if (caplen > length)
302*05b00f60SXin Li 				caplen = length;
303*05b00f60SXin Li 		}
304*05b00f60SXin Li 
305*05b00f60SXin Li 		/*
306*05b00f60SXin Li 		 * Cut off the snapshot length to the end of the
307*05b00f60SXin Li 		 * payload.
308*05b00f60SXin Li 		 */
309*05b00f60SXin Li 		if (!nd_push_snaplen(ndo, p, length)) {
310*05b00f60SXin Li 			(*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
311*05b00f60SXin Li 				"%s: can't push snaplen on buffer stack", __func__);
312*05b00f60SXin Li 		}
313*05b00f60SXin Li 
314*05b00f60SXin Li 		if (ndo->ndo_eflag) {
315*05b00f60SXin Li 			ND_PRINT("802.3");
316*05b00f60SXin Li 			if (!printed_length)
317*05b00f60SXin Li 				ND_PRINT(", length %u: ", length);
318*05b00f60SXin Li 		}
319*05b00f60SXin Li 
320*05b00f60SXin Li 		/*
321*05b00f60SXin Li 		 * An LLC header follows the length.  Print that and
322*05b00f60SXin Li 		 * higher layers.
323*05b00f60SXin Li 		 */
324*05b00f60SXin Li 		llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
325*05b00f60SXin Li 		if (llc_hdrlen < 0) {
326*05b00f60SXin Li 			/* packet type not known, print raw packet */
327*05b00f60SXin Li 			if (!ndo->ndo_suppress_default_print)
328*05b00f60SXin Li 				ND_DEFAULTPRINT(p, caplen);
329*05b00f60SXin Li 			llc_hdrlen = -llc_hdrlen;
330*05b00f60SXin Li 		}
331*05b00f60SXin Li 		hdrlen += llc_hdrlen;
332*05b00f60SXin Li 		nd_pop_packet_info(ndo);
333*05b00f60SXin Li 	} else if (length_type == ETHERTYPE_JUMBO) {
334*05b00f60SXin Li 		/*
335*05b00f60SXin Li 		 * It's a type field, with the type for Alteon jumbo frames.
336*05b00f60SXin Li 		 * See
337*05b00f60SXin Li 		 *
338*05b00f60SXin Li 		 *	https://tools.ietf.org/html/draft-ietf-isis-ext-eth-01
339*05b00f60SXin Li 		 *
340*05b00f60SXin Li 		 * which indicates that, following the type field,
341*05b00f60SXin Li 		 * there's an LLC header and payload.
342*05b00f60SXin Li 		 */
343*05b00f60SXin Li 		/* Try to print the LLC-layer header & higher layers */
344*05b00f60SXin Li 		llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst);
345*05b00f60SXin Li 		if (llc_hdrlen < 0) {
346*05b00f60SXin Li 			/* packet type not known, print raw packet */
347*05b00f60SXin Li 			if (!ndo->ndo_suppress_default_print)
348*05b00f60SXin Li 				ND_DEFAULTPRINT(p, caplen);
349*05b00f60SXin Li 			llc_hdrlen = -llc_hdrlen;
350*05b00f60SXin Li 		}
351*05b00f60SXin Li 		hdrlen += llc_hdrlen;
352*05b00f60SXin Li 	} else if (length_type == ETHERTYPE_ARISTA) {
353*05b00f60SXin Li 		if (caplen < 2) {
354*05b00f60SXin Li 			ND_PRINT("[|arista]");
355*05b00f60SXin Li 			return hdrlen + caplen;
356*05b00f60SXin Li 		}
357*05b00f60SXin Li 		if (length < 2) {
358*05b00f60SXin Li 			ND_PRINT("[|arista]");
359*05b00f60SXin Li 			return hdrlen + length;
360*05b00f60SXin Li 		}
361*05b00f60SXin Li 		ether_type_print(ndo, length_type);
362*05b00f60SXin Li 		ND_PRINT(", length %u: ", orig_length);
363*05b00f60SXin Li 		int bytesConsumed = arista_ethertype_print(ndo, p, length);
364*05b00f60SXin Li 		if (bytesConsumed > 0) {
365*05b00f60SXin Li 			p += bytesConsumed;
366*05b00f60SXin Li 			length -= bytesConsumed;
367*05b00f60SXin Li 			caplen -= bytesConsumed;
368*05b00f60SXin Li 			hdrlen += bytesConsumed;
369*05b00f60SXin Li 			goto recurse;
370*05b00f60SXin Li 		} else {
371*05b00f60SXin Li 			/* subtype/version not known, print raw packet */
372*05b00f60SXin Li 			if (!ndo->ndo_eflag && length_type > MAX_ETHERNET_LENGTH_VAL) {
373*05b00f60SXin Li 				ether_addresses_print(ndo, src.addr, dst.addr);
374*05b00f60SXin Li 				ether_type_print(ndo, length_type);
375*05b00f60SXin Li 				ND_PRINT(", length %u: ", orig_length);
376*05b00f60SXin Li 			}
377*05b00f60SXin Li 			 if (!ndo->ndo_suppress_default_print)
378*05b00f60SXin Li 				 ND_DEFAULTPRINT(p, caplen);
379*05b00f60SXin Li 		}
380*05b00f60SXin Li 	} else {
381*05b00f60SXin Li 		/*
382*05b00f60SXin Li 		 * It's a type field with some other value.
383*05b00f60SXin Li 		 */
384*05b00f60SXin Li 		if (ndo->ndo_eflag) {
385*05b00f60SXin Li 			ether_type_print(ndo, length_type);
386*05b00f60SXin Li 			if (!printed_length)
387*05b00f60SXin Li 				ND_PRINT(", length %u: ", orig_length);
388*05b00f60SXin Li 			else
389*05b00f60SXin Li 				ND_PRINT(", ");
390*05b00f60SXin Li 		}
391*05b00f60SXin Li 		if (ethertype_print(ndo, length_type, p, length, caplen, &src, &dst) == 0) {
392*05b00f60SXin Li 			/* type not known, print raw packet */
393*05b00f60SXin Li 			if (!ndo->ndo_eflag) {
394*05b00f60SXin Li 				/*
395*05b00f60SXin Li 				 * We didn't print the full link-layer
396*05b00f60SXin Li 				 * header, as -e wasn't specified, so
397*05b00f60SXin Li 				 * print only the source and destination
398*05b00f60SXin Li 				 * MAC addresses and the final Ethernet
399*05b00f60SXin Li 				 * type.
400*05b00f60SXin Li 				 */
401*05b00f60SXin Li 				ether_addresses_print(ndo, src.addr, dst.addr);
402*05b00f60SXin Li 				ether_type_print(ndo, length_type);
403*05b00f60SXin Li 				ND_PRINT(", length %u: ", orig_length);
404*05b00f60SXin Li 			}
405*05b00f60SXin Li 
406*05b00f60SXin Li 			if (!ndo->ndo_suppress_default_print)
407*05b00f60SXin Li 				ND_DEFAULTPRINT(p, caplen);
408*05b00f60SXin Li 		}
409*05b00f60SXin Li 	}
410*05b00f60SXin Li invalid:
411*05b00f60SXin Li 	return hdrlen;
412*05b00f60SXin Li }
413*05b00f60SXin Li 
414*05b00f60SXin Li /*
415*05b00f60SXin Li  * Print an Ethernet frame while specyfing a non-standard Ethernet header
416*05b00f60SXin Li  * length.
417*05b00f60SXin Li  * This might be encapsulated within another frame; we might be passed
418*05b00f60SXin Li  * a pointer to a function that can print header information for that
419*05b00f60SXin Li  * frame's protocol, and an argument to pass to that function.
420*05b00f60SXin Li  *
421*05b00f60SXin Li  * FIXME: caplen can and should be derived from ndo->ndo_snapend and p.
422*05b00f60SXin Li  */
423*05b00f60SXin Li u_int
ether_switch_tag_print(netdissect_options * ndo,const u_char * p,u_int length,u_int caplen,void (* print_switch_tag)(netdissect_options *,const u_char *),u_int switch_tag_len)424*05b00f60SXin Li ether_switch_tag_print(netdissect_options *ndo, const u_char *p, u_int length,
425*05b00f60SXin Li     u_int caplen,
426*05b00f60SXin Li     void (*print_switch_tag)(netdissect_options *, const u_char *),
427*05b00f60SXin Li     u_int switch_tag_len)
428*05b00f60SXin Li {
429*05b00f60SXin Li 	return ether_common_print(ndo, p, length, caplen, print_switch_tag,
430*05b00f60SXin Li 				  switch_tag_len, NULL, NULL);
431*05b00f60SXin Li }
432*05b00f60SXin Li 
433*05b00f60SXin Li /*
434*05b00f60SXin Li  * Print an Ethernet frame.
435*05b00f60SXin Li  * This might be encapsulated within another frame; we might be passed
436*05b00f60SXin Li  * a pointer to a function that can print header information for that
437*05b00f60SXin Li  * frame's protocol, and an argument to pass to that function.
438*05b00f60SXin Li  *
439*05b00f60SXin Li  * FIXME: caplen can and should be derived from ndo->ndo_snapend and p.
440*05b00f60SXin Li  */
441*05b00f60SXin Li 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)442*05b00f60SXin Li ether_print(netdissect_options *ndo,
443*05b00f60SXin Li 	    const u_char *p, u_int length, u_int caplen,
444*05b00f60SXin Li 	    void (*print_encap_header)(netdissect_options *ndo, const u_char *),
445*05b00f60SXin Li 	    const u_char *encap_header_arg)
446*05b00f60SXin Li {
447*05b00f60SXin Li 	ndo->ndo_protocol = "ether";
448*05b00f60SXin Li 	return ether_common_print(ndo, p, length, caplen, NULL, 0,
449*05b00f60SXin Li 				  print_encap_header, encap_header_arg);
450*05b00f60SXin Li }
451*05b00f60SXin Li 
452*05b00f60SXin Li /*
453*05b00f60SXin Li  * This is the top level routine of the printer.  'p' points
454*05b00f60SXin Li  * to the ether header of the packet, 'h->len' is the length
455*05b00f60SXin Li  * of the packet off the wire, and 'h->caplen' is the number
456*05b00f60SXin Li  * of bytes actually captured.
457*05b00f60SXin Li  */
458*05b00f60SXin Li void
ether_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)459*05b00f60SXin Li ether_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
460*05b00f60SXin Li 	       const u_char *p)
461*05b00f60SXin Li {
462*05b00f60SXin Li 	ndo->ndo_protocol = "ether";
463*05b00f60SXin Li 	ndo->ndo_ll_hdr_len +=
464*05b00f60SXin Li 		ether_print(ndo, p, h->len, h->caplen, NULL, NULL);
465*05b00f60SXin Li }
466*05b00f60SXin Li 
467*05b00f60SXin Li /*
468*05b00f60SXin Li  * This is the top level routine of the printer.  'p' points
469*05b00f60SXin Li  * to the ether header of the packet, 'h->len' is the length
470*05b00f60SXin Li  * of the packet off the wire, and 'h->caplen' is the number
471*05b00f60SXin Li  * of bytes actually captured.
472*05b00f60SXin Li  *
473*05b00f60SXin Li  * This is for DLT_NETANALYZER, which has a 4-byte pseudo-header
474*05b00f60SXin Li  * before the Ethernet header.
475*05b00f60SXin Li  */
476*05b00f60SXin Li void
netanalyzer_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)477*05b00f60SXin Li netanalyzer_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
478*05b00f60SXin Li 		     const u_char *p)
479*05b00f60SXin Li {
480*05b00f60SXin Li 	/*
481*05b00f60SXin Li 	 * Fail if we don't have enough data for the Hilscher pseudo-header.
482*05b00f60SXin Li 	 */
483*05b00f60SXin Li 	ndo->ndo_protocol = "netanalyzer";
484*05b00f60SXin Li 	ND_TCHECK_LEN(p, 4);
485*05b00f60SXin Li 
486*05b00f60SXin Li 	/* Skip the pseudo-header. */
487*05b00f60SXin Li 	ndo->ndo_ll_hdr_len += 4;
488*05b00f60SXin Li 	ndo->ndo_ll_hdr_len +=
489*05b00f60SXin Li 		ether_print(ndo, p + 4, h->len - 4, h->caplen - 4, NULL, NULL);
490*05b00f60SXin Li }
491*05b00f60SXin Li 
492*05b00f60SXin Li /*
493*05b00f60SXin Li  * This is the top level routine of the printer.  'p' points
494*05b00f60SXin Li  * to the ether header of the packet, 'h->len' is the length
495*05b00f60SXin Li  * of the packet off the wire, and 'h->caplen' is the number
496*05b00f60SXin Li  * of bytes actually captured.
497*05b00f60SXin Li  *
498*05b00f60SXin Li  * This is for DLT_NETANALYZER_TRANSPARENT, which has a 4-byte
499*05b00f60SXin Li  * pseudo-header, a 7-byte Ethernet preamble, and a 1-byte Ethernet SOF
500*05b00f60SXin Li  * before the Ethernet header.
501*05b00f60SXin Li  */
502*05b00f60SXin Li void
netanalyzer_transparent_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)503*05b00f60SXin Li netanalyzer_transparent_if_print(netdissect_options *ndo,
504*05b00f60SXin Li 				 const struct pcap_pkthdr *h,
505*05b00f60SXin Li 				 const u_char *p)
506*05b00f60SXin Li {
507*05b00f60SXin Li 	/*
508*05b00f60SXin Li 	 * Fail if we don't have enough data for the Hilscher pseudo-header,
509*05b00f60SXin Li 	 * preamble, and SOF.
510*05b00f60SXin Li 	 */
511*05b00f60SXin Li 	ndo->ndo_protocol = "netanalyzer_transparent";
512*05b00f60SXin Li 	ND_TCHECK_LEN(p, 12);
513*05b00f60SXin Li 
514*05b00f60SXin Li 	/* Skip the pseudo-header, preamble, and SOF. */
515*05b00f60SXin Li 	ndo->ndo_ll_hdr_len += 12;
516*05b00f60SXin Li 	ndo->ndo_ll_hdr_len +=
517*05b00f60SXin Li 		ether_print(ndo, p + 12, h->len - 12, h->caplen - 12, NULL, NULL);
518*05b00f60SXin Li }
519*05b00f60SXin Li 
520*05b00f60SXin Li /*
521*05b00f60SXin Li  * Prints the packet payload, given an Ethernet type code for the payload's
522*05b00f60SXin Li  * protocol.
523*05b00f60SXin Li  *
524*05b00f60SXin Li  * Returns non-zero if it can do so, zero if the ethertype is unknown.
525*05b00f60SXin Li  */
526*05b00f60SXin Li 
527*05b00f60SXin Li int
ethertype_print(netdissect_options * ndo,u_short ether_type,const u_char * p,u_int length,u_int caplen,const struct lladdr_info * src,const struct lladdr_info * dst)528*05b00f60SXin Li ethertype_print(netdissect_options *ndo,
529*05b00f60SXin Li 		u_short ether_type, const u_char *p,
530*05b00f60SXin Li 		u_int length, u_int caplen,
531*05b00f60SXin Li 		const struct lladdr_info *src, const struct lladdr_info *dst)
532*05b00f60SXin Li {
533*05b00f60SXin Li 	switch (ether_type) {
534*05b00f60SXin Li 
535*05b00f60SXin Li 	case ETHERTYPE_IP:
536*05b00f60SXin Li 		ip_print(ndo, p, length);
537*05b00f60SXin Li 		return (1);
538*05b00f60SXin Li 
539*05b00f60SXin Li 	case ETHERTYPE_IPV6:
540*05b00f60SXin Li 		ip6_print(ndo, p, length);
541*05b00f60SXin Li 		return (1);
542*05b00f60SXin Li 
543*05b00f60SXin Li 	case ETHERTYPE_ARP:
544*05b00f60SXin Li 	case ETHERTYPE_REVARP:
545*05b00f60SXin Li 		arp_print(ndo, p, length, caplen);
546*05b00f60SXin Li 		return (1);
547*05b00f60SXin Li 
548*05b00f60SXin Li 	case ETHERTYPE_DN:
549*05b00f60SXin Li 		decnet_print(ndo, p, length, caplen);
550*05b00f60SXin Li 		return (1);
551*05b00f60SXin Li 
552*05b00f60SXin Li 	case ETHERTYPE_ATALK:
553*05b00f60SXin Li 		if (ndo->ndo_vflag)
554*05b00f60SXin Li 			ND_PRINT("et1 ");
555*05b00f60SXin Li 		atalk_print(ndo, p, length);
556*05b00f60SXin Li 		return (1);
557*05b00f60SXin Li 
558*05b00f60SXin Li 	case ETHERTYPE_AARP:
559*05b00f60SXin Li 		aarp_print(ndo, p, length);
560*05b00f60SXin Li 		return (1);
561*05b00f60SXin Li 
562*05b00f60SXin Li 	case ETHERTYPE_IPX:
563*05b00f60SXin Li 		ND_PRINT("(NOV-ETHII) ");
564*05b00f60SXin Li 		ipx_print(ndo, p, length);
565*05b00f60SXin Li 		return (1);
566*05b00f60SXin Li 
567*05b00f60SXin Li 	case ETHERTYPE_ISO:
568*05b00f60SXin Li 		if (length == 0 || caplen == 0) {
569*05b00f60SXin Li 			ndo->ndo_protocol = "isoclns";
570*05b00f60SXin Li 			nd_print_trunc(ndo);
571*05b00f60SXin Li 			return (1);
572*05b00f60SXin Li 		}
573*05b00f60SXin Li 		/* At least one byte is required */
574*05b00f60SXin Li 		/* FIXME: Reference for this byte? */
575*05b00f60SXin Li 		ND_TCHECK_LEN(p, 1);
576*05b00f60SXin Li 		isoclns_print(ndo, p + 1, length - 1);
577*05b00f60SXin Li 		return(1);
578*05b00f60SXin Li 
579*05b00f60SXin Li 	case ETHERTYPE_PPPOED:
580*05b00f60SXin Li 	case ETHERTYPE_PPPOES:
581*05b00f60SXin Li 	case ETHERTYPE_PPPOED2:
582*05b00f60SXin Li 	case ETHERTYPE_PPPOES2:
583*05b00f60SXin Li 		pppoe_print(ndo, p, length);
584*05b00f60SXin Li 		return (1);
585*05b00f60SXin Li 
586*05b00f60SXin Li 	case ETHERTYPE_EAPOL:
587*05b00f60SXin Li 		eapol_print(ndo, p);
588*05b00f60SXin Li 		return (1);
589*05b00f60SXin Li 
590*05b00f60SXin Li 	case ETHERTYPE_REALTEK:
591*05b00f60SXin Li 		rtl_print(ndo, p, length, src, dst);
592*05b00f60SXin Li 		return (1);
593*05b00f60SXin Li 
594*05b00f60SXin Li 	case ETHERTYPE_PPP:
595*05b00f60SXin Li 		if (length) {
596*05b00f60SXin Li 			ND_PRINT(": ");
597*05b00f60SXin Li 			ppp_print(ndo, p, length);
598*05b00f60SXin Li 		}
599*05b00f60SXin Li 		return (1);
600*05b00f60SXin Li 
601*05b00f60SXin Li 	case ETHERTYPE_MPCP:
602*05b00f60SXin Li 		mpcp_print(ndo, p, length);
603*05b00f60SXin Li 		return (1);
604*05b00f60SXin Li 
605*05b00f60SXin Li 	case ETHERTYPE_SLOW:
606*05b00f60SXin Li 		slow_print(ndo, p, length);
607*05b00f60SXin Li 		return (1);
608*05b00f60SXin Li 
609*05b00f60SXin Li 	case ETHERTYPE_CFM:
610*05b00f60SXin Li 	case ETHERTYPE_CFM_OLD:
611*05b00f60SXin Li 		cfm_print(ndo, p, length);
612*05b00f60SXin Li 		return (1);
613*05b00f60SXin Li 
614*05b00f60SXin Li 	case ETHERTYPE_LLDP:
615*05b00f60SXin Li 		lldp_print(ndo, p, length);
616*05b00f60SXin Li 		return (1);
617*05b00f60SXin Li 
618*05b00f60SXin Li 	case ETHERTYPE_NSH:
619*05b00f60SXin Li 		nsh_print(ndo, p, length);
620*05b00f60SXin Li 		return (1);
621*05b00f60SXin Li 
622*05b00f60SXin Li 	case ETHERTYPE_LOOPBACK:
623*05b00f60SXin Li 		loopback_print(ndo, p, length);
624*05b00f60SXin Li 		return (1);
625*05b00f60SXin Li 
626*05b00f60SXin Li 	case ETHERTYPE_MPLS:
627*05b00f60SXin Li 	case ETHERTYPE_MPLS_MULTI:
628*05b00f60SXin Li 		mpls_print(ndo, p, length);
629*05b00f60SXin Li 		return (1);
630*05b00f60SXin Li 
631*05b00f60SXin Li 	case ETHERTYPE_TIPC:
632*05b00f60SXin Li 		tipc_print(ndo, p, length, caplen);
633*05b00f60SXin Li 		return (1);
634*05b00f60SXin Li 
635*05b00f60SXin Li 	case ETHERTYPE_MS_NLB_HB:
636*05b00f60SXin Li 		msnlb_print(ndo, p);
637*05b00f60SXin Li 		return (1);
638*05b00f60SXin Li 
639*05b00f60SXin Li 	case ETHERTYPE_GEONET_OLD:
640*05b00f60SXin Li 	case ETHERTYPE_GEONET:
641*05b00f60SXin Li 		geonet_print(ndo, p, length, src);
642*05b00f60SXin Li 		return (1);
643*05b00f60SXin Li 
644*05b00f60SXin Li 	case ETHERTYPE_CALM_FAST:
645*05b00f60SXin Li 		calm_fast_print(ndo, p, length, src);
646*05b00f60SXin Li 		return (1);
647*05b00f60SXin Li 
648*05b00f60SXin Li 	case ETHERTYPE_AOE:
649*05b00f60SXin Li 		aoe_print(ndo, p, length);
650*05b00f60SXin Li 		return (1);
651*05b00f60SXin Li 
652*05b00f60SXin Li 	case ETHERTYPE_PTP:
653*05b00f60SXin Li 		ptp_print(ndo, p, length);
654*05b00f60SXin Li 		return (1);
655*05b00f60SXin Li 
656*05b00f60SXin Li 	case ETHERTYPE_LAT:
657*05b00f60SXin Li 	case ETHERTYPE_SCA:
658*05b00f60SXin Li 	case ETHERTYPE_MOPRC:
659*05b00f60SXin Li 	case ETHERTYPE_MOPDL:
660*05b00f60SXin Li 	case ETHERTYPE_IEEE1905_1:
661*05b00f60SXin Li 		/* default_print for now */
662*05b00f60SXin Li 	default:
663*05b00f60SXin Li 		return (0);
664*05b00f60SXin Li 	}
665*05b00f60SXin Li }
666