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