117680Spst/*
298527Sfenner * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2053146Sbrian *
2153146Sbrian * $FreeBSD$
2217680Spst */
2317680Spst#ifndef lint
24127675Sbmsstatic const char rcsid[] _U_ =
25214478Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-ether.c,v 1.106 2008-02-06 10:47:53 guy Exp $ (LBL)";
2617680Spst#endif
2717680Spst
28235530Sdelphij#define NETDISSECT_REWORKED
2956896Sfenner#ifdef HAVE_CONFIG_H
3056896Sfenner#include "config.h"
3156896Sfenner#endif
3256896Sfenner
33127675Sbms#include <tcpdump-stdinc.h>
3417680Spst
3517680Spst#include <stdio.h>
3617680Spst#include <pcap.h>
3717680Spst
3817680Spst#include "interface.h"
39214478Srpaulo#include "extract.h"
4017680Spst#include "addrtoname.h"
4117680Spst#include "ethertype.h"
4275118Sfenner#include "ether.h"
4375118Sfenner
44127675Sbmsconst struct tok ethertype_values[] = {
45127675Sbms    { ETHERTYPE_IP,		"IPv4" },
46127675Sbms    { ETHERTYPE_MPLS,		"MPLS unicast" },
47127675Sbms    { ETHERTYPE_MPLS_MULTI,	"MPLS multicast" },
48127675Sbms    { ETHERTYPE_IPV6,		"IPv6" },
49127675Sbms    { ETHERTYPE_8021Q,		"802.1Q" },
50235530Sdelphij    { ETHERTYPE_8021Q9100,	"802.1Q-9100" },
51235530Sdelphij    { ETHERTYPE_8021QinQ,	"802.1Q-QinQ" },
52235530Sdelphij    { ETHERTYPE_8021Q9200,	"802.1Q-9200" },
53127675Sbms    { ETHERTYPE_VMAN,		"VMAN" },
54127675Sbms    { ETHERTYPE_PUP,            "PUP" },
55127675Sbms    { ETHERTYPE_ARP,            "ARP"},
56172686Smlaier    { ETHERTYPE_REVARP,         "Reverse ARP"},
57127675Sbms    { ETHERTYPE_NS,             "NS" },
58127675Sbms    { ETHERTYPE_SPRITE,         "Sprite" },
59127675Sbms    { ETHERTYPE_TRAIL,          "Trail" },
60127675Sbms    { ETHERTYPE_MOPDL,          "MOP DL" },
61127675Sbms    { ETHERTYPE_MOPRC,          "MOP RC" },
62127675Sbms    { ETHERTYPE_DN,             "DN" },
63127675Sbms    { ETHERTYPE_LAT,            "LAT" },
64127675Sbms    { ETHERTYPE_SCA,            "SCA" },
65214478Srpaulo    { ETHERTYPE_TEB,            "TEB" },
66127675Sbms    { ETHERTYPE_LANBRIDGE,      "Lanbridge" },
67127675Sbms    { ETHERTYPE_DECDNS,         "DEC DNS" },
68127675Sbms    { ETHERTYPE_DECDTS,         "DEC DTS" },
69127675Sbms    { ETHERTYPE_VEXP,           "VEXP" },
70127675Sbms    { ETHERTYPE_VPROD,          "VPROD" },
71127675Sbms    { ETHERTYPE_ATALK,          "Appletalk" },
72127675Sbms    { ETHERTYPE_AARP,           "Appletalk ARP" },
73127675Sbms    { ETHERTYPE_IPX,            "IPX" },
74127675Sbms    { ETHERTYPE_PPP,            "PPP" },
75190207Srpaulo    { ETHERTYPE_MPCP,           "MPCP" },
76162021Ssam    { ETHERTYPE_SLOW,           "Slow Protocols" },
77127675Sbms    { ETHERTYPE_PPPOED,         "PPPoE D" },
78127675Sbms    { ETHERTYPE_PPPOES,         "PPPoE S" },
79146778Ssam    { ETHERTYPE_EAPOL,          "EAPOL" },
80190207Srpaulo    { ETHERTYPE_RRCP,           "RRCP" },
81251158Sdelphij    { ETHERTYPE_MS_NLB_HB,      "MS NLB heartbeat" },
82146778Ssam    { ETHERTYPE_JUMBO,          "Jumbo" },
83127675Sbms    { ETHERTYPE_LOOPBACK,       "Loopback" },
84146778Ssam    { ETHERTYPE_ISO,            "OSI" },
85146778Ssam    { ETHERTYPE_GRE_ISO,        "GRE-OSI" },
86190207Srpaulo    { ETHERTYPE_CFM_OLD,        "CFM (old)" },
87190207Srpaulo    { ETHERTYPE_CFM,            "CFM" },
88190207Srpaulo    { ETHERTYPE_LLDP,           "LLDP" },
89241235Sdelphij    { ETHERTYPE_TIPC,           "TIPC"},
90127675Sbms    { 0, NULL}
91127675Sbms};
92127675Sbms
9317680Spststatic inline void
94235530Sdelphijether_hdr_print(netdissect_options *ndo,
95235530Sdelphij                const u_char *bp, u_int length)
9617680Spst{
9717680Spst	register const struct ether_header *ep;
98214478Srpaulo	u_int16_t ether_type;
99214478Srpaulo
100127675Sbms	ep = (const struct ether_header *)bp;
10117680Spst
102235530Sdelphij	(void)ND_PRINT((ndo, "%s > %s",
103127675Sbms		     etheraddr_string(ESRC(ep)),
104235530Sdelphij		     etheraddr_string(EDST(ep))));
105127675Sbms
106214478Srpaulo	ether_type = EXTRACT_16BITS(&ep->ether_type);
107235530Sdelphij	if (!ndo->ndo_qflag) {
108214478Srpaulo	        if (ether_type <= ETHERMTU)
109235530Sdelphij		          (void)ND_PRINT((ndo, ", 802.3"));
110127675Sbms                else
111235530Sdelphij		          (void)ND_PRINT((ndo, ", ethertype %s (0x%04x)",
112214478Srpaulo				       tok2str(ethertype_values,"Unknown", ether_type),
113235530Sdelphij                                       ether_type));
114127675Sbms        } else {
115214478Srpaulo                if (ether_type <= ETHERMTU)
116235530Sdelphij                          (void)ND_PRINT((ndo, ", 802.3"));
117127675Sbms                else
118235530Sdelphij                          (void)ND_PRINT((ndo, ", %s", tok2str(ethertype_values,"Unknown Ethertype (0x%04x)", ether_type)));
119127675Sbms        }
120127675Sbms
121235530Sdelphij	(void)ND_PRINT((ndo, ", length %u: ", length));
12217680Spst}
12317680Spst
124214478Srpaulo/*
125214478Srpaulo * Print an Ethernet frame.
126214478Srpaulo * This might be encapsulated within another frame; we might be passed
127214478Srpaulo * a pointer to a function that can print header information for that
128214478Srpaulo * frame's protocol, and an argument to pass to that function.
129214478Srpaulo */
13017680Spstvoid
131235530Sdelphijether_print(netdissect_options *ndo,
132235530Sdelphij            const u_char *p, u_int length, u_int caplen,
133235530Sdelphij            void (*print_encap_header)(netdissect_options *ndo, const u_char *), const u_char *encap_header_arg)
13417680Spst{
13517680Spst	struct ether_header *ep;
136214478Srpaulo	u_int orig_length;
13717680Spst	u_short ether_type;
138127675Sbms	u_short extracted_ether_type;
13917680Spst
140214478Srpaulo	if (caplen < ETHER_HDRLEN || length < ETHER_HDRLEN) {
141235530Sdelphij		ND_PRINT((ndo, "[|ether]"));
142127675Sbms		return;
14317680Spst	}
14417680Spst
145235530Sdelphij	if (ndo->ndo_eflag) {
146214478Srpaulo		if (print_encap_header != NULL)
147235530Sdelphij			(*print_encap_header)(ndo, encap_header_arg);
148235530Sdelphij		ether_hdr_print(ndo, p, length);
149214478Srpaulo	}
150214478Srpaulo	orig_length = length;
15117680Spst
15275118Sfenner	length -= ETHER_HDRLEN;
15375118Sfenner	caplen -= ETHER_HDRLEN;
15417680Spst	ep = (struct ether_header *)p;
15575118Sfenner	p += ETHER_HDRLEN;
15617680Spst
157214478Srpaulo	ether_type = EXTRACT_16BITS(&ep->ether_type);
15817680Spst
159214478Srpaulorecurse:
16017680Spst	/*
16117680Spst	 * Is it (gag) an 802.3 encapsulation?
16217680Spst	 */
16317689Spst	if (ether_type <= ETHERMTU) {
16417680Spst		/* Try to print the LLC-layer header & higher layers */
16575118Sfenner		if (llc_print(p, length, caplen, ESRC(ep), EDST(ep),
166127675Sbms		    &extracted_ether_type) == 0) {
16717680Spst			/* ether_type not known, print raw packet */
168235530Sdelphij			if (!ndo->ndo_eflag) {
169214478Srpaulo				if (print_encap_header != NULL)
170235530Sdelphij					(*print_encap_header)(ndo, encap_header_arg);
171235530Sdelphij				ether_hdr_print(ndo, (u_char *)ep, orig_length);
172214478Srpaulo			}
173127675Sbms
174235530Sdelphij			if (!ndo->ndo_suppress_default_print)
175235530Sdelphij				ndo->ndo_default_print(ndo, p, caplen);
17617680Spst		}
177235530Sdelphij	} else if (ether_type == ETHERTYPE_8021Q  ||
178235530Sdelphij                ether_type == ETHERTYPE_8021Q9100 ||
179235530Sdelphij                ether_type == ETHERTYPE_8021Q9200 ||
180235530Sdelphij                ether_type == ETHERTYPE_8021QinQ) {
181214478Srpaulo		/*
182214478Srpaulo		 * Print VLAN information, and then go back and process
183214478Srpaulo		 * the enclosed type field.
184214478Srpaulo		 */
185214478Srpaulo		if (caplen < 4 || length < 4) {
186235530Sdelphij			ND_PRINT((ndo, "[|vlan]"));
187214478Srpaulo			return;
188214478Srpaulo		}
189235530Sdelphij	        if (ndo->ndo_eflag) {
190214478Srpaulo	        	u_int16_t tag = EXTRACT_16BITS(p);
191127675Sbms
192235530Sdelphij			ND_PRINT((ndo, "vlan %u, p %u%s, ",
193214478Srpaulo			    tag & 0xfff,
194214478Srpaulo			    tag >> 13,
195235530Sdelphij			    (tag & 0x1000) ? ", CFI" : ""));
196214478Srpaulo		}
197214478Srpaulo
198214478Srpaulo		ether_type = EXTRACT_16BITS(p + 2);
199235530Sdelphij		if (ndo->ndo_eflag && ether_type > ETHERMTU)
200235530Sdelphij			ND_PRINT((ndo, "ethertype %s, ", tok2str(ethertype_values,"0x%04x", ether_type)));
201214478Srpaulo		p += 4;
202214478Srpaulo		length -= 4;
203214478Srpaulo		caplen -= 4;
204214478Srpaulo		goto recurse;
205214478Srpaulo	} else if (ether_type == ETHERTYPE_JUMBO) {
206214478Srpaulo		/*
207214478Srpaulo		 * Alteon jumbo frames.
208214478Srpaulo		 * See
209214478Srpaulo		 *
210214478Srpaulo		 *	http://tools.ietf.org/html/draft-ietf-isis-ext-eth-01
211214478Srpaulo		 *
212214478Srpaulo		 * which indicates that, following the type field,
213214478Srpaulo		 * there's an LLC header and payload.
214214478Srpaulo		 */
215214478Srpaulo		/* Try to print the LLC-layer header & higher layers */
216214478Srpaulo		if (llc_print(p, length, caplen, ESRC(ep), EDST(ep),
217214478Srpaulo		    &extracted_ether_type) == 0) {
218214478Srpaulo			/* ether_type not known, print raw packet */
219235530Sdelphij			if (!ndo->ndo_eflag) {
220214478Srpaulo				if (print_encap_header != NULL)
221235530Sdelphij					(*print_encap_header)(ndo, encap_header_arg);
222235530Sdelphij				ether_hdr_print(ndo, (u_char *)ep, orig_length);
223214478Srpaulo			}
224214478Srpaulo
225235530Sdelphij			if (!ndo->ndo_suppress_default_print)
226235530Sdelphij				ndo->ndo_default_print(ndo, p, caplen);
227214478Srpaulo		}
228214478Srpaulo	} else {
229235530Sdelphij		if (ethertype_print(ndo, ether_type, p, length, caplen) == 0) {
230214478Srpaulo			/* ether_type not known, print raw packet */
231235530Sdelphij			if (!ndo->ndo_eflag) {
232214478Srpaulo				if (print_encap_header != NULL)
233235530Sdelphij					(*print_encap_header)(ndo, encap_header_arg);
234235530Sdelphij				ether_hdr_print(ndo, (u_char *)ep, orig_length);
235214478Srpaulo			}
236214478Srpaulo
237235530Sdelphij			if (!ndo->ndo_suppress_default_print)
238235530Sdelphij				ndo->ndo_default_print(ndo, p, caplen);
239214478Srpaulo		}
240214478Srpaulo	}
24117680Spst}
24217680Spst
24317680Spst/*
244127675Sbms * This is the top level routine of the printer.  'p' points
245127675Sbms * to the ether header of the packet, 'h->ts' is the timestamp,
246146778Ssam * 'h->len' is the length of the packet off the wire, and 'h->caplen'
247127675Sbms * is the number of bytes actually captured.
248127675Sbms */
249127675Sbmsu_int
250235530Sdelphijether_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
251235530Sdelphij               const u_char *p)
252127675Sbms{
253235530Sdelphij	ether_print(ndo, p, h->len, h->caplen, NULL, NULL);
254127675Sbms
255127675Sbms	return (ETHER_HDRLEN);
256127675Sbms}
257127675Sbms
258127675Sbms/*
259235530Sdelphij * This is the top level routine of the printer.  'p' points
260235530Sdelphij * to the ether header of the packet, 'h->ts' is the timestamp,
261235530Sdelphij * 'h->len' is the length of the packet off the wire, and 'h->caplen'
262235530Sdelphij * is the number of bytes actually captured.
263235530Sdelphij *
264235530Sdelphij * This is for DLT_NETANALYZER, which has a 4-byte pseudo-header
265235530Sdelphij * before the Ethernet header.
266235530Sdelphij */
267235530Sdelphiju_int
268235530Sdelphijnetanalyzer_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h,
269235530Sdelphij                     const u_char *p)
270235530Sdelphij{
271235530Sdelphij	/*
272235530Sdelphij	 * Fail if we don't have enough data for the Hilscher pseudo-header.
273235530Sdelphij	 */
274235530Sdelphij	if (h->len < 4 || h->caplen < 4) {
275235530Sdelphij		printf("[|netanalyzer]");
276235530Sdelphij		return (h->caplen);
277235530Sdelphij	}
278235530Sdelphij
279235530Sdelphij	/* Skip the pseudo-header. */
280235530Sdelphij	ether_print(ndo, p + 4, h->len - 4, h->caplen - 4, NULL, NULL);
281235530Sdelphij
282235530Sdelphij	return (4 + ETHER_HDRLEN);
283235530Sdelphij}
284235530Sdelphij
285235530Sdelphij/*
286235530Sdelphij * This is the top level routine of the printer.  'p' points
287235530Sdelphij * to the ether header of the packet, 'h->ts' is the timestamp,
288235530Sdelphij * 'h->len' is the length of the packet off the wire, and 'h->caplen'
289235530Sdelphij * is the number of bytes actually captured.
290235530Sdelphij *
291235530Sdelphij * This is for DLT_NETANALYZER_TRANSPARENT, which has a 4-byte
292235530Sdelphij * pseudo-header, a 7-byte Ethernet preamble, and a 1-byte Ethernet SOF
293235530Sdelphij * before the Ethernet header.
294235530Sdelphij */
295235530Sdelphiju_int
296235530Sdelphijnetanalyzer_transparent_if_print(netdissect_options *ndo,
297235530Sdelphij                                 const struct pcap_pkthdr *h,
298235530Sdelphij                                 const u_char *p)
299235530Sdelphij{
300235530Sdelphij	/*
301235530Sdelphij	 * Fail if we don't have enough data for the Hilscher pseudo-header,
302235530Sdelphij	 * preamble, and SOF.
303235530Sdelphij	 */
304235530Sdelphij	if (h->len < 12 || h->caplen < 12) {
305235530Sdelphij		printf("[|netanalyzer-transparent]");
306235530Sdelphij		return (h->caplen);
307235530Sdelphij	}
308235530Sdelphij
309235530Sdelphij	/* Skip the pseudo-header, preamble, and SOF. */
310235530Sdelphij	ether_print(ndo, p + 12, h->len - 12, h->caplen - 12, NULL, NULL);
311235530Sdelphij
312235530Sdelphij	return (12 + ETHER_HDRLEN);
313235530Sdelphij}
314235530Sdelphij
315235530Sdelphij/*
316214478Srpaulo * Prints the packet payload, given an Ethernet type code for the payload's
317214478Srpaulo * protocol.
31817680Spst *
31917680Spst * Returns non-zero if it can do so, zero if the ethertype is unknown.
32017680Spst */
32117680Spst
32217680Spstint
323235530Sdelphijethertype_print(netdissect_options *ndo,
324235530Sdelphij                u_short ether_type, const u_char *p,
325235530Sdelphij                u_int length, u_int caplen)
32617680Spst{
327127675Sbms	switch (ether_type) {
32817680Spst
32917680Spst	case ETHERTYPE_IP:
330235530Sdelphij	        ip_print(ndo, p, length);
33117680Spst		return (1);
33217680Spst
33356896Sfenner#ifdef INET6
33456896Sfenner	case ETHERTYPE_IPV6:
335235530Sdelphij		ip6_print(ndo, p, length);
33656896Sfenner		return (1);
33756896Sfenner#endif /*INET6*/
33856896Sfenner
33917680Spst	case ETHERTYPE_ARP:
34017680Spst	case ETHERTYPE_REVARP:
341235530Sdelphij  	        arp_print(ndo, p, length, caplen);
34217680Spst		return (1);
34317680Spst
34417680Spst	case ETHERTYPE_DN:
345235530Sdelphij		decnet_print(/*ndo,*/p, length, caplen);
34617680Spst		return (1);
34717680Spst
34817680Spst	case ETHERTYPE_ATALK:
349235530Sdelphij		if (ndo->ndo_vflag)
35017680Spst			fputs("et1 ", stdout);
351235530Sdelphij		atalk_print(/*ndo,*/p, length);
35217680Spst		return (1);
35317680Spst
35417680Spst	case ETHERTYPE_AARP:
355235530Sdelphij		aarp_print(/*ndo,*/p, length);
35617680Spst		return (1);
35717680Spst
35818308Spst	case ETHERTYPE_IPX:
359235530Sdelphij		ND_PRINT((ndo, "(NOV-ETHII) "));
360235530Sdelphij		ipx_print(/*ndo,*/p, length);
36118308Spst		return (1);
36218308Spst
363146778Ssam        case ETHERTYPE_ISO:
364235530Sdelphij                isoclns_print(/*ndo,*/p+1, length-1, length-1);
365146778Ssam                return(1);
366146778Ssam
36756896Sfenner	case ETHERTYPE_PPPOED:
36856896Sfenner	case ETHERTYPE_PPPOES:
36984019Sjulian	case ETHERTYPE_PPPOED2:
37084019Sjulian	case ETHERTYPE_PPPOES2:
371235530Sdelphij		pppoe_print(/*ndo,*/p, length);
372127675Sbms		return (1);
373127675Sbms
374146778Ssam	case ETHERTYPE_EAPOL:
375235530Sdelphij	        eap_print(ndo, p, length);
376146778Ssam		return (1);
377146778Ssam
378190207Srpaulo	case ETHERTYPE_RRCP:
379235530Sdelphij	        rrcp_print(ndo, p - 14 , length + 14);
380190207Srpaulo		return (1);
381190207Srpaulo
38298527Sfenner	case ETHERTYPE_PPP:
38398527Sfenner		if (length) {
38498527Sfenner			printf(": ");
385235530Sdelphij			ppp_print(/*ndo,*/p, length);
38698527Sfenner		}
38798527Sfenner		return (1);
38898527Sfenner
389190207Srpaulo	case ETHERTYPE_MPCP:
390235530Sdelphij	        mpcp_print(/*ndo,*/p, length);
391190207Srpaulo		return (1);
392190207Srpaulo
393162021Ssam	case ETHERTYPE_SLOW:
394235530Sdelphij	        slow_print(/*ndo,*/p, length);
395162021Ssam		return (1);
396162021Ssam
397190207Srpaulo	case ETHERTYPE_CFM:
398190207Srpaulo	case ETHERTYPE_CFM_OLD:
399235530Sdelphij	        cfm_print(/*ndo,*/p, length);
400190207Srpaulo		return (1);
401190207Srpaulo
402190207Srpaulo	case ETHERTYPE_LLDP:
403235530Sdelphij	        lldp_print(/*ndo,*/p, length);
404190207Srpaulo		return (1);
405190207Srpaulo
406127675Sbms        case ETHERTYPE_LOOPBACK:
407147904Ssam                return (1);
408127675Sbms
40998527Sfenner	case ETHERTYPE_MPLS:
41098527Sfenner	case ETHERTYPE_MPLS_MULTI:
411235530Sdelphij		mpls_print(/*ndo,*/p, length);
41298527Sfenner		return (1);
41398527Sfenner
414241235Sdelphij	case ETHERTYPE_TIPC:
415241235Sdelphij		tipc_print(ndo, p, length, caplen);
416241235Sdelphij		return (1);
417241235Sdelphij
418251158Sdelphij	case ETHERTYPE_MS_NLB_HB:
419251158Sdelphij		msnlb_print(ndo, p, length);
420251158Sdelphij		return (1);
421251158Sdelphij
42217680Spst	case ETHERTYPE_LAT:
42317680Spst	case ETHERTYPE_SCA:
42417680Spst	case ETHERTYPE_MOPRC:
42517680Spst	case ETHERTYPE_MOPDL:
42617680Spst		/* default_print for now */
42717680Spst	default:
42817680Spst		return (0);
42917680Spst	}
43017680Spst}
431146778Ssam
432146778Ssam
433146778Ssam/*
434146778Ssam * Local Variables:
435146778Ssam * c-style: whitesmith
436146778Ssam * c-basic-offset: 8
437146778Ssam * End:
438146778Ssam */
439146778Ssam
440